55 vtkPolyData *
const outputCriticalPoints,
56 vtkPolyData *
const outputSeparatrices1,
57 vtkPolyData *
const outputSeparatrices2,
58 const triangulationType &triangulation) {
60 const int dimensionality = triangulation.getDimensionality();
63 const int ret = this->
execute(criticalPoints_, separatrices1_, separatrices2_,
64 segmentations_, vectors,
65 inputVectors->GetMTime(), triangulation);
67#ifndef TTK_ENABLE_KAMIKAZE
69 this->
printErr(
"TopologicalSkeleton.execute() error");
76 vtkNew<vtkPoints> points{};
77 vtkNew<vtkSignedCharArray> cellDimensions{};
78 vtkNew<ttkSimplexIdTypeArray> cellIds{};
79 vtkNew<vtkSignedCharArray> isOnBoundary{};
80 vtkNew<ttkSimplexIdTypeArray> PLVertexIdentifiers{};
81 vtkNew<ttkSimplexIdTypeArray> manifoldSizeScalars{};
82 const auto nPoints = criticalPoints_.points_.size();
84#ifndef TTK_ENABLE_KAMIKAZE
85 if(!points || !cellDimensions || !cellIds || !isOnBoundary
86 || !PLVertexIdentifiers || !manifoldSizeScalars) {
87 this->
printErr(
"Critical points vtkDataArray allocation problem.");
92 points->SetNumberOfPoints(nPoints);
94 cellDimensions->SetNumberOfComponents(1);
95 cellDimensions->SetName(
"CellDimension");
96 setArray(cellDimensions, criticalPoints_.cellDimensions_);
98 cellIds->SetNumberOfComponents(1);
99 cellIds->SetName(
"CellId");
100 setArray(cellIds, criticalPoints_.cellIds_);
102#ifdef TTK_ENABLE_OPENMP
103#pragma omp parallel for num_threads(this->threadNumber_)
105 for(
size_t i = 0; i < nPoints; ++i) {
106 points->SetPoint(i, criticalPoints_.points_[i].data());
109 isOnBoundary->SetNumberOfComponents(1);
110 isOnBoundary->SetName(
"IsOnBoundary");
111 setArray(isOnBoundary, criticalPoints_.isOnBoundary_);
113 PLVertexIdentifiers->SetNumberOfComponents(1);
115 setArray(PLVertexIdentifiers, criticalPoints_.PLVertexIdentifiers_);
117 manifoldSizeScalars->SetNumberOfComponents(1);
118 manifoldSizeScalars->SetName(
"ManifoldSize");
120 criticalPoints_.manifoldSize_.resize(nPoints);
121 std::fill(criticalPoints_.manifoldSize_.begin(),
122 criticalPoints_.manifoldSize_.end(), -1);
124 setArray(manifoldSizeScalars, criticalPoints_.manifoldSize_);
128 auto pointData = outputCriticalPoints->GetPointData();
129#ifndef TTK_ENABLE_KAMIKAZE
131 this->
printErr(
"outputCriticalPoints has no point data.");
136 pointData->SetScalars(cellDimensions);
137 pointData->AddArray(cellIds);
138 pointData->AddArray(isOnBoundary);
139 pointData->AddArray(PLVertexIdentifiers);
140 pointData->AddArray(manifoldSizeScalars);
148 vtkNew<vtkFloatArray> pointsCoords{};
149 vtkNew<vtkSignedCharArray> smoothingMask{};
150 vtkNew<vtkSignedCharArray> cellDimensions{};
151 vtkNew<ttkSimplexIdTypeArray> cellIds{};
152 vtkNew<ttkSimplexIdTypeArray> sourceIds{};
153 vtkNew<ttkSimplexIdTypeArray> destinationIds{};
154 vtkNew<ttkSimplexIdTypeArray> separatrixIds{};
155 vtkNew<vtkSignedCharArray> separatrixTypes{};
156 vtkNew<vtkSignedCharArray> isOnBoundary{};
157 vtkNew<vtkSignedCharArray> isOrbit{};
159#ifndef TTK_ENABLE_KAMIKAZE
160 if(!pointsCoords || !smoothingMask || !cellDimensions || !cellIds
161 || !sourceIds || !destinationIds || !separatrixIds || !separatrixTypes
162 || !isOnBoundary || !isOrbit) {
163 this->
printErr(
"1-separatrices vtkDataArray allocation problem.");
168 pointsCoords->SetNumberOfComponents(3);
169 setArray(pointsCoords, separatrices1_.pt.points_);
171 smoothingMask->SetNumberOfComponents(1);
173 setArray(smoothingMask, separatrices1_.pt.smoothingMask_);
175 cellDimensions->SetNumberOfComponents(1);
176 cellDimensions->SetName(
"CellDimension");
177 setArray(cellDimensions, separatrices1_.pt.cellDimensions_);
179 cellIds->SetNumberOfComponents(1);
180 cellIds->SetName(
"CellId");
181 setArray(cellIds, separatrices1_.pt.cellIds_);
183 sourceIds->SetNumberOfComponents(1);
184 sourceIds->SetName(
"SourceId");
185 setArray(sourceIds, separatrices1_.cl.sourceIds_);
187 destinationIds->SetNumberOfComponents(1);
188 destinationIds->SetName(
"DestinationId");
189 setArray(destinationIds, separatrices1_.cl.destinationIds_);
191 separatrixIds->SetNumberOfComponents(1);
192 separatrixIds->SetName(
"SeparatrixId");
193 setArray(separatrixIds, separatrices1_.cl.separatrixIds_);
195 separatrixTypes->SetNumberOfComponents(1);
196 separatrixTypes->SetName(
"SeparatrixType");
197 setArray(separatrixTypes, separatrices1_.cl.separatrixTypes_);
199 isOnBoundary->SetNumberOfComponents(1);
200 isOnBoundary->SetName(
"NumberOfCriticalPointsOnBoundary");
201 setArray(isOnBoundary, separatrices1_.cl.isOnBoundary_);
203 isOrbit->SetNumberOfComponents(1);
204 isOrbit->SetName(
"IsAnOrbit");
205 setArray(isOrbit, separatrices1_.cl.isOrbit_);
207 vtkNew<ttkSimplexIdTypeArray> offsets{}, connectivity{};
208 offsets->SetNumberOfComponents(1);
209 offsets->SetNumberOfTuples(separatrices1_.cl.numberOfCells_ + 1);
210 connectivity->SetNumberOfComponents(1);
211 setArray(connectivity, separatrices1_.cl.connectivity_);
213#ifdef TTK_ENABLE_OPENMP
214#pragma omp parallel for num_threads(this->threadNumber_)
216 for(
SimplexId i = 0; i < separatrices1_.cl.numberOfCells_ + 1; ++i) {
217 offsets->SetTuple1(i, 2 * i);
220 vtkNew<vtkPoints> points{};
221 points->SetData(pointsCoords);
222 outputSeparatrices1->SetPoints(points);
223 vtkNew<vtkCellArray> cells{};
224#ifndef TTK_ENABLE_64BIT_IDS
225 cells->Use32BitStorage();
227 cells->SetData(offsets, connectivity);
228 outputSeparatrices1->SetLines(cells);
230 auto pointData = outputSeparatrices1->GetPointData();
231 auto cellData = outputSeparatrices1->GetCellData();
233#ifndef TTK_ENABLE_KAMIKAZE
234 if(!pointData || !cellData) {
235 this->
printErr(
"outputSeparatrices1 has no point or no cell data.");
240 pointData->AddArray(smoothingMask);
241 pointData->AddArray(cellDimensions);
242 pointData->AddArray(cellIds);
244 cellData->AddArray(sourceIds);
245 cellData->AddArray(destinationIds);
246 cellData->AddArray(separatrixIds);
247 cellData->SetScalars(separatrixTypes);
248 cellData->AddArray(isOnBoundary);
249 cellData->AddArray(isOrbit);
253 if(dimensionality == 3
256 vtkNew<vtkFloatArray> pointsCoords{};
257 vtkNew<ttkSimplexIdTypeArray> sourceIds{};
258 vtkNew<ttkSimplexIdTypeArray> separatrixIds{};
259 vtkNew<vtkSignedCharArray> separatrixTypes{};
260 vtkNew<vtkSignedCharArray> isOnBoundary{};
262#ifndef TTK_ENABLE_KAMIKAZE
263 if(!pointsCoords || !sourceIds || !separatrixIds || !separatrixTypes
265 this->
printErr(
"2-separatrices vtkDataArray allocation problem.");
270 pointsCoords->SetNumberOfComponents(3);
271 setArray(pointsCoords, separatrices2_.pt.points_);
273 sourceIds->SetNumberOfComponents(1);
274 sourceIds->SetName(
"SourceId");
275 setArray(sourceIds, separatrices2_.cl.sourceIds_);
277 separatrixIds->SetNumberOfComponents(1);
278 separatrixIds->SetName(
"SeparatrixId");
279 setArray(separatrixIds, separatrices2_.cl.separatrixIds_);
281 separatrixTypes->SetNumberOfComponents(1);
282 separatrixTypes->SetName(
"SeparatrixType");
283 setArray(separatrixTypes, separatrices2_.cl.separatrixTypes_);
285 isOnBoundary->SetNumberOfComponents(1);
286 isOnBoundary->SetName(
"NumberOfCriticalPointsOnBoundary");
287 setArray(isOnBoundary, separatrices2_.cl.isOnBoundary_);
289 vtkNew<ttkSimplexIdTypeArray> offsets{}, connectivity{};
290 offsets->SetNumberOfComponents(1);
291 setArray(offsets, separatrices2_.cl.offsets_);
292 connectivity->SetNumberOfComponents(1);
293 setArray(connectivity, separatrices2_.cl.connectivity_);
295 vtkNew<vtkPoints> points{};
296 points->SetData(pointsCoords);
297 outputSeparatrices2->SetPoints(points);
298 vtkNew<vtkCellArray> cells{};
299#ifndef TTK_ENABLE_64BIT_IDS
300 cells->Use32BitStorage();
302 cells->SetData(offsets, connectivity);
303 outputSeparatrices2->SetPolys(cells);
305 auto cellData = outputSeparatrices2->GetCellData();
306#ifndef TTK_ENABLE_KAMIKAZE
308 this->
printErr(
"outputSeparatrices2 has no cell data.");
313 cellData->AddArray(sourceIds);
314 cellData->AddArray(separatrixIds);
315 cellData->AddArray(separatrixTypes);
316 cellData->AddArray(isOnBoundary);
323 vtkInformationVector **inputVector,
324 vtkInformationVector *outputVector) {
326 const auto input = vtkDataSet::GetData(inputVector[0]);
327 auto outputCriticalPoints = vtkPolyData::GetData(outputVector, 0);
328 auto outputSeparatrices1 = vtkPolyData::GetData(outputVector, 1);
329 auto outputSeparatrices2 = vtkPolyData::GetData(outputVector, 2);
330 auto outputMorseComplexes = vtkDataSet::GetData(outputVector, 3);
332#ifndef TTK_ENABLE_KAMIKAZE
334 this->
printErr(
"Input pointer is NULL.");
337 if(input->GetNumberOfPoints() == 0) {
338 this->
printErr(
"Input has no point.");
341 if(!outputCriticalPoints or !outputSeparatrices1 or !outputSeparatrices2
342 or !outputMorseComplexes) {
343 this->
printErr(
"Output pointers are NULL.");
349 if(triangulation ==
nullptr) {
350 this->
printErr(
"Triangulation is null");
355 const auto inputValues = this->GetInputArrayToProcess(0, inputVector);
357#ifndef TTK_ENABLE_KAMIKAZE
358 if(inputValues ==
nullptr) {
364 this->
printMsg(
"Launching computation on field `"
365 + std::string(inputValues->GetName()) +
"'...");
368 const SimplexId numberOfVertices = triangulation->getNumberOfVertices();
369#ifndef TTK_ENABLE_KAMIKAZE
370 if(!numberOfVertices) {
371 this->
printErr(
"Input has no vertices.");
376 vtkNew<ttkSimplexIdTypeArray> ascendingManifold{};
377 vtkNew<ttkSimplexIdTypeArray> descendingManifold{};
378 vtkNew<ttkSimplexIdTypeArray> morseSmaleManifold{};
379#ifndef TTK_ENABLE_KAMIKAZE
380 if(!ascendingManifold || !descendingManifold || !morseSmaleManifold) {
381 this->
printErr(
"Manifold vtkDataArray allocation problem.");
385 ascendingManifold->SetNumberOfComponents(1);
386 ascendingManifold->SetNumberOfTuples(numberOfVertices);
387 ascendingManifold->SetName(
"AscendingManifold");
389 descendingManifold->SetNumberOfComponents(1);
390 descendingManifold->SetNumberOfTuples(numberOfVertices);
391 descendingManifold->SetName(
"DescendingManifold");
393 morseSmaleManifold->SetNumberOfComponents(1);
394 morseSmaleManifold->SetNumberOfTuples(numberOfVertices);
395 morseSmaleManifold->SetName(
"IntersectingManifold");
408 inputValues->GetDataType(), triangulation->getType(),
410 inputValues, outputCriticalPoints, outputSeparatrices1,
411 outputSeparatrices2, *
static_cast<TTK_TT *
>(triangulation->getData()))));
417 outputMorseComplexes->ShallowCopy(input);
420 vtkPointData *pointData = outputMorseComplexes->GetPointData();
421#ifndef TTK_ENABLE_KAMIKAZE
423 this->
printErr(
"outputMorseComplexes has no point data.");
428 if(ComputeDescendingSegmentation)
429 pointData->AddArray(descendingManifold);
431 pointData->AddArray(ascendingManifold);
434 pointData->AddArray(morseSmaleManifold);