TTK
Loading...
Searching...
No Matches
ttkMeshSubdivision.cpp
Go to the documentation of this file.
1#include <vtkCellArray.h>
2#include <vtkCellData.h>
3#include <vtkDoubleArray.h>
4#include <vtkGenericCell.h>
5#include <vtkInformation.h>
6#include <vtkNew.h>
7#include <vtkObjectFactory.h>
8#include <vtkPointData.h>
9#include <vtkUnstructuredGrid.h>
10
11#include <ttkMeshSubdivision.h>
12
14
16 this->setDebugMsgPrefix("MeshSubdivision");
17 this->SetNumberOfInputPorts(1);
18 this->SetNumberOfOutputPorts(1);
19}
20
22 vtkInformation *info) {
23 if(port == 0) {
24 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid");
25 return 1;
26 }
27 return 0;
28}
29
31 vtkInformation *info) {
32 if(port == 0) {
34 return 1;
35 }
36 return 0;
37}
38
39int ttkMeshSubdivision::RequestData(vtkInformation *ttkNotUsed(request),
40 vtkInformationVector **inputVector,
41 vtkInformationVector *outputVector) {
42
43 using ttk::SimplexId;
44 ttk::Timer t;
45
46 auto input = vtkUnstructuredGrid::GetData(inputVector[0]);
47 auto output = vtkUnstructuredGrid::GetData(outputVector);
48
49 vtkNew<vtkUnstructuredGrid> tmpGrid{};
50
51 output->DeepCopy(input);
52 tmpGrid->DeepCopy(input);
53
54 for(int i = 0; i < IterationNumber; i++) {
55
56 std::vector<std::vector<vtkNew<vtkIdList>>> newCells(
57 tmpGrid->GetNumberOfCells());
58 std::vector<std::vector<std::vector<double>>> newPoints(
59 tmpGrid->GetNumberOfCells());
60
61 // for each cell, for each point, several scalar fields
62 std::vector<std::vector<std::vector<double>>> newPointData(
63 tmpGrid->GetNumberOfCells());
64 std::vector<std::vector<std::vector<double>>> newCellData(
65 tmpGrid->GetNumberOfCells());
66
67 // make the call thread-safe
68 vtkNew<vtkGenericCell> const threadCell{};
69 tmpGrid->GetCell(0, threadCell);
70 double value = 0;
71 for(int j = 0; j < tmpGrid->GetPointData()->GetNumberOfArrays(); j++) {
72 if(tmpGrid->GetPointData()->GetArray(j)->GetNumberOfComponents() == 1) {
73 tmpGrid->GetPointData()->GetArray(j)->GetTuple(0, &value);
74 }
75 }
76 for(int j = 0; j < tmpGrid->GetCellData()->GetNumberOfArrays(); j++) {
77 if(tmpGrid->GetCellData()->GetArray(j)->GetNumberOfComponents() == 1) {
78 tmpGrid->GetCellData()->GetArray(j)->GetTuple(0, &value);
79 }
80 }
81
82#ifdef TTK_ENABLE_OPENMP
83#pragma omp parallel for num_threads(threadNumber_)
84#endif
85 for(SimplexId j = 0; j < tmpGrid->GetNumberOfCells(); j++) {
86
87 vtkNew<vtkGenericCell> cell{};
88 tmpGrid->GetCell(j, cell);
89
90 std::vector<double> cellValues(
91 tmpGrid->GetCellData()->GetNumberOfArrays());
92 for(int k = 0; k < (int)cellValues.size(); k++) {
93 if(tmpGrid->GetCellData()->GetArray(k)->GetNumberOfComponents() == 1) {
94 tmpGrid->GetCellData()->GetArray(k)->GetTuple(j, &(cellValues[k]));
95 }
96 }
97
98 newCells[j].resize(cell->GetNumberOfPoints());
99 newCellData[j].resize(cell->GetNumberOfPoints());
100 for(int k = 0; k < (int)newCellData[j].size(); k++) {
101 newCellData[j][k] = cellValues;
102 }
103
104 newPoints[j].resize(cell->GetNumberOfPoints() + cell->GetNumberOfEdges()
105 + cell->GetNumberOfFaces() + 1);
106 newPointData[j].resize(cell->GetNumberOfPoints()
107 + cell->GetNumberOfEdges()
108 + cell->GetNumberOfFaces() + 1);
109 for(int k = 0; k < (int)newPointData[j].size(); k++) {
110 newPointData[j][k].resize(tmpGrid->GetPointData()->GetNumberOfArrays());
111 }
112
113 SimplexId pointCounter = 0;
114 SimplexId globalPointCounter
115 = j
116 * (cell->GetNumberOfPoints() + cell->GetNumberOfEdges()
117 + cell->GetNumberOfFaces() + 1);
118
119 // 0) add the vertices themselves
120 std::vector<SimplexId> vertexMap(cell->GetNumberOfPoints());
121 for(int k = 0; k < (int)cell->GetNumberOfPoints(); k++) {
122 double p[3];
123 tmpGrid->GetPoint(cell->GetPointId(k), p);
124 newPoints[j][pointCounter].resize(3, 0);
125 for(int l = 0; l < 3; l++)
126 newPoints[j][pointCounter][l] = p[l];
127
128 // copy the point data
129 double val;
130 for(int l = 0; l < tmpGrid->GetPointData()->GetNumberOfArrays(); l++) {
131 if(tmpGrid->GetPointData()->GetArray(l)->GetNumberOfComponents()
132 == 1) {
133 tmpGrid->GetPointData()->GetArray(l)->GetTuple(
134 cell->GetPointId(k), &val);
135 newPointData[j][pointCounter][l] = val;
136 }
137 }
138
139 vertexMap[k] = globalPointCounter;
140 pointCounter++;
141 globalPointCounter++;
142 }
143
144 std::vector<SimplexId> edgeMap(cell->GetNumberOfEdges());
145 // 1) create the edge list and create one new vertex per edge
146 for(int k = 0; k < cell->GetNumberOfEdges(); k++) {
147
148 vtkCell *edge = cell->GetEdge(k);
149 double p0[3], p1[3];
150 tmpGrid->GetPoint(edge->GetPointId(0), p0);
151 tmpGrid->GetPoint(edge->GetPointId(1), p1);
152
153 edgeMap[k] = globalPointCounter;
154
155 newPoints[j][pointCounter].resize(3);
156 for(int l = 0; l < 3; l++)
157 newPoints[j][pointCounter][l] = 0.5 * (p0[l] + p1[l]);
158
159 // take care of the point data
160 double value0 = 0, value1 = 0;
161 for(int l = 0; l < tmpGrid->GetPointData()->GetNumberOfArrays(); l++) {
162 if(tmpGrid->GetPointData()->GetArray(l)->GetNumberOfComponents()
163 == 1) {
164 tmpGrid->GetPointData()->GetArray(l)->GetTuple(
165 edge->GetPointId(0), &value0);
166 tmpGrid->GetPointData()->GetArray(l)->GetTuple(
167 edge->GetPointId(1), &value1);
168 newPointData[j][pointCounter][l] = 0.5 * value0 + 0.5 * value1;
169 }
170 }
171
172 pointCounter++;
173 globalPointCounter++;
174 }
175
176 // 2) create the face list and create one new vertex per face
177 std::vector<SimplexId> faceMap(cell->GetNumberOfFaces());
178 for(int k = 0; k < cell->GetNumberOfFaces(); k++) {
179
180 vtkCell *face = cell->GetFace(k);
181 newPoints[j][pointCounter].resize(3, 0);
182
183 for(int l = 0; l < face->GetNumberOfPoints(); l++) {
184 double p[3];
185 tmpGrid->GetPoint(face->GetPointId(l), p);
186 for(int m = 0; m < 3; m++) {
187 newPoints[j][pointCounter][m] += p[m];
188 }
189
190 // take care of the point data
191 double val = 0;
192 for(int m = 0; m < tmpGrid->GetPointData()->GetNumberOfArrays();
193 m++) {
194
195 if(tmpGrid->GetPointData()->GetArray(m)->GetNumberOfComponents()
196 == 1) {
197 tmpGrid->GetPointData()->GetArray(m)->GetTuple(
198 face->GetPointId(l), &val);
199 newPointData[j][pointCounter][m]
200 += (1 / ((double)face->GetNumberOfPoints())) * val;
201 }
202 }
203 }
204
205 faceMap[k] = globalPointCounter;
206
207 for(int l = 0; l < 3; l++)
208 newPoints[j][pointCounter][l] /= (double)face->GetNumberOfPoints();
209
210 pointCounter++;
211 globalPointCounter++;
212 }
213
214 // 3) create one new vertex per cell
215 for(int k = 0; k < (int)cell->GetNumberOfPoints(); k++) {
216 double p[3];
217 tmpGrid->GetPoint(cell->GetPointId(k), p);
218 newPoints[j][pointCounter].resize(3, 0);
219 for(int l = 0; l < 3; l++)
220 newPoints[j][pointCounter][l] += p[l];
221
222 // take care of the point data
223 double val = 0;
224 for(int l = 0; l < tmpGrid->GetPointData()->GetNumberOfArrays(); l++) {
225
226 if(tmpGrid->GetPointData()->GetArray(l)->GetNumberOfComponents()
227 == 1) {
228 tmpGrid->GetPointData()->GetArray(l)->GetTuple(
229 cell->GetPointId(k), &val);
230 newPointData[j][pointCounter][l]
231 += (1 / ((double)cell->GetNumberOfPoints())) * val;
232 }
233 }
234 }
235 for(int k = 0; k < 3; k++)
236 newPoints[j][pointCounter][k] /= (double)cell->GetNumberOfPoints();
237
238 // 4) create the new cells:
239 // for each cell, take each vertex:
240 // grab all incoming edges and faces + barycenter + vertex
241 // make a cell out of that
242 for(int k = 0; k < (int)cell->GetNumberOfPoints(); k++) {
243
244 SimplexId const vertexId = cell->GetPointId(k);
245
246 if(cell->GetCellDimension() == 2) {
247 // insert the id of the vertex
248 newCells[j][k]->InsertNextId(vertexMap[k]);
249
250 // take care of the edges
251 SimplexId firstEdge = -1;
252 for(size_t l = 0; l < edgeMap.size(); l++) {
253
254 vtkCell *edge = cell->GetEdge(l);
255 SimplexId const vertexId0 = edge->GetPointId(0);
256 SimplexId const vertexId1 = edge->GetPointId(1);
257
258 if((vertexId == vertexId0) || (vertexId == vertexId1)) {
259 // add the point id to the cell
260 newCells[j][k]->InsertNextId(edgeMap[l]);
261 firstEdge = l;
262 break;
263 }
264 }
265
266 // insert the id of the barycenter of the cell
267 newCells[j][k]->InsertNextId(globalPointCounter);
268
269 // take care of the second edge
270 for(SimplexId l = 0; l < static_cast<SimplexId>(edgeMap.size());
271 l++) {
272
273 vtkCell *edge = cell->GetEdge(l);
274 SimplexId const vertexId0 = edge->GetPointId(0);
275 SimplexId const vertexId1 = edge->GetPointId(1);
276
277 if((l != firstEdge)
278 && ((vertexId == vertexId0) || (vertexId == vertexId1))) {
279 // add the point id to the cell
280 newCells[j][k]->InsertNextId(edgeMap[l]);
281 break;
282 }
283 }
284 } else if(cell->GetCellDimension() == 3) {
285
286 // insert the id of the vertex
287 newCells[j][k]->InsertNextId(vertexMap[k]);
288
289 // take care of the edges
290 SimplexId firstEdge = -1;
291 std::pair<SimplexId, SimplexId> firstEdgeVertices;
292 for(size_t l = 0; l < edgeMap.size(); l++) {
293
294 vtkCell *edge = cell->GetEdge(l);
295 SimplexId const vertexId0 = edge->GetPointId(0);
296 SimplexId const vertexId1 = edge->GetPointId(1);
297
298 if((vertexId == vertexId0) || (vertexId == vertexId1)) {
299 // add the point id to the cell
300 newCells[j][k]->InsertNextId(edgeMap[l]);
301 firstEdgeVertices.first = vertexId0;
302 firstEdgeVertices.second = vertexId1;
303 firstEdge = l;
304 break;
305 }
306 }
307
308 std::vector<SimplexId> firstFaceVertices;
309 SimplexId firstFace = -1;
310 // take care of the faces
311 for(size_t l = 0; l < faceMap.size(); l++) {
312 vtkCell *face = cell->GetFace(l);
313
314 // test if this face contains the first edge
315 bool vertex0In = false;
316 bool vertex1In = false;
317 for(int m = 0; m < (int)face->GetNumberOfPoints(); m++) {
318 if(face->GetPointId(m) == firstEdgeVertices.first) {
319 vertex0In = true;
320 }
321 if(face->GetPointId(m) == firstEdgeVertices.second) {
322 vertex1In = true;
323 }
324 }
325
326 if((vertex0In) && (vertex1In)) {
327 newCells[j][k]->InsertNextId(faceMap[l]);
328
329 firstFace = l;
330 for(int n = 0; n < face->GetNumberOfPoints(); n++) {
331 firstFaceVertices.push_back(face->GetPointId(n));
332 }
333
334 break;
335 }
336 if(firstFace != -1)
337 break;
338 }
339
340 // take care of the second edge
341 SimplexId secondEdge = -1;
342 for(SimplexId l = 0; l < static_cast<SimplexId>(edgeMap.size());
343 l++) {
344 // make sure the found edge belongs to the face identified above
345 // cell->GetEdge(l)->GetPointId(0)
346 // cell->GetEdge(l)->GetPointId(1)
347 // both should be in
348
349 vtkCell *edge = cell->GetEdge(l);
350 SimplexId const vertexId0 = edge->GetPointId(0);
351 SimplexId const vertexId1 = edge->GetPointId(1);
352
353 // check if this edge belongs to the face identified right before
354 bool vertex0In = false;
355 bool vertex1In = false;
356 for(size_t m = 0; m < firstFaceVertices.size(); m++) {
357 if(firstFaceVertices[m] == vertexId0)
358 vertex0In = true;
359 if(firstFaceVertices[m] == vertexId1)
360 vertex1In = true;
361 }
362
363 if((l != firstEdge) && (vertex0In) && (vertex1In)
364 && ((vertexId == vertexId0) || (vertexId == vertexId1))) {
365 // add the point id to the cell
366 newCells[j][k]->InsertNextId(edgeMap[l]);
367
368 secondEdge = l;
369 break;
370 }
371 }
372
373 // front face done
374
375 // take care of the third edge
376 std::pair<SimplexId, SimplexId> thirdEdgeVertices;
377 for(SimplexId l = 0; l < static_cast<SimplexId>(edgeMap.size());
378 l++) {
379
380 vtkCell *edge = cell->GetEdge(l);
381 SimplexId const vertexId0 = edge->GetPointId(0);
382 SimplexId const vertexId1 = edge->GetPointId(1);
383
384 if((l != firstEdge) && (l != secondEdge)
385 && ((vertexId == vertexId0) || (vertexId == vertexId1))) {
386 // add the point id to the cell
387 newCells[j][k]->InsertNextId(edgeMap[l]);
388 thirdEdgeVertices.first = vertexId0;
389 thirdEdgeVertices.second = vertexId1;
390 break;
391 }
392 }
393
394 // take care of the second face
395 SimplexId secondFace = -1;
396 // take care of the faces
397 for(SimplexId l = faceMap.size() - 1; l >= 0; l--) {
398 vtkCell *face = cell->GetFace(l);
399
400 if(l != firstFace) {
401
402 bool vertex0In = false;
403 bool vertex1In = false;
404 for(vtkIdType m = 0; m < face->GetNumberOfPoints(); m++) {
405 if(face->GetPointId(m) == thirdEdgeVertices.first) {
406 vertex0In = true;
407 }
408 if(face->GetPointId(m) == thirdEdgeVertices.second) {
409 vertex1In = true;
410 }
411 }
412
413 if((vertex0In) && (vertex1In)) {
414 newCells[j][k]->InsertNextId(faceMap[l]);
415
416 secondFace = l;
417 break;
418 }
419 }
420 }
421
422 // insert the id of the barycenter of the cell
423 newCells[j][k]->InsertNextId(globalPointCounter);
424
425 // take care of the last face
426 SimplexId thirdFace = -1;
427 for(SimplexId l = 0; l < static_cast<SimplexId>(faceMap.size());
428 l++) {
429 vtkCell *face = cell->GetFace(l);
430
431 if((l != firstFace) && (l != secondFace)) {
432 for(int m = 0; m < (int)face->GetNumberOfPoints(); m++) {
433 if(face->GetPointId(m) == vertexId) {
434 newCells[j][k]->InsertNextId(faceMap[l]);
435
436 thirdFace = l;
437 break;
438 }
439 }
440 if(thirdFace != -1)
441 break;
442 }
443 }
444 }
445 }
446 }
447
448 // now merge things
449 vtkNew<vtkPoints> pointSet{};
450 vtkNew<vtkCellArray> cellArray{};
451
452 std::vector<vtkNew<vtkDoubleArray>> pointData;
453 pointData.resize(tmpGrid->GetPointData()->GetNumberOfArrays());
454 for(int j = 0; j < (int)pointData.size(); j++) {
455 pointData[j]->SetName(tmpGrid->GetPointData()->GetArray(j)->GetName());
456 }
457
458 std::vector<vtkNew<vtkDoubleArray>> cellData;
459 cellData.resize(tmpGrid->GetCellData()->GetNumberOfArrays());
460 for(int j = 0; j < (int)cellData.size(); j++) {
461 cellData[j]->SetName(tmpGrid->GetCellData()->GetArray(j)->GetName());
462 }
463
464 // order is really important here
465 for(size_t j = 0; j < newPoints.size(); j++) {
466 for(int k = 0; k < (int)newPoints[j].size(); k++) {
467 pointSet->InsertNextPoint(newPoints[j][k].data());
468 }
469 for(int k = 0; k < (int)newPointData[j].size(); k++) {
470 for(int l = 0; l < (int)newPointData[j][k].size(); l++) {
471 pointData[l]->InsertNextTuple1(newPointData[j][k][l]);
472 }
473 }
474 }
475 output->SetPoints(pointSet);
476 for(int j = 0; j < (int)pointData.size(); j++) {
477 output->GetPointData()->AddArray(pointData[j]);
478 }
479
480 for(size_t j = 0; j < newCells.size(); j++) {
481 for(int k = 0; k < (int)newCells[j].size(); k++) {
482 cellArray->InsertNextCell(newCells[j][k]);
483 }
484
485 for(int k = 0; k < (int)newCellData[j].size(); k++) {
486 for(int l = 0; l < (int)newCellData[j][k].size(); l++) {
487 cellData[l]->InsertNextTuple1(newCellData[j][k][l]);
488 }
489 }
490 }
491 if(tmpGrid->GetCell(0)->GetCellDimension() == 3) {
492 output->SetCells(VTK_HEXAHEDRON, cellArray);
493 } else if(tmpGrid->GetCell(0)->GetCellDimension() == 2) {
494 output->SetCells(VTK_POLYGON, cellArray);
495 }
496 for(int j = 0; j < (int)cellData.size(); j++) {
497 output->GetCellData()->AddArray(cellData[j]);
498 }
499
500 if(i != IterationNumber - 1) {
501 tmpGrid->DeepCopy(output);
502 }
503 }
504
505 this->printMsg(std::vector<std::vector<std::string>>{
506 {"#OutputCells", std::to_string(output->GetNumberOfCells())}});
507 this->printMsg(
508 "Subdivision computed", 1.0, t.getElapsedTime(), this->threadNumber_);
509
510 return 1;
511}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
static vtkInformationIntegerKey * SAME_DATA_TYPE_AS_INPUT_PORT()
TTK VTK-filter for the computation of mesh subdivisions (without vertex displacement).
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
double getElapsedTime()
Definition Timer.h:15
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
vtkStandardNewMacro(ttkMeshSubdivision)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)