TTK
Loading...
Searching...
No Matches
ttkMorseSmaleComplex.cpp
Go to the documentation of this file.
1#include <ttkMacros.h>
3#include <ttkUtils.h>
4
5#include <vtkCellData.h>
6#include <vtkDataArray.h>
7#include <vtkDataObject.h>
8#include <vtkDataSet.h>
9#include <vtkDoubleArray.h>
10#include <vtkFloatArray.h>
11#include <vtkIdTypeArray.h>
12#include <vtkImageData.h>
13#include <vtkInformation.h>
14#include <vtkNew.h>
15#include <vtkPointData.h>
16#include <vtkPolyData.h>
17#include <vtkSignedCharArray.h>
18#include <vtkUnsignedCharArray.h>
19
21
23 this->setDebugMsgPrefix("MorseSmaleComplex");
24 SetNumberOfInputPorts(1);
25 SetNumberOfOutputPorts(4);
26}
27
29 vtkInformation *info) {
30 if(port == 0) {
31 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
32 return 1;
33 }
34 return 0;
35}
36
38 vtkInformation *info) {
39 if(port == 0 || port == 1 || port == 2) {
40 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData");
41 return 1;
42 } else if(port == 3) {
44 return 1;
45 }
46 return 0;
47}
48
49template <typename vtkArrayType, typename vectorType>
50void setArray(vtkArrayType &vtkArray, vectorType &vector) {
51 vtkArray->SetNumberOfTuples(vector.size());
52 for(unsigned int i = 0; i < vector.size(); i++) {
53 vtkArray->SetValue(i, vector[i]);
54 }
55}
56
57template <typename scalarType, typename triangulationType>
58int ttkMorseSmaleComplex::dispatch(vtkDataArray *const inputScalars,
59 vtkPolyData *const outputCriticalPoints,
60 vtkPolyData *const outputSeparatrices1,
61 vtkPolyData *const outputSeparatrices2,
62 const SimplexId *const inputOffsets,
63 const triangulationType &triangulation) {
64
65 const int dimensionality = triangulation.getDimensionality();
66 const auto scalars = ttkUtils::GetPointer<scalarType>(inputScalars);
67
68 OutputCriticalPoints criticalPoints_{};
69 Output1Separatrices separatrices1_{};
70 Output2Separatrices separatrices2_{};
71 const int ret
72 = this->execute(criticalPoints_, separatrices1_, separatrices2_,
73 segmentations_, scalars, inputScalars->GetMTime(),
74 inputOffsets, triangulation, StochasticGradientSeed);
75
76#ifndef TTK_ENABLE_KAMIKAZE
77 if(ret != 0) {
78 this->printErr("MorseSmaleComplex.execute() error");
79 return -1;
80 }
81#endif
82
83 // critical points
84 {
85 vtkNew<vtkPoints> points{};
86 vtkNew<vtkSignedCharArray> cellDimensions{};
87 vtkNew<ttkSimplexIdTypeArray> cellIds{};
88 vtkSmartPointer<vtkDataArray> const cellScalars{
89 inputScalars->NewInstance()};
90 vtkNew<vtkSignedCharArray> isOnBoundary{};
91 vtkNew<ttkSimplexIdTypeArray> PLVertexIdentifiers{};
92 vtkNew<ttkSimplexIdTypeArray> manifoldSizeScalars{};
93 const auto nPoints = criticalPoints_.points_.size();
94
95#ifndef TTK_ENABLE_KAMIKAZE
96 if(!points || !cellDimensions || !cellIds || !cellScalars || !isOnBoundary
97 || !PLVertexIdentifiers || !manifoldSizeScalars) {
98 this->printErr("Critical points vtkDataArray allocation problem.");
99 return -1;
100 }
101#endif
102
103 points->SetNumberOfPoints(nPoints);
104
105 cellDimensions->SetNumberOfComponents(1);
106 cellDimensions->SetName(ttk::MorseSmaleCellDimensionName);
107 setArray(cellDimensions, criticalPoints_.cellDimensions_);
108
109 cellIds->SetNumberOfComponents(1);
110 cellIds->SetName(ttk::MorseSmaleCellIdName);
111 setArray(cellIds, criticalPoints_.cellIds_);
112
113 cellScalars->SetNumberOfComponents(1);
114 cellScalars->SetName(inputScalars->GetName());
115 cellScalars->SetNumberOfTuples(nPoints);
116#ifdef TTK_ENABLE_OPENMP
117#pragma omp parallel for num_threads(this->threadNumber_)
118#endif // TTK_ENABLE_OPENMP
119 for(size_t i = 0; i < nPoints; ++i) {
120 points->SetPoint(i, criticalPoints_.points_[i].data());
121 cellScalars->SetTuple1(
122 i, scalars[criticalPoints_.PLVertexIdentifiers_[i]]);
123 }
124
125 isOnBoundary->SetNumberOfComponents(1);
126 isOnBoundary->SetName(ttk::MorseSmaleBoundaryName);
127 setArray(isOnBoundary, criticalPoints_.isOnBoundary_);
128
129 PLVertexIdentifiers->SetNumberOfComponents(1);
130 PLVertexIdentifiers->SetName(ttk::VertexScalarFieldName);
131 setArray(PLVertexIdentifiers, criticalPoints_.PLVertexIdentifiers_);
132
133 manifoldSizeScalars->SetNumberOfComponents(1);
134 manifoldSizeScalars->SetName(ttk::MorseSmaleManifoldSizeName);
136 criticalPoints_.manifoldSize_.resize(nPoints);
137 std::fill(criticalPoints_.manifoldSize_.begin(),
138 criticalPoints_.manifoldSize_.end(), -1);
139 }
140 setArray(manifoldSizeScalars, criticalPoints_.manifoldSize_);
141
142 ttkUtils::CellVertexFromPoints(outputCriticalPoints, points);
143
144 auto pointData = outputCriticalPoints->GetPointData();
145#ifndef TTK_ENABLE_KAMIKAZE
146 if(!pointData) {
147 this->printErr("outputCriticalPoints has no point data.");
148 return -1;
149 }
150#endif
151
152 pointData->SetScalars(cellDimensions);
153 pointData->AddArray(cellIds);
154 pointData->AddArray(cellScalars);
155 pointData->AddArray(isOnBoundary);
156 pointData->AddArray(PLVertexIdentifiers);
157 pointData->AddArray(manifoldSizeScalars);
158 }
159 // 1-separatrices
162
163 vtkNew<vtkFloatArray> pointsCoords{};
164 vtkNew<vtkSignedCharArray> smoothingMask{};
165 vtkNew<vtkSignedCharArray> cellDimensions{};
166 vtkNew<ttkSimplexIdTypeArray> cellIds{};
167 vtkNew<ttkSimplexIdTypeArray> sourceIds{};
168 vtkNew<ttkSimplexIdTypeArray> destinationIds{};
169 vtkNew<ttkSimplexIdTypeArray> separatrixIds{};
170 vtkNew<vtkSignedCharArray> separatrixTypes{};
171 vtkNew<vtkDoubleArray> separatrixFunctionMaxima{};
172 vtkNew<vtkDoubleArray> separatrixFunctionMinima{};
173 vtkNew<vtkDoubleArray> separatrixFunctionDiffs{};
174 vtkNew<vtkSignedCharArray> isOnBoundary{};
175
176#ifndef TTK_ENABLE_KAMIKAZE
177 if(!pointsCoords || !smoothingMask || !cellDimensions || !cellIds
178 || !sourceIds || !destinationIds || !separatrixIds || !separatrixTypes
179 || !separatrixFunctionMaxima || !separatrixFunctionMinima
180 || !separatrixFunctionDiffs || !isOnBoundary) {
181 this->printErr("1-separatrices vtkDataArray allocation problem.");
182 return -1;
183 }
184#endif
185
186 pointsCoords->SetNumberOfComponents(3);
187 pointsCoords->SetNumberOfTuples(separatrices1_.pt.numberOfPoints_);
188 for(int i = 0; i < separatrices1_.pt.numberOfPoints_; i++) {
189 pointsCoords->SetTuple3(i, separatrices1_.pt.points_[3 * i],
190 separatrices1_.pt.points_[3 * i + 1],
191 separatrices1_.pt.points_[3 * i + 2]);
192 }
193
194 smoothingMask->SetNumberOfComponents(1);
195 smoothingMask->SetName(ttk::MaskScalarFieldName);
196 setArray(smoothingMask, separatrices1_.pt.smoothingMask_);
197
198 cellDimensions->SetNumberOfComponents(1);
199 cellDimensions->SetName(ttk::MorseSmaleCellDimensionName);
200 setArray(cellDimensions, separatrices1_.pt.cellDimensions_);
201
202 cellIds->SetNumberOfComponents(1);
203 cellIds->SetName(ttk::MorseSmaleCellIdName);
204 setArray(cellIds, separatrices1_.pt.cellIds_);
205
206 sourceIds->SetNumberOfComponents(1);
207 sourceIds->SetName(ttk::MorseSmaleSourceIdName);
208 setArray(sourceIds, separatrices1_.cl.sourceIds_);
209
210 destinationIds->SetNumberOfComponents(1);
211 destinationIds->SetName(ttk::MorseSmaleDestinationIdName);
212 setArray(destinationIds, separatrices1_.cl.destinationIds_);
213
214 separatrixIds->SetNumberOfComponents(1);
215 separatrixIds->SetName(ttk::MorseSmaleSeparatrixIdName);
216 setArray(separatrixIds, separatrices1_.cl.separatrixIds_);
217
218 separatrixTypes->SetNumberOfComponents(1);
219 separatrixTypes->SetName(ttk::MorseSmaleSeparatrixTypeName);
220 setArray(separatrixTypes, separatrices1_.cl.separatrixTypes_);
221
222 separatrixFunctionMaxima->SetNumberOfComponents(1);
223 separatrixFunctionMaxima->SetName(ttk::MorseSmaleSeparatrixMaximumName);
224 separatrixFunctionMaxima->SetNumberOfTuples(
225 separatrices1_.cl.numberOfCells_);
226
227 separatrixFunctionMinima->SetNumberOfComponents(1);
228 separatrixFunctionMinima->SetName(ttk::MorseSmaleSeparatrixMinimumName);
229 separatrixFunctionMinima->SetNumberOfTuples(
230 separatrices1_.cl.numberOfCells_);
231
232 separatrixFunctionDiffs->SetNumberOfComponents(1);
233 separatrixFunctionDiffs->SetName(ttk::MorseSmaleSeparatrixDifferenceName);
234 separatrixFunctionDiffs->SetNumberOfTuples(
235 separatrices1_.cl.numberOfCells_);
236
237#ifdef TTK_ENABLE_OPENMP
238#pragma omp parallel for num_threads(this->threadNumber_)
239#endif // TTK_ENABLE_OPENMP
240 for(SimplexId i = 0; i < separatrices1_.cl.numberOfCells_; ++i) {
241 const auto sepId = separatrices1_.cl.separatrixIds_[i];
242 // inputScalars->GetTuple1 not thread safe...
243 const auto min = scalars[separatrices1_.cl.sepFuncMinId_[sepId]];
244 const auto max = scalars[separatrices1_.cl.sepFuncMaxId_[sepId]];
245 separatrixFunctionMinima->SetTuple1(i, min);
246 separatrixFunctionMaxima->SetTuple1(i, max);
247 separatrixFunctionDiffs->SetTuple1(i, max - min);
248 }
249
250 isOnBoundary->SetNumberOfComponents(1);
251 isOnBoundary->SetName(ttk::MorseSmaleCriticalPointsOnBoundaryName);
252 setArray(isOnBoundary, separatrices1_.cl.isOnBoundary_);
253
254 vtkNew<ttkSimplexIdTypeArray> offsets{}, connectivity{};
255 offsets->SetNumberOfComponents(1);
256 offsets->SetNumberOfTuples(separatrices1_.cl.numberOfCells_ + 1);
257 connectivity->SetNumberOfComponents(1);
258 setArray(connectivity, separatrices1_.cl.connectivity_);
259
260#ifdef TTK_ENABLE_OPENMP
261#pragma omp parallel for num_threads(this->threadNumber_)
262#endif // TTK_ENABLE_OPENMP
263 for(SimplexId i = 0; i < separatrices1_.cl.numberOfCells_ + 1; ++i) {
264 offsets->SetTuple1(i, 2 * i);
265 }
266
267 vtkNew<vtkPoints> points{};
268 points->SetData(pointsCoords);
269 outputSeparatrices1->SetPoints(points);
270 vtkNew<vtkCellArray> cells{};
271#ifndef TTK_ENABLE_64BIT_IDS
272 cells->Use32BitStorage();
273#endif // TTK_ENABLE_64BIT_IDS
274 cells->SetData(offsets, connectivity);
275 outputSeparatrices1->SetLines(cells);
276
277 auto pointData = outputSeparatrices1->GetPointData();
278 auto cellData = outputSeparatrices1->GetCellData();
279
280#ifndef TTK_ENABLE_KAMIKAZE
281 if(!pointData || !cellData) {
282 this->printErr("outputSeparatrices1 has no point or no cell data.");
283 return -1;
284 }
285#endif
286
287 pointData->AddArray(smoothingMask);
288 pointData->AddArray(cellDimensions);
289 pointData->AddArray(cellIds);
290
291 cellData->AddArray(sourceIds);
292 cellData->AddArray(destinationIds);
293 cellData->AddArray(separatrixIds);
294 cellData->SetScalars(separatrixTypes);
295 cellData->AddArray(separatrixFunctionMaxima);
296 cellData->AddArray(separatrixFunctionMinima);
297 cellData->AddArray(separatrixFunctionDiffs);
298 cellData->AddArray(isOnBoundary);
299 }
300
301 // 2-separatrices
302 if(dimensionality == 3
304
305 vtkNew<vtkFloatArray> pointsCoords{};
306 vtkNew<ttkSimplexIdTypeArray> sourceIds{};
307 vtkNew<ttkSimplexIdTypeArray> separatrixIds{};
308 vtkNew<vtkSignedCharArray> separatrixTypes{};
309 vtkNew<vtkDoubleArray> separatrixFunctionMaxima{};
310 vtkNew<vtkDoubleArray> separatrixFunctionMinima{};
311 vtkNew<vtkDoubleArray> separatrixFunctionDiffs{};
312 vtkNew<vtkSignedCharArray> isOnBoundary{};
313
314#ifndef TTK_ENABLE_KAMIKAZE
315 if(!pointsCoords || !sourceIds || !separatrixIds || !separatrixTypes
316 || !separatrixFunctionMaxima || !separatrixFunctionMinima
317 || !separatrixFunctionDiffs || !isOnBoundary) {
318 this->printErr("2-separatrices vtkDataArray allocation problem.");
319 return -1;
320 }
321#endif
322
323 pointsCoords->SetNumberOfComponents(3);
324 pointsCoords->SetNumberOfTuples(separatrices2_.pt.points_.size());
325 for(int i = 0; i < separatrices2_.pt.numberOfPoints_; i++) {
326 pointsCoords->SetTuple3(i, separatrices2_.pt.points_[3 * i],
327 separatrices2_.pt.points_[3 * i + 1],
328 separatrices2_.pt.points_[3 * i + 2]);
329 }
330
331 sourceIds->SetNumberOfComponents(1);
332 sourceIds->SetName(ttk::MorseSmaleSourceIdName);
333 setArray(sourceIds, separatrices2_.cl.sourceIds_);
334
335 separatrixIds->SetNumberOfComponents(1);
336 separatrixIds->SetName(ttk::MorseSmaleSeparatrixIdName);
337 setArray(separatrixIds, separatrices2_.cl.separatrixIds_);
338
339 separatrixTypes->SetNumberOfComponents(1);
340 separatrixTypes->SetName(ttk::MorseSmaleSeparatrixTypeName);
341 setArray(separatrixTypes, separatrices2_.cl.separatrixTypes_);
342
343 separatrixFunctionMaxima->SetNumberOfComponents(1);
344 separatrixFunctionMaxima->SetName(ttk::MorseSmaleSeparatrixMaximumName);
345 separatrixFunctionMaxima->SetNumberOfTuples(
346 separatrices2_.cl.numberOfCells_);
347
348 separatrixFunctionMinima->SetNumberOfComponents(1);
349 separatrixFunctionMinima->SetName(ttk::MorseSmaleSeparatrixMinimumName);
350 separatrixFunctionMinima->SetNumberOfTuples(
351 separatrices2_.cl.numberOfCells_);
352
353 separatrixFunctionDiffs->SetNumberOfComponents(1);
354 separatrixFunctionDiffs->SetName(ttk::MorseSmaleSeparatrixDifferenceName);
355 separatrixFunctionDiffs->SetNumberOfTuples(
356 separatrices2_.cl.numberOfCells_);
357
358#ifdef TTK_ENABLE_OPENMP
359#pragma omp parallel for num_threads(this->threadNumber_)
360#endif // TTK_ENABLE_OPENMP
361 for(SimplexId i = 0; i < separatrices2_.cl.numberOfCells_; ++i) {
362 const auto sepId = separatrices2_.cl.separatrixIds_[i];
363 // inputScalars->GetTuple1 not thread safe...
364 const auto min = scalars[separatrices2_.cl.sepFuncMinId_[sepId]];
365 const auto max = scalars[separatrices2_.cl.sepFuncMaxId_[sepId]];
366 separatrixFunctionMinima->SetTuple1(i, min);
367 separatrixFunctionMaxima->SetTuple1(i, max);
368 separatrixFunctionDiffs->SetTuple1(i, max - min);
369 }
370
371 isOnBoundary->SetNumberOfComponents(1);
372 isOnBoundary->SetName(ttk::MorseSmaleCriticalPointsOnBoundaryName);
373 setArray(isOnBoundary, separatrices2_.cl.isOnBoundary_);
374
375 vtkNew<ttkSimplexIdTypeArray> offsets{}, connectivity{};
376 offsets->SetNumberOfComponents(1);
377 setArray(offsets, separatrices2_.cl.offsets_);
378 connectivity->SetNumberOfComponents(1);
379 setArray(connectivity, separatrices2_.cl.connectivity_);
380
381 vtkNew<vtkPoints> points{};
382 points->SetData(pointsCoords);
383 outputSeparatrices2->SetPoints(points);
384 vtkNew<vtkCellArray> cells{};
385#ifndef TTK_ENABLE_64BIT_IDS
386 cells->Use32BitStorage();
387#endif // TTK_ENABLE_64BIT_IDS
388 cells->SetData(offsets, connectivity);
389 outputSeparatrices2->SetPolys(cells);
390
391 auto cellData = outputSeparatrices2->GetCellData();
392#ifndef TTK_ENABLE_KAMIKAZE
393 if(!cellData) {
394 this->printErr("outputSeparatrices2 has no cell data.");
395 return -1;
396 }
397#endif
398
399 cellData->AddArray(sourceIds);
400 cellData->AddArray(separatrixIds);
401 cellData->AddArray(separatrixTypes);
402 cellData->AddArray(separatrixFunctionMaxima);
403 cellData->AddArray(separatrixFunctionMinima);
404 cellData->AddArray(separatrixFunctionDiffs);
405 cellData->AddArray(isOnBoundary);
406 }
407 return ret;
408}
409
411 vtkInformationVector **inputVector,
412 vtkInformationVector *outputVector) {
413
414 const auto input
415 = vtkDataSet::SafeDownCast(vtkDataSet::GetData(inputVector[0]));
416 auto outputCriticalPoints = vtkPolyData::GetData(outputVector, 0);
417 auto outputSeparatrices1 = vtkPolyData::GetData(outputVector, 1);
418 auto outputSeparatrices2 = vtkPolyData::GetData(outputVector, 2);
419 auto outputMorseComplexes = vtkDataSet::GetData(outputVector, 3);
420
421#ifndef TTK_ENABLE_KAMIKAZE
422 if(!input) {
423 this->printErr("Input pointer is NULL.");
424 return -1;
425 }
426 if(input->GetNumberOfPoints() == 0) {
427 this->printErr("Input has no point.");
428 return -1;
429 }
430 if(!outputCriticalPoints or !outputSeparatrices1 or !outputSeparatrices2
431 or !outputMorseComplexes) {
432 this->printErr("Output pointers are NULL.");
433 return -1;
434 }
435#endif
436
437 const auto triangulation = ttkAlgorithm::GetTriangulation(input);
438 if(triangulation == nullptr) {
439 this->printErr("Triangulation is null");
440 return 0;
441 }
442 this->preconditionTriangulation(triangulation);
443
444 const auto inputScalars = this->GetInputArrayToProcess(0, inputVector);
445
446#ifndef TTK_ENABLE_KAMIKAZE
447 if(inputScalars == nullptr) {
448 this->printErr("wrong scalars.");
449 return -1;
450 }
451#endif
452
453 auto inputOffsets = ttkAlgorithm::GetOrderArray(
454 input, 0, triangulation, false, 1, this->ForceInputOffsetScalarField);
455
456#ifndef TTK_ENABLE_KAMIKAZE
457 if(inputOffsets == nullptr) {
458 this->printErr("wrong offsets.");
459 return -1;
460 }
461 if(inputOffsets->GetDataType() != VTK_INT
462 and inputOffsets->GetDataType() != VTK_ID_TYPE) {
463 this->printErr("input offset field type not supported.");
464 return -1;
465 }
466#endif
467
468 this->printMsg("Launching computation on field `"
469 + std::string(inputScalars->GetName()) + "'...");
470
471 // morse complexes
472 const SimplexId numberOfVertices = triangulation->getNumberOfVertices();
473#ifndef TTK_ENABLE_KAMIKAZE
474 if(!numberOfVertices) {
475 this->printErr("Input has no vertices.");
476 return -1;
477 }
478#endif
479
480 vtkNew<ttkSimplexIdTypeArray> ascendingManifold{};
481 vtkNew<ttkSimplexIdTypeArray> descendingManifold{};
482 vtkNew<ttkSimplexIdTypeArray> morseSmaleManifold{};
483#ifndef TTK_ENABLE_KAMIKAZE
484 if(!ascendingManifold || !descendingManifold || !morseSmaleManifold) {
485 this->printErr("Manifold vtkDataArray allocation problem.");
486 return -1;
487 }
488#endif
489
490 ascendingManifold->SetNumberOfComponents(1);
491 ascendingManifold->SetNumberOfTuples(numberOfVertices);
492 ascendingManifold->SetName(ttk::MorseSmaleAscendingName);
493
494 descendingManifold->SetNumberOfComponents(1);
495 descendingManifold->SetNumberOfTuples(numberOfVertices);
496 descendingManifold->SetName(ttk::MorseSmaleDescendingName);
497
498 morseSmaleManifold->SetNumberOfComponents(1);
499 morseSmaleManifold->SetNumberOfTuples(numberOfVertices);
500 morseSmaleManifold->SetName(ttk::MorseSmaleManifoldName);
501
502 this->segmentations_ = {ttkUtils::GetPointer<SimplexId>(ascendingManifold),
503 ttkUtils::GetPointer<SimplexId>(descendingManifold),
504 ttkUtils::GetPointer<SimplexId>(morseSmaleManifold)};
505
509
510 const auto imageDataInput = vtkImageData::SafeDownCast(input);
511
512 if(DiscreteGradientBackend == 0) {
514 DiscreteGradient::BACKEND::CLASSIC_BACKEND);
515 }
516 if(DiscreteGradientBackend == 1 && !imageDataInput) {
518 DiscreteGradient::BACKEND::CLASSIC_BACKEND);
519 this->printWrn("The stochastic gradient (IEEE TVCG 2012) can only");
520 this->printWrn("be used on vtkImageData (.vti).");
521 this->printWrn("Defaulting to homotopic expansion (IEEE PAMI 2011)");
522 }
523 if(DiscreteGradientBackend == 1 && imageDataInput) {
525 DiscreteGradient::BACKEND::STOCHASTIC_BACKEND);
526 }
527
528 int ret{};
529
530 /*
531
532 WARNING :
533
534 When this->ReturnSaddleConnectors == false, the discrete gradient is stored in
535 the cache associated with the triangulation. If the user creates another
536 MorseSmaleComplex object and execute the filter with
537 this->ReturnSaddleConnectors==false, the output will be the gradient in the
538 cache which may not be calculated with the same parameters (backend or seed).
539
540 */
541
543 inputScalars->GetDataType(), triangulation->getType(),
545 inputScalars, outputCriticalPoints, outputSeparatrices1,
546 outputSeparatrices2, ttkUtils::GetPointer<SimplexId>(inputOffsets),
547 *static_cast<TTK_TT *>(triangulation->getData()))));
548
549 if(ret != 0) {
550 return -1;
551 }
552
553 outputMorseComplexes->ShallowCopy(input);
554 // morse complexes
556 vtkPointData *pointData = outputMorseComplexes->GetPointData();
557#ifndef TTK_ENABLE_KAMIKAZE
558 if(!pointData) {
559 this->printErr("outputMorseComplexes has no point data.");
560 return -1;
561 }
562#endif
563
564 if(ComputeDescendingSegmentation)
565 pointData->AddArray(descendingManifold);
567 pointData->AddArray(ascendingManifold);
570 pointData->AddArray(morseSmaleManifold);
571 }
572
573 return !ret;
574}
#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::Triangulation * GetTriangulation(vtkDataSet *dataSet)
vtkDataArray * GetOrderArray(vtkDataSet *const inputData, const int scalarArrayIdx, ttk::Triangulation *triangulation, const bool getGlobalOrder=false, const int orderArrayIdx=0, const bool enforceOrderArrayIdx=false)
TTK VTK-filter that wraps the morseSmaleComplex processing package.
int dispatch(vtkDataArray *const inputScalars, vtkPolyData *const outputCriticalPoints, vtkPolyData *const outputSeparatrices1, vtkPolyData *const outputSeparatrices2, const SimplexId *const inputOffsets, const triangulationType &triangulation)
int FillInputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillOutputPortInformation(int port, vtkInformation *info) override
static int CellVertexFromPoints(vtkDataSet *const dataSet, vtkPoints *const points)
Definition ttkUtils.cpp:329
static DT * GetPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.h:59
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
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
int execute(OutputCriticalPoints &outCP, Output1Separatrices &outSeps1, Output2Separatrices &outSeps2, OutputManifold &outManifold, const dataType *const scalars, const size_t scalarsMTime, const SimplexId *const offsets, const triangulationType &triangulation, const unsigned int &seed=0)
void setSaddleConnectorsPersistenceThreshold(const double threshold)
void preconditionTriangulation(AbstractTriangulation *const data)
void setReturnSaddleConnectors(const bool state)
void setDiscreteGradientBackend(const DiscreteGradient::BACKEND selectedBackend)
const char MorseSmaleDestinationIdName[]
Definition DataTypes.h:53
const char MorseSmaleSeparatrixDifferenceName[]
Definition DataTypes.h:59
const char MorseSmaleManifoldName[]
Definition DataTypes.h:64
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
const char MorseSmaleSeparatrixMaximumName[]
Definition DataTypes.h:56
const char MorseSmaleSourceIdName[]
Definition DataTypes.h:52
const char MorseSmaleAscendingName[]
Definition DataTypes.h:62
const char MorseSmaleCellDimensionName[]
Definition DataTypes.h:48
const char MorseSmaleDescendingName[]
Definition DataTypes.h:63
const char MorseSmaleCriticalPointsOnBoundaryName[]
Definition DataTypes.h:61
const char MorseSmaleCellIdName[]
Definition DataTypes.h:49
const char MorseSmaleSeparatrixTypeName[]
Definition DataTypes.h:55
const char MorseSmaleManifoldSizeName[]
Definition DataTypes.h:51
const char MorseSmaleBoundaryName[]
Definition DataTypes.h:50
const char VertexScalarFieldName[]
default name for vertex scalar field
Definition DataTypes.h:35
const char MorseSmaleSeparatrixMinimumName[]
Definition DataTypes.h:57
const char MorseSmaleSeparatrixIdName[]
Definition DataTypes.h:54
const char MaskScalarFieldName[]
default name for mask scalar field
Definition DataTypes.h:32
1-Separatrices point and cell data arrays
2-Separatrices point and cell data arrays
#define ttkVtkTemplateMacro(dataType, triangulationType, call)
Definition ttkMacros.h:69
vtkStandardNewMacro(ttkMorseSmaleComplex)
void setArray(vtkArrayType &vtkArray, vectorType &vector)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)