TTK
Loading...
Searching...
No Matches
ttkDelaunayRipsPersistenceGenerators.cpp
Go to the documentation of this file.
4
5#include <vtkCellData.h>
6#include <vtkDoubleArray.h>
7#include <vtkInformation.h>
8#include <vtkInformationVector.h>
9#include <vtkPointData.h>
10#include <vtkTable.h>
11
12#include <regex>
13
15
16using namespace ttk::rpd;
17
18static void MakeVtkPoints(vtkPoints *vtkPoints,
19 const std::vector<std::vector<double>> &pointsData) {
20
21 const int dimension = pointsData[0].size();
22 vtkPoints->SetNumberOfPoints(pointsData.size());
23
24 for(unsigned i = 0; i < pointsData.size(); ++i) {
25 if(dimension >= 3)
26 vtkPoints->SetPoint(
27 i, pointsData[i][0], pointsData[i][1], pointsData[i][2]);
28 else
29 vtkPoints->SetPoint(i, pointsData[i][0], pointsData[i][1], 0.);
30 }
31}
32
33void GeneratorsToVTU(vtkUnstructuredGrid *vtu,
34 vtkPoints *inputPoints,
35 const std::vector<Generator2> &generators) {
36 const auto cd = vtu->GetCellData();
37
38 int n_triangles = 0;
39 for(auto const &g : generators)
40 n_triangles += g.first.size();
41
42 // cell data arrays
43 vtkNew<vtkIntArray> triangleId{};
44 triangleId->SetName("TriangleIdentifier");
45 triangleId->SetNumberOfTuples(n_triangles);
46 cd->AddArray(triangleId);
47
48 vtkNew<vtkIntArray> classId{};
49 classId->SetName("ClassIdentifier");
50 classId->SetNumberOfTuples(n_triangles);
51 cd->AddArray(classId);
52
53 vtkNew<vtkDoubleArray> classBirth{};
54 classBirth->SetName("ClassBirth");
55 classBirth->SetNumberOfTuples(n_triangles);
56 cd->AddArray(classBirth);
57
58 vtkNew<vtkDoubleArray> classDeath{};
59 classDeath->SetName("ClassDeath");
60 classDeath->SetNumberOfTuples(n_triangles);
61 cd->AddArray(classDeath);
62
63 vtkNew<vtkDoubleArray> classPersistence{};
64 classPersistence->SetName("ClassPersistence");
65 classPersistence->SetNumberOfTuples(n_triangles);
66 cd->AddArray(classPersistence);
67
68 vtkNew<vtkIntArray> classDimension{};
69 classDimension->SetName("ClassDimension");
70 classDimension->SetNumberOfTuples(n_triangles);
71 cd->AddArray(classDimension);
72
73 // grid
74 vtkNew<vtkIdTypeArray> offsets{}, connectivity{};
75 offsets->SetNumberOfComponents(1);
76 offsets->SetNumberOfTuples(n_triangles + 1);
77 connectivity->SetNumberOfComponents(1);
78 connectivity->SetNumberOfTuples(3 * n_triangles);
79
80 unsigned i = 0;
81 for(unsigned j = 0; j < generators.size(); ++j) {
82 const Generator2 &g = generators[j];
83 for(auto const &t : g.first) {
84 const unsigned i0 = 3 * i, i1 = 3 * i + 1, i2 = 3 * i + 2;
85 triangleId->SetTuple1(i, i);
86 classId->SetTuple1(i, j);
87 classBirth->SetTuple1(i, g.second.first);
88 classDeath->SetTuple1(i, g.second.second);
89 classPersistence->SetTuple1(i, g.second.second - g.second.first);
90 classDimension->SetTuple1(i, 2);
91
92 connectivity->SetTuple1(i0, t[0]);
93 connectivity->SetTuple1(i1, t[1]);
94 connectivity->SetTuple1(i2, t[2]);
95 offsets->SetTuple1(i, 3 * i);
96
97 ++i;
98 }
99 }
100 offsets->SetTuple1(n_triangles, connectivity->GetNumberOfTuples());
101
102 vtkNew<vtkCellArray> cells{};
103 cells->SetData(offsets, connectivity);
104 vtu->SetPoints(inputPoints);
105 vtu->SetCells(VTK_TRIANGLE, cells);
106}
107
109 this->SetNumberOfInputPorts(1);
110 this->SetNumberOfOutputPorts(3);
111}
112
114 int port, vtkInformation *info) {
115 if(port == 0) {
116 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
117 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPointSet");
118 return 1;
119 }
120 return 0;
121}
122
124 int port, vtkInformation *info) {
125 if(port == 0 || port == 1 || port == 2) {
126 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid");
127 return 1;
128 }
129 return 0;
130}
131
133 vtkInformation *ttkNotUsed(request),
134 vtkInformationVector **inputVector,
135 vtkInformationVector *outputVector) {
136
137 ttk::Timer tm{};
138
139 vtkInformation *info = inputVector[0]->GetInformationObject(0);
140 vtkDataObject *input = info->Get(vtkDataObject::DATA_OBJECT());
141 vtkUnstructuredGrid *outputPersistenceDiagram
142 = vtkUnstructuredGrid::GetData(outputVector, 0);
143 vtkUnstructuredGrid *outputGenerators1
144 = vtkUnstructuredGrid::GetData(outputVector, 1);
145 vtkUnstructuredGrid *outputGenerators2
146 = vtkUnstructuredGrid::GetData(outputVector, 2);
147
148 if(!input)
149 return 0;
150
151 PointCloud points;
152 int numberOfPoints = 0;
153 int dimension = 0;
154
155 if(vtkTable *table = vtkTable::SafeDownCast(input)) {
156 if(SelectFieldsWithRegexp) {
157 // select all input columns whose name is matching the regexp
158 ScalarFields.clear();
159 const auto n = table->GetNumberOfColumns();
160 for(int i = 0; i < n; ++i) {
161 const auto &name = table->GetColumnName(i);
162 if(std::regex_match(name, std::regex(RegexpString))) {
163 ScalarFields.emplace_back(name);
164 }
165 }
166 }
167
168 if(table->GetNumberOfRows() <= 0 || ScalarFields.size() <= 1) {
169 this->printErr("Input matrix has invalid dimensions (rows: "
170 + std::to_string(table->GetNumberOfRows()) + ", columns: "
171 + std::to_string(ScalarFields.size()) + ")");
172 return 0;
173 }
174
175 std::vector<vtkAbstractArray *> arrays;
176 arrays.reserve(ScalarFields.size());
177 for(const auto &s : ScalarFields)
178 arrays.push_back(table->GetColumnByName(s.data()));
179
180 numberOfPoints = table->GetNumberOfRows();
181 dimension = ScalarFields.size();
182
183 points.resize(numberOfPoints);
184 for(int i = 0; i < numberOfPoints; ++i) {
185 for(int j = 0; j < dimension; ++j)
186 points[i].push_back(arrays[j]->GetVariantValue(i).ToDouble());
187 }
188 }
189
190 else if(vtkPointSet *pointset = vtkPointSet::SafeDownCast(input)) {
191 numberOfPoints = pointset->GetNumberOfPoints();
192 dimension = 3;
193 points.resize(numberOfPoints, std::vector<double>(3));
194 for(int i = 0; i < numberOfPoints; ++i)
195 pointset->GetPoint(i, points[i].data());
196 }
197
198 this->printMsg("Computing Delaunay-Rips persistence diagram", 1.0,
199 tm.getElapsedTime(), getThreadNumber());
200 this->printMsg("#dimensions: " + std::to_string(dimension)
201 + ", #points: " + std::to_string(numberOfPoints),
202 0.0, tm.getElapsedTime(), getThreadNumber());
203
205 std::vector<Generator1> generators1;
206 std::vector<Generator2> generators2;
207
208 if(this->execute(points, diagram, generators1, generators2) != 0)
209 return 0;
210
211 DiagramToVTU(outputPersistenceDiagram, diagram, inf);
212 const vtkNew<vtkPoints> vtkPoints{};
213 MakeVtkPoints(vtkPoints, points);
214 GeneratorsToVTU(outputGenerators1, vtkPoints, generators1, true);
215 GeneratorsToVTU(outputGenerators2, vtkPoints, generators2);
216
217 this->printMsg("Complete", 1.0, tm.getElapsedTime(), getThreadNumber());
218
219 // shallow copy input Field Data
220 outputPersistenceDiagram->GetFieldData()->ShallowCopy(input->GetFieldData());
221 outputGenerators1->GetFieldData()->ShallowCopy(input->GetFieldData());
222 outputGenerators2->GetFieldData()->ShallowCopy(input->GetFieldData());
223
224 // return success
225 return 1;
226}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
TTK VTK-filter that wraps the ttk::DelaunayRipsPersistenceGenerators module.
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int getThreadNumber() const
Definition BaseClass.h:76
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(const rpd::PointCloud &points, rpd::MultidimensionalDiagram &ph) const
Main entry point (without generators)
constexpr value_t inf
std::vector< std::vector< value_t > > PointCloud
std::vector< Diagram > MultidimensionalDiagram
std::pair< std::vector< Facet >, std::pair< value_t, value_t > > Generator2
vtkStandardNewMacro(ttkDelaunayRipsPersistenceGenerators)
void GeneratorsToVTU(vtkUnstructuredGrid *vtu, vtkPoints *inputPoints, const std::vector< Generator2 > &generators)
void GeneratorsToVTU(vtkUnstructuredGrid *vtu, vtkPoints *inputPoints, const std::vector< ttk::rpd::Generator2 > &generators)
int DiagramToVTU(vtkUnstructuredGrid *vtu, const ttk::DiagramType &diagram, vtkDataArray *const inputScalars, const ttk::Debug &dbg, const int dim, const bool embedInDomain)
Converts a Persistence Diagram in the ttk::DiagramType format to the VTK Unstructured Grid format (as...
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)