40 vtkInformationVector **inputVector,
41 vtkInformationVector *outputVector) {
45 vtkDataSet *input = vtkDataSet::GetData(inputVector[0]);
46 vtkUnstructuredGrid *output = vtkUnstructuredGrid::GetData(outputVector);
52 const int dimensionality = triangulation->getDimensionality();
54 vtkNew<vtkPoints> points{};
55 vtkNew<vtkUnstructuredGrid> cells{};
56 vtkNew<ttkSimplexIdTypeArray> cellIds{};
57 cellIds->SetNumberOfComponents(1);
58 cellIds->SetName(
"CellId");
59 vtkNew<vtkSignedCharArray> cellDims{};
60 cellDims->SetNumberOfComponents(1);
61 cellDims->SetName(
"CellDimension");
65 std::vector<SimplexId> vertices;
66 const SimplexId numberOfVertices = triangulation->getNumberOfVertices();
67 std::vector<SimplexId> isVisited(numberOfVertices, -1);
72 {
"#Vertices", std::to_string(numberOfVertices)},
75 auto addVertex = [&](
const SimplexId vertexId) {
79 std::array<float, 3> p{};
80 triangulation->getVertexPoint(vertexId, p[0], p[1], p[2]);
81 vertices.push_back(vertexId);
82 return points->InsertNextPoint(p.data());
85 auto addEdge = [&](
const SimplexId edgeId) {
86 std::array<vtkIdType, 2> pointIds{};
87 std::array<SimplexId, 2> vertexIds{};
89 for(
int i = 0; i < 2; ++i) {
90 triangulation->getEdgeVertex(edgeId, i, vertexIds[i]);
92 const SimplexId vertexId = vertexIds[i];
96 if(isVisited[vertexId] == -1) {
97 pointIds[i] = addVertex(vertexId);
98 isVisited[vertexId] = pointIds[i];
100 pointIds[i] = isVisited[vertexId];
103 cells->InsertNextCell(VTK_LINE, 2, pointIds.data());
104 cellIds->InsertNextTuple1(edgeId);
105 cellDims->InsertNextTuple1(1);
110 auto addTriangle = [&](
const SimplexId triangleId) {
111 std::array<vtkIdType, 3> pointIds{};
112 std::array<SimplexId, 3> vertexIds{};
114 for(
int i = 0; i < 3; ++i) {
115 if(dimensionality == 3)
116 triangulation->getTriangleVertex(triangleId, i, vertexIds[i]);
118 triangulation->getCellVertex(triangleId, i, vertexIds[i]);
120 const SimplexId vertexId = vertexIds[i];
124 if(isVisited[vertexId] == -1) {
125 pointIds[i] = addVertex(vertexId);
126 isVisited[vertexId] = pointIds[i];
128 pointIds[i] = isVisited[vertexId];
131 cells->InsertNextCell(VTK_TRIANGLE, 3, pointIds.data());
132 cellIds->InsertNextTuple1(triangleId);
133 cellDims->InsertNextTuple1(2);
138 auto addTetra = [&](
const SimplexId tetraId) {
139 std::array<vtkIdType, 4> pointIds{};
140 std::array<SimplexId, 4> vertexIds{};
142 for(
int i = 0; i < 4; ++i) {
143 triangulation->getCellVertex(tetraId, i, vertexIds[i]);
145 const SimplexId vertexId = vertexIds[i];
149 if(isVisited[vertexId] == -1) {
150 pointIds[i] = addVertex(vertexId);
151 isVisited[vertexId] = pointIds[i];
153 pointIds[i] = isVisited[vertexId];
156 cells->InsertNextCell(VTK_TETRA, 4, pointIds.data());
157 cellIds->InsertNextTuple1(tetraId);
158 cellDims->InsertNextTuple1(3);
163 auto addStar = [&](
const SimplexId starId) {
164 if(dimensionality == 2)
166 else if(dimensionality == 3)
171 std::vector<SimplexId> ids{};
172 std::istringstream iss(this->SimplexIdentifier);
173 for(SimplexId i; iss >> i;) {
175 if(iss.peek() ==
',') {
182 std::sort(ids.rbegin(), ids.rend());
183 const auto last = std::unique(ids.begin(), ids.end());
184 ids.erase(last, ids.end());
187 const auto it = std::find_if(
188 ids.begin(), ids.end(), [](
const SimplexId a) { return a < 0; });
190 ids.erase(it, ids.end());
193 const auto detectOutOfBounds = [
this, numberOfVertices, dimensionality,
194 &triangulation](
const SimplexId si) {
195 switch(this->SimplexType) {
197 if(si >= numberOfVertices) {
198 this->
printWrn(
"Vertex ID " + std::to_string(si)
199 +
" out of bounds (max. "
200 + std::to_string(numberOfVertices) +
").");
206 triangulation->preconditionEdges();
207 if(si >= triangulation->getNumberOfEdges()) {
209 "Edge ID " + std::to_string(si) +
" out of bounds (max. "
210 + std::to_string(triangulation->getNumberOfEdges()) +
").");
216 if(dimensionality == 3) {
217 triangulation->preconditionTriangles();
219 const auto numberOfTriangles
220 = dimensionality == 2 ? triangulation->getNumberOfCells()
221 : triangulation->getNumberOfTriangles();
222 if(si >= numberOfTriangles) {
223 this->
printWrn(
"Triangle ID " + std::to_string(si)
224 +
" out of bounds (max. "
225 + std::to_string(numberOfTriangles) +
").");
231 if(dimensionality == 3)
232 if(si >= triangulation->getNumberOfCells()) {
234 "Tetrahedron ID " + std::to_string(si) +
" out of bounds (max. "
235 + std::to_string(triangulation->getNumberOfCells()) +
").");
245 const auto last = std::remove_if(ids.begin(), ids.end(), detectOutOfBounds);
246 ids.erase(last, ids.end());
251 this->
printErr(
"Invalid simplex indices");
256 for(
const auto si : ids) {
257 switch(this->RequestType) {
259 switch(this->SimplexType) {
261 const auto vid = addVertex(si);
262 cells->InsertNextCell(VTK_VERTEX, 1, &vid);
263 cellIds->InsertNextTuple1(vid);
264 cellDims->InsertNextTuple1(0);
276 if(dimensionality == 3)
283 switch(this->SimplexType) {
288 for(
int i = 0; i < 2; ++i) {
290 triangulation->getEdgeVertex(si, i, vertexId);
296 if(dimensionality == 2) {
297 triangulation->preconditionCellEdges();
298 for(
int i = 0; i < 3; ++i) {
300 triangulation->getCellEdge(si, i, edgeId);
303 }
else if(dimensionality == 3) {
304 triangulation->preconditionTriangleEdges();
305 for(
int i = 0; i < 3; ++i) {
307 triangulation->getTriangleEdge(si, i, edgeId);
314 if(dimensionality == 3) {
315 triangulation->preconditionCellTriangles();
316 for(
int i = 0; i < 4; ++i) {
317 SimplexId triangleId;
318 triangulation->getCellTriangle(si, i, triangleId);
319 addTriangle(triangleId);
327 switch(this->SimplexType) {
329 triangulation->preconditionVertexNeighbors();
330 triangulation->preconditionVertexEdges();
332 const SimplexId edgeNumber
333 = triangulation->getVertexEdgeNumber(si);
334 for(SimplexId i = 0; i < edgeNumber; ++i) {
336 triangulation->getVertexEdge(si, i, edgeId);
343 if(dimensionality == 2) {
344 triangulation->preconditionEdgeStars();
345 const SimplexId starNumber = triangulation->getEdgeStarNumber(si);
346 for(SimplexId i = 0; i < starNumber; ++i) {
348 triangulation->getEdgeStar(si, i, starId);
351 }
else if(dimensionality == 3) {
352 triangulation->preconditionEdgeTriangles();
353 const SimplexId triangleNumber
354 = triangulation->getEdgeTriangleNumber(si);
355 for(SimplexId i = 0; i < triangleNumber; ++i) {
356 SimplexId triangleId;
357 triangulation->getEdgeTriangle(si, i, triangleId);
358 addTriangle(triangleId);
364 if(dimensionality == 3) {
365 triangulation->preconditionTriangleStars();
366 const SimplexId starNumber
367 = triangulation->getTriangleStarNumber(si);
368 for(SimplexId i = 0; i < starNumber; ++i) {
370 triangulation->getTriangleStar(si, i, starId);
382 switch(this->SimplexType) {
384 triangulation->preconditionVertexStars();
386 const SimplexId starNumber
387 = triangulation->getVertexStarNumber(si);
388 for(SimplexId i = 0; i < starNumber; ++i) {
390 triangulation->getVertexStar(si, i, starId);
397 triangulation->preconditionEdgeStars();
399 const SimplexId starNumber = triangulation->getEdgeStarNumber(si);
400 for(SimplexId i = 0; i < starNumber; ++i) {
402 triangulation->getEdgeStar(si, i, starId);
409 if(dimensionality == 3) {
410 triangulation->preconditionTriangleStars();
411 const SimplexId starNumber
412 = triangulation->getTriangleStarNumber(si);
413 for(SimplexId i = 0; i < starNumber; ++i) {
415 triangulation->getTriangleStar(si, i, starId);
427 switch(this->SimplexType) {
429 triangulation->preconditionVertexLinks();
430 if(dimensionality == 2) {
431 triangulation->preconditionEdges();
432 const SimplexId linkNumber
433 = triangulation->getVertexLinkNumber(si);
434 for(SimplexId i = 0; i < linkNumber; ++i) {
436 triangulation->getVertexLink(si, i, linkId);
439 }
else if(dimensionality == 3) {
440 triangulation->preconditionVertexTriangles();
441 const SimplexId linkNumber
442 = triangulation->getVertexLinkNumber(si);
443 for(SimplexId i = 0; i < linkNumber; ++i) {
445 triangulation->getVertexLink(si, i, linkId);
452 triangulation->preconditionEdgeLinks();
453 if(dimensionality == 2) {
454 const SimplexId linkNumber = triangulation->getEdgeLinkNumber(si);
455 for(SimplexId i = 0; i < linkNumber; ++i) {
457 triangulation->getEdgeLink(si, i, linkId);
460 }
else if(dimensionality == 3) {
461 const SimplexId linkNumber = triangulation->getEdgeLinkNumber(si);
462 for(SimplexId i = 0; i < linkNumber; ++i) {
464 triangulation->getEdgeLink(si, i, linkId);
471 if(dimensionality == 3) {
472 triangulation->preconditionTriangleLinks();
473 const SimplexId linkNumber
474 = triangulation->getTriangleLinkNumber(si);
475 for(SimplexId i = 0; i < linkNumber; ++i) {
477 triangulation->getTriangleLink(si, i, linkId);
488 switch(this->SimplexType) {
490 triangulation->preconditionBoundaryVertices();
491 for(SimplexId v = 0; v < triangulation->getNumberOfVertices();
493 if(triangulation->isVertexOnBoundary(v)) {
494 const auto vid = addVertex(v);
495 cells->InsertNextCell(VTK_VERTEX, 1, &vid);
496 cellIds->InsertNextTuple1(vid);
497 cellDims->InsertNextTuple1(0);
502 if(dimensionality == 1) {
503 triangulation->preconditionBoundaryVertices();
504 triangulation->preconditionVertexStars();
505 for(SimplexId v = 0; v < triangulation->getNumberOfVertices();
507 if(triangulation->isVertexOnBoundary(v)) {
509 triangulation->getVertexStar(v, 0, e);
514 triangulation->preconditionBoundaryEdges();
515 for(SimplexId e = 0; e < triangulation->getNumberOfEdges(); ++e) {
516 if(triangulation->isEdgeOnBoundary(e)) {
523 if(dimensionality == 2) {
524 triangulation->preconditionBoundaryEdges();
525 triangulation->preconditionEdgeStars();
526 for(SimplexId e = 0; e < triangulation->getNumberOfEdges(); ++e) {
527 if(triangulation->isEdgeOnBoundary(e)) {
529 triangulation->getEdgeStar(e, 0, t);
533 }
else if(dimensionality == 3) {
534 triangulation->preconditionBoundaryTriangles();
535 for(SimplexId t = 0; t < triangulation->getNumberOfTriangles();
537 if(triangulation->isTriangleOnBoundary(t)) {
542 this->
printErr(
"No triangles on the boundary of 1D data-sets");
546 if(dimensionality == 3) {
547 triangulation->preconditionBoundaryTriangles();
548 triangulation->preconditionTriangleStars();
549 for(SimplexId t = 0; t < triangulation->getNumberOfTriangles();
551 if(triangulation->isTriangleOnBoundary(t)) {
553 triangulation->getTriangleStar(t, 0, T);
559 "No tetrahedron on the boundary of 1D or 2D data-sets");
567 cells->SetPoints(points);
568 cells->GetCellData()->AddArray(cellIds);
569 cells->GetCellData()->AddArray(cellDims);
571 output->ShallowCopy(cells);
573 if(KeepAllDataArrays) {
574 vtkPointData *inputPointData = input->GetPointData();
575#ifndef TTK_ENABLE_KAMIKAZE
576 if(!inputPointData) {
577 this->
printErr(
"Input has no point data.");
581 const int numberOfInputArrays = inputPointData->GetNumberOfArrays();
583 vtkPointData *outputPointData = output->GetPointData();
584#ifndef TTK_ENABLE_KAMIKAZE
585 if(!outputPointData) {
586 this->
printErr(
"Output has no point data.");
591 for(
int i = 0; i < numberOfInputArrays; ++i) {
592 vtkDataArray *arr = inputPointData->GetArray(i);
594 if(arr and arr->GetNumberOfComponents() == 1) {
595 vtkDataArray *newArr = arr->NewInstance();
596 if(newArr ==
nullptr) {
599 newArr->SetName(arr->GetName());
600 newArr->SetNumberOfComponents(1);
602 for(SimplexId
const v : vertices)
603 newArr->InsertNextTuple1(arr->GetTuple1(v));
605 outputPointData->AddArray(newArr);