23#ifndef VCG_REEB_GRAPH_H
24#define VCG_REEB_GRAPH_H
26#include <vcg/complex/complex.h>
27#include <vcg/complex/algorithms/mesh_assert.h>
28#include <vcg/complex/algorithms/update/topology.h>
85template <
class MeshType>
89 typedef typename MeshType::FaceType FaceType;
112 template <
class EdgeMeshType>
113 void Compute(MeshType &m, EdgeMeshType &graph)
115 RequirePerVertexQuality(m);
116 RequireFFAdjacency(m);
117 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
118 MeshAssert<MeshType>::FFTwoManifoldEdge(m);
119 MeshAssert<MeshType>::VertexQualityFinite(m);
122 std::vector<int> order;
123 for (
size_t i = 0; i < m.vert.size(); ++i)
124 if (!m.vert[i].IsD()) order.push_back(
int(i));
125 std::sort(order.begin(), order.end(), [&](
int a,
int b) {
126 const auto qa = m.vert[a].cQ(), qb = m.vert[b].cQ();
127 return qa < qb || (qa == qb && a < b); });
128 rank.assign(m.vert.size(), -1);
129 for (
size_t i = 0; i < order.size(); ++i)
rank[order[i]] =
int(i);
132 faceEdge.assign(3 * m.face.size(), -1);
134 std::vector<int> edgeFaces;
135 std::vector<int> vertFaces(m.vert.size(), 0);
136 for (FaceType &f : m.face)
if (!f.IsD())
138 const size_t fi = tri::Index(m, f);
139 for (
int z = 0; z < 3; ++z)
141 ++vertFaces[tri::Index(m, f.V(z))];
142 if (
faceEdge[3 * fi + z] >= 0)
continue;
143 int v0 = int(tri::Index(m, f.V0(z))), v1 = int(tri::Index(m, f.V1(z)));
144 if (
Below(v1, v0)) std::swap(v0, v1);
149 edgeVert.push_back(std::make_pair(v0, v1));
154 up.assign(m.vert.size(), std::vector<int>());
155 down.assign(m.vert.size(), std::vector<int>());
156 path.assign(
edgeVert.size(), std::vector<int>());
157 pathHi.assign(
edgeVert.size(), std::vector<int>());
158 active.assign(
edgeVert.size(),
false);
159 std::vector<int> label(m.vert.size(), -1);
163 std::vector<int> faceOrder;
164 std::vector<int> faceTop(m.face.size(), -1);
165 for (FaceType &f : m.face)
if (!f.IsD())
167 const int fi = int(tri::Index(m, f));
168 for (
int z = 0; z < 3; ++z) faceTop[fi] = std::max(faceTop[fi],
rank[tri::Index(m, f.V(z))]);
169 faceOrder.push_back(fi);
171 std::sort(faceOrder.begin(), faceOrder.end(), [&](
int a,
int b) { return faceTop[a] < faceTop[b]; });
173 for (
int fi : faceOrder)
175 FaceType &f = m.face[fi];
177 for (
int z = 0; z < 3; ++z) { v[z] = int(tri::Index(m, f.V(z))); e[z] =
faceEdge[3 * fi + z]; }
178 for (
int z = 0; z < 3; ++z)
179 if (path[e[z]].empty()) NewEdge(e[z]);
181 int lo = 0, mid = 1, hi = 2;
182 if (
Below(v[mid], v[lo])) std::swap(lo, mid);
183 if (
Below(v[hi], v[mid])) std::swap(mid, hi);
184 if (
Below(v[mid], v[lo])) std::swap(lo, mid);
185 auto side = [&](
int a,
int b) {
return (a + 1) % 3 == b ? e[a] : e[b]; };
186 Glue(side(lo, hi), side(lo, mid), side(mid, hi));
188 for (
int z = 0; z < 3; ++z)
189 if (--edgeFaces[e[z]] == 0) Finish(e[z]);
190 for (
int z = 0; z < 3; ++z)
191 if (--vertFaces[v[z]] == 0) RemoveRegular(v[z], label);
195 for (
int vi : order) RemoveRegular(vi, label);
198 std::vector<int> arcId(wArc.size(), -1);
200 for (
size_t a = 0; a < wArc.size(); ++a)
if (wArc[a].merged < 0) arcId[a] = na++;
203 vertArc.assign(m.vert.size(), -1);
207 else if (label[vi] >= 0)
vertArc[vi] = arcId[Resolve(label[vi], 2 *
rank[vi])];
211 for (
size_t i = 0; i <
nodeVert.size(); ++i)
212 graph.vert[i].P() = EdgeMeshType::CoordType::Construct(m.vert[
nodeVert[i]].cP());
214 for (
size_t a = 0; a < wArc.size(); ++a)
217 graph.edge[arcId[a]].V(0) = &graph.vert[
vertNode[wArc[a].lo]];
218 graph.edge[arcId[a]].V(1) = &graph.vert[
vertNode[wArc[a].hi]];
224 auto node = [&](
int a,
int k) {
return int(tri::Index(graph, graph.edge[a].cV(k))); };
225 for (
size_t ei = 0; ei <
edgeVert.size(); ++ei)
230 const int a = au >= 0 && (au == aw || (aw < 0 && node(au, 1) ==
vertNode[w])) ? au
231 : aw >= 0 && au < 0 && node(aw, 0) ==
vertNode[u] ? aw : -1;
232 if (a >= 0) {
edgePath[ei].push_back(a);
continue; }
238 while (2 *
rank[pathHi[ei][k]] < pos) ++k;
239 const int y = Resolve(path[ei][k], pos);
241 pos = 2 *
rank[wArc[y].hi] + 1;
244 wArc.clear(); up.clear(); down.clear(); path.clear(); pathHi.clear(); active.clear();
253 std::vector<int> edges;
254 std::vector<std::pair<int,int> > below;
256 std::vector<WArc> wArc;
257 std::vector<std::vector<int> > up, down;
258 std::vector<std::vector<int> > path;
259 std::vector<std::vector<int> > pathHi;
260 std::vector<bool> active;
262 int NewArc(
int lo,
int hi)
264 wArc.push_back(WArc{lo, hi, -1, std::vector<int>(), std::vector<std::pair<int,int> >()});
265 const int a = int(wArc.size()) - 1;
267 down[hi].push_back(a);
274 path[e].push_back(a);
275 wArc[a].edges.push_back(e);
282 for (
int a : path[e]) pathHi[e].push_back(wArc[a].hi);
285 static void Erase(std::vector<int> &v,
int x) { v.erase(std::find(v.begin(), v.end(), x)); }
288 void Glue(
int lh,
int lm,
int mh)
290 const std::vector<int> p = path[lh];
291 std::vector<int> q = path[lm];
292 q.insert(q.end(), path[mh].begin(), path[mh].end());
294 while (i < p.size() && j < q.size())
296 const int a = p[i], b = q[j];
297 assert(wArc[a].lo == wArc[b].lo);
298 if (a == b) { ++i; ++j; }
299 else if (wArc[a].hi == wArc[b].hi)
302 if (wArc[a].edges.size() < wArc[b].edges.size()) Merge(b, a);
else Merge(a, b);
305 else if (
Below(wArc[a].hi, wArc[b].hi)) { Split(b, a); ++i; }
306 else { Split(a, b); ++j; }
311 void Merge(
int a,
int b)
313 for (
int e : wArc[b].edges)
if (active[e])
315 *std::find(path[e].begin(), path[e].end(), b) = a;
316 wArc[a].edges.push_back(e);
318 Erase(up[wArc[b].lo], b);
319 Erase(down[wArc[b].hi], b);
321 wArc[b].edges.clear();
325 void Split(
int b,
int a)
329 B.below.push_back(std::make_pair(B.lo, a));
331 up[B.lo].push_back(b);
332 std::vector<int> still;
333 for (
int e : B.edges)
if (active[e])
335 path[e].insert(std::find(path[e].begin(), path[e].end(), b), a);
336 wArc[a].edges.push_back(e);
344 void RemoveRegular(
int v, std::vector<int> &label)
346 if (up[v].size() != 1 || down[v].size() != 1)
return;
347 const int d = down[v][0], u = up[v][0];
348 for (
int e : wArc[u].edges)
if (active[e]) Erase(path[e], u);
349 wArc[d].hi = wArc[u].hi;
350 *std::find(down[wArc[u].hi].begin(), down[wArc[u].hi].end(), u) = d;
352 wArc[u].edges.clear();
353 up[v].clear(); down[v].clear();
359 int Resolve(
int x,
int pos)
const
363 const WArc &X = wArc[x];
364 if (pos < 2 *
rank[X.lo])
367 x = std::partition_point(X.below.begin(), X.below.end(),
368 [&](
const std::pair<int,int> &s) { return 2 * rank[s.first] < pos; })[-1].second;
370 else if (X.merged >= 0) x = X.merged;
static EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater< EdgePointer > &pu)
Add n edges to the mesh. Function to add n edges to the mesh. The elements are added always to the en...
Definition: allocate.h:339
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:195
Reeb graph of the vertex quality of a triangle mesh.
Definition: reeb_graph.h:87
std::vector< int > vertNode
node of each mesh vertex, -1 for vertices inside an arc
Definition: reeb_graph.h:92
std::vector< int > vertArc
arc of each mesh vertex inside an arc, -1 for nodes
Definition: reeb_graph.h:93
void Compute(MeshType &m, EdgeMeshType &graph)
Compute the Reeb graph of the vertex quality of m into graph.
Definition: reeb_graph.h:113
bool Below(int v, int w) const
True if mesh vertex v comes before w in the order by quality.
Definition: reeb_graph.h:100
std::vector< int > faceEdge
edge number of side z of face fi, at 3*fi+z
Definition: reeb_graph.h:95
std::vector< std::pair< int, int > > edgeVert
lower and upper mesh vertex of each edge
Definition: reeb_graph.h:96
std::vector< std::vector< int > > edgePath
arcs crossed by each mesh edge, going up
Definition: reeb_graph.h:97
std::vector< int > rank
position of each mesh vertex in the order by quality
Definition: reeb_graph.h:94
std::vector< int > nodeVert
mesh vertex of each node
Definition: reeb_graph.h:91
Generation of per-vertex and per-face topological information.
Definition: topology.h:43
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55