216 vtkNew<vtkAppendPolyData> app{};
218 vtkDoubleArray *scalars{};
220 vtkIntArray *typeScalars{};
222 vtkDoubleArray *spanScalars{};
223 int const type =
static_cast<int>(TreeComponent::Arc);
226 vector<double> point2(3);
228 vector<vector<double>> skeletonScalars{};
246 upVertex, coordUp[0], coordUp[1], coordUp[2]);
252 downVertex, coordDown[0], coordDown[1], coordDown[2]);
256 regionId = currentZone++;
259 if(barycenters_[
static_cast<int>(treeType_)][i].size()) {
262 if(treeType_ == TreeType::Split)
268 downNodeVId, point1[0], point1[1], point1[2]);
271 line->SetPoint1(point1);
273 const auto nbBarycenter
274 = barycenters_[
static_cast<int>(treeType_)][i].size();
275 for(
unsigned int j = 0; j < nbBarycenter; ++j) {
276 point2 = barycenters_[
static_cast<int>(treeType_)][i][j];
277 line->SetPoint2(point2.data());
281 vtkPolyData *lineData = line->GetOutput();
285 inputScalar = skeletonScalars[i][j];
287 scalars = vtkDoubleArray::New();
288 scalars->SetName(vtkInputScalars_->GetName());
289 for(
unsigned int k = 0; k < 2; ++k)
290 scalars->InsertTuple1(k, inputScalar);
291 lineData->GetPointData()->AddArray(scalars);
297 identifierScalars = ttkSimplexIdTypeArray::New();
298 identifierScalars->SetName(
"SegmentationId");
299 for(
unsigned int k = 0; k < 2; ++k)
300 identifierScalars->InsertTuple1(k, regionId);
301 lineData->GetCellData()->AddArray(identifierScalars);
302 identifierScalars->Delete();
304 typeScalars = vtkIntArray::New();
305 typeScalars->SetName(
"Type");
306 for(
unsigned int k = 0; k < 2; ++k)
307 typeScalars->InsertTuple1(k, type);
308 lineData->GetCellData()->AddArray(typeScalars);
309 typeScalars->Delete();
311 sizeScalars = ttkSimplexIdTypeArray::New();
312 sizeScalars->SetName(
"RegionSize");
313 for(
unsigned int k = 0; k < 2; ++k)
314 sizeScalars->InsertTuple1(k, regionSize);
315 lineData->GetCellData()->AddArray(sizeScalars);
316 sizeScalars->Delete();
318 spanScalars = vtkDoubleArray::New();
319 spanScalars->SetName(
"RegionSpan");
320 for(
unsigned int k = 0; k < 2; ++k)
321 spanScalars->InsertTuple1(k, regionSpan);
322 lineData->GetCellData()->AddArray(spanScalars);
323 spanScalars->Delete();
325 app->AddInputData(lineData);
329 line->SetPoint1(point2.data());
334 if(treeType_ == TreeType::Split)
339 std::array<float, 3> pt{};
344 line->SetPoint2(point2.data());
348 vtkPolyData *lineData = line->GetOutput();
353 = skeletonScalars[i][barycenters_[
static_cast<int>(treeType_)][i]
356 scalars = vtkDoubleArray::New();
357 scalars->SetName(vtkInputScalars_->GetName());
358 for(
unsigned int k = 0; k < 2; ++k)
359 scalars->InsertTuple1(k, inputScalar);
360 lineData->GetPointData()->AddArray(scalars);
366 identifierScalars = ttkSimplexIdTypeArray::New();
367 identifierScalars->SetName(
"SegmentationId");
368 for(
unsigned int k = 0; k < 2; ++k)
369 identifierScalars->InsertTuple1(k, regionId);
370 lineData->GetCellData()->AddArray(identifierScalars);
371 identifierScalars->Delete();
373 typeScalars = vtkIntArray::New();
374 typeScalars->SetName(
"Type");
375 for(
unsigned int k = 0; k < 2; ++k)
376 typeScalars->InsertTuple1(k, type);
377 lineData->GetCellData()->AddArray(typeScalars);
378 typeScalars->Delete();
380 sizeScalars = ttkSimplexIdTypeArray::New();
381 sizeScalars->SetName(
"RegionSize");
382 for(
unsigned int k = 0; k < 2; ++k)
383 sizeScalars->InsertTuple1(k, regionSize);
384 lineData->GetCellData()->AddArray(sizeScalars);
385 sizeScalars->Delete();
387 spanScalars = vtkDoubleArray::New();
388 spanScalars->SetName(
"RegionSpan");
389 for(
unsigned int k = 0; k < 2; ++k)
390 spanScalars->InsertTuple1(k, regionSpan);
391 lineData->GetCellData()->AddArray(spanScalars);
392 spanScalars->Delete();
394 app->AddInputData(lineData);
397 vtkNew<vtkLineSource> line{};
402 downNodeVId, point1[0], point1[1], point1[2]);
403 line->SetPoint1(point1);
407 std::array<float, 3> pt{};
412 line->SetPoint2(point2.data());
416 vtkPolyData *lineData = line->GetOutput();
420 inputScalar = skeletonScalars[i][0];
422 scalars = vtkDoubleArray::New();
423 scalars->SetName(vtkInputScalars_->GetName());
424 for(
unsigned int k = 0; k < 2; ++k)
425 scalars->InsertTuple1(k, inputScalar);
426 lineData->GetPointData()->AddArray(scalars);
432 identifierScalars = ttkSimplexIdTypeArray::New();
433 identifierScalars->SetName(
"SegmentationId");
434 for(
int k = 0; k < 2; ++k)
435 identifierScalars->InsertTuple1(k, regionId);
436 lineData->GetCellData()->AddArray(identifierScalars);
437 identifierScalars->Delete();
439 typeScalars = vtkIntArray::New();
440 typeScalars->SetName(
"Type");
441 for(
unsigned int k = 0; k < 2; ++k)
442 typeScalars->InsertTuple1(k, type);
443 lineData->GetCellData()->AddArray(typeScalars);
444 typeScalars->Delete();
446 sizeScalars = ttkSimplexIdTypeArray::New();
447 sizeScalars->SetName(
"RegionSize");
448 for(
unsigned int k = 0; k < 2; ++k)
449 sizeScalars->InsertTuple1(k, regionSize);
450 lineData->GetCellData()->AddArray(sizeScalars);
451 sizeScalars->Delete();
453 spanScalars = vtkDoubleArray::New();
454 spanScalars->SetName(
"RegionSpan");
455 for(
unsigned int k = 0; k < 2; ++k)
456 spanScalars->InsertTuple1(k, regionSpan);
457 lineData->GetCellData()->AddArray(spanScalars);
458 spanScalars->Delete();
460 app->AddInputData(lineData);
471 skeletonArcs_->ShallowCopy(app->GetOutput());
548 vtkNew<vtkPoints> points{};
552 vtkNew<vtkDoubleArray> scalars{};
553 scalars->SetName(vtkInputScalars_->GetName());
555 vtkNew<ttkSimplexIdTypeArray> nodeIdentifierScalars{};
556 nodeIdentifierScalars->SetName(
"NodeIdentifier");
558 vtkNew<ttkSimplexIdTypeArray> vertexIdentifierScalars{};
562 vtkNew<vtkIntArray> nodeTypeScalars{};
563 nodeTypeScalars->SetName(
"CriticalType");
565 vtkNew<ttkSimplexIdTypeArray> regionSizeScalars{};
566 regionSizeScalars->SetName(
"RegionSize");
569 for(
unsigned i = 0; i < criticalPoints_.size(); ++i) {
570 SimplexId const nodeId = criticalPoints_[i];
576 if((nodeType == CriticalType::Local_minimum and showMin_)
577 or (nodeType == CriticalType::Local_maximum and showMax_)
578 or (nodeType == CriticalType::Saddle1 and showSaddle1_)
579 or (nodeType == CriticalType::Saddle2 and showSaddle2_)
580 or ((showSaddle1_ and showSaddle2_)
581 and (nodeType == CriticalType::Regular
582 or nodeType == CriticalType::Degenerate))) {
584 triangulation_->
getVertexPoint(vertexId, point[0], point[1], point[2]);
585 points->InsertPoint(identifier, point);
588 scalar = vertexScalars_[vertexId];
589 scalars->InsertTuple1(identifier, scalar);
592 nodeIdentifierScalars->InsertTuple1(identifier, nodeId);
595 vertexIdentifierScalars->InsertTuple1(identifier, vertexId);
598 type =
static_cast<int>(nodeType);
599 nodeTypeScalars->InsertTuple1(identifier, type);
603 if(nodeType == CriticalType::Local_maximum) {
605 regionSize = tree_->
getSuperArc(arcId)->getNumberOfRegularNodes() + 1;
606 }
else if(nodeType == CriticalType::Local_minimum) {
608 regionSize = tree_->
getSuperArc(arcId)->getNumberOfRegularNodes() + 1;
610 regionSizeScalars->InsertTuple1(identifier, regionSize);
615 skeletonNodes_->SetPoints(points);
616 skeletonNodes_->GetPointData()->AddArray(scalars);
617 skeletonNodes_->GetPointData()->AddArray(nodeIdentifierScalars);
618 skeletonNodes_->GetPointData()->AddArray(vertexIdentifierScalars);
619 skeletonNodes_->GetPointData()->AddArray(nodeTypeScalars);
620 skeletonNodes_->GetPointData()->AddArray(regionSizeScalars);
826 int const N = barycenters_[
static_cast<int>(treeType_)][idArc].size();
829 vector<vector<double>> barycenterList(N);
830 for(
unsigned int i = 0; i < barycenterList.size(); ++i)
831 barycenterList[i].resize(3);
847 std::array<float, 3> p0{};
848 std::array<float, 3> p1{};
855 for(
unsigned int k = 0; k < 3; ++k)
857 = (p0[k] + barycenters_[
static_cast<int>(treeType_)][idArc][1][k])
861 for(
int i = 1; i < N - 1; ++i) {
862 for(
unsigned int k = 0; k < 3; ++k)
864 = (barycenters_[
static_cast<int>(treeType_)][idArc][i - 1][k]
865 + barycenters_[
static_cast<int>(treeType_)][idArc][i + 1][k])
869 for(
unsigned int k = 0; k < 3; ++k)
870 barycenterList[N - 1][k]
871 = (p1[k] + barycenters_[
static_cast<int>(treeType_)][idArc][N - 1][k])
874 for(
unsigned int k = 0; k < 3; ++k)
875 barycenterList[0][k] = (p0[k] + p1[k]) * 0.5;
879 for(
int i = 0; i < N; ++i) {
880 for(
unsigned int k = 0; k < 3; ++k)
881 barycenters_[
static_cast<int>(treeType_)][idArc][i][k]
882 = barycenterList[i][k];
919 vtkNew<ttkSimplexIdTypeArray> scalarsRegionId{};
920 scalarsRegionId->SetName(
"SegmentationId");
921 scalarsRegionId->SetNumberOfTuples(vertexScalars_.size());
924 vtkNew<vtkIntArray> scalarsRegionType{};
925 scalarsRegionType->SetName(
"RegionType");
926 scalarsRegionType->SetNumberOfTuples(vertexScalars_.size());
929 vtkNew<ttkSimplexIdTypeArray> scalarsRegionSize{};
930 scalarsRegionSize->SetName(
"RegionSize");
931 scalarsRegionSize->SetNumberOfTuples(vertexScalars_.size());
934 vtkNew<vtkDoubleArray> scalarsRegionSpan{};
935 scalarsRegionSpan->SetName(
"RegionSpan");
936 scalarsRegionSpan->SetNumberOfTuples(vertexScalars_.size());
941 segmentation_ = input->NewInstance();
942 segmentation_->ShallowCopy(input);
945 for(
SimplexId i = 0; i < numberOfVertices_; i++) {
946 scalarsRegionId->SetTuple1(i, -1);
951 SimplexId const nodeId = criticalPoints_[it];
956 scalarsRegionType->SetTuple1(vertexId, regionType);
968 upVertex, coordUp[0], coordUp[1], coordUp[2]);
975 downVertex, coordDown[0], coordDown[1], coordDown[2]);
979 regionId = currentZone++;
992 scalarsRegionId->SetTuple1(
994 scalarsRegionId->SetTuple1(
997 scalarsRegionSize->SetTuple1(
999 scalarsRegionSize->SetTuple1(
1002 scalarsRegionSpan->SetTuple1(
1004 scalarsRegionSpan->SetTuple1(
1018 scalarsRegionId->SetTuple1(vertexId, regionId);
1019 scalarsRegionSize->SetTuple1(vertexId, regionSize);
1020 scalarsRegionSpan->SetTuple1(vertexId, regionSpan);
1025 if((upNodeType == CriticalType::Local_minimum
1026 && downNodeType == CriticalType::Local_maximum)
1027 || (upNodeType == CriticalType::Local_minimum
1028 || downNodeType == CriticalType::Local_minimum))
1029 regionType =
static_cast<int>(ArcType::Min_arc);
1030 else if(upNodeType == CriticalType::Local_maximum
1031 || downNodeType == CriticalType::Local_maximum)
1032 regionType =
static_cast<int>(ArcType::Max_arc);
1033 else if(upNodeType == CriticalType::Saddle1
1034 && downNodeType == CriticalType::Saddle1)
1035 regionType =
static_cast<int>(ArcType::Saddle1_arc);
1036 else if(upNodeType == CriticalType::Saddle2
1037 && downNodeType == CriticalType::Saddle2)
1038 regionType =
static_cast<int>(ArcType::Saddle2_arc);
1040 regionType =
static_cast<int>(ArcType::Saddle1_saddle2_arc);
1050 scalarsRegionType->SetTuple1(vertexId, regionType);
1056 segmentation_->GetPointData()->AddArray(scalarsRegionId);
1057 segmentation_->GetPointData()->AddArray(scalarsRegionType);
1058 segmentation_->GetPointData()->AddArray(scalarsRegionSize);
1059 segmentation_->GetPointData()->AddArray(scalarsRegionSpan);
1062 this->threadNumber_);
1063 this->
printMsg(std::vector<std::vector<std::string>>{
1064 {
"Region type", std::to_string(scalarsRegionType->GetNumberOfTuples())},
1065 {
"Segmentation Id", std::to_string(scalarsRegionId->GetNumberOfTuples())}});
1067 toComputeSegmentation_ =
false;
1118 vtkInformationVector **inputVector,
1119 vtkInformationVector *outputVector) {
1121 "DEPRECATED This plugin will be removed in a future release, please use "
1122 "FTM instead for contour trees and FTR for Reeb graphs.");
1124 const auto input = vtkDataSet::GetData(inputVector[0]);
1125 auto outputSkeletonNodes = vtkPolyData::GetData(outputVector, 0);
1126 auto outputSkeletonArcs = vtkPolyData::GetData(outputVector, 1);
1127 auto outputSegmentation = vtkDataSet::GetData(outputVector, 2);
1129#ifndef TTK_ENABLE_KAMIKAZE
1131 this->
printErr(
"Input pointer is NULL.");
1135 if(!outputSkeletonNodes || !outputSkeletonArcs || !outputSegmentation) {
1136 this->
printErr(
"Output pointer is NULL.");
1140 if(!input->GetNumberOfPoints()) {
1141 this->
printErr(
"Input has no point.");
1148#ifndef TTK_ENABLE_KAMIKAZE
1149 if(!triangulation_) {
1150 this->
printErr(
"Input triangulation is NULL.");
1155 varyingMesh_ =
false;
1157 varyingMesh_ =
true;
1160 if(varyingMesh_ || !numberOfVertices_) {
1161 numberOfVertices_ = input->GetNumberOfPoints();
1165 segmentation_ = input->NewInstance();
1166 if(segmentation_ !=
nullptr) {
1167 segmentation_->ShallowCopy(input);
1171#ifndef TTK_ENABLE_KAMIKAZE
1172 if(!input->GetPointData()) {
1173 this->
printErr(
"Input has no point data.");
1179 vtkInputScalars_ = this->GetInputArrayToProcess(0, input);
1181#ifndef TTK_ENABLE_KAMIKAZE
1182 if(!vtkInputScalars_) {
1183 this->
printErr(
"Input scalar is NULL.");
1188 varyingDataValues_ = (vtkInputScalars_->GetMTime() > GetMTime());
1189 if(input->GetPointData()) {
1191 vertexScalars_.resize(numberOfVertices_);
1192 for(
SimplexId j = 0; j < numberOfVertices_; ++j) {
1193 vertexScalars_[j] = vtkInputScalars_->GetTuple1(j);
1198 = std::minmax_element(vertexScalars_.begin(), vertexScalars_.end());
1199 double const scalarMin = *result.first;
1200 double const scalarMax = *result.second;
1201 deltaScalar_ = (scalarMax - scalarMin);
1204 if(varyingMesh_ || varyingDataValues_ || vertexSoSoffsets_ ==
nullptr) {
1207 input, 0, triangulation_,
false, 1, ForceInputOffsetScalarField);
1209 if(offsets !=
nullptr) {
1214 toUpdateVertexSoSoffsets_ =
false;
1217 if(varyingMesh_ || varyingDataValues_ || !isLoaded_) {
1218 this->
printMsg(
"Convenient data storage loaded", debug::Priority::DETAIL);
1220 std::vector<std::vector<std::string>>{
1221 {
"#Tuples", std::to_string(vertexScalars_.size())},
1222 {
"#Vertices", std::to_string(numberOfVertices_)},
1223 {
"Min", std::to_string(scalarMin)},
1224 {
"Max", std::to_string(scalarMax)},
1226 debug::Priority::DETAIL);
1229 this->
printMsg(
"Launching computation for field `"
1230 + std::string{vtkInputScalars_->GetName()} +
"'...");
1234 if(simplificationType_ == 0) {
1235 simplificationThreshold_ = simplificationThresholdBuffer_ * deltaScalar_;
1236 }
else if(simplificationType_ == 1) {
1237 double coord0[3], coord1[3], spanTotal;
1238 double *bounds = input->GetBounds();
1239 coord0[0] = bounds[0];
1240 coord1[0] = bounds[1];
1241 coord0[1] = bounds[2];
1242 coord1[1] = bounds[3];
1243 coord0[2] = bounds[4];
1244 coord1[2] = bounds[5];
1246 simplificationThreshold_ = simplificationThresholdBuffer_ * spanTotal;
1247 }
else if(simplificationType_ == 2) {
1248 simplificationThreshold_
1253 if(varyingMesh_ || varyingDataValues_ || toComputeContourTree_) {
1260 if(varyingMesh_ || varyingDataValues_ || toComputeSkeleton_) {
1261#ifndef TTK_ENABLE_KAMIKAZE
1262 if(tree_ ==
nullptr) {
1263 this->
printErr(
"MergeTree pointer is NULL.");
1272 if(varyingMesh_ || varyingDataValues_ || toComputeSegmentation_)
1278 outputSkeletonNodes->ShallowCopy(skeletonNodes_);
1279 outputSkeletonArcs->ShallowCopy(skeletonArcs_);
1281 outputSegmentation->ShallowCopy(segmentation_);