TTK
Loading...
Searching...
No Matches
CompactTriangulation.cpp
Go to the documentation of this file.
2
3using namespace ttk;
4
11
13 : AbstractTriangulation(rhs), doublePrecision_(rhs.doublePrecision_),
14 maxCellDim_(rhs.maxCellDim_), cellNumber_(rhs.cellNumber_),
15 vertexNumber_(rhs.vertexNumber_), nodeNumber_(rhs.nodeNumber_),
16 pointSet_(rhs.pointSet_), vertexIndices_(rhs.vertexIndices_),
17 vertexIntervals_(rhs.vertexIntervals_), edgeIntervals_(rhs.edgeIntervals_),
18 triangleIntervals_(rhs.triangleIntervals_),
19 cellIntervals_(rhs.cellIntervals_), cellArray_(rhs.cellArray_),
20 externalCells_(rhs.externalCells_) {
21}
22
43
45
46int CompactTriangulation::reorderVertices(std::vector<SimplexId> &vertexMap) {
47 // get the number of nodes (the max value in the array)
48 nodeNumber_ = 0;
49 for(SimplexId vid = 0; vid < vertexNumber_; vid++) {
50 if(vertexIndices_[vid] > nodeNumber_) {
52 }
53 }
54 nodeNumber_++; // since the index starts from 0
55 std::vector<std::vector<SimplexId>> nodeVertices(nodeNumber_);
56 for(SimplexId vid = 0; vid < vertexNumber_; vid++) {
57 nodeVertices[vertexIndices_[vid]].push_back(vid);
58 }
59
60 // update the vertex intervals
61 vertexIntervals_.resize(nodeNumber_ + 1);
62 vertexIntervals_[0] = -1;
63 SimplexId vertexCount = 0;
64 for(SimplexId nid = 0; nid < nodeNumber_; nid++) {
65 for(SimplexId const vid : nodeVertices[nid]) {
66 vertexMap[vid] = vertexCount++;
67 }
68 vertexIntervals_[nid + 1] = vertexCount - 1;
69 }
70
71 // rearange the vertex coordinate values
73 std::vector<double> newPointSet(3 * vertexNumber_);
74 for(SimplexId vid = 0; vid < vertexNumber_; vid++) {
75 for(int j = 0; j < 3; j++) {
76 newPointSet[3 * vertexMap[vid] + j]
77 = ((const double *)pointSet_)[3 * vid + j];
78 }
79 }
80 for(SimplexId vid = 0; vid < vertexNumber_; vid++) {
81 for(int j = 0; j < 3; j++) {
82 const_cast<double *>((const double *)pointSet_)[3 * vid + j]
83 = newPointSet[3 * vid + j];
84 }
85 }
86 } else {
87 std::vector<float> newPointSet(3 * vertexNumber_);
88 for(SimplexId vid = 0; vid < vertexNumber_; vid++) {
89 for(int j = 0; j < 3; j++) {
90 newPointSet[3 * vertexMap[vid] + j]
91 = ((const float *)pointSet_)[3 * vid + j];
92 }
93 }
94 for(SimplexId vid = 0; vid < vertexNumber_; vid++) {
95 for(int j = 0; j < 3; j++) {
96 const_cast<float *>((const float *)pointSet_)[3 * vid + j]
97 = newPointSet[3 * vid + j];
98 }
99 }
100 }
101
102 // change the vertex indices
103 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
104 for(SimplexId vid = vertexIntervals_[nid - 1] + 1;
105 vid <= vertexIntervals_[nid]; vid++) {
106 const_cast<int *>(vertexIndices_)[vid] = nid;
107 }
108 }
109
110 return 0;
111}
112
113int CompactTriangulation::reorderCells(const std::vector<SimplexId> &vertexMap,
114 const SimplexId &cellNumber,
115 const LongSimplexId *connectivity,
116 const LongSimplexId *offset) {
117 // change the indices in cell array
118 SimplexId cellCount = 0, verticesPerCell = offset[1] - offset[0];
119 std::vector<std::vector<SimplexId>> nodeCells(nodeNumber_ + 1);
120 LongSimplexId *cellArr = const_cast<LongSimplexId *>(connectivity);
121
122 for(SimplexId cid = 0; cid < cellNumber; cid++) {
123 SimplexId const cellId = offset[cid];
124 for(int j = 0; j < verticesPerCell; j++) {
125 cellArr[cellId + j] = vertexMap[cellArr[cellId + j]];
126 }
127 std::sort(cellArr + cellId, cellArr + cellId + verticesPerCell);
128 nodeCells[vertexIndices_[cellArr[cellId]]].push_back(cid);
129 }
130
131 // rearange the cell array
132 cellIntervals_.resize(nodeNumber_ + 1);
133 externalCells_.resize(nodeNumber_ + 1);
134 cellIntervals_[0] = -1;
135 std::vector<LongSimplexId> newCellArray(verticesPerCell * cellNumber);
136 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
137 for(SimplexId const cid : nodeCells[nid]) {
138 SimplexId const cellId = verticesPerCell * cid;
139 SimplexId const newCellId = verticesPerCell * cellCount;
140 for(int j = 0; j < verticesPerCell; j++) {
141 newCellArray[newCellId + j] = connectivity[cellId + j];
142 if(newCellArray[newCellId + j] > vertexIntervals_[nid]) {
143 SimplexId const nodeNum = vertexIndices_[newCellArray[newCellId + j]];
144 if(externalCells_[nodeNum].empty()
145 || externalCells_[nodeNum].back() != cid) {
146 externalCells_[nodeNum].push_back(cid);
147 }
148 }
149 }
150 cellCount++;
151 }
152 cellIntervals_[nid] = cellCount - 1;
153 }
154
155 // copy the new cell array back to original one
156 for(SimplexId i = 0; i < verticesPerCell * cellNumber; i++) {
157 const_cast<LongSimplexId *>(connectivity)[i] = newCellArray[i];
158 }
159
160 return 0;
161}
162
163int CompactTriangulation::reorderCells(const std::vector<SimplexId> &vertexMap,
164 const LongSimplexId *cellArray) {
165 // change the indices in cell array
166 SimplexId cellCount = 0, verticesPerCell = cellArray[0];
167 std::vector<std::vector<SimplexId>> nodeCells(nodeNumber_ + 1);
168 LongSimplexId *cellArr = const_cast<LongSimplexId *>(cellArray);
169
170 for(SimplexId cid = 0; cid < cellNumber_; cid++) {
171 SimplexId const cellId = (verticesPerCell + 1) * cid;
172 for(int j = 1; j <= verticesPerCell; j++) {
173 cellArr[cellId + j] = vertexMap[cellArr[cellId + j]];
174 }
175 std::sort(cellArr + cellId + 1, cellArr + cellId + 1 + verticesPerCell);
176 nodeCells[vertexIndices_[cellArr[cellId + 1]]].push_back(cid);
177 }
178
179 // rearange the cell array
180 cellIntervals_.resize(nodeNumber_ + 1);
181 externalCells_.resize(nodeNumber_ + 1);
182 cellIntervals_[0] = -1;
183 std::vector<LongSimplexId> newCellArray((verticesPerCell + 1) * cellNumber_);
184 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
185 for(SimplexId const cid : nodeCells[nid]) {
186 SimplexId const cellId = (verticesPerCell + 1) * cid;
187 SimplexId const newCellId = (verticesPerCell + 1) * cellCount;
188 newCellArray[newCellId] = verticesPerCell;
189 for(int j = 1; j <= verticesPerCell; j++) {
190 newCellArray[newCellId + j] = cellArray[cellId + j];
191 if(newCellArray[newCellId + j] > vertexIntervals_[nid]) {
192 SimplexId const nodeNum = vertexIndices_[newCellArray[newCellId + j]];
193 if(externalCells_[nodeNum].empty()
194 || externalCells_[nodeNum].back() != cid) {
195 externalCells_[nodeNum].push_back(cid);
196 }
197 }
198 }
199 cellCount++;
200 }
201 cellIntervals_[nid] = cellCount - 1;
202 }
203
204 // copy the new cell array back to original one
205 for(SimplexId i = 0; i < (verticesPerCell + 1) * cellNumber_; i++) {
206 const_cast<LongSimplexId *>(cellArray)[i] = newCellArray[i];
207 }
208
209 return 0;
210}
211
213 ImplicitCluster *const nodePtr,
214 bool computeInternalEdgeList,
215 bool computeInternalEdgeMap) const {
216
217#ifndef TTK_ENABLE_KAMIKAZE
218 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
219 return -1;
220#endif
221
222 SimplexId edgeCount = 0, verticesPerCell = cellArray_->getCellVertexNumber(0);
223
224 if(!nodePtr->internalEdgeMap_.empty()) {
225 // if the edge map has been computed and only request the edge list
226 if(computeInternalEdgeList) {
227 nodePtr->internalEdgeList_ = std::vector<std::array<SimplexId, 2>>(
228 nodePtr->internalEdgeMap_.size());
229 for(auto iter = nodePtr->internalEdgeMap_.begin();
230 iter != nodePtr->internalEdgeMap_.end(); iter++) {
231 nodePtr->internalEdgeList_[iter->second - 1] = iter->first;
232 }
233 return 0;
234 }
235 }
236
237 // loop through the internal cell list
238 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
239 cid <= cellIntervals_[nodePtr->nid]; cid++) {
240 std::array<SimplexId, 2> edgeIds;
241
242 // loop through each edge of the cell
243 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
244 edgeIds[0] = cellArray_->getCellVertex(cid, j);
245 // the edge does not belong to the current node
246 if(edgeIds[0] > vertexIntervals_[nodePtr->nid]) {
247 break;
248 }
249 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
250 edgeIds[1] = cellArray_->getCellVertex(cid, k);
251
252 // not found in the edge map - assign new edge id
253 if(nodePtr->internalEdgeMap_.find(edgeIds)
254 == nodePtr->internalEdgeMap_.end()) {
255 edgeCount++;
256 nodePtr->internalEdgeMap_[edgeIds] = edgeCount;
257 }
258 }
259 }
260 }
261
262 // loop through the external cell list
263 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
264 std::array<SimplexId, 2> edgeIds;
265
266 // loop through each edge of the cell
267 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
268 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
269 edgeIds[0] = cellArray_->getCellVertex(cid, j);
270 edgeIds[1] = cellArray_->getCellVertex(cid, k);
271
272 // the edge is in the current node
273 if(edgeIds[0] > vertexIntervals_[nodePtr->nid - 1]
274 && edgeIds[0] <= vertexIntervals_[nodePtr->nid]) {
275 if(nodePtr->internalEdgeMap_.find(edgeIds)
276 == nodePtr->internalEdgeMap_.end()) {
277 edgeCount++;
278 (nodePtr->internalEdgeMap_)[edgeIds] = edgeCount;
279 }
280 }
281 }
282 }
283 }
284
285 if(computeInternalEdgeList) {
286 nodePtr->internalEdgeList_
287 = std::vector<std::array<SimplexId, 2>>(nodePtr->internalEdgeMap_.size());
288 for(auto iter = nodePtr->internalEdgeMap_.begin();
289 iter != nodePtr->internalEdgeMap_.end(); iter++) {
290 nodePtr->internalEdgeList_[iter->second - 1] = iter->first;
291 }
292 }
293
294 if(!computeInternalEdgeMap) {
295 nodePtr->internalEdgeMap_.clear();
296 }
297
298 return 0;
299}
300
302 ImplicitCluster *const nodePtr) const {
303
304#ifndef TTK_ENABLE_KAMIKAZE
305 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
306 return -1;
307#endif
308
309 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
310 boost::unordered_map<SimplexId, std::vector<std::array<SimplexId, 2>>>
311 edgeNodes;
312
313 // loop through the external cell list
314 for(size_t i = 0; i < externalCells_[nodePtr->nid].size(); i++) {
315 std::array<SimplexId, 2> edgeIds;
316 SimplexId const cellId = externalCells_[nodePtr->nid][i];
317
318 // loop through each edge of the cell
319 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
320 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
321 edgeIds[0] = cellArray_->getCellVertex(cellId, j);
322 edgeIds[1] = cellArray_->getCellVertex(cellId, k);
323
324 // check if the edge is an external edge
325 if(edgeIds[0] <= vertexIntervals_[nodePtr->nid - 1]
326 && edgeIds[1] > vertexIntervals_[nodePtr->nid - 1]
327 && edgeIds[1] <= vertexIntervals_[nodePtr->nid]) {
328 SimplexId const nid = vertexIndices_[edgeIds[0]];
329 edgeNodes[nid].push_back(edgeIds);
330 }
331 }
332 }
333 }
334
335 boost::unordered_map<SimplexId,
336 std::vector<std::array<SimplexId, 2>>>::iterator iter;
337 for(iter = edgeNodes.begin(); iter != edgeNodes.end(); iter++) {
338 ImplicitCluster *exnode = searchCache(iter->first, nodePtr->nid);
339 if(exnode) {
340 if(exnode->internalEdgeMap_.empty())
341 buildInternalEdgeMap(exnode, false, true);
342 for(std::array<SimplexId, 2> const edgePair : iter->second) {
343 (nodePtr->externalEdgeMap_)[edgePair]
344 = exnode->internalEdgeMap_.at(edgePair)
345 + edgeIntervals_[iter->first - 1];
346 }
347 } else {
348 ImplicitCluster tmpCluster(iter->first);
349 buildInternalEdgeMap(&tmpCluster, false, true);
350 for(std::array<SimplexId, 2> const edgePair : iter->second) {
351 (nodePtr->externalEdgeMap_)[edgePair]
352 = tmpCluster.internalEdgeMap_.at(edgePair)
353 + edgeIntervals_[iter->first - 1];
354 }
355 }
356 }
357
358 return 0;
359}
360
362 ImplicitCluster *const nodePtr,
363 bool computeInternalTriangleList,
364 bool computeInternalTriangleMap) const {
365
366#ifndef TTK_ENABLE_KAMIKAZE
367 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
368 return -1;
369#endif
370
371 SimplexId triangleCount = 0, verticesPerCell = 4;
372 std::vector<std::vector<SimplexId>> const localTriangleStars;
373
374 if(!nodePtr->internalTriangleMap_.empty()) {
375 if(computeInternalTriangleList) {
376 nodePtr->internalTriangleList_ = std::vector<std::array<SimplexId, 3>>(
377 nodePtr->internalTriangleMap_.size());
378 for(auto iter = nodePtr->internalTriangleMap_.begin();
379 iter != nodePtr->internalTriangleMap_.end(); iter++) {
380 (nodePtr->internalTriangleList_)[iter->second - 1] = iter->first;
381 }
382 return 0;
383 }
384 }
385
386 // loop through the internal cell list
387 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
388 cid <= cellIntervals_[nodePtr->nid]; cid++) {
389 std::array<SimplexId, 3> triangleIds;
390
391 // loop through each triangle of the cell
392 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
393 triangleIds[0] = cellArray_->getCellVertex(cid, j);
394 // the triangle does not belong to the current node
395 if(triangleIds[0] > vertexIntervals_[nodePtr->nid]) {
396 break;
397 }
398 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
399 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
400 triangleIds[1] = cellArray_->getCellVertex(cid, k);
401 triangleIds[2] = cellArray_->getCellVertex(cid, l);
402
403 if(nodePtr->internalTriangleMap_.find(triangleIds)
404 == nodePtr->internalTriangleMap_.end()) {
405 triangleCount++;
406 (nodePtr->internalTriangleMap_)[triangleIds] = triangleCount;
407 }
408 }
409 }
410 }
411 }
412
413 // loop through the external cell list
414 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
415 std::array<SimplexId, 3> triangleIds;
416
417 // loop through each triangle of the cell
418 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
419 triangleIds[0] = cellArray_->getCellVertex(cid, j);
420 if(triangleIds[0] > vertexIntervals_[nodePtr->nid - 1]
421 && triangleIds[0] <= vertexIntervals_[nodePtr->nid]) {
422 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
423 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
424 triangleIds[1] = cellArray_->getCellVertex(cid, k);
425 triangleIds[2] = cellArray_->getCellVertex(cid, l);
426
427 if(nodePtr->internalTriangleMap_.find(triangleIds)
428 == nodePtr->internalTriangleMap_.end()) {
429 triangleCount++;
430 (nodePtr->internalTriangleMap_)[triangleIds] = triangleCount;
431 }
432 }
433 }
434 }
435 }
436 }
437
438 if(computeInternalTriangleList) {
439 nodePtr->internalTriangleList_ = std::vector<std::array<SimplexId, 3>>(
440 nodePtr->internalTriangleMap_.size());
441 for(auto iter = nodePtr->internalTriangleMap_.begin();
442 iter != nodePtr->internalTriangleMap_.end(); iter++) {
443 (nodePtr->internalTriangleList_)[iter->second - 1] = iter->first;
444 }
445 }
446
447 if(!computeInternalTriangleMap) {
448 nodePtr->internalTriangleMap_.clear();
449 }
450
451 return 0;
452}
453
455 ImplicitCluster *const nodePtr) const {
456
457#ifndef TTK_ENABLE_KAMIKAZE
458 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
459 return -1;
460#endif
461
462 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
463 boost::unordered_map<SimplexId, std::vector<std::array<SimplexId, 3>>>
464 nodeTriangles;
465
466 // loop through the external cell list
467 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
468 std::array<SimplexId, 3> triangleIds;
469
470 // loop through each triangle of the cell
471 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
472 triangleIds[0] = cellArray_->getCellVertex(cid, j);
473 if(triangleIds[0] <= vertexIntervals_[nodePtr->nid - 1]) {
474 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
475 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
476 triangleIds[1] = cellArray_->getCellVertex(cid, k);
477 triangleIds[2] = cellArray_->getCellVertex(cid, l);
478
479 if(triangleIds[1] > vertexIntervals_[nodePtr->nid - 1]
480 && triangleIds[1] <= vertexIntervals_[nodePtr->nid]) {
481 SimplexId const nodeNum = vertexIndices_[triangleIds[0]];
482 nodeTriangles[nodeNum].push_back(triangleIds);
483 } else if(triangleIds[2] > vertexIntervals_[nodePtr->nid - 1]
484 && triangleIds[2] <= vertexIntervals_[nodePtr->nid]) {
485 SimplexId const nodeNum = vertexIndices_[triangleIds[0]];
486 nodeTriangles[nodeNum].push_back(triangleIds);
487 }
488 }
489 }
490 }
491 }
492 }
493
494 boost::unordered_map<SimplexId,
495 std::vector<std::array<SimplexId, 3>>>::iterator iter;
496 for(iter = nodeTriangles.begin(); iter != nodeTriangles.end(); iter++) {
497 ImplicitCluster *exnode = searchCache(iter->first, nodePtr->nid);
498 if(exnode) {
499 if(exnode->internalTriangleMap_.empty())
500 buildInternalTriangleMap(exnode, false, true);
501 for(std::array<SimplexId, 3> const triangleVec : iter->second) {
502 (nodePtr->externalTriangleMap_)[triangleVec]
503 = exnode->internalTriangleMap_.at(triangleVec)
504 + triangleIntervals_[iter->first - 1];
505 }
506 } else {
507 ImplicitCluster tmpCluster(iter->first);
508 buildInternalTriangleMap(&tmpCluster, false, true);
509 for(std::array<SimplexId, 3> const triangleVec : iter->second) {
510 (nodePtr->externalTriangleMap_)[triangleVec]
511 = tmpCluster.internalTriangleMap_.at(triangleVec)
512 + triangleIntervals_[iter->first - 1];
513 }
514 }
515 }
516
517 return 0;
518}
519
521
522#ifndef TTK_ENABLE_KAMIKAZE
523 if(nodeId <= 0 || nodeId > nodeNumber_)
524 return -1;
525#endif
526
527 SimplexId edgeCount = 0, verticesPerCell = cellArray_->getCellVertexNumber(0);
528 boost::unordered_set<std::array<SimplexId, 2>,
529 boost::hash<std::array<SimplexId, 2>>>
530 edgeSet;
531
532 // loop through the internal cell list
533 for(SimplexId cid = cellIntervals_[nodeId - 1] + 1;
534 cid <= cellIntervals_[nodeId]; cid++) {
535 std::array<SimplexId, 2> edgeIds{};
536
537 // loop through each edge of the cell
538 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
539 edgeIds[0] = cellArray_->getCellVertex(cid, j);
540 // the edge does not belong to the current node
541 if(edgeIds[0] > vertexIntervals_[nodeId]) {
542 break;
543 }
544 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
545 edgeIds[1] = cellArray_->getCellVertex(cid, k);
546
547 // not found in the edge map - assign new edge id
548 if(edgeSet.find(edgeIds) == edgeSet.end()) {
549 edgeCount++;
550 edgeSet.insert(edgeIds);
551 }
552 }
553 }
554 }
555
556 // loop through the external cell list
557 for(SimplexId const cid : externalCells_[nodeId]) {
558 std::array<SimplexId, 2> edgeIds{};
559
560 // loop through each edge of the cell
561 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
562 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
563 edgeIds[0] = cellArray_->getCellVertex(cid, j);
564 edgeIds[1] = cellArray_->getCellVertex(cid, k);
565
566 // the edge is in the current node
567 if(edgeIds[0] > vertexIntervals_[nodeId - 1]
568 && edgeIds[0] <= vertexIntervals_[nodeId]) {
569 if(edgeSet.find(edgeIds) == edgeSet.end()) {
570 edgeCount++;
571 edgeSet.insert(edgeIds);
572 }
573 }
574 }
575 }
576 }
577
578 return edgeCount;
579}
580
582
583#ifndef TTK_ENABLE_KAMIKAZE
584 if(nodeId <= 0 || nodeId > nodeNumber_)
585 return -1;
586#endif
587
588 SimplexId triangleCount = 0,
589 verticesPerCell = cellArray_->getCellVertexNumber(0);
590 boost::unordered_set<std::array<SimplexId, 3>> triangleSet;
591
592 // loop through the internal cell list
593 for(SimplexId cid = cellIntervals_[nodeId - 1] + 1;
594 cid <= cellIntervals_[nodeId]; cid++) {
595 std::array<SimplexId, 3> triangleIds{};
596
597 // loop through each triangle of the cell
598 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
599 triangleIds[0] = cellArray_->getCellVertex(cid, j);
600 // the triangle does not belong to the current node
601 if(triangleIds[0] > vertexIntervals_[nodeId]) {
602 break;
603 }
604 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
605 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
606 triangleIds[1] = cellArray_->getCellVertex(cid, k);
607 triangleIds[2] = cellArray_->getCellVertex(cid, l);
608
609 if(triangleSet.find(triangleIds) == triangleSet.end()) {
610 triangleCount++;
611 triangleSet.insert(triangleIds);
612 }
613 }
614 }
615 }
616 }
617
618 // loop through the external cell list
619 for(SimplexId const cid : externalCells_[nodeId]) {
620 std::array<SimplexId, 3> triangleIds{};
621
622 // loop through each triangle of the cell
623 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
624 triangleIds[0] = cellArray_->getCellVertex(cid, j);
625 if(triangleIds[0] > vertexIntervals_[nodeId - 1]
626 && triangleIds[0] <= vertexIntervals_[nodeId]) {
627 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
628 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
629 triangleIds[1] = cellArray_->getCellVertex(cid, k);
630 triangleIds[2] = cellArray_->getCellVertex(cid, l);
631
632 if(triangleSet.find(triangleIds) == triangleSet.end()) {
633 triangleCount++;
634 triangleSet.insert(triangleIds);
635 }
636 }
637 }
638 }
639 }
640 }
641
642 return triangleCount;
643}
644
646 ImplicitCluster *const nodePtr) const {
647
648#ifndef TTK_ENABLE_KAMIKAZE
649 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
650 return -1;
651#endif
652
653 std::vector<std::vector<SimplexId>> localCellNeighbors(
654 cellIntervals_[nodePtr->nid] - cellIntervals_[nodePtr->nid - 1]);
655 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
656 std::vector<std::vector<SimplexId>> localVertexStars;
657
658 if(nodePtr->vertexStars_.empty()) {
659 getClusterVertexStars(nodePtr);
660 }
661 // sort the vertex star vector
662 nodePtr->vertexStars_.copyTo(localVertexStars);
663 for(size_t i = 0; i < localVertexStars.size(); i++) {
664 sort(localVertexStars[i].begin(), localVertexStars[i].end());
665 }
666
667 boost::unordered_map<SimplexId, std::vector<std::vector<SimplexId>>> nodeMaps;
668 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
669 cid <= cellIntervals_[nodePtr->nid]; cid++) {
670 for(SimplexId j = 1; j < verticesPerCell; j++) {
671 if(cellArray_->getCellVertex(cid, j) > vertexIntervals_[nodePtr->nid]) {
672 SimplexId const nodeId
673 = vertexIndices_[cellArray_->getCellVertex(cid, j)];
674 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
675 ImplicitCluster newNode(nodeId);
676 getClusterVertexStars(&newNode);
677 // sort the vertex star list
678 std::vector<std::vector<SimplexId>> tmpVec;
679 newNode.vertexStars_.copyTo(tmpVec);
680 for(size_t i = 0; i < tmpVec.size(); i++) {
681 sort(tmpVec[i].begin(), tmpVec[i].end());
682 }
683 nodeMaps[nodeId] = tmpVec;
684 }
685 }
686 }
687 }
688
689 if(getDimensionality() == 2) {
690 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
691 cid <= cellIntervals_[nodePtr->nid]; cid++) {
692 for(SimplexId j = 0; j < 3; j++) {
693
694 SimplexId const v0 = cellArray_->getCellVertex(cid, j);
695 SimplexId const v1 = cellArray_->getCellVertex(cid, (j + 1) % 3);
696 SimplexId localV0 = v0 - vertexIntervals_[nodePtr->nid - 1] - 1;
697 SimplexId localV1 = v1 - vertexIntervals_[nodePtr->nid - 1] - 1;
698
699 std::vector<SimplexId> stars0, stars1;
700 if(v0 <= vertexIntervals_[nodePtr->nid]) {
701 stars0 = localVertexStars[localV0];
702 } else {
703 localV0 = v0 - vertexIntervals_[vertexIndices_[v0] - 1] - 1;
704 stars0 = nodeMaps[vertexIndices_[v0]][localV0];
705 }
706 if(v1 <= vertexIntervals_[nodePtr->nid]) {
707 stars1 = localVertexStars[localV1];
708 } else {
709 localV1 = v1 - vertexIntervals_[vertexIndices_[v1] - 1] - 1;
710 stars1 = nodeMaps[vertexIndices_[v1]][localV1];
711 }
712
713 // perform an intersection of the 2 sorted star lists
714 SimplexId pos0 = 0, pos1 = 0;
715 SimplexId intersection = -1;
716
717 while((pos0 < (SimplexId)stars0.size())
718 && (pos1 < (SimplexId)stars1.size())) {
719 SimplexId biggest = stars0[pos0];
720 if(stars1[pos1] > biggest) {
721 biggest = stars1[pos1];
722 }
723
724 for(SimplexId l = pos0; l < (SimplexId)stars0.size(); l++) {
725 if(stars0[l] < biggest) {
726 pos0++;
727 } else {
728 break;
729 }
730 }
731 for(SimplexId l = pos1; l < (SimplexId)stars1.size(); l++) {
732 if(stars1[l] < biggest) {
733 pos1++;
734 } else {
735 break;
736 }
737 }
738
739 if(pos0 >= (SimplexId)stars0.size()
740 || pos1 >= (SimplexId)stars1.size())
741 break;
742
743 if(stars0[pos0] == stars1[pos1]) {
744 if(stars0[pos0] != cid) {
745 intersection = stars0[pos0];
746 break;
747 }
748 pos0++;
749 pos1++;
750 }
751 }
752
753 if(intersection != -1) {
754 localCellNeighbors[cid - cellIntervals_[nodePtr->nid - 1] - 1]
755 .push_back(intersection);
756 }
757 }
758 }
759 }
760
761 else if(getDimensionality() == 3) {
762 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
763 cid <= cellIntervals_[nodePtr->nid]; cid++) {
764 // go triangle by triangle
765 for(SimplexId j = 0; j < 4; j++) {
766
767 SimplexId const v0 = cellArray_->getCellVertex(cid, j % 4);
768 SimplexId const v1 = cellArray_->getCellVertex(cid, (j + 1) % 4);
769 SimplexId const v2 = cellArray_->getCellVertex(cid, (j + 2) % 4);
770
771 SimplexId localV0 = v0 - vertexIntervals_[nodePtr->nid - 1] - 1;
772 SimplexId localV1 = v1 - vertexIntervals_[nodePtr->nid - 1] - 1;
773 SimplexId localV2 = v2 - vertexIntervals_[nodePtr->nid - 1] - 1;
774
775 std::vector<SimplexId> stars0, stars1, stars2;
776 if(v0 <= vertexIntervals_[nodePtr->nid]) {
777 stars0 = localVertexStars[localV0];
778 } else {
779 localV0 = v0 - vertexIntervals_[vertexIndices_[v0] - 1] - 1;
780 stars0 = nodeMaps[vertexIndices_[v0]][localV0];
781 }
782 if(v1 <= vertexIntervals_[nodePtr->nid]) {
783 stars1 = localVertexStars[localV1];
784 } else {
785 localV1 = v1 - vertexIntervals_[vertexIndices_[v1] - 1] - 1;
786 stars1 = nodeMaps[vertexIndices_[v1]][localV1];
787 }
788 if(v2 <= vertexIntervals_[nodePtr->nid]) {
789 stars2 = localVertexStars[localV2];
790 } else {
791 localV2 = v2 - vertexIntervals_[vertexIndices_[v2] - 1] - 1;
792 stars2 = nodeMaps[vertexIndices_[v2]][localV2];
793 }
794
795 // perform an intersection of the 3 (sorted) star lists
796 SimplexId pos0 = 0, pos1 = 0, pos2 = 0;
797 SimplexId intersection = -1;
798
799 while((pos0 < (SimplexId)stars0.size())
800 && (pos1 < (SimplexId)stars1.size())
801 && (pos2 < (SimplexId)stars2.size())) {
802
803 SimplexId biggest = stars0[pos0];
804 if(stars1[pos1] > biggest) {
805 biggest = stars1[pos1];
806 }
807 if(stars2[pos2] > biggest) {
808 biggest = stars2[pos2];
809 }
810
811 for(SimplexId l = pos0; l < (SimplexId)stars0.size(); l++) {
812 if(stars0[l] < biggest) {
813 pos0++;
814 } else {
815 break;
816 }
817 }
818 for(SimplexId l = pos1; l < (SimplexId)stars1.size(); l++) {
819 if(stars1[l] < biggest) {
820 pos1++;
821 } else {
822 break;
823 }
824 }
825 for(SimplexId l = pos2; l < (SimplexId)stars2.size(); l++) {
826 if(stars2[l] < biggest) {
827 pos2++;
828 } else {
829 break;
830 }
831 }
832
833 if(pos0 >= (SimplexId)stars0.size()
834 || pos1 >= (SimplexId)stars1.size()
835 || pos2 >= (SimplexId)stars2.size())
836 break;
837
838 if((stars0[pos0] == stars1[pos1]) && (stars0[pos0] == stars2[pos2])) {
839 if(stars0[pos0] != cid) {
840 intersection = stars0[pos0];
841 break;
842 }
843 pos0++;
844 pos1++;
845 pos2++;
846 }
847 }
848
849 if(intersection != -1) {
850 localCellNeighbors[cid - cellIntervals_[nodePtr->nid - 1] - 1]
851 .push_back(intersection);
852 }
853 }
854 }
855 }
856
857 nodePtr->cellNeighbors_.fillFrom(localCellNeighbors);
858 return 0;
859}
860
862 ImplicitCluster *const nodePtr) const {
863
864#ifndef TTK_ENABLE_KAMIKAZE
865 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
866 return -1;
867#endif
868
869 SimplexId const verticesPerCell = 4;
870 boost::unordered_map<SimplexId, std::vector<std::vector<SimplexId>>>
871 nodeTriangles;
872
873 nodePtr->tetraTriangles_ = std::vector<std::array<SimplexId, 4>>(
874 cellIntervals_[nodePtr->nid] - cellIntervals_[nodePtr->nid - 1]);
875
876 if(nodePtr->internalTriangleMap_.empty()) {
877 buildInternalTriangleMap(nodePtr, false, true);
878 }
879
880 for(SimplexId i = cellIntervals_[nodePtr->nid - 1] + 1;
881 i <= cellIntervals_[nodePtr->nid]; i++) {
882 std::array<SimplexId, 3> triangleVec;
883 // get the internal triangle from the map
884 triangleVec[0] = cellArray_->getCellVertex(i, 0);
885 for(SimplexId k = 1; k < verticesPerCell - 1; k++) {
886 triangleVec[1] = cellArray_->getCellVertex(i, k);
887 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
888 triangleVec[2] = cellArray_->getCellVertex(i, l);
889 (nodePtr->tetraTriangles_)[i - cellIntervals_[nodePtr->nid - 1] - 1]
890 [k + l - 3]
891 = nodePtr->internalTriangleMap_.at(triangleVec)
892 + triangleIntervals_[nodePtr->nid - 1];
893 }
894 }
895 // group the external triangles by node id
896 triangleVec[0] = cellArray_->getCellVertex(i, 1);
897 triangleVec[1] = cellArray_->getCellVertex(i, 2);
898 triangleVec[2] = cellArray_->getCellVertex(i, 3);
899 if(triangleVec[0] <= vertexIntervals_[nodePtr->nid]) {
900 (nodePtr->tetraTriangles_)[i - cellIntervals_[nodePtr->nid - 1] - 1]
901 .back()
902 = nodePtr->internalTriangleMap_.at(triangleVec)
903 + triangleIntervals_[nodePtr->nid - 1];
904 } else {
905 std::vector<SimplexId> const triangleTuple
906 = {i, triangleVec[0], triangleVec[1], triangleVec[2]};
907 SimplexId const nodeNum = vertexIndices_[triangleVec[0]];
908 nodeTriangles[nodeNum].push_back(triangleTuple);
909 }
910 }
911
912 for(auto iter = nodeTriangles.begin(); iter != nodeTriangles.end(); iter++) {
913 ImplicitCluster *exnode = searchCache(iter->first, nodePtr->nid);
914 if(exnode) {
915 if(exnode->internalTriangleMap_.empty())
916 buildInternalTriangleMap(exnode, false, true);
917 for(std::vector<SimplexId> triangleVec : iter->second) {
918 std::array<SimplexId, 3> const triangle
919 = {triangleVec[1], triangleVec[2], triangleVec[3]};
920 (nodePtr->tetraTriangles_)[triangleVec[0]
921 - cellIntervals_[nodePtr->nid - 1] - 1]
922 .back()
923 = exnode->internalTriangleMap_.at(triangle)
924 + triangleIntervals_[iter->first - 1];
925 }
926 } else {
927 ImplicitCluster tmpCluster(iter->first);
928 buildInternalTriangleMap(&tmpCluster, false, true);
929 for(std::vector<SimplexId> triangleVec : iter->second) {
930 std::array<SimplexId, 3> const triangle
931 = {triangleVec[1], triangleVec[2], triangleVec[3]};
932 (nodePtr->tetraTriangles_)[triangleVec[0]
933 - cellIntervals_[nodePtr->nid - 1] - 1]
934 .back()
935 = tmpCluster.internalTriangleMap_.at(triangle)
936 + triangleIntervals_[iter->first - 1];
937 }
938 }
939 }
940
941 return 0;
942}
943
945 ImplicitCluster *const nodePtr) const {
946
947#ifndef TTK_ENABLE_KAMIKAZE
948 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
949 return -1;
950#endif
951
952 SimplexId const localEdgeNum
953 = edgeIntervals_[nodePtr->nid] - edgeIntervals_[nodePtr->nid - 1];
954 std::vector<SimplexId> offsets(localEdgeNum + 1, 0),
955 linksCount(localEdgeNum, 0);
956
957 if(getDimensionality() == 2) {
958 if(nodePtr->edgeStars_.empty()) {
959 getClusterEdgeStars(nodePtr);
960 }
961 // set the offsets vector
962 boost::unordered_map<std::array<SimplexId, 2>, SimplexId>::const_iterator
963 iter;
964 for(iter = nodePtr->internalEdgeMap_.begin();
965 iter != nodePtr->internalEdgeMap_.end(); iter++) {
966 for(SimplexId j = 0; j < nodePtr->edgeStars_.size(iter->second - 1);
967 j++) {
968 SimplexId const cellId = nodePtr->edgeStars_.get(iter->second - 1, j);
969 for(int k = 0; k < 3; k++) {
970 SimplexId const vertexId = cellArray_->getCellVertex(cellId, k);
971 if((vertexId != iter->first[0]) && (vertexId != iter->first[1])) {
972 offsets[iter->second]++;
973 break;
974 }
975 }
976 }
977 }
978
979 // compute partial sum of number of links per edge
980 for(SimplexId i = 1; i <= localEdgeNum; i++) {
981 offsets[i] += offsets[i - 1];
982 }
983
984 // allocate the flat vector for edge link data
985 std::vector<SimplexId> edgeLinkData(offsets.back());
986
987 // fill the flat vector using offsets and count vectors
988 for(iter = nodePtr->internalEdgeMap_.begin();
989 iter != nodePtr->internalEdgeMap_.end(); iter++) {
990 for(SimplexId j = 0; j < nodePtr->edgeStars_.size(iter->second - 1);
991 j++) {
992 SimplexId const cellId = nodePtr->edgeStars_.get(iter->second - 1, j);
993 for(int k = 0; k < 3; k++) {
994 SimplexId const vertexId = cellArray_->getCellVertex(cellId, k);
995 if((vertexId != iter->first[0]) && (vertexId != iter->first[1])) {
996 SimplexId const localEdgeId = iter->second - 1;
997 edgeLinkData[offsets[localEdgeId] + linksCount[localEdgeId]]
998 = vertexId;
999 linksCount[localEdgeId]++;
1000 break;
1001 }
1002 }
1003 }
1004 }
1005
1006 // fill FlatJaggedArray struct
1007 nodePtr->edgeLinks_.setData(std::move(edgeLinkData), std::move(offsets));
1008 } else if(getDimensionality() == 3) {
1009 if(nodePtr->tetraEdges_.empty()) {
1010 getClusterTetraEdges(nodePtr);
1011 }
1012 if(nodePtr->internalEdgeMap_.empty()) {
1013 buildInternalEdgeMap(nodePtr, false, true);
1014 }
1015
1016 // set the offsets vector
1017 SimplexId const localCellNum
1018 = cellIntervals_[nodePtr->nid] - cellIntervals_[nodePtr->nid - 1];
1019 for(SimplexId cid = 0; cid < localCellNum; cid++) {
1020 SimplexId const cellId = cid + cellIntervals_[nodePtr->nid - 1] + 1;
1021 std::array<SimplexId, 4> vertexIds
1022 = {(SimplexId)cellArray_->getCellVertex(cellId, 0),
1023 (SimplexId)cellArray_->getCellVertex(cellId, 1),
1024 (SimplexId)cellArray_->getCellVertex(cellId, 2),
1025 (SimplexId)cellArray_->getCellVertex(cellId, 3)};
1026 std::array<SimplexId, 2> edgePair;
1027 edgePair[0] = vertexIds[0];
1028 for(SimplexId j = 1; j < 4; j++) {
1029 edgePair[1] = vertexIds[j];
1030 offsets[nodePtr->internalEdgeMap_.at(edgePair)]++;
1031 }
1032 if(vertexIds[1] <= vertexIntervals_[nodePtr->nid]) {
1033 edgePair[0] = vertexIds[1];
1034 for(int j = 2; j < 4; j++) {
1035 edgePair[1] = vertexIds[j];
1036 offsets[nodePtr->internalEdgeMap_.at(edgePair)]++;
1037 }
1038 if(vertexIds[2] <= vertexIntervals_[nodePtr->nid]) {
1039 edgePair = {vertexIds[2], vertexIds[3]};
1040 offsets[nodePtr->internalEdgeMap_.at(edgePair)]++;
1041 }
1042 }
1043 }
1044
1045 // loop through the external cell list
1046 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1047 std::array<SimplexId, 2> edgeIds;
1048 std::array<SimplexId, 4> vertexIds
1049 = {(SimplexId)cellArray_->getCellVertex(cid, 0),
1050 (SimplexId)cellArray_->getCellVertex(cid, 1),
1051 (SimplexId)cellArray_->getCellVertex(cid, 2),
1052 (SimplexId)cellArray_->getCellVertex(cid, 3)};
1053
1054 // loop through each edge of the cell
1055 for(SimplexId j = 0; j < 3; j++) {
1056 for(SimplexId k = j + 1; k < 4; k++) {
1057 edgeIds[0] = vertexIds[j];
1058 edgeIds[1] = vertexIds[k];
1059
1060 // the edge is in the current node
1061 if(edgeIds[0] > vertexIntervals_[nodePtr->nid - 1]
1062 && edgeIds[0] <= vertexIntervals_[nodePtr->nid]) {
1063 offsets[nodePtr->internalEdgeMap_.at(edgeIds)]++;
1064 }
1065 }
1066 }
1067 }
1068
1069 // compute partial sum of number of neighbors per vertex
1070 for(SimplexId i = 1; i <= localEdgeNum; i++) {
1071 offsets[i] += offsets[i - 1];
1072 }
1073
1074 // allocate the flat vector for edge link data
1075 std::vector<SimplexId> edgeLinkData(offsets.back());
1076
1077 // fill the flat vector using offsets and count vectors
1078 for(SimplexId cid = 0; cid < localCellNum; cid++) {
1079 SimplexId const cellId = cid + cellIntervals_[nodePtr->nid - 1] + 1;
1080 std::array<SimplexId, 4> vertexIds
1081 = {(SimplexId)cellArray_->getCellVertex(cellId, 0),
1082 (SimplexId)cellArray_->getCellVertex(cellId, 1),
1083 (SimplexId)cellArray_->getCellVertex(cellId, 2),
1084 (SimplexId)cellArray_->getCellVertex(cellId, 3)};
1085 std::array<SimplexId, 2> edgePair;
1086 edgePair[0] = vertexIds[0];
1087 for(SimplexId j = 1; j < 4; j++) {
1088 edgePair[1] = vertexIds[j];
1089 SimplexId const localEdgeId
1090 = nodePtr->internalEdgeMap_.at(edgePair) - 1;
1091 edgeLinkData[offsets[localEdgeId] + linksCount[localEdgeId]]
1092 = nodePtr->tetraEdges_.at(cid)[6 - j];
1093 linksCount[localEdgeId]++;
1094 }
1095 if(vertexIds[1] <= vertexIntervals_[nodePtr->nid]) {
1096 edgePair[0] = vertexIds[1];
1097 for(int j = 2; j < 4; j++) {
1098 edgePair[1] = vertexIds[j];
1099 SimplexId const localEdgeId
1100 = nodePtr->internalEdgeMap_.at(edgePair) - 1;
1101 edgeLinkData[offsets[localEdgeId] + linksCount[localEdgeId]]
1102 = nodePtr->tetraEdges_.at(cid)[4 - j];
1103 linksCount[localEdgeId]++;
1104 }
1105 if(vertexIds[2] <= vertexIntervals_[nodePtr->nid]) {
1106 edgePair = {vertexIds[2], vertexIds[3]};
1107 SimplexId const localEdgeId
1108 = nodePtr->internalEdgeMap_.at(edgePair) - 1;
1109 edgeLinkData[offsets[localEdgeId] + linksCount[localEdgeId]]
1110 = nodePtr->tetraEdges_.at(cid)[0];
1111 linksCount[localEdgeId]++;
1112 }
1113 }
1114 }
1115
1116 // loop through the external cell list
1117 boost::unordered_map<SimplexId, ImplicitCluster> nodeMaps;
1118 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1119 std::array<SimplexId, 4> vertexIds
1120 = {(SimplexId)cellArray_->getCellVertex(cid, 0),
1121 (SimplexId)cellArray_->getCellVertex(cid, 1),
1122 (SimplexId)cellArray_->getCellVertex(cid, 2),
1123 (SimplexId)cellArray_->getCellVertex(cid, 3)};
1124
1125 std::array<SimplexId, 2> edgeIds;
1126 // loop through each edge of the cell
1127 for(SimplexId j = 0; j < 3; j++) {
1128 for(SimplexId k = j + 1; k < 4; k++) {
1129 edgeIds[0] = vertexIds[j];
1130 edgeIds[1] = vertexIds[k];
1131
1132 // the edge is in the current node
1133 if(edgeIds[0] > vertexIntervals_[nodePtr->nid - 1]
1134 && edgeIds[0] <= vertexIntervals_[nodePtr->nid]) {
1135 std::array<SimplexId, 2> otherEdge = {-1, -1};
1136 for(int i = 0; i < 4; i++) {
1137 if(vertexIds[i] != edgeIds[0] && vertexIds[i] != edgeIds[1]) {
1138 if(otherEdge[0] == -1) {
1139 otherEdge[0] = vertexIds[i];
1140 } else if(otherEdge[1] == -1) {
1141 otherEdge[1] = vertexIds[i];
1142 } else {
1143 printErr("[CompactTriangulation] More than two other "
1144 "vertices are "
1145 "found in the edge!\n");
1146 }
1147 }
1148 }
1149 SimplexId const nodeId = vertexIndices_[otherEdge[0]];
1150 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
1151 nodeMaps[nodeId] = ImplicitCluster(nodeId);
1152 buildInternalEdgeMap(&nodeMaps[nodeId], false, true);
1153 }
1154 SimplexId const localEdgeId
1155 = nodePtr->internalEdgeMap_.at(edgeIds) - 1;
1156 edgeLinkData[offsets[localEdgeId] + linksCount[localEdgeId]]
1157 = nodeMaps[nodeId].internalEdgeMap_.at(otherEdge);
1158 linksCount[localEdgeId]++;
1159 }
1160 }
1161 }
1162 }
1163
1164 // fill FlatJaggedArray struct
1165 nodePtr->edgeLinks_.setData(std::move(edgeLinkData), std::move(offsets));
1166 }
1167
1168 return 0;
1169}
1170
1172 ImplicitCluster *const nodePtr) const {
1173
1174#ifndef TTK_ENABLE_KAMIKAZE
1175 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1176 return -1;
1177#endif
1178
1179 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
1180 SimplexId const localEdgeNum
1181 = edgeIntervals_[nodePtr->nid] - edgeIntervals_[nodePtr->nid - 1];
1182 std::vector<SimplexId> offsets(localEdgeNum + 1, 0), starsCount(localEdgeNum);
1183
1184 if(nodePtr->internalEdgeMap_.empty()) {
1185 buildInternalEdgeMap(nodePtr, false, true);
1186 }
1187
1188 // set the offsets vector
1189 // loop through the internal cell list
1190 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1191 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1192 std::array<SimplexId, 2> edgeIds;
1193 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
1194 edgeIds[0] = cellArray_->getCellVertex(cid, j);
1195 // the edge does not belong to the current node
1196 if(edgeIds[0] > vertexIntervals_[nodePtr->nid]) {
1197 break;
1198 }
1199 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
1200 edgeIds[1] = cellArray_->getCellVertex(cid, k);
1201 offsets[nodePtr->internalEdgeMap_.at(edgeIds)]++;
1202 }
1203 }
1204 }
1205 // loop through the external cell list
1206 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1207 std::array<SimplexId, 2> edgeIds;
1208 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
1209 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
1210 edgeIds[0] = cellArray_->getCellVertex(cid, j);
1211 edgeIds[1] = cellArray_->getCellVertex(cid, k);
1212 if(edgeIds[0] > vertexIntervals_[nodePtr->nid - 1]
1213 && edgeIds[0] <= vertexIntervals_[nodePtr->nid]) {
1214 offsets[nodePtr->internalEdgeMap_.at(edgeIds)]++;
1215 }
1216 }
1217 }
1218 }
1219
1220 // compute partial sum of number of stars per edge
1221 for(SimplexId i = 1; i <= localEdgeNum; i++) {
1222 offsets[i] += offsets[i - 1];
1223 }
1224
1225 // allocate the flat vector for edge star data
1226 std::vector<SimplexId> edgeStarData(offsets.back());
1227
1228 // fill the flat vector using offsets and count vectors
1229 // loop through the internal cell list
1230 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1231 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1232 std::array<SimplexId, 2> edgeIds;
1233 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
1234 edgeIds[0] = cellArray_->getCellVertex(cid, j);
1235 // the edge does not belong to the current node
1236 if(edgeIds[0] > vertexIntervals_[nodePtr->nid]) {
1237 break;
1238 }
1239 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
1240 edgeIds[1] = cellArray_->getCellVertex(cid, k);
1241 SimplexId const localEdgeId = nodePtr->internalEdgeMap_.at(edgeIds) - 1;
1242 edgeStarData[offsets[localEdgeId] + starsCount[localEdgeId]] = cid;
1243 starsCount[localEdgeId]++;
1244 }
1245 }
1246 }
1247 // loop through the external cell list
1248 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1249 std::array<SimplexId, 2> edgeIds;
1250 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
1251 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
1252 edgeIds[0] = cellArray_->getCellVertex(cid, j);
1253 edgeIds[1] = cellArray_->getCellVertex(cid, k);
1254 if(edgeIds[0] > vertexIntervals_[nodePtr->nid - 1]
1255 && edgeIds[0] <= vertexIntervals_[nodePtr->nid]) {
1256 SimplexId const localEdgeId
1257 = nodePtr->internalEdgeMap_.at(edgeIds) - 1;
1258 edgeStarData[offsets[localEdgeId] + starsCount[localEdgeId]] = cid;
1259 starsCount[localEdgeId]++;
1260 }
1261 }
1262 }
1263 }
1264
1265 // fill FlatJaggedArray struct
1266 nodePtr->edgeStars_.setData(std::move(edgeStarData), std::move(offsets));
1267
1268 return 0;
1269}
1270
1272 ImplicitCluster *const nodePtr) const {
1273
1274#ifndef TTK_ENABLE_KAMIKAZE
1275 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1276 return -1;
1277#endif
1278
1279 SimplexId const localEdgeNum
1280 = edgeIntervals_[nodePtr->nid] - edgeIntervals_[nodePtr->nid - 1];
1281 std::vector<SimplexId> offsets(localEdgeNum + 1, 0),
1282 trianglesCount(localEdgeNum, 0);
1283
1284 if(nodePtr->internalEdgeMap_.empty()) {
1285 buildInternalEdgeMap(nodePtr, false, true);
1286 }
1287 if(nodePtr->internalTriangleMap_.empty()) {
1288 buildInternalTriangleMap(nodePtr, false, true);
1289 }
1290 if(nodePtr->externalTriangleMap_.empty()) {
1291 buildExternalTriangleMap(nodePtr);
1292 }
1293
1294 // set the offsets vector
1295 boost::unordered_map<std::array<SimplexId, 3>, SimplexId>::iterator iter;
1296 for(iter = nodePtr->internalTriangleMap_.begin();
1297 iter != nodePtr->internalTriangleMap_.end(); iter++) {
1298 std::array<SimplexId, 2> edge1 = {iter->first[0], iter->first[1]};
1299 std::array<SimplexId, 2> const edge2 = {iter->first[0], iter->first[2]};
1300 offsets[nodePtr->internalEdgeMap_.at(edge1)]++;
1301 offsets[nodePtr->internalEdgeMap_.at(edge2)]++;
1302 if(iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
1303 edge1 = {iter->first[1], iter->first[2]};
1304 offsets[nodePtr->internalEdgeMap_.at(edge1)]++;
1305 }
1306 }
1307 for(iter = nodePtr->externalTriangleMap_.begin();
1308 iter != nodePtr->externalTriangleMap_.end(); iter++) {
1309 std::array<SimplexId, 2> edge = {iter->first.at(1), iter->first.at(2)};
1310 if(edge[0] > vertexIntervals_[nodePtr->nid - 1]
1311 && edge[0] <= vertexIntervals_[nodePtr->nid]) {
1312 offsets[nodePtr->internalEdgeMap_.at(edge)]++;
1313 }
1314 }
1315
1316 // compute partial sum of number of triangles per edge
1317 for(SimplexId i = 1; i <= localEdgeNum; i++) {
1318 offsets[i] += offsets[i - 1];
1319 }
1320
1321 // allocate the flat vector for edge triangle data
1322 std::vector<SimplexId> edgeTriangleData(offsets.back());
1323
1324 // fill the flat vector using offsets and count vectors
1325 for(iter = nodePtr->internalTriangleMap_.begin();
1326 iter != nodePtr->internalTriangleMap_.end(); iter++) {
1327 std::array<SimplexId, 2> edge1 = {iter->first[0], iter->first[1]};
1328 std::array<SimplexId, 2> const edge2 = {iter->first[0], iter->first[2]};
1329 SimplexId localEdgeId = nodePtr->internalEdgeMap_.at(edge1) - 1;
1330 edgeTriangleData[offsets[localEdgeId] + trianglesCount[localEdgeId]]
1331 = iter->second + triangleIntervals_[nodePtr->nid - 1];
1332 trianglesCount[localEdgeId]++;
1333 localEdgeId = nodePtr->internalEdgeMap_.at(edge2) - 1;
1334 edgeTriangleData[offsets[localEdgeId] + trianglesCount[localEdgeId]]
1335 = iter->second + triangleIntervals_[nodePtr->nid - 1];
1336 trianglesCount[localEdgeId]++;
1337
1338 if(iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
1339 edge1 = {iter->first[1], iter->first[2]};
1340 localEdgeId = nodePtr->internalEdgeMap_.at(edge1) - 1;
1341 edgeTriangleData[offsets[localEdgeId] + trianglesCount[localEdgeId]]
1342 = iter->second + triangleIntervals_[nodePtr->nid - 1];
1343 trianglesCount[localEdgeId]++;
1344 }
1345 }
1346
1347 // for external triangles
1348 for(iter = nodePtr->externalTriangleMap_.begin();
1349 iter != nodePtr->externalTriangleMap_.end(); iter++) {
1350 std::array<SimplexId, 2> edge = {iter->first.at(1), iter->first.at(2)};
1351 if(edge[0] > vertexIntervals_[nodePtr->nid - 1]
1352 && edge[0] <= vertexIntervals_[nodePtr->nid]) {
1353 SimplexId const localEdgeId = nodePtr->internalEdgeMap_.at(edge) - 1;
1354 edgeTriangleData[offsets[localEdgeId] + trianglesCount[localEdgeId]]
1355 = iter->second;
1356 trianglesCount[localEdgeId]++;
1357 }
1358 }
1359
1360 // fill FlatJaggedArray struct
1361 nodePtr->edgeTriangles_.setData(
1362 std::move(edgeTriangleData), std::move(offsets));
1363
1364 return 0;
1365}
1366
1368 ImplicitCluster *const nodePtr) const {
1369
1370#ifndef TTK_ENABLE_KAMIKAZE
1371 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1372 return -1;
1373#endif
1374
1375 SimplexId const verticesPerCell = 4;
1376 nodePtr->tetraEdges_ = std::vector<std::array<SimplexId, 6>>(
1377 cellIntervals_[nodePtr->nid] - cellIntervals_[nodePtr->nid - 1]);
1378 boost::unordered_map<SimplexId, std::vector<std::vector<SimplexId>>>
1379 edgeNodes;
1380
1381 if(nodePtr->internalEdgeMap_.empty()) {
1382 buildInternalEdgeMap(nodePtr, false, true);
1383 }
1384
1385 for(SimplexId i = cellIntervals_[nodePtr->nid - 1] + 1;
1386 i <= cellIntervals_[nodePtr->nid]; i++) {
1387 int cnt = 0;
1388 // get the internal edge id from the map
1389 for(SimplexId k = 1; k < verticesPerCell; k++) {
1390 std::array<SimplexId, 2> const edgePair
1391 = {(SimplexId)cellArray_->getCellVertex(i, 0),
1392 (SimplexId)cellArray_->getCellVertex(i, k)};
1393 (nodePtr->tetraEdges_)[i - cellIntervals_[nodePtr->nid - 1] - 1][cnt++]
1394 = nodePtr->internalEdgeMap_.at(edgePair)
1395 + edgeIntervals_[nodePtr->nid - 1];
1396 }
1397 for(SimplexId j = 1; j < verticesPerCell - 1; j++) {
1398 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
1399 std::array<SimplexId, 2> edgePair
1400 = {(SimplexId)cellArray_->getCellVertex(i, j),
1401 (SimplexId)cellArray_->getCellVertex(i, k)};
1402 if(edgePair[0] <= vertexIntervals_[nodePtr->nid]) {
1403 (nodePtr
1404 ->tetraEdges_)[i - cellIntervals_[nodePtr->nid - 1] - 1][cnt++]
1405 = nodePtr->internalEdgeMap_.at(edgePair)
1406 + edgeIntervals_[nodePtr->nid - 1];
1407 }
1408 // group the external edges by node id
1409 else {
1410 std::vector<SimplexId> const edgeTuple{
1411 i, cnt++, edgePair[0], edgePair[1]};
1412 SimplexId const nodeNum = vertexIndices_[edgePair[0]];
1413 edgeNodes[nodeNum].push_back(edgeTuple);
1414 }
1415 }
1416 }
1417 }
1418
1419 for(auto iter = edgeNodes.begin(); iter != edgeNodes.end(); iter++) {
1420 ImplicitCluster *exnode = searchCache(iter->first, nodePtr->nid);
1421 if(exnode) {
1422 if(exnode->internalEdgeMap_.empty())
1423 buildInternalEdgeMap(exnode, false, true);
1424 for(std::vector<SimplexId> edgeTuple : iter->second) {
1425 std::array<SimplexId, 2> const edgePair = {edgeTuple[2], edgeTuple[3]};
1426 (nodePtr->tetraEdges_)[edgeTuple[0] - cellIntervals_[nodePtr->nid - 1]
1427 - 1][edgeTuple[1]]
1428 = exnode->internalEdgeMap_.at(edgePair)
1429 + edgeIntervals_[iter->first - 1];
1430 }
1431 } else {
1432 ImplicitCluster tmpCluster(iter->first);
1433 buildInternalEdgeMap(&tmpCluster, false, true);
1434 for(std::vector<SimplexId> edgeTuple : iter->second) {
1435 std::array<SimplexId, 2> const edgePair = {edgeTuple[2], edgeTuple[3]};
1436 (nodePtr->tetraEdges_)[edgeTuple[0] - cellIntervals_[nodePtr->nid - 1]
1437 - 1][edgeTuple[1]]
1438 = tmpCluster.internalEdgeMap_.at(edgePair)
1439 + edgeIntervals_[iter->first - 1];
1440 }
1441 }
1442 }
1443
1444 return 0;
1445}
1446
1448 ImplicitCluster *const nodePtr) const {
1449
1450#ifndef TTK_ENABLE_KAMIKAZE
1451 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1452 return -1;
1453#endif
1454 nodePtr->triangleEdges_ = std::vector<std::array<SimplexId, 3>>(
1455 triangleIntervals_[nodePtr->nid] - triangleIntervals_[nodePtr->nid - 1]);
1456 boost::unordered_map<SimplexId, std::vector<std::vector<SimplexId>>>
1457 edgeNodes;
1458
1459 if(nodePtr->internalEdgeMap_.empty()) {
1460 buildInternalEdgeMap(nodePtr, false, true);
1461 }
1462
1463 if(getDimensionality() == 2) {
1464 for(SimplexId i = cellIntervals_[nodePtr->nid - 1] + 1;
1465 i <= cellIntervals_[nodePtr->nid]; i++) {
1466 // {v0, v1}
1467 std::array<SimplexId, 2> edgePair
1468 = {(SimplexId)cellArray_->getCellVertex(i, 0),
1469 (SimplexId)cellArray_->getCellVertex(i, 1)};
1470 (nodePtr->triangleEdges_)[i - cellIntervals_[nodePtr->nid - 1] - 1][0]
1471 = nodePtr->internalEdgeMap_.at(edgePair)
1472 + edgeIntervals_[nodePtr->nid - 1];
1473 // {v0, v2};
1474 edgePair[1] = cellArray_->getCellVertex(i, 2);
1475 (nodePtr->triangleEdges_)[i - cellIntervals_[nodePtr->nid - 1] - 1][1]
1476 = nodePtr->internalEdgeMap_.at(edgePair)
1477 + edgeIntervals_[nodePtr->nid - 1];
1478 // {v1, v2}
1479 edgePair[0] = cellArray_->getCellVertex(i, 1);
1480 if(edgePair[0] <= vertexIntervals_[nodePtr->nid]) {
1481 (nodePtr->triangleEdges_)[i - cellIntervals_[nodePtr->nid - 1] - 1][2]
1482 = nodePtr->internalEdgeMap_.at(edgePair)
1483 + edgeIntervals_[nodePtr->nid - 1];
1484 }
1485 // group the external edges by node id
1486 else {
1487 std::vector<SimplexId> const edgeTuple{i, edgePair[0], edgePair[1]};
1488 SimplexId const nodeNum = vertexIndices_[edgePair[0]];
1489 edgeNodes[nodeNum].push_back(edgeTuple);
1490 }
1491 }
1492
1493 for(auto iter = edgeNodes.begin(); iter != edgeNodes.end(); iter++) {
1494 ImplicitCluster *exnode = searchCache(iter->first, nodePtr->nid);
1495 if(exnode) {
1496 if(exnode->internalEdgeMap_.empty())
1497 buildInternalEdgeMap(exnode, false, true);
1498 for(std::vector<SimplexId> edgeTuple : iter->second) {
1499 std::array<SimplexId, 2> const edgePair
1500 = {edgeTuple[1], edgeTuple[2]};
1501 (nodePtr->triangleEdges_)[edgeTuple[0]
1502 - cellIntervals_[nodePtr->nid - 1] - 1][2]
1503 = exnode->internalEdgeMap_.at(edgePair)
1504 + edgeIntervals_[iter->first - 1];
1505 }
1506 } else {
1507 ImplicitCluster tmpCluster(iter->first);
1508 buildInternalEdgeMap(&tmpCluster, false, true);
1509 for(std::vector<SimplexId> edgeTuple : iter->second) {
1510 std::array<SimplexId, 2> const edgePair
1511 = {edgeTuple[1], edgeTuple[2]};
1512 (nodePtr->triangleEdges_)[edgeTuple[0]
1513 - cellIntervals_[nodePtr->nid - 1] - 1][2]
1514 = tmpCluster.internalEdgeMap_.at(edgePair)
1515 + edgeIntervals_[iter->first - 1];
1516 }
1517 }
1518 }
1519 } else if(getDimensionality() == 3) {
1520 if(nodePtr->internalTriangleMap_.empty()) {
1521 buildInternalTriangleMap(nodePtr, false, true);
1522 }
1523
1524 for(auto iter = nodePtr->internalTriangleMap_.begin();
1525 iter != nodePtr->internalTriangleMap_.end(); iter++) {
1526 // since the first vertex of the triangle is in the node ...
1527 std::array<SimplexId, 2> edgePair = {iter->first[0], iter->first[1]};
1528 (nodePtr->triangleEdges_)[iter->second - 1][0]
1529 = nodePtr->internalEdgeMap_.at(edgePair)
1530 + edgeIntervals_[nodePtr->nid - 1];
1531 edgePair[1] = iter->first[2];
1532 (nodePtr->triangleEdges_)[iter->second - 1][1]
1533 = nodePtr->internalEdgeMap_.at(edgePair)
1534 + edgeIntervals_[nodePtr->nid - 1];
1535 edgePair[0] = iter->first[1];
1536 if(edgePair[0] > vertexIntervals_[nodePtr->nid - 1]
1537 && edgePair[0] <= vertexIntervals_[nodePtr->nid]) {
1538 (nodePtr->triangleEdges_)[iter->second - 1][2]
1539 = nodePtr->internalEdgeMap_.at(edgePair)
1540 + edgeIntervals_[nodePtr->nid - 1];
1541 } else {
1542 std::vector<SimplexId> const edgeTuple{
1543 iter->second - 1, edgePair[0], edgePair[1]};
1544 SimplexId const nodeNum = vertexIndices_[edgePair[0]];
1545 edgeNodes[nodeNum].push_back(edgeTuple);
1546 }
1547 }
1548
1549 for(auto iter = edgeNodes.begin(); iter != edgeNodes.end(); iter++) {
1550 ImplicitCluster *exnode = searchCache(iter->first, nodePtr->nid);
1551 if(exnode) {
1552 if(exnode->internalEdgeMap_.empty())
1553 buildInternalEdgeMap(exnode, false, true);
1554 for(std::vector<SimplexId> edgeTuple : iter->second) {
1555 std::array<SimplexId, 2> const edgePair
1556 = {edgeTuple[1], edgeTuple[2]};
1557 (nodePtr->triangleEdges_)[edgeTuple[0]][2]
1558 = exnode->internalEdgeMap_.at(edgePair)
1559 + edgeIntervals_[iter->first - 1];
1560 }
1561 } else {
1562 ImplicitCluster tmpCluster(iter->first);
1563 buildInternalEdgeMap(&tmpCluster, false, true);
1564 for(std::vector<SimplexId> edgeTuple : iter->second) {
1565 std::array<SimplexId, 2> const edgePair
1566 = {edgeTuple[1], edgeTuple[2]};
1567 (nodePtr->triangleEdges_)[edgeTuple[0]][2]
1568 = tmpCluster.internalEdgeMap_.at(edgePair)
1569 + edgeIntervals_[iter->first - 1];
1570 }
1571 }
1572 }
1573 }
1574
1575 return 0;
1576}
1577
1579 ImplicitCluster *const nodePtr) const {
1580
1581#ifndef TTK_ENABLE_KAMIKAZE
1582 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1583 return -1;
1584#endif
1585
1586 SimplexId const localTriangleNum
1587 = triangleIntervals_[nodePtr->nid] - triangleIntervals_[nodePtr->nid - 1];
1588 std::vector<SimplexId> offsets(localTriangleNum + 1, 0),
1589 linksCount(localTriangleNum, 0);
1590
1591 if(nodePtr->triangleStars_.empty()) {
1592 getClusterTriangleStars(nodePtr);
1593 }
1594
1595 // set the offsets vector
1596 boost::unordered_map<std::array<SimplexId, 3>, SimplexId>::const_iterator
1597 iter;
1598 for(iter = nodePtr->internalTriangleMap_.begin();
1599 iter != nodePtr->internalTriangleMap_.end(); iter++) {
1600 for(SimplexId i = 0; i < nodePtr->triangleStars_.size(iter->second - 1);
1601 i++) {
1602 SimplexId const cellId = nodePtr->triangleStars_.get(iter->second - 1, i);
1603 for(int j = 0; j < 4; j++) {
1604 SimplexId const vertexId = cellArray_->getCellVertex(cellId, j);
1605 if((vertexId != iter->first[0]) && (vertexId != iter->first[1])
1606 && (vertexId != iter->first[2])) {
1607 offsets[iter->second]++;
1608 break;
1609 }
1610 }
1611 }
1612 }
1613
1614 // compute partial sum of number of links per triangle
1615 for(SimplexId i = 1; i <= localTriangleNum; i++) {
1616 offsets[i] += offsets[i - 1];
1617 }
1618
1619 // allocate the flat vector for triangle link data
1620 std::vector<SimplexId> triangleLinkData(offsets.back());
1621
1622 // fill the flat vector using offsets and count vectors
1623 for(iter = nodePtr->internalTriangleMap_.begin();
1624 iter != nodePtr->internalTriangleMap_.end(); iter++) {
1625 for(SimplexId i = 0; i < nodePtr->triangleStars_.size(iter->second - 1);
1626 i++) {
1627 SimplexId const cellId = nodePtr->triangleStars_.get(iter->second - 1, i);
1628 for(int j = 0; j < 4; j++) {
1629 SimplexId const vertexId = cellArray_->getCellVertex(cellId, j);
1630 if((vertexId != iter->first[0]) && (vertexId != iter->first[1])
1631 && (vertexId != iter->first[2])) {
1632 triangleLinkData[offsets[iter->second - 1]
1633 + linksCount[iter->second - 1]]
1634 = vertexId;
1635 linksCount[iter->second - 1]++;
1636 break;
1637 }
1638 }
1639 }
1640 }
1641
1642 // fill FlatJaggedArray struct
1643 nodePtr->triangleLinks_.setData(
1644 std::move(triangleLinkData), std::move(offsets));
1645
1646 return 0;
1647}
1648
1650 ImplicitCluster *const nodePtr) const {
1651
1652#ifndef TTK_ENABLE_KAMIKAZE
1653 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1654 return -1;
1655#endif
1656
1657 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
1658 SimplexId const localTriangleNum
1659 = triangleIntervals_[nodePtr->nid] - triangleIntervals_[nodePtr->nid - 1];
1660 std::vector<SimplexId> offsets(localTriangleNum + 1, 0),
1661 starsCount(localTriangleNum, 0);
1662
1663 if(nodePtr->internalTriangleMap_.empty()) {
1664 buildInternalTriangleMap(nodePtr, false, true);
1665 }
1666
1667 // set the offsets vector
1668 // loop through the internal cell list
1669 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1670 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1671 std::array<SimplexId, 3> triangleIds;
1672 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
1673 triangleIds[0] = cellArray_->getCellVertex(cid, j);
1674 if(triangleIds[0] > vertexIntervals_[nodePtr->nid]) {
1675 break;
1676 }
1677 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
1678 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
1679 triangleIds[1] = cellArray_->getCellVertex(cid, k);
1680 triangleIds[2] = cellArray_->getCellVertex(cid, l);
1681 offsets[nodePtr->internalTriangleMap_.at(triangleIds)]++;
1682 }
1683 }
1684 }
1685 }
1686 // loop through the external cell list
1687 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1688 std::array<SimplexId, 3> triangleIds;
1689 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
1690 triangleIds[0] = cellArray_->getCellVertex(cid, j);
1691 if(triangleIds[0] > vertexIntervals_[nodePtr->nid - 1]
1692 && triangleIds[0] <= vertexIntervals_[nodePtr->nid]) {
1693 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
1694 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
1695 triangleIds[1] = cellArray_->getCellVertex(cid, k);
1696 triangleIds[2] = cellArray_->getCellVertex(cid, l);
1697 offsets[nodePtr->internalTriangleMap_.at(triangleIds)]++;
1698 }
1699 }
1700 }
1701 }
1702 }
1703
1704 // compute partial sum of number of stars per triangle
1705 for(SimplexId i = 1; i <= localTriangleNum; i++) {
1706 offsets[i] += offsets[i - 1];
1707 }
1708
1709 // allocate the flat vector for triangle star data
1710 std::vector<SimplexId> triangleStarData(offsets.back());
1711
1712 // fill the flat vector using offsets and count vectors
1713 // loop through the internal cell list
1714 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1715 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1716 std::array<SimplexId, 3> triangleIds;
1717 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
1718 triangleIds[0] = cellArray_->getCellVertex(cid, j);
1719 // the triangle does not belong to the current node
1720 if(triangleIds[0] > vertexIntervals_[nodePtr->nid]) {
1721 break;
1722 }
1723 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
1724 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
1725 triangleIds[1] = cellArray_->getCellVertex(cid, k);
1726 triangleIds[2] = cellArray_->getCellVertex(cid, l);
1727 SimplexId const localTriangleId
1728 = nodePtr->internalTriangleMap_.at(triangleIds) - 1;
1729 triangleStarData[offsets[localTriangleId]
1730 + starsCount[localTriangleId]]
1731 = cid;
1732 starsCount[localTriangleId]++;
1733 }
1734 }
1735 }
1736 }
1737 // loop through the external cell list
1738 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1739 std::array<SimplexId, 3> triangleIds;
1740
1741 // loop through each triangle of the cell
1742 for(SimplexId j = 0; j < verticesPerCell - 2; j++) {
1743 triangleIds[0] = cellArray_->getCellVertex(cid, j);
1744 if(triangleIds[0] > vertexIntervals_[nodePtr->nid - 1]
1745 && triangleIds[0] <= vertexIntervals_[nodePtr->nid]) {
1746 for(SimplexId k = j + 1; k < verticesPerCell - 1; k++) {
1747 for(SimplexId l = k + 1; l < verticesPerCell; l++) {
1748 triangleIds[1] = cellArray_->getCellVertex(cid, k);
1749 triangleIds[2] = cellArray_->getCellVertex(cid, l);
1750 SimplexId const localTriangleId
1751 = nodePtr->internalTriangleMap_.at(triangleIds) - 1;
1752 triangleStarData[offsets[localTriangleId]
1753 + starsCount[localTriangleId]]
1754 = cid;
1755 starsCount[localTriangleId]++;
1756 }
1757 }
1758 }
1759 }
1760 }
1761
1762 // fill FlatJaggedArray struct
1763 nodePtr->triangleStars_.setData(
1764 std::move(triangleStarData), std::move(offsets));
1765
1766 return 0;
1767}
1768
1770 ImplicitCluster *const nodePtr) const {
1771
1772#ifndef TTK_ENABLE_KAMIKAZE
1773 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1774 return -1;
1775#endif
1776
1777 SimplexId const localVertexNum
1778 = vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1];
1779 std::vector<SimplexId> offsets(localVertexNum + 1, 0),
1780 edgesCount(localVertexNum, 0);
1781
1782 if(nodePtr->internalEdgeMap_.empty()) {
1783 buildInternalEdgeMap(nodePtr, false, true);
1784 }
1785 if(nodePtr->externalEdgeMap_.empty()) {
1786 buildExternalEdgeMap(nodePtr);
1787 }
1788
1789 // set the offsets vector
1790 boost::unordered_map<std::array<SimplexId, 2>, SimplexId>::iterator iter;
1791 for(iter = nodePtr->internalEdgeMap_.begin();
1792 iter != nodePtr->internalEdgeMap_.end(); iter++) {
1793 offsets[iter->first[0] - vertexIntervals_[nodePtr->nid - 1]]++;
1794 if(iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
1795 offsets[iter->first[1] - vertexIntervals_[nodePtr->nid - 1]]++;
1796 }
1797 }
1798 for(iter = nodePtr->externalEdgeMap_.begin();
1799 iter != nodePtr->externalEdgeMap_.end(); iter++) {
1800 offsets[iter->first[1] - vertexIntervals_[nodePtr->nid - 1]]++;
1801 }
1802 // compute partial sum of number of edges per vertex
1803 for(SimplexId i = 1; i <= localVertexNum; i++) {
1804 offsets[i] += offsets[i - 1];
1805 }
1806
1807 // allocate the flat vector for vertex edge data
1808 std::vector<SimplexId> vertexEdgeData(offsets.back());
1809
1810 // fill the flat vector using offsets and count vectors
1811 for(iter = nodePtr->internalEdgeMap_.begin();
1812 iter != nodePtr->internalEdgeMap_.end(); iter++) {
1813 SimplexId localVertexId
1814 = iter->first[0] - vertexIntervals_[nodePtr->nid - 1] - 1;
1815 vertexEdgeData[offsets[localVertexId] + edgesCount[localVertexId]]
1816 = iter->second + edgeIntervals_[nodePtr->nid - 1];
1817 edgesCount[localVertexId]++;
1818 if(iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
1819 localVertexId = iter->first[1] - vertexIntervals_[nodePtr->nid - 1] - 1;
1820 vertexEdgeData[offsets[localVertexId] + edgesCount[localVertexId]]
1821 = iter->second + edgeIntervals_[nodePtr->nid - 1];
1822 edgesCount[localVertexId]++;
1823 }
1824 }
1825 for(iter = nodePtr->externalEdgeMap_.begin();
1826 iter != nodePtr->externalEdgeMap_.end(); iter++) {
1827 SimplexId const localVertexId
1828 = iter->first[1] - vertexIntervals_[nodePtr->nid - 1] - 1;
1829 vertexEdgeData[offsets[localVertexId] + edgesCount[localVertexId]]
1830 = iter->second;
1831 edgesCount[localVertexId]++;
1832 }
1833
1834 // fill FlatJaggedArray struct
1835 nodePtr->vertexEdges_.setData(std::move(vertexEdgeData), std::move(offsets));
1836
1837 return 0;
1838}
1839
1841 ImplicitCluster *const nodePtr) const {
1842
1843#ifndef TTK_ENABLE_KAMIKAZE
1844 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
1845 return -1;
1846#endif
1847
1848 SimplexId const localVertexNum
1849 = vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1];
1850 std::vector<SimplexId> offsets(localVertexNum + 1, 0),
1851 linksCount(localVertexNum, 0);
1852 boost::unordered_map<SimplexId, ImplicitCluster> nodeMaps;
1853 // triangle mesh
1854 if(getDimensionality() == 2) {
1855 if(nodePtr->internalEdgeMap_.empty()) {
1856 buildInternalEdgeMap(nodePtr, false, true);
1857 }
1858
1859 // set the offsets vector
1860 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1861 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1862 offsets[cellArray_->getCellVertex(cid, 0)
1863 - vertexIntervals_[nodePtr->nid - 1]]++;
1864 for(SimplexId j = 1; j < 3; j++) {
1865 if(cellArray_->getCellVertex(cid, j)
1866 <= vertexIntervals_[nodePtr->nid]) {
1867 offsets[cellArray_->getCellVertex(cid, j)
1868 - vertexIntervals_[nodePtr->nid - 1]]++;
1869 }
1870 }
1871 }
1872 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1873 for(SimplexId j = 1; j < 3; j++) {
1874 SimplexId const vertexId = cellArray_->getCellVertex(cid, j);
1875 if(vertexId > vertexIntervals_[nodePtr->nid - 1]
1876 && vertexId <= vertexIntervals_[nodePtr->nid]) {
1877 offsets[vertexId - vertexIntervals_[nodePtr->nid - 1]]++;
1878 }
1879 }
1880 }
1881
1882 // compute partial sum of number of links per vertex
1883 for(SimplexId i = 1; i <= localVertexNum; i++) {
1884 offsets[i] += offsets[i - 1];
1885 }
1886
1887 // allocate the flat vector for vertex link data
1888 std::vector<SimplexId> vertexLinkData(offsets.back());
1889
1890 // fill the flat vector using offsets and count vectors
1891 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1892 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1893 std::array<SimplexId, 3> vertexIds
1894 = {(SimplexId)cellArray_->getCellVertex(cid, 0),
1895 (SimplexId)cellArray_->getCellVertex(cid, 1),
1896 (SimplexId)cellArray_->getCellVertex(cid, 2)};
1897 // the first vertex of the cell must be in the cluster
1898 std::array<SimplexId, 2> edgePair = {vertexIds[1], vertexIds[2]};
1899 SimplexId const nodeId = vertexIndices_[vertexIds[1]];
1900 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
1901 nodeMaps[nodeId] = ImplicitCluster(nodeId);
1902 buildInternalEdgeMap(&nodeMaps[nodeId], false, true);
1903 }
1904 SimplexId localVertexId
1905 = vertexIds[0] - vertexIntervals_[nodePtr->nid - 1] - 1;
1906 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
1907 = nodeMaps[nodeId].internalEdgeMap_.at(edgePair)
1908 + edgeIntervals_[nodeId - 1];
1909 linksCount[localVertexId]++;
1910
1911 if(vertexIds[1] <= vertexIntervals_[nodePtr->nid]) {
1912 edgePair[0] = vertexIds[0];
1913 localVertexId = vertexIds[1] - vertexIntervals_[nodePtr->nid - 1] - 1;
1914 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
1915 = nodePtr->internalEdgeMap_.at(edgePair)
1916 + edgeIntervals_[nodePtr->nid - 1];
1917 linksCount[localVertexId]++;
1918 if(vertexIds[2] <= vertexIntervals_[nodePtr->nid]) {
1919 localVertexId = vertexIds[2] - vertexIntervals_[nodePtr->nid - 1] - 1;
1920 edgePair[1] = vertexIds[1];
1921 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
1922 = nodePtr->internalEdgeMap_.at(edgePair)
1923 + edgeIntervals_[nodePtr->nid - 1];
1924 linksCount[localVertexId]++;
1925 }
1926 }
1927 }
1928 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1929 std::array<SimplexId, 3> vertexIds
1930 = {(SimplexId)cellArray_->getCellVertex(cid, 0),
1931 (SimplexId)cellArray_->getCellVertex(cid, 1),
1932 (SimplexId)cellArray_->getCellVertex(cid, 2)};
1933 std::array<SimplexId, 2> edgePair = {vertexIds[0], vertexIds[2]};
1934 SimplexId const nodeId = vertexIndices_[edgePair[0]];
1935 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
1936 nodeMaps[nodeId] = ImplicitCluster(nodeId);
1937 buildInternalEdgeMap(&nodeMaps[nodeId], false, true);
1938 }
1939 SimplexId localVertexId
1940 = vertexIds[1] - vertexIntervals_[nodePtr->nid - 1] - 1;
1941 if(vertexIds[1] > vertexIntervals_[nodePtr->nid - 1]
1942 && vertexIds[1] <= vertexIntervals_[nodePtr->nid]) {
1943 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
1944 = nodeMaps[nodeId].internalEdgeMap_.at(edgePair)
1945 + edgeIntervals_[nodeId - 1];
1946 linksCount[localVertexId]++;
1947 }
1948 if(vertexIds[2] > vertexIntervals_[nodePtr->nid - 1]
1949 && vertexIds[2] <= vertexIntervals_[nodePtr->nid]) {
1950 edgePair[1] = vertexIds[1];
1951 localVertexId = vertexIds[2] - vertexIntervals_[nodePtr->nid - 1] - 1;
1952 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
1953 = nodeMaps[nodeId].internalEdgeMap_.at(edgePair)
1954 + edgeIntervals_[nodeId - 1];
1955 linksCount[localVertexId]++;
1956 }
1957 }
1958
1959 // fill FlatJaggedArray struct
1960 nodePtr->vertexLinks_.setData(
1961 std::move(vertexLinkData), std::move(offsets));
1962
1963 // tetrahedral mesh
1964 } else if(getDimensionality() == 3) {
1965
1966 if(nodePtr->internalTriangleMap_.empty()) {
1967 buildInternalTriangleMap(nodePtr, false, true);
1968 }
1969
1970 // set the offsets vector
1971 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
1972 cid <= cellIntervals_[nodePtr->nid]; cid++) {
1973 offsets[cellArray_->getCellVertex(cid, 0)
1974 - vertexIntervals_[nodePtr->nid - 1]]++;
1975 for(SimplexId j = 1; j < 4; j++) {
1976 if(cellArray_->getCellVertex(cid, j)
1977 <= vertexIntervals_[nodePtr->nid]) {
1978 offsets[cellArray_->getCellVertex(cid, j)
1979 - vertexIntervals_[nodePtr->nid - 1]]++;
1980 }
1981 }
1982 }
1983 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
1984 for(SimplexId j = 1; j < 4; j++) {
1985 SimplexId const vertexId = cellArray_->getCellVertex(cid, j);
1986 if(vertexId > vertexIntervals_[nodePtr->nid - 1]
1987 && vertexId <= vertexIntervals_[nodePtr->nid]) {
1988 offsets[vertexId - vertexIntervals_[nodePtr->nid - 1]]++;
1989 }
1990 }
1991 }
1992
1993 // compute partial sum of number of links per vertex
1994 for(SimplexId i = 1; i <= localVertexNum; i++) {
1995 offsets[i] += offsets[i - 1];
1996 }
1997
1998 // allocate the flat vector for vertex link data
1999 std::vector<SimplexId> vertexLinkData(offsets.back());
2000
2001 // fill the flat vector using offsets and count vectors
2002 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
2003 cid <= cellIntervals_[nodePtr->nid]; cid++) {
2004 std::array<SimplexId, 4> vertexIds
2005 = {(SimplexId)cellArray_->getCellVertex(cid, 0),
2006 (SimplexId)cellArray_->getCellVertex(cid, 1),
2007 (SimplexId)cellArray_->getCellVertex(cid, 2),
2008 (SimplexId)cellArray_->getCellVertex(cid, 3)};
2009
2010 // v1: (v2, v3, v4)
2011 std::array<SimplexId, 3> triangleVec
2012 = {vertexIds[1], vertexIds[2], vertexIds[3]};
2013 SimplexId const nodeId = vertexIndices_[vertexIds[1]];
2014 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
2015 nodeMaps[nodeId] = ImplicitCluster(nodeId);
2016 buildInternalTriangleMap(&nodeMaps[nodeId], false, true);
2017 }
2018 SimplexId localVertexId
2019 = vertexIds[0] - vertexIntervals_[nodePtr->nid - 1] - 1;
2020 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2021 = nodeMaps[nodeId].internalTriangleMap_.at(triangleVec)
2022 + triangleIntervals_[nodeId - 1];
2023 linksCount[localVertexId]++;
2024 // v2: (v1, v3, v4)
2025 if(vertexIds[1] <= vertexIntervals_[nodePtr->nid]) {
2026 triangleVec[0] = vertexIds[0];
2027 localVertexId = vertexIds[1] - vertexIntervals_[nodePtr->nid - 1] - 1;
2028 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2029 = nodePtr->internalTriangleMap_.at(triangleVec)
2030 + triangleIntervals_[nodePtr->nid - 1];
2031 linksCount[localVertexId]++;
2032 // v3: (v1, v2, v4)
2033 if(vertexIds[2] <= vertexIntervals_[nodePtr->nid]) {
2034 triangleVec[1] = vertexIds[1];
2035 localVertexId = vertexIds[2] - vertexIntervals_[nodePtr->nid - 1] - 1;
2036 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2037 = nodePtr->internalTriangleMap_.at(triangleVec)
2038 + triangleIntervals_[nodePtr->nid - 1];
2039 linksCount[localVertexId]++;
2040 }
2041 // v4: (v1, v2, v3)
2042 if(vertexIds[3] <= vertexIntervals_[nodePtr->nid]) {
2043 triangleVec[2] = vertexIds[2];
2044 localVertexId = vertexIds[3] - vertexIntervals_[nodePtr->nid - 1] - 1;
2045 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2046 = nodePtr->internalTriangleMap_.at(triangleVec)
2047 + triangleIntervals_[nodePtr->nid - 1];
2048 linksCount[localVertexId]++;
2049 }
2050 }
2051 }
2052
2053 // loop through the external cell list
2054 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
2055 std::array<SimplexId, 4> vertexIds
2056 = {(SimplexId)cellArray_->getCellVertex(cid, 0),
2057 (SimplexId)cellArray_->getCellVertex(cid, 1),
2058 (SimplexId)cellArray_->getCellVertex(cid, 2),
2059 (SimplexId)cellArray_->getCellVertex(cid, 3)};
2060 // start from v2
2061 std::array<SimplexId, 3> triangleVec
2062 = {vertexIds[0], vertexIds[2], vertexIds[3]};
2063 SimplexId const nodeId = vertexIndices_[vertexIds[0]];
2064 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
2065 nodeMaps[nodeId] = ImplicitCluster(nodeId);
2066 buildInternalTriangleMap(&nodeMaps[nodeId], false, true);
2067 }
2068 SimplexId localVertexId
2069 = vertexIds[1] - vertexIntervals_[nodePtr->nid - 1] - 1;
2070 if(vertexIds[1] > vertexIntervals_[nodePtr->nid - 1]
2071 && vertexIds[1] <= vertexIntervals_[nodePtr->nid]) {
2072 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2073 = nodeMaps[nodeId].internalTriangleMap_.at(triangleVec)
2074 + triangleIntervals_[nodeId - 1];
2075 linksCount[localVertexId]++;
2076 }
2077 if(vertexIds[2] > vertexIntervals_[nodePtr->nid - 1]
2078 && vertexIds[2] <= vertexIntervals_[nodePtr->nid]) {
2079 triangleVec[1] = vertexIds[1];
2080 localVertexId = vertexIds[2] - vertexIntervals_[nodePtr->nid - 1] - 1;
2081 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2082 = nodeMaps[nodeId].internalTriangleMap_.at(triangleVec)
2083 + triangleIntervals_[nodeId - 1];
2084 linksCount[localVertexId]++;
2085 }
2086 if(vertexIds[3] > vertexIntervals_[nodePtr->nid - 1]
2087 && vertexIds[3] <= vertexIntervals_[nodePtr->nid]) {
2088 triangleVec[1] = vertexIds[1];
2089 triangleVec[2] = vertexIds[2];
2090 localVertexId = vertexIds[3] - vertexIntervals_[nodePtr->nid - 1] - 1;
2091 vertexLinkData[offsets[localVertexId] + linksCount[localVertexId]]
2092 = nodeMaps[nodeId].internalTriangleMap_.at(triangleVec)
2093 + triangleIntervals_[nodeId - 1];
2094 linksCount[localVertexId]++;
2095 }
2096 }
2097
2098 // fill FlatJaggedArray struct
2099 nodePtr->vertexLinks_.setData(
2100 std::move(vertexLinkData), std::move(offsets));
2101 }
2102
2103 return 0;
2104}
2105
2107 ImplicitCluster *const nodePtr) const {
2108
2109#ifndef TTK_ENABLE_KAMIKAZE
2110 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
2111 return -1;
2112#endif
2113
2114 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
2115 SimplexId const localVertexNum
2116 = vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1];
2117 std::vector<SimplexId> vertexNeighborData, offsets(localVertexNum + 1, 0);
2118
2119 SimplexId v1, v2;
2120 std::vector<boost::unordered_set<SimplexId>> vertexNeighborSet(
2121 localVertexNum);
2122
2123 // loop through the internal cells
2124 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
2125 cid <= cellIntervals_[nodePtr->nid]; cid++) {
2126 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
2127 v1 = cellArray_->getCellVertex(cid, j);
2128 if(v1 <= vertexIntervals_[nodePtr->nid]) {
2129 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
2130 v2 = cellArray_->getCellVertex(cid, k);
2131 vertexNeighborSet[v1 - vertexIntervals_[nodePtr->nid - 1] - 1].insert(
2132 v2);
2133 if(v2 <= vertexIntervals_[nodePtr->nid]) {
2134 vertexNeighborSet[v2 - vertexIntervals_[nodePtr->nid - 1] - 1]
2135 .insert(v1);
2136 }
2137 }
2138 }
2139 }
2140 }
2141
2142 // loop through external cells
2143 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
2144 for(SimplexId j = 0; j < verticesPerCell - 1; j++) {
2145 for(SimplexId k = j + 1; k < verticesPerCell; k++) {
2146 v1 = cellArray_->getCellVertex(cid, j);
2147 v2 = cellArray_->getCellVertex(cid, k);
2148 if(v1 > vertexIntervals_[nodePtr->nid - 1]
2149 && v1 <= vertexIntervals_[nodePtr->nid])
2150 vertexNeighborSet[v1 - vertexIntervals_[nodePtr->nid - 1] - 1].insert(
2151 v2);
2152 if(v2 > vertexIntervals_[nodePtr->nid - 1]
2153 && v2 <= vertexIntervals_[nodePtr->nid])
2154 vertexNeighborSet[v2 - vertexIntervals_[nodePtr->nid - 1] - 1].insert(
2155 v1);
2156 }
2157 }
2158 }
2159
2160 for(SimplexId i = 1; i <= localVertexNum; i++) {
2161 offsets[i] = offsets[i - 1] + vertexNeighborSet[i - 1].size();
2162 vertexNeighborData.insert(vertexNeighborData.end(),
2163 vertexNeighborSet[i - 1].begin(),
2164 vertexNeighborSet[i - 1].end());
2165 }
2166
2167 nodePtr->vertexNeighbors_.setData(
2168 std::move(vertexNeighborData), std::move(offsets));
2169 return 0;
2170}
2171
2173 ImplicitCluster *const nodePtr) const {
2174
2175#ifndef TTK_ENABLE_KAMIKAZE
2176 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
2177 return -1;
2178#endif
2179
2180 SimplexId const verticesPerCell = cellArray_->getCellVertexNumber(0);
2181 SimplexId const localVertexNum
2182 = vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1];
2183 std::vector<SimplexId> offsets(localVertexNum + 1, 0),
2184 starsCount(localVertexNum, 0);
2185
2186 // set the offsets vector
2187 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
2188 cid <= cellIntervals_[nodePtr->nid]; cid++) {
2189 SimplexId vertexId = cellArray_->getCellVertex(cid, 0);
2190 offsets[vertexId - vertexIntervals_[nodePtr->nid - 1]]++;
2191 for(SimplexId j = 1; j < verticesPerCell; j++) {
2192 vertexId = cellArray_->getCellVertex(cid, j);
2193 if(vertexId > vertexIntervals_[nodePtr->nid - 1]
2194 && vertexId <= vertexIntervals_[nodePtr->nid]) {
2195 offsets[vertexId - vertexIntervals_[nodePtr->nid - 1]]++;
2196 }
2197 }
2198 }
2199 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
2200 for(SimplexId j = 1; j < verticesPerCell; j++) {
2201 SimplexId const vertexId = cellArray_->getCellVertex(cid, j);
2202 if(vertexId > vertexIntervals_[nodePtr->nid - 1]
2203 && vertexId <= vertexIntervals_[nodePtr->nid]) {
2204 offsets[vertexId - vertexIntervals_[nodePtr->nid - 1]]++;
2205 }
2206 }
2207 }
2208
2209 // compute partial sum of number of stars per vertex
2210 for(SimplexId i = 1; i <= localVertexNum; i++) {
2211 offsets[i] += offsets[i - 1];
2212 }
2213
2214 // allocate the flat vector for vertex star data
2215 std::vector<SimplexId> vertexStarData(offsets.back());
2216
2217 // fill the flat vector using offsets and count vectors
2218 for(SimplexId cid = cellIntervals_[nodePtr->nid - 1] + 1;
2219 cid <= cellIntervals_[nodePtr->nid]; cid++) {
2220 SimplexId localVertexId = cellArray_->getCellVertex(cid, 0)
2221 - vertexIntervals_[nodePtr->nid - 1] - 1;
2222 vertexStarData[offsets[localVertexId] + starsCount[localVertexId]] = cid;
2223 starsCount[localVertexId]++;
2224 for(SimplexId j = 1; j < verticesPerCell; j++) {
2225 SimplexId const vertexId = cellArray_->getCellVertex(cid, j);
2226 // see if it is in the current node
2227 if(vertexId > vertexIntervals_[nodePtr->nid - 1]
2228 && vertexId <= vertexIntervals_[nodePtr->nid]) {
2229 localVertexId = vertexId - vertexIntervals_[nodePtr->nid - 1] - 1;
2230 vertexStarData[offsets[localVertexId] + starsCount[localVertexId]]
2231 = cid;
2232 starsCount[localVertexId]++;
2233 }
2234 }
2235 }
2236 for(SimplexId const cid : externalCells_[nodePtr->nid]) {
2237 for(SimplexId j = 0; j < verticesPerCell; j++) {
2238 // see if it is in the current node
2239 SimplexId const vertexId = cellArray_->getCellVertex(cid, j);
2240 if(vertexId > vertexIntervals_[nodePtr->nid - 1]
2241 && vertexId <= vertexIntervals_[nodePtr->nid]) {
2242 SimplexId const localVertexId
2243 = vertexId - vertexIntervals_[nodePtr->nid - 1] - 1;
2244 vertexStarData[offsets[localVertexId] + starsCount[localVertexId]]
2245 = cid;
2246 starsCount[localVertexId]++;
2247 }
2248 }
2249 }
2250
2251 // fill FlatJaggedArray struct
2252 nodePtr->vertexStars_.setData(std::move(vertexStarData), std::move(offsets));
2253
2254 return 0;
2255}
2256
2258 ImplicitCluster *const nodePtr) const {
2259
2260#ifndef TTK_ENABLE_KAMIKAZE
2261 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
2262 return -1;
2263#endif
2264
2265 SimplexId const localVertexNum
2266 = vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1];
2267 std::vector<SimplexId> offsets(localVertexNum + 1, 0),
2268 trianglesCount(localVertexNum, 0);
2269
2270 if(nodePtr->internalTriangleMap_.empty()) {
2271 buildInternalTriangleMap(nodePtr, false, true);
2272 }
2273 if(nodePtr->externalTriangleMap_.empty()) {
2274 buildExternalTriangleMap(nodePtr);
2275 }
2276
2277 // set the offsets vector
2278 boost::unordered_map<std::array<SimplexId, 3>, SimplexId>::iterator iter;
2279 for(iter = nodePtr->internalTriangleMap_.begin();
2280 iter != nodePtr->internalTriangleMap_.end(); iter++) {
2281 for(SimplexId j = 0; j < 3; j++) {
2282 if(iter->first[j] > vertexIntervals_[nodePtr->nid - 1]
2283 && iter->first[j] <= vertexIntervals_[nodePtr->nid])
2284 offsets[iter->first[j] - vertexIntervals_[nodePtr->nid - 1]]++;
2285 }
2286 }
2287 for(iter = nodePtr->externalTriangleMap_.begin();
2288 iter != nodePtr->externalTriangleMap_.end(); iter++) {
2289 for(SimplexId j = 0; j < 3; j++) {
2290 if(iter->first[j] > vertexIntervals_[nodePtr->nid - 1]
2291 && iter->first[j] <= vertexIntervals_[nodePtr->nid])
2292 offsets[iter->first[j] - vertexIntervals_[nodePtr->nid - 1]]++;
2293 }
2294 }
2295
2296 // compute partial sum of number of triangles per vertex
2297 for(SimplexId i = 1; i <= localVertexNum; i++) {
2298 offsets[i] += offsets[i - 1];
2299 }
2300
2301 // allocate the flat vector for vertex triangle data
2302 std::vector<SimplexId> vertexTriangleData(offsets.back());
2303
2304 // fill the flat vector using offsets and count vectors
2305 for(iter = nodePtr->internalTriangleMap_.begin();
2306 iter != nodePtr->internalTriangleMap_.end(); iter++) {
2307 for(SimplexId j = 0; j < 3; j++) {
2308 if(iter->first[j] > vertexIntervals_[nodePtr->nid - 1]
2309 && iter->first[j] <= vertexIntervals_[nodePtr->nid]) {
2310 SimplexId const localVertexId
2311 = iter->first[j] - vertexIntervals_[nodePtr->nid - 1] - 1;
2312 vertexTriangleData[offsets[localVertexId]
2313 + trianglesCount[localVertexId]]
2314 = iter->second + triangleIntervals_[nodePtr->nid - 1];
2315 trianglesCount[localVertexId]++;
2316 }
2317 }
2318 }
2319 for(iter = nodePtr->externalTriangleMap_.begin();
2320 iter != nodePtr->externalTriangleMap_.end(); iter++) {
2321 for(SimplexId j = 0; j < 3; j++) {
2322 if(iter->first[j] > vertexIntervals_[nodePtr->nid - 1]
2323 && iter->first[j] <= vertexIntervals_[nodePtr->nid]) {
2324 SimplexId const localVertexId
2325 = iter->first[j] - vertexIntervals_[nodePtr->nid - 1] - 1;
2326 vertexTriangleData[offsets[localVertexId]
2327 + trianglesCount[localVertexId]]
2328 = iter->second;
2329 trianglesCount[localVertexId]++;
2330 }
2331 }
2332 }
2333
2334 // fill FlatJaggedArray struct
2335 nodePtr->vertexTriangles_.setData(
2336 std::move(vertexTriangleData), std::move(offsets));
2337
2338 return 0;
2339}
2340
2342 const SimplexId dim) const {
2343
2344#ifndef TTK_ENABLE_KAMIKAZE
2345 if(nodePtr->nid <= 0 || nodePtr->nid > nodeNumber_)
2346 return -1;
2347#endif
2348
2349 if(getDimensionality() == 2) {
2350 SimplexId const localEdgeNum
2351 = edgeIntervals_[nodePtr->nid] - edgeIntervals_[nodePtr->nid - 1];
2352 if(nodePtr->boundaryEdges_.empty()) {
2353 nodePtr->boundaryEdges_ = std::vector<bool>(localEdgeNum, false);
2354 if(nodePtr->edgeStars_.empty()) {
2355 getClusterEdgeStars(nodePtr);
2356 }
2357 for(SimplexId i = 0; i < localEdgeNum; i++) {
2358 if(nodePtr->edgeStars_.size(i) == 1) {
2359 nodePtr->boundaryEdges_.at(i) = true;
2360 }
2361 }
2362 }
2363 // if boundary vertices are requested
2364 if(dim == 0 && nodePtr->boundaryVertices_.empty()) {
2365 nodePtr->boundaryVertices_ = std::vector<bool>(
2366 vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1],
2367 false);
2368 if(nodePtr->externalEdgeMap_.empty()) {
2369 buildExternalEdgeMap(nodePtr);
2370 }
2371 // internal edges
2372 for(auto iter = nodePtr->internalEdgeMap_.begin();
2373 iter != nodePtr->internalEdgeMap_.end(); iter++) {
2374 if((nodePtr->boundaryEdges_)[iter->second - 1]) {
2375 (nodePtr->boundaryVertices_)[iter->first[0]
2376 - vertexIntervals_[nodePtr->nid - 1] - 1]
2377 = true;
2378 if(iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
2379 (nodePtr
2380 ->boundaryVertices_)[iter->first[1]
2381 - vertexIntervals_[nodePtr->nid - 1] - 1]
2382 = true;
2383 }
2384 }
2385 }
2386 // external edges
2387 boost::unordered_map<SimplexId, ImplicitCluster> nodeMaps;
2388 for(auto iter = nodePtr->externalEdgeMap_.begin();
2389 iter != nodePtr->externalEdgeMap_.end(); iter++) {
2390 SimplexId const nodeId = vertexIndices_[iter->first[0]];
2391 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
2392 nodeMaps[nodeId] = ImplicitCluster(nodeId);
2393 getBoundaryCells(&nodeMaps[nodeId]);
2394 }
2395 if((nodeMaps[nodeId]
2396 .boundaryEdges_)[iter->second - edgeIntervals_[nodeId - 1] - 1]) {
2397 (nodePtr->boundaryVertices_)[iter->first[1]
2398 - vertexIntervals_[nodePtr->nid - 1] - 1]
2399 = true;
2400 }
2401 }
2402 }
2403 } else if(getDimensionality() == 3) {
2404 // get the boundary triangles first
2405 SimplexId const localTriangleNum
2406 = triangleIntervals_[nodePtr->nid] - triangleIntervals_[nodePtr->nid - 1];
2407 if(nodePtr->boundaryTriangles_.empty()) {
2408 nodePtr->boundaryTriangles_ = std::vector<bool>(localTriangleNum, false);
2409 if(nodePtr->triangleStars_.empty()) {
2410 getClusterTriangleStars(nodePtr);
2411 }
2412 for(SimplexId i = 0; i < localTriangleNum; i++) {
2413 if(nodePtr->triangleStars_.size(i) == 1) {
2414 (nodePtr->boundaryTriangles_)[i] = true;
2415 }
2416 }
2417 }
2418 // if the boundary edges are requested
2419 if(dim == 1 && nodePtr->boundaryEdges_.empty()) {
2420 nodePtr->boundaryEdges_ = std::vector<bool>(
2421 edgeIntervals_[nodePtr->nid] - edgeIntervals_[nodePtr->nid - 1], false);
2422 if(nodePtr->externalTriangleMap_.empty()) {
2423 buildExternalTriangleMap(nodePtr);
2424 }
2425 if(nodePtr->internalEdgeMap_.empty()) {
2426 buildInternalEdgeMap(nodePtr, false, true);
2427 }
2428 // internal triangles
2429 for(auto iter = nodePtr->internalTriangleMap_.begin();
2430 iter != nodePtr->internalTriangleMap_.end(); iter++) {
2431 if((nodePtr->boundaryTriangles_)[iter->second - 1]) {
2432 std::array<SimplexId, 2> edgePair = {iter->first[0], iter->first[1]};
2433 (nodePtr->boundaryEdges_)[nodePtr->internalEdgeMap_.at(edgePair) - 1]
2434 = true;
2435 edgePair[1] = iter->first[2];
2436 (nodePtr->boundaryEdges_)[nodePtr->internalEdgeMap_.at(edgePair) - 1]
2437 = true;
2438 if(iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
2439 edgePair[0] = iter->first[1];
2440 (nodePtr
2441 ->boundaryEdges_)[nodePtr->internalEdgeMap_.at(edgePair) - 1]
2442 = true;
2443 }
2444 }
2445 }
2446 // external triangles
2447 boost::unordered_map<SimplexId, ImplicitCluster> nodeMaps;
2448 for(auto iter = nodePtr->externalTriangleMap_.begin();
2449 iter != nodePtr->externalTriangleMap_.end(); iter++) {
2450 SimplexId const nodeId = vertexIndices_[iter->first[0]];
2451 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
2452 nodeMaps[nodeId] = ImplicitCluster(nodeId);
2453 getBoundaryCells(&nodeMaps[nodeId]);
2454 }
2455 if((nodeMaps[nodeId]
2456 .boundaryTriangles_)[iter->second - triangleIntervals_[nodeId - 1]
2457 - 1]) {
2458 if(iter->first[1] > vertexIntervals_[nodePtr->nid - 1]
2459 && iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
2460 std::array<SimplexId, 2> const edgePair
2461 = {iter->first[1], iter->first[2]};
2462 (nodePtr
2463 ->boundaryEdges_)[nodePtr->internalEdgeMap_.at(edgePair) - 1]
2464 = true;
2465 }
2466 }
2467 }
2468 }
2469
2470 // if the boundary vertices are requested
2471 else if(dim == 0 && nodePtr->boundaryVertices_.empty()) {
2472 nodePtr->boundaryVertices_ = std::vector<bool>(
2473 vertexIntervals_[nodePtr->nid] - vertexIntervals_[nodePtr->nid - 1],
2474 false);
2475 if(nodePtr->externalTriangleMap_.empty()) {
2476 buildExternalTriangleMap(nodePtr);
2477 }
2478 // internal triangles
2479 for(auto iter = nodePtr->internalTriangleMap_.begin();
2480 iter != nodePtr->internalTriangleMap_.end(); iter++) {
2481 if((nodePtr->boundaryTriangles_)[iter->second - 1]) {
2482 for(int j = 0; j < 3; j++) {
2483 SimplexId const vid = iter->first[j];
2484 if(vid <= vertexIntervals_[nodePtr->nid]) {
2485 (nodePtr
2486 ->boundaryVertices_)[vid - vertexIntervals_[nodePtr->nid - 1]
2487 - 1]
2488 = true;
2489 }
2490 }
2491 }
2492 }
2493 // external triangles
2494 boost::unordered_map<SimplexId, ImplicitCluster> nodeMaps;
2495 for(auto iter = nodePtr->externalTriangleMap_.begin();
2496 iter != nodePtr->externalTriangleMap_.end(); iter++) {
2497 SimplexId const nodeId = vertexIndices_[iter->first[0]];
2498 if(nodeMaps.find(nodeId) == nodeMaps.end()) {
2499 nodeMaps[nodeId] = ImplicitCluster(nodeId);
2500 ;
2501 getBoundaryCells(&nodeMaps[nodeId]);
2502 }
2503 if((nodeMaps[nodeId]
2504 .boundaryTriangles_)[iter->second - triangleIntervals_[nodeId - 1]
2505 - 1]) {
2506 if(iter->first[1] > vertexIntervals_[nodePtr->nid - 1]
2507 && iter->first[1] <= vertexIntervals_[nodePtr->nid]) {
2508 (nodePtr
2509 ->boundaryVertices_)[iter->first[1]
2510 - vertexIntervals_[nodePtr->nid - 1] - 1]
2511 = true;
2512 }
2513 if(iter->first[2] > vertexIntervals_[nodePtr->nid - 1]
2514 && iter->first[2] <= vertexIntervals_[nodePtr->nid]) {
2515 (nodePtr
2516 ->boundaryVertices_)[iter->first[2]
2517 - vertexIntervals_[nodePtr->nid - 1] - 1]
2518 = true;
2519 }
2520 }
2521 }
2522 }
2523 } else {
2524 return -1;
2525 }
2526
2527 return 0;
2528}
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
CompactTriangulation is a class implemented based on the TopoCluster data structure,...
int getClusterEdgeStars(ImplicitCluster *const nodePtr) const
int getClusterVertexTriangles(ImplicitCluster *const nodePtr) const
~CompactTriangulation() override
int getClusterVertexStars(ImplicitCluster *const nodePtr) const
int getClusterTriangleStars(ImplicitCluster *const nodePtr) const
CompactTriangulation & operator=(const CompactTriangulation &rhs)
std::vector< std::vector< SimplexId > > externalCells_
std::vector< SimplexId > cellIntervals_
int countInternalTriangles(SimplexId nodeId) const
int getClusterTriangleEdges(ImplicitCluster *const nodePtr) const
int getClusterCellTriangles(ImplicitCluster *const nodePtr) const
int getBoundaryCells(ImplicitCluster *const nodePtr, const SimplexId dim=2) const
std::vector< boost::unordered_map< SimplexId, std::list< ImplicitCluster >::iterator > > cacheMaps_
int buildInternalTriangleMap(ImplicitCluster *const nodePtr, bool computeInternalTriangleList, bool computeInternalTriangleMap) const
int getClusterVertexNeighbors(ImplicitCluster *const nodePtr) const
int getClusterVertexEdges(ImplicitCluster *const nodePtr) const
std::vector< SimplexId > vertexIntervals_
int getClusterEdgeLinks(ImplicitCluster *const nodePtr) const
int buildInternalEdgeMap(ImplicitCluster *const nodePtr, bool computeInternalEdgeList, bool computeInternalEdgeMap) const
int getClusterVertexLinks(ImplicitCluster *const nodePtr) const
std::vector< SimplexId > edgeIntervals_
int reorderVertices(std::vector< SimplexId > &vertexMap)
int reorderCells(const std::vector< SimplexId > &vertexMap, const SimplexId &cellNumber, const LongSimplexId *connectivity, const LongSimplexId *offset)
SimplexId countInternalEdges(SimplexId nodeId) const
int getClusterEdgeTriangles(ImplicitCluster *const nodePtr) const
std::shared_ptr< CellArray > cellArray_
std::vector< SimplexId > triangleIntervals_
int buildExternalEdgeMap(ImplicitCluster *const nodePtr) const
int getClusterCellNeighbors(ImplicitCluster *const nodePtr) const
int getClusterTriangleLinks(ImplicitCluster *const nodePtr) const
std::vector< std::list< ImplicitCluster > > caches_
ImplicitCluster * searchCache(const SimplexId &nodeId, const SimplexId reservedId=0) const
int TTK_TRIANGULATION_INTERNAL() getDimensionality() const override
int buildExternalTriangleMap(ImplicitCluster *const nodePtr) const
int getClusterTetraEdges(ImplicitCluster *const nodePtr) const
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
void copyTo(std::vector< std::vector< SimplexId > > &dst, int threadNumber=1) const
Copy buffers to a std::vector<std::vector<SimplexId>>
SimplexId get(SimplexId id, SimplexId local) const
Returns the data inside the sub-vectors.
void setData(std::vector< SimplexId > &&data, std::vector< SimplexId > &&offsets)
Set internal data from pre-existing vectors.
void fillFrom(const std::vector< T > &src, int threadNumber=1)
Fill buffers from a std::vector<std::vector<SimplexId>>
SimplexId size(SimplexId id) const
Get the size of a particular sub-vector.
bool empty() const
If the underlying buffers are empty.
The Topology ToolKit.
long long int LongSimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:15
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
T end(std::pair< T, T > &p)
Definition ripserpy.cpp:483
T begin(std::pair< T, T > &p)
Definition ripserpy.cpp:479