TTK
Loading...
Searching...
No Matches
ManifoldCheck.h
Go to the documentation of this file.
1
24#pragma once
25
26// base code includes
27#include <Triangulation.h>
28#include <UnionFind.h>
29
30namespace ttk {
31
32 class ManifoldCheck : virtual public Debug {
33
34 public:
36
37 ~ManifoldCheck() override;
38
40 template <class triangulationType = AbstractTriangulation>
41 int execute(const triangulationType *triangulation) const;
42
45 std::vector<ttk::SimplexId> *vertexVector) {
46 vertexLinkComponentNumber_ = vertexVector;
47 return 0;
48 }
49
52 std::vector<ttk::SimplexId> *edgeVector) {
53 edgeLinkComponentNumber_ = edgeVector;
54 return 0;
55 }
56
59 std::vector<ttk::SimplexId> *triangleVector) {
60 triangleLinkComponentNumber_ = triangleVector;
61 return 0;
62 }
63
82 inline int
84
85 if(triangulation) {
86
87 triangulation->preconditionVertexLinks();
88 triangulation->preconditionEdgeLinks();
89 triangulation->preconditionTriangleLinks();
90 triangulation->preconditionVertexEdges();
91 triangulation->preconditionVertexTriangles();
92 }
93
94 return 0;
95 }
96
97 protected:
98 template <class triangulationType = AbstractTriangulation>
99 int vertexManifoldCheck(const triangulationType *triangulation,
100 const ttk::SimplexId &vertexId) const;
101
102 template <class triangulationType = AbstractTriangulation>
103 int edgeManifoldCheck(const triangulationType *triangulation,
104 const ttk::SimplexId &edgeId) const;
105
106 std::vector<ttk::SimplexId> *vertexLinkComponentNumber_;
107 std::vector<ttk::SimplexId> *edgeLinkComponentNumber_;
108 std::vector<ttk::SimplexId> *triangleLinkComponentNumber_;
109 };
110} // namespace ttk
111
112template <class triangulationType>
113int ttk::ManifoldCheck::execute(const triangulationType *triangulation) const {
114
116
117 Timer t;
118
119// check the consistency of the variables -- to adapt
120#ifndef TTK_ENABLE_KAMIKAZE
121 if(!triangulation)
122 return -1;
123#endif
124
125 SimplexId const vertexNumber = triangulation->getNumberOfVertices();
126
128
129 vertexLinkComponentNumber_->resize(vertexNumber);
130
131#ifdef TTK_ENABLE_OPENMP
132#pragma omp parallel for num_threads(threadNumber_)
133#endif
134 for(SimplexId i = 0; i < vertexNumber; i++) {
135 (*vertexLinkComponentNumber_)[i] = vertexManifoldCheck(triangulation, i);
136 }
137 }
138
139 if((edgeLinkComponentNumber_) && (triangulation->getDimensionality() >= 2)) {
140
141 SimplexId const edgeNumber = triangulation->getNumberOfEdges();
142 edgeLinkComponentNumber_->resize(edgeNumber);
143
144#ifdef TTK_ENABLE_OPENMP
145#pragma omp parallel for num_threads(threadNumber_)
146#endif
147 for(SimplexId i = 0; i < edgeNumber; i++) {
148 (*edgeLinkComponentNumber_)[i] = edgeManifoldCheck(triangulation, i);
149 }
150 }
151
153 && (triangulation->getDimensionality() == 3)) {
154
155 SimplexId const triangleNumber = triangulation->getNumberOfTriangles();
156 triangleLinkComponentNumber_->resize(triangleNumber);
157
158#ifdef TTK_ENABLE_OPENMP
159#pragma omp parallel for num_threads(threadNumber_)
160#endif
161 for(SimplexId i = 0; i < triangleNumber; i++) {
162 (*triangleLinkComponentNumber_)[i]
163 = triangulation->getTriangleLinkNumber(i);
164 }
165 }
166
167 printMsg("Processed " + std::to_string(vertexNumber) + " vertices", 1,
169
171
172 return 0;
173}
174
175template <class triangulationType>
177 const triangulationType *triangulation, const SimplexId &vertexId) const {
178
179 SimplexId const linkSize = triangulation->getVertexLinkNumber(vertexId);
180
181 if(triangulation->getDimensionality() == 1)
182 return linkSize;
183
184 std::vector<SimplexId> linkNeighbors;
185
186 for(SimplexId i = 0; i < linkSize; i++) {
187 SimplexId linkId = -1;
188 triangulation->getVertexLink(vertexId, i, linkId);
189
190 bool isIn = false;
191 SimplexId neighborId = -1;
192
193 if(triangulation->getDimensionality() == 2) {
194 triangulation->getEdgeVertex(linkId, 0, neighborId);
195 isIn = false;
196 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
197 if(linkNeighbors[j] == neighborId) {
198 isIn = true;
199 break;
200 }
201 }
202 if(!isIn)
203 linkNeighbors.push_back(neighborId);
204
205 triangulation->getEdgeVertex(linkId, 1, neighborId);
206 isIn = false;
207 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
208 if(linkNeighbors[j] == neighborId) {
209 isIn = true;
210 break;
211 }
212 }
213 if(!isIn)
214 linkNeighbors.push_back(neighborId);
215 }
216 if(triangulation->getDimensionality() == 3) {
217 triangulation->getTriangleVertex(linkId, 0, neighborId);
218 isIn = false;
219 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
220 if(linkNeighbors[j] == neighborId) {
221 isIn = true;
222 break;
223 }
224 }
225 if(!isIn)
226 linkNeighbors.push_back(neighborId);
227
228 triangulation->getTriangleVertex(linkId, 1, neighborId);
229 isIn = false;
230 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
231 if(linkNeighbors[j] == neighborId) {
232 isIn = true;
233 break;
234 }
235 }
236 if(!isIn)
237 linkNeighbors.push_back(neighborId);
238
239 triangulation->getTriangleVertex(linkId, 2, neighborId);
240 isIn = false;
241 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
242 if(linkNeighbors[j] == neighborId) {
243 isIn = true;
244 break;
245 }
246 }
247 if(!isIn)
248 linkNeighbors.push_back(neighborId);
249 }
250 }
251
252 std::vector<UnionFind> seeds(linkNeighbors.size());
253 std::vector<UnionFind *> seedList(linkNeighbors.size());
254
255 for(SimplexId i = 0; i < (SimplexId)seeds.size(); i++) {
256 seedList[i] = &(seeds[i]);
257 }
258
259 for(SimplexId i = 0; i < linkSize; i++) {
260
261 SimplexId linkId = -1;
262 triangulation->getVertexLink(vertexId, i, linkId);
263
264 SimplexId neighborId0 = -1, neighborId1 = -1, neighborId2 = -1;
265 SimplexId uf0 = -1, uf1 = -1, uf2 = -1;
266
267 if(triangulation->getDimensionality() == 2) {
268 triangulation->getEdgeVertex(linkId, 0, neighborId0);
269 triangulation->getEdgeVertex(linkId, 1, neighborId1);
270
271 // connect the two uf together
272 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
273 if(linkNeighbors[j] == neighborId0) {
274 uf0 = j;
275 break;
276 }
277 }
278 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
279 if(linkNeighbors[j] == neighborId1) {
280 uf1 = j;
281 break;
282 }
283 }
284
285 seedList[uf0] = UnionFind::makeUnion(seedList[uf0], seedList[uf1]);
286 seedList[uf1] = seedList[uf0];
287 }
288
289 if(triangulation->getDimensionality() == 3) {
290 triangulation->getTriangleVertex(linkId, 0, neighborId0);
291 triangulation->getTriangleVertex(linkId, 1, neighborId1);
292 triangulation->getTriangleVertex(linkId, 2, neighborId2);
293
294 // connect the two uf together
295 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
296 if(linkNeighbors[j] == neighborId0) {
297 uf0 = j;
298 break;
299 }
300 }
301 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
302 if(linkNeighbors[j] == neighborId1) {
303 uf1 = j;
304 break;
305 }
306 }
307 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
308 if(linkNeighbors[j] == neighborId2) {
309 uf2 = j;
310 break;
311 }
312 }
313
314 seedList[uf0] = UnionFind::makeUnion(seedList[uf0], seedList[uf1]);
315 seedList[uf0] = UnionFind::makeUnion(seedList[uf0], seedList[uf2]);
316 seedList[uf1] = seedList[uf0];
317 seedList[uf2] = seedList[uf0];
318 }
319 }
320
321 // let's remove duplicates now
322
323 // update the UF if necessary
324 for(SimplexId i = 0; i < (SimplexId)seedList.size(); i++) {
325 seedList[i] = seedList[i]->find();
326 }
327
328 std::vector<UnionFind *>::iterator it;
329 sort(seedList.begin(), seedList.end());
330 it = unique(seedList.begin(), seedList.end());
331 seedList.resize(distance(seedList.begin(), it));
332
333 return (SimplexId)seedList.size();
334}
335
336template <class triangulationType>
338 const triangulationType *triangulation, const SimplexId &edgeId) const {
339
340 SimplexId const linkSize = triangulation->getEdgeLinkNumber(edgeId);
341
342 if(triangulation->getDimensionality() == 2)
343 return linkSize;
344
345 std::vector<SimplexId> linkNeighbors;
346
347 for(SimplexId i = 0; i < linkSize; i++) {
348 SimplexId linkId = -1;
349 triangulation->getEdgeLink(edgeId, i, linkId);
350
351 bool isIn = false;
352 SimplexId neighborId = -1;
353
354 triangulation->getEdgeVertex(linkId, 0, neighborId);
355 isIn = false;
356 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
357 if(linkNeighbors[j] == neighborId) {
358 isIn = true;
359 break;
360 }
361 }
362 if(!isIn)
363 linkNeighbors.push_back(neighborId);
364
365 triangulation->getEdgeVertex(linkId, 1, neighborId);
366 isIn = false;
367 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
368 if(linkNeighbors[j] == neighborId) {
369 isIn = true;
370 break;
371 }
372 }
373 if(!isIn)
374 linkNeighbors.push_back(neighborId);
375 }
376
377 std::vector<UnionFind> seeds(linkNeighbors.size());
378 std::vector<UnionFind *> seedList(linkNeighbors.size());
379
380 for(SimplexId i = 0; i < (SimplexId)seeds.size(); i++) {
381 seedList[i] = &(seeds[i]);
382 }
383
384 for(SimplexId i = 0; i < linkSize; i++) {
385
386 SimplexId linkId = -1;
387 triangulation->getEdgeLink(edgeId, i, linkId);
388
389 SimplexId neighborId0 = -1, neighborId1 = -1;
390 SimplexId uf0 = -1, uf1 = -1;
391
392 triangulation->getEdgeVertex(linkId, 0, neighborId0);
393 triangulation->getEdgeVertex(linkId, 1, neighborId1);
394
395 // connect the two uf together
396 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
397 if(linkNeighbors[j] == neighborId0) {
398 uf0 = j;
399 break;
400 }
401 }
402 for(SimplexId j = 0; j < (SimplexId)linkNeighbors.size(); j++) {
403 if(linkNeighbors[j] == neighborId1) {
404 uf1 = j;
405 break;
406 }
407 }
408
409 seedList[uf0] = UnionFind::makeUnion(seedList[uf0], seedList[uf1]);
410 seedList[uf1] = seedList[uf0];
411 }
412
413 // let's remove duplicates now
414
415 // update the UF if necessary
416 for(SimplexId i = 0; i < (SimplexId)seedList.size(); i++) {
417 seedList[i] = seedList[i]->find();
418 }
419
420 std::vector<UnionFind *>::iterator it;
421 sort(seedList.begin(), seedList.end());
422 it = unique(seedList.begin(), seedList.end());
423 seedList.resize(distance(seedList.begin(), it));
424
425 return (SimplexId)seedList.size();
426}
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
Minimalist debugging class.
Definition Debug.h:88
TTK processing package for manifold checks.
std::vector< ttk::SimplexId > * triangleLinkComponentNumber_
std::vector< ttk::SimplexId > * edgeLinkComponentNumber_
int vertexManifoldCheck(const triangulationType *triangulation, const ttk::SimplexId &vertexId) const
int setEdgeLinkComponentNumberVector(std::vector< ttk::SimplexId > *edgeVector)
Register the output std::vector for edge link component number.
std::vector< ttk::SimplexId > * vertexLinkComponentNumber_
int edgeManifoldCheck(const triangulationType *triangulation, const ttk::SimplexId &edgeId) const
int setTriangleLinkComponentNumberVector(std::vector< ttk::SimplexId > *triangleVector)
Register the output std::vector for triangle link component number.
int setVertexLinkComponentNumberVector(std::vector< ttk::SimplexId > *vertexVector)
Register the output std::vector for vertex link component number.
~ManifoldCheck() override
int preconditionTriangulation(AbstractTriangulation *const triangulation)
int execute(const triangulationType *triangulation) const
Execute the package.
double getElapsedTime()
Definition Timer.h:15
static UnionFind * makeUnion(UnionFind *uf0, UnionFind *uf1)
Definition UnionFind.h:40
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)