TTK
Loading...
Searching...
No Matches
ttkMergeTreeStructures.h
Go to the documentation of this file.
1#pragma once
2
3#include <ExTreeM.h>
4#include <FTMTree.h>
5#include <ttkAlgorithm.h>
6
7#include <vtkCellData.h>
8#include <vtkDataArray.h>
9#include <vtkPointData.h>
10#include <vtkSmartPointer.h>
11#include <vtkType.h>
12#include <vtkUnstructuredGrid.h>
13
14#include <vtkCharArray.h>
15#include <vtkDoubleArray.h>
16#include <vtkFloatArray.h>
17#include <vtkIntArray.h>
18
19#include <ttkMacros.h>
20
21namespace ttk {
22 namespace ftm {
23
28
29 struct WrapperData {
30 template <typename vtkArrayType>
31 inline vtkSmartPointer<vtkArrayType> initArray(const char *fieldName,
32 size_t nbElmnt) {
35 arr->SetName(fieldName);
36 arr->SetNumberOfComponents(1);
37 arr->SetNumberOfTuples(nbElmnt);
38
39#ifndef TTK_ENABLE_KAMIKAZE
40 if(!arr) {
41 std::cerr << "[ttkMergeTree] Error, unable to allocate " << fieldName
42 << " the program will likely crash" << std::endl;
43 }
44#endif
45 return arr;
46 }
47
48 inline static CriticalType
49 getNodeType(FTMTree_MT &tree, const idNode nodeId, Params params) {
50 const Node *node = tree.getNode(nodeId);
51 int upDegree{};
52 int downDegree{};
53 if(params.treeType == TreeType::Join
54 or params.treeType == TreeType::Contour) {
55 upDegree = node->getNumberOfUpSuperArcs();
56 downDegree = node->getNumberOfDownSuperArcs();
57 } else {
58 downDegree = node->getNumberOfUpSuperArcs();
59 upDegree = node->getNumberOfDownSuperArcs();
60 }
61 int const degree = upDegree + downDegree;
62
63 // saddle point
64 if(degree > 1) {
65 if(upDegree == 2 and downDegree == 1)
67 else if(upDegree == 1 and downDegree == 2)
69 else if(upDegree == 1 and downDegree == 1)
71 else
73 }
74 // local extremum
75 else {
76 if(upDegree)
78 else
80 }
81 }
82 };
83
84 struct ArcData : public WrapperData {
85 std::vector<SimplexId> point_ids;
93
94 inline int init(std::vector<LocalFTM> &ftmTree, Params params) {
95 idSuperArc nbArcs = 0;
96 idSuperArc samplePoints = 0;
97 SimplexId nbVerts = 0;
98
99 for(auto &t : ftmTree) {
100 FTMTree_MT *tree = t.tree.getTree(params.treeType);
101 nbArcs += tree->getNumberOfSuperArcs();
102 samplePoints
103 += params.samplingLvl >= 0
104 ? tree->getNumberOfNodes() + (nbArcs * params.samplingLvl)
105 : tree->getNumberOfVertices();
106 nbVerts += tree->getNumberOfVertices();
107 }
108
109 point_ids.resize(nbVerts, nullVertex);
111 = initArray<ttkSimplexIdTypeArray>("SegmentationId", samplePoints);
113 = initArray<ttkSimplexIdTypeArray>("upNodeId", samplePoints);
115 = initArray<ttkSimplexIdTypeArray>("downNodeId", samplePoints);
117 = initArray<vtkCharArray>(MaskScalarFieldName, samplePoints);
118 point_scalar = initArray<vtkFloatArray>("Scalar", samplePoints);
119
120 if(params.advStats) {
121 if(params.segm) {
123 = initArray<ttkSimplexIdTypeArray>("RegionSize", samplePoints);
124 }
125 cell_spanArcs = initArray<vtkDoubleArray>("RegionSpan", samplePoints);
126 }
127
128 return 0;
129 }
130
131 inline bool hasPoint(const SimplexId vertId) {
132 return point_ids[vertId] != nullVertex;
133 }
134
135 inline void addPoint(const SimplexId globalId,
136 const SimplexId id,
137 const float scalar,
138 const bool reg) {
139 point_ids[globalId] = id;
140 setPoint(id, scalar, reg);
141 }
142
143 inline void
144 setPoint(const SimplexId id, const float scalar, const bool reg) {
145 point_scalar->SetTuple1(id, scalar);
146 point_regularMask->SetTuple1(id, reg);
147 }
148
149 inline void fillArrayCell(const SimplexId pos,
150 const idSuperArc arcId,
151 LocalFTM &ftmTree,
152 Triangulation *triangulation,
153 Params params) {
154 const idNode idOffset = ftmTree.offset;
155 FTMTree_MT *tree = ftmTree.tree.getTree(params.treeType);
156 SuperArc *arc = tree->getSuperArc(arcId);
157
158 if(params.normalize) {
159 cell_ids->SetTuple1(pos, idOffset + arc->getNormalizedId());
160 } else {
161 cell_ids->SetTuple1(pos, idOffset + arcId);
162 }
163
164 cell_upNode->SetTuple1(pos, arc->getUpNodeId());
165 cell_downNode->SetTuple1(pos, arc->getDownNodeId());
166
167 if(params.advStats) {
168 if(params.segm) {
169 cell_sizeArcs->SetTuple1(pos, tree->getArcSize(arcId));
170 }
171
172 float downPoints[3];
173 const SimplexId downNodeId = tree->getLowerNodeId(arc);
174 const SimplexId downVertexId
175 = tree->getNode(downNodeId)->getVertexId();
176 triangulation->getVertexPoint(
177 downVertexId, downPoints[0], downPoints[1], downPoints[2]);
178
179 float upPoints[3];
180 const SimplexId upNodeId = tree->getUpperNodeId(arc);
181 const SimplexId upVertexId = tree->getNode(upNodeId)->getVertexId();
182 triangulation->getVertexPoint(
183 upVertexId, upPoints[0], upPoints[1], upPoints[2]);
184
185 cell_spanArcs->SetTuple1(
186 pos, Geometry::distance(downPoints, upPoints));
187 }
188 }
189
190 inline void addArray(vtkUnstructuredGrid *skeletonArcs, Params params) {
191 // Some arcs might have been less sampled than the desired value, if
192 // they have not enough regular vertices. Here we ensur that we will no
193 // keep noise in these arrays.
194 const size_t nbPoints = skeletonArcs->GetNumberOfPoints();
195 const size_t nbCells = skeletonArcs->GetNumberOfCells();
196
197 cell_ids->SetNumberOfTuples(nbCells);
198 skeletonArcs->GetCellData()->SetScalars(cell_ids);
199
200 cell_upNode->SetNumberOfTuples(nbCells);
201 cell_downNode->SetNumberOfTuples(nbCells);
202 skeletonArcs->GetCellData()->AddArray(cell_upNode);
203 skeletonArcs->GetCellData()->AddArray(cell_downNode);
204
205 if(params.advStats) {
206 if(params.segm) {
207 cell_sizeArcs->SetNumberOfTuples(nbCells);
208 skeletonArcs->GetCellData()->AddArray(cell_sizeArcs);
209 }
210 cell_spanArcs->SetNumberOfTuples(nbCells);
211 skeletonArcs->GetCellData()->AddArray(cell_spanArcs);
212 }
213
214 point_scalar->SetNumberOfTuples(nbPoints);
215 skeletonArcs->GetPointData()->AddArray(point_scalar);
216 point_regularMask->SetNumberOfTuples(nbPoints);
217 skeletonArcs->GetPointData()->AddArray(point_regularMask);
218
219 point_ids.clear();
220 }
221 };
222
223 struct NodeData : public WrapperData {
231
232 inline int init(std::vector<LocalFTM> &ftmTree, Params params) {
233 idNode numberOfNodes = 0;
234 for(auto &t : ftmTree) {
235 FTMTree_MT *tree = t.tree.getTree(params.treeType);
236 numberOfNodes += tree->getNumberOfNodes();
237 }
238
239 ids = initArray<ttkSimplexIdTypeArray>("NodeId", numberOfNodes);
240 vertIds = initArray<ttkSimplexIdTypeArray>("VertexId", numberOfNodes);
241 type = initArray<vtkIntArray>("CriticalType", numberOfNodes);
242 scalars = initArray<vtkFloatArray>("Scalar", numberOfNodes);
243
244 if(params.advStats) {
245 if(params.segm) {
247 = initArray<ttkSimplexIdTypeArray>("RegionSize", numberOfNodes);
248 }
250 = initArray<ttkSimplexIdTypeArray>("RegionSpan", numberOfNodes);
251 }
252
253 return 0;
254 }
255
256 void setScalarType(const int s) {
257 scalarType = s;
258 }
259
260 inline void fillArrayPoint(SimplexId arrIdx,
261 const idNode nodeId,
262 LocalFTM &ftmTree,
263 vtkDataArray *idMapper,
264 Triangulation *triangulation,
265 Params params) {
266 const idNode idOffset = ftmTree.offset;
267 FTMTree_MT *tree = ftmTree.tree.getTree(params.treeType);
268 const Node *node = tree->getNode(nodeId);
269 // local (per cc) id
270 const SimplexId l_vertexId = node->getVertexId();
271 // global id
272 const SimplexId g_vertexId = idMapper->GetTuple1(l_vertexId);
273 float cellScalar = 0;
274 switch(scalarType) {
275 vtkTemplateMacro(cellScalar
276 = (float)tree->getValue<VTK_TT>(l_vertexId));
277 }
278
279 ids->SetTuple1(arrIdx, idOffset + nodeId);
280 scalars->SetTuple1(arrIdx, cellScalar);
281 vertIds->SetTuple1(arrIdx, g_vertexId);
282 type->SetTuple1(
283 arrIdx, static_cast<int>(getNodeType(*tree, nodeId, params)));
284
285 if(params.advStats) {
286 idSuperArc const saId = getAdjSa(node);
287 if(params.segm) {
288 regionSize->SetTuple1(arrIdx, tree->getArcSize(saId));
289 }
290
291 SuperArc *arc = tree->getSuperArc(saId);
292
293 float downPoints[3];
294 const SimplexId downNodeId = tree->getLowerNodeId(arc);
295 const SimplexId downVertexId
296 = tree->getNode(downNodeId)->getVertexId();
297 triangulation->getVertexPoint(
298 downVertexId, downPoints[0], downPoints[1], downPoints[2]);
299
300 float upPoints[3];
301 const SimplexId upNodeId = tree->getUpperNodeId(arc);
302 const SimplexId upVertexId = tree->getNode(upNodeId)->getVertexId();
303 triangulation->getVertexPoint(
304 upVertexId, upPoints[0], upPoints[1], upPoints[2]);
305
306 regionSpan->SetTuple1(
307 arrIdx, Geometry::distance(downPoints, upPoints));
308 }
309 }
310
311 inline void addArray(vtkPointData *pointData, Params params) {
312 pointData->AddArray(ids);
313 pointData->AddArray(scalars);
314 pointData->AddArray(vertIds);
315 pointData->SetScalars(type);
316 if(params.advStats) {
317 if(params.segm) {
318 pointData->AddArray(regionSize);
319 }
320 pointData->AddArray(regionSpan);
321 }
322 }
323
324 private:
325 idSuperArc getAdjSa(const Node *node) {
326 if(node->getNumberOfDownSuperArcs() == 1) {
327 return node->getDownSuperArcId(0);
328 }
329
330 if(node->getNumberOfUpSuperArcs() == 1) {
331 return node->getUpSuperArcId(0);
332 }
333
334 // Degenerate case, arbitrary choice
335 if(node->getNumberOfDownSuperArcs()) {
336 return node->getDownSuperArcId(0);
337 }
338
339 if(node->getNumberOfDownSuperArcs()) {
340 return node->getDownSuperArcId(0);
341 }
342
343 // Empty node
344#ifndef TTK_ENABLE_KAMIKAZE
345 std::cerr << "[ttkMergeTree]: node without arcs:" << node->getVertexId()
346 << std::endl;
347#endif
348 return nullSuperArc;
349 }
350 };
351
352 struct VertData : public WrapperData {
357
358 inline int init(std::vector<LocalFTM> &ftmTrees, Params params) {
359 if(!params.segm)
360 return 0;
361
362 SimplexId numberOfVertices = 0;
363
364 for(auto &t : ftmTrees) {
365 FTMTree_MT *tree = t.tree.getTree(params.treeType);
366 numberOfVertices += tree->getNumberOfVertices();
367 }
368
369 ids = initArray<ttkSimplexIdTypeArray>(
370 "SegmentationId", numberOfVertices);
371 typeRegion = initArray<vtkCharArray>("RegionType", numberOfVertices);
372
373 if(params.advStats) {
375 = initArray<ttkSimplexIdTypeArray>("RegionSize", numberOfVertices);
377 = initArray<vtkDoubleArray>("RegionSpan", numberOfVertices);
378 }
379
380 return 0;
381 }
382
383 void fillArrayPoint(const idSuperArc arcId,
384 LocalFTM &l_tree,
385 Triangulation *triangulation,
386 vtkDataArray *idMapper,
387 Params params) {
388 if(!params.segm)
389 return;
390
391 FTMTree_MT *tree = l_tree.tree.getTree(params.treeType);
392 const idNode idOffset = l_tree.offset;
393 SuperArc *arc = tree->getSuperArc(arcId);
394
395 const idNode upNodeId = arc->getUpNodeId();
396 const Node *upNode = tree->getNode(upNodeId);
397 const SimplexId l_upVertexId = upNode->getVertexId();
398 const SimplexId g_upVertexId = idMapper->GetTuple1(l_upVertexId);
399 const CriticalType upNodeType = getNodeType(*tree, upNodeId, params);
400 float coordUp[3];
401 triangulation->getVertexPoint(
402 l_upVertexId, coordUp[0], coordUp[1], coordUp[2]);
403
404 const idNode downNodeId = arc->getDownNodeId();
405 const Node *downNode = tree->getNode(downNodeId);
406 const SimplexId l_downVertexId = downNode->getVertexId();
407 const SimplexId g_downVertexId = idMapper->GetTuple1(l_downVertexId);
408 const CriticalType downNodeType
409 = getNodeType(*tree, downNodeId, params);
410 float coordDown[3];
411 triangulation->getVertexPoint(
412 l_downVertexId, coordDown[0], coordDown[1], coordDown[2]);
413
414 const SimplexId regionSize
415 = tree->getSuperArc(arcId)->getNumberOfRegularNodes();
416 const double regionSpan = Geometry::distance(coordUp, coordDown);
417
418 idSuperArc const nid = arc->getNormalizedId();
419
420 ArcType regionType;
421 // RegionType
422 if((upNodeType == CriticalType::Local_minimum
423 && downNodeType == CriticalType::Local_maximum)
424 || (upNodeType == CriticalType::Local_minimum
425 || downNodeType == CriticalType::Local_minimum)) {
426 regionType = ArcType::Min_arc;
427 } else if(upNodeType == CriticalType::Local_maximum
428 || downNodeType == CriticalType::Local_maximum) {
429 regionType = ArcType::Max_arc;
430 } else if(upNodeType == CriticalType::Saddle1
431 && downNodeType == CriticalType::Saddle1) {
432 regionType = ArcType::Saddle1_arc;
433 } else if(upNodeType == CriticalType::Saddle2
434 && downNodeType == CriticalType::Saddle2) {
435 regionType = ArcType::Saddle2_arc;
436 } else {
437 regionType = ArcType::Saddle1_saddle2_arc;
438 }
439
440 // fill extrema and regular verts of this arc
441
442 // critical points
443 if(params.normalize) {
444 ids->SetTuple1(g_upVertexId, idOffset + nid);
445 ids->SetTuple1(g_downVertexId, idOffset + nid);
446 } else {
447 ids->SetTuple1(g_upVertexId, idOffset + arcId);
448 ids->SetTuple1(g_downVertexId, idOffset + arcId);
449 }
450
451 if(params.advStats) {
452 sizeRegion->SetTuple1(g_upVertexId, regionSize);
453 sizeRegion->SetTuple1(g_downVertexId, regionSize);
454 spanRegion->SetTuple1(g_upVertexId, regionSpan);
455 spanRegion->SetTuple1(g_downVertexId, regionSpan);
456 }
457 typeRegion->SetTuple1(g_upVertexId, static_cast<char>(regionType));
458 typeRegion->SetTuple1(g_downVertexId, static_cast<char>(regionType));
459
460 // regular nodes
461 for(const SimplexId l_vertexId : *arc) {
462 const SimplexId g_vertexId = idMapper->GetTuple1(l_vertexId);
463 if(params.normalize) {
464 ids->SetTuple1(g_vertexId, idOffset + nid);
465 } else {
466 ids->SetTuple1(g_vertexId, idOffset + arcId);
467 }
468 if(params.advStats) {
469 sizeRegion->SetTuple1(g_vertexId, regionSize);
470 spanRegion->SetTuple1(g_vertexId, regionSpan);
471 }
472 typeRegion->SetTuple1(g_vertexId, static_cast<char>(regionType));
473 }
474 }
475
476 void addArray(vtkPointData *pointData, Params params) {
477 if(!params.segm)
478 return;
479
480 pointData->AddArray(ids);
481 pointData->SetActiveScalars(ids->GetName());
482
483 if(params.advStats) {
484 pointData->AddArray(sizeRegion);
485 pointData->AddArray(spanRegion);
486 }
487 pointData->AddArray(typeRegion);
488 }
489 };
490 }; // namespace ftm
491}; // namespace ttk
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
int getVertexPoint(const SimplexId &vertexId, float &x, float &y, float &z) const override
FTMTree_MT * getTree(const TreeType tt)
Definition FTMTree_CT.h:55
const scalarType & getValue(SimplexId nodeId) const
Definition FTMTree_MT.h:339
SuperArc * getSuperArc(idSuperArc i)
Definition FTMTree_MT.h:367
idNode getNumberOfNodes() const
Definition FTMTree_MT.h:389
idNode getLowerNodeId(const SuperArc *a)
SimplexId getNumberOfVertices() const
Definition FTMTree_MT.h:429
idSuperArc getNumberOfSuperArcs() const
Definition FTMTree_MT.h:363
idNode getUpperNodeId(const SuperArc *a)
Node * getNode(idNode nodeId)
Definition FTMTree_MT.h:393
SimplexId getArcSize(const idSuperArc arcId)
Definition FTMTree_MT.h:285
TTK processing package that efficiently computes the contour tree of scalar data and more (data segme...
Definition FTMTree.h:53
idSuperArc getUpSuperArcId(idSuperArc neighborId) const
Definition FTMNode.h:105
idSuperArc getNumberOfDownSuperArcs() const
Definition FTMNode.h:82
idSuperArc getDownSuperArcId(idSuperArc neighborId) const
Definition FTMNode.h:94
SimplexId getVertexId() const
Definition FTMNode.h:54
idSuperArc getNumberOfUpSuperArcs() const
Definition FTMNode.h:86
SimplexId getNumberOfRegularNodes() const
idNode getUpNodeId() const
Definition FTMSuperArc.h:68
idNode getDownNodeId() const
Definition FTMSuperArc.h:72
idSuperArc getNormalizedId() const
T distance(const T *p0, const T *p1, const int &dimension=3)
Definition Geometry.cpp:362
long unsigned int idSuperArc
SuperArc index in vect_superArcs_.
unsigned int idNode
Node index in vect_nodes_.
The Topology ToolKit.
CriticalType
default value for critical index
Definition DataTypes.h:80
const char MaskScalarFieldName[]
default name for mask scalar field
Definition DataTypes.h:32
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
void fillArrayCell(const SimplexId pos, const idSuperArc arcId, LocalFTM &ftmTree, Triangulation *triangulation, Params params)
void addPoint(const SimplexId globalId, const SimplexId id, const float scalar, const bool reg)
int init(std::vector< LocalFTM > &ftmTree, Params params)
vtkSmartPointer< vtkFloatArray > point_scalar
vtkSmartPointer< vtkDoubleArray > cell_spanArcs
bool hasPoint(const SimplexId vertId)
vtkSmartPointer< ttkSimplexIdTypeArray > cell_downNode
vtkSmartPointer< ttkSimplexIdTypeArray > cell_sizeArcs
std::vector< SimplexId > point_ids
vtkSmartPointer< ttkSimplexIdTypeArray > cell_upNode
void addArray(vtkUnstructuredGrid *skeletonArcs, Params params)
vtkSmartPointer< ttkSimplexIdTypeArray > cell_ids
void setPoint(const SimplexId id, const float scalar, const bool reg)
vtkSmartPointer< vtkCharArray > point_regularMask
vtkSmartPointer< ttkSimplexIdTypeArray > regionSize
vtkSmartPointer< ttkSimplexIdTypeArray > regionSpan
int init(std::vector< LocalFTM > &ftmTree, Params params)
void fillArrayPoint(SimplexId arrIdx, const idNode nodeId, LocalFTM &ftmTree, vtkDataArray *idMapper, Triangulation *triangulation, Params params)
vtkSmartPointer< ttkSimplexIdTypeArray > ids
void addArray(vtkPointData *pointData, Params params)
vtkSmartPointer< vtkIntArray > type
vtkSmartPointer< vtkFloatArray > scalars
void setScalarType(const int s)
vtkSmartPointer< ttkSimplexIdTypeArray > vertIds
void addArray(vtkPointData *pointData, Params params)
void fillArrayPoint(const idSuperArc arcId, LocalFTM &l_tree, Triangulation *triangulation, vtkDataArray *idMapper, Params params)
int init(std::vector< LocalFTM > &ftmTrees, Params params)
vtkSmartPointer< vtkCharArray > typeRegion
vtkSmartPointer< ttkSimplexIdTypeArray > ids
vtkSmartPointer< vtkDoubleArray > spanRegion
vtkSmartPointer< ttkSimplexIdTypeArray > sizeRegion
vtkSmartPointer< vtkArrayType > initArray(const char *fieldName, size_t nbElmnt)
static CriticalType getNodeType(FTMTree_MT &tree, const idNode nodeId, Params params)