5#include <vtkDoubleArray.h>
6#include <vtkFloatArray.h>
7#include <vtkInformation.h>
8#include <vtkIntArray.h>
9#include <vtkMultiBlockDataSet.h>
10#include <vtkPointData.h>
11#include <vtkUnstructuredGrid.h>
16 SetNumberOfInputPorts(1);
17 SetNumberOfOutputPorts(2);
21 vtkInformation *info) {
23 info->Set(ttkAlgorithm::INPUT_REQUIRED_DATA_TYPE(),
"vtkMultiBlockDataSet");
30 vtkInformation *info) {
32 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkMultiBlockDataSet");
34 }
else if(port == 1) {
35 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkUnstructuredGrid");
41static int generateMatchings(vtkUnstructuredGrid *
const outputCT3,
44 const std::vector<ttk::MatchingType> &matchings,
45 const std::array<double, 3> &distances,
46 const double globalDist,
48 const bool isBottleneck,
52 vtkNew<vtkUnstructuredGrid> vtu{};
54 vtkNew<vtkPoints> points{};
55 points->SetNumberOfPoints(2 * matchings.size());
56 vtu->SetPoints(points);
58 vtkNew<vtkDoubleArray> costs{};
59 costs->SetName(
"Cost");
60 costs->SetNumberOfComponents(1);
61 costs->SetNumberOfTuples(matchings.size());
62 vtu->GetCellData()->AddArray(costs);
64 vtkNew<vtkIntArray> matchingIds{};
65 matchingIds->SetName(
"MatchingIdentifier");
66 matchingIds->SetNumberOfComponents(1);
67 matchingIds->SetNumberOfTuples(matchings.size());
68 vtu->GetCellData()->AddArray(matchingIds);
71 for(
size_t i = 0; i < matchings.size(); ++i) {
72 const auto &t = matchings[i];
73 const auto n1 = std::get<0>(t);
74 const auto n2 = std::get<1>(t);
76 const auto &pair0 = diagram1[n1];
77 const auto &pair1 = diagram2[n2];
80 const double zval) -> std::array<double, 3> {
89 const auto p0 = pairPoint(pair0, is2D0, -spacing / 2.0);
90 points->SetPoint(2 * i + 0, p0.data());
91 const auto p1 = pairPoint(pair1, is2D1, spacing / 2.0);
92 points->SetPoint(2 * i + 1, p1.data());
94 std::array<vtkIdType, 2> ids{
95 2 *
static_cast<vtkIdType
>(i) + 0,
96 2 *
static_cast<vtkIdType
>(i) + 1,
98 vtu->InsertNextCell(VTK_LINE, 2, ids.data());
100 costs->SetTuple1(i, std::get<2>(t));
101 matchingIds->SetTuple1(i, i);
105 vtkNew<vtkDoubleArray> minSad{};
106 minSad->SetName(
"MinSaddleCost");
107 minSad->SetNumberOfTuples(1);
108 minSad->SetTuple1(0, distances[0]);
110 vtkNew<vtkDoubleArray> sadSad{};
111 sadSad->SetName(
"SaddleSaddleCost");
112 sadSad->SetNumberOfTuples(1);
113 sadSad->SetTuple1(0, distances[1]);
115 vtkNew<vtkDoubleArray> sadMax{};
116 sadMax->SetName(
"SaddleMaxCost");
117 sadMax->SetNumberOfTuples(1);
118 sadMax->SetTuple1(0, distances[2]);
120 vtkNew<vtkDoubleArray> wass{};
121 wass->SetName(isBottleneck ?
"BottleneckDistance" :
"WassersteinDistance");
122 wass->SetNumberOfTuples(1);
123 wass->SetTuple1(0, globalDist);
125 vtu->GetFieldData()->AddArray(minSad);
126 vtu->GetFieldData()->AddArray(sadSad);
127 vtu->GetFieldData()->AddArray(sadMax);
128 vtu->GetFieldData()->AddArray(wass);
130 outputCT3->ShallowCopy(vtu);
136 vtkInformationVector **inputVector,
137 vtkInformationVector *outputVector) {
139 auto outputDiagrams = vtkMultiBlockDataSet::GetData(outputVector, 0);
140 auto outputMatchings = vtkUnstructuredGrid::GetData(outputVector, 1);
142 auto blocks = vtkMultiBlockDataSet::GetData(inputVector[0]);
143 std::vector<vtkUnstructuredGrid *> inputDiags{};
145 if(blocks ==
nullptr) {
146 this->
printErr(
"No input diagrams");
150 for(
size_t i = 0; i < blocks->GetNumberOfBlocks(); ++i) {
151 const auto diag = vtkUnstructuredGrid::SafeDownCast(blocks->GetBlock(i));
152 if(diag !=
nullptr) {
153 inputDiags.emplace_back(diag);
157 if(inputDiags.size() < 2) {
158 this->
printErr(
"Less than two input diagrams");
161 if(inputDiags.size() > 2) {
162 this->
printWrn(
"More than two input diagrams: "
163 + std::to_string(inputDiags.size()));
166 const auto coords0 = vtkFloatArray::SafeDownCast(
167 inputDiags[0]->GetPointData()->GetArray(
"Coordinates"));
168 const auto coords1 = vtkFloatArray::SafeDownCast(
169 inputDiags[1]->GetPointData()->GetArray(
"Coordinates"));
171 const bool is2D0 = coords0 !=
nullptr;
172 const bool is2D1 = coords1 !=
nullptr;
178 std::vector<ttk::MatchingType> matchings{};
182 this->
printErr(
"Could not extract diagram from first input data-set");
188 this->
printErr(
"Could not extract diagram from second input data-set");
193 status = this->
execute(diagram0, diagram1, matchings);
195 this->
printErr(
"Base layer failed with error status "
196 + std::to_string(status));
201 if(this->UseOutputMatching) {
202 status = generateMatchings(outputMatchings, diagram0, diagram1, matchings,
207 this->
printErr(
"Could not compute matchings");
213 vtkNew<vtkUnstructuredGrid> vtu0{}, vtu1{};
214 if(this->UseGeometricSpacing) {
215 vtu0->ShallowCopy(inputDiags[0]);
218 vtu1->ShallowCopy(inputDiags[1]);
222 vtu0->ShallowCopy(inputDiags[0]);
223 vtu1->ShallowCopy(inputDiags[1]);
229 this->
printErr(
"Could not augment diagrams");
234 outputDiagrams->SetNumberOfBlocks(2);
235 outputDiagrams->SetBlock(0, vtu0);
236 outputDiagrams->SetBlock(1, vtu1);
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
TTK VTK-filter that wraps the bottleneckDistance processing package.
int FillOutputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillInputPortInformation(int port, vtkInformation *info) override
int execute(const ttk::DiagramType &diag0, const ttk::DiagramType &diag1, std::vector< MatchingType > &matchings)
std::array< double, 3 > costs_
std::string WassersteinMetric
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
std::vector< PersistencePair > DiagramType
Persistence Diagram type as a vector of Persistence pairs.
std::array< float, 3 > coords
ttk::CriticalVertex birth
ttk::CriticalVertex death
int augmentDiagrams(const std::vector< ttk::MatchingType > &matchings, vtkUnstructuredGrid *const vtu0, vtkUnstructuredGrid *const vtu1)
vtkStandardNewMacro(ttkBottleneckDistance)
int TranslateDiagram(vtkUnstructuredGrid *const diagram, const std::array< double, 3 > &trans)
Translate a diagram to a new position.
int VTUToDiagram(ttk::DiagramType &diagram, vtkUnstructuredGrid *vtu, const ttk::Debug &dbg)
Converts a Persistence Diagram in the VTK Unstructured Grid format (as generated by the ttkPersistenc...
int ResetDiagramPosition(vtkUnstructuredGrid *const diagram, const ttk::Debug &dbg)
Translate back a canonical diagram into its original position.