TTK
Loading...
Searching...
No Matches
ttkBarycentricSubdivision.cpp
Go to the documentation of this file.
2#include <ttkMacros.h>
3#include <ttkUtils.h>
4
5#include <vtkCellData.h>
6#include <vtkInformation.h>
7#include <vtkPointData.h>
8#include <vtkUnstructuredGrid.h>
9
11
13 SetNumberOfInputPorts(1);
14 SetNumberOfOutputPorts(1);
15}
16
18 vtkInformation *info) {
19 if(port == 0) {
20 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
21 return 1;
22 }
23 return 0;
24}
25
27 vtkInformation *info) {
28 if(port == 0) {
29 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid");
30 return 1;
31 }
32 return 0;
33}
34
36 vtkDataArray *const inputScalarField, int ntuples) const {
37
39
40 // allocate the memory for the output scalar field
41 switch(inputScalarField->GetDataType()) {
42 case VTK_CHAR:
43 case VTK_DOUBLE:
44 case VTK_FLOAT:
45 case VTK_INT:
46 case VTK_ID_TYPE:
47 case VTK_LONG:
48 res = inputScalarField->NewInstance();
49 break;
50 default:
51 this->printErr("Unsupported data array type");
52 break;
53 }
54 res->SetNumberOfComponents(1);
55 res->SetNumberOfTuples(ntuples);
56 res->SetName(inputScalarField->GetName());
57 return res;
58}
59
61 vtkDataSet *const input,
62 vtkUnstructuredGrid *const output,
63 ttk::Triangulation &inputTriangulation) const {
64
65 const size_t npointdata = input->GetPointData()->GetNumberOfArrays();
66 const size_t ncelldata = input->GetCellData()->GetNumberOfArrays();
67
68 const auto outPointsNumber = this->getNumberOfVertices();
69
70 for(size_t i = 0; i < npointdata; ++i) {
71 auto inputScalarField = input->GetPointData()->GetArray(i);
72 if(inputScalarField == nullptr) {
73 return -2;
74 }
75
76#define DISPATCH_INTERPOLATE_DIS(CASE, TYPE) \
77 case CASE: \
78 this->interpolateDiscreteScalarField<TYPE>( \
79 static_cast<TYPE *>(ttkUtils::GetVoidPointer(inputScalarField)), \
80 static_cast<TYPE *>(ttkUtils::GetVoidPointer(outputScalarField))); \
81 break
82#define DISPATCH_INTERPOLATE_CONT(CASE, TYPE) \
83 case CASE: \
84 switch(inputTriangulation.getType()) { \
85 BARYSUBD_TRIANGL_CALLS( \
86 TYPE, ttk::Triangulation::Type::EXPLICIT, ttk::ExplicitTriangulation) \
87 BARYSUBD_TRIANGL_CALLS(TYPE, ttk::Triangulation::Type::IMPLICIT, \
88 ttk::ImplicitNoPreconditions) \
89 BARYSUBD_TRIANGL_CALLS(TYPE, ttk::Triangulation::Type::HYBRID_IMPLICIT, \
90 ttk::ImplicitWithPreconditions) \
91 BARYSUBD_TRIANGL_CALLS( \
92 TYPE, ttk::Triangulation::Type::COMPACT, ttk::CompactTriangulation) \
93 BARYSUBD_TRIANGL_CALLS(TYPE, ttk::Triangulation::Type::PERIODIC, \
94 ttk::PeriodicNoPreconditions) \
95 BARYSUBD_TRIANGL_CALLS(TYPE, ttk::Triangulation::Type::HYBRID_PERIODIC, \
96 ttk::PeriodicWithPreconditions) \
97 } \
98 break;
99#define BARYSUBD_TRIANGL_CALLS(DATATYPE, TRIANGL_CASE, TRIANGL_TYPE) \
100 case TRIANGL_CASE: { \
101 const auto inpTri \
102 = static_cast<TRIANGL_TYPE *>(inputTriangulation.getData()); \
103 if(inpTri != nullptr) { \
104 this->interpolateContinuousScalarField<DATATYPE, TRIANGL_TYPE>( \
105 static_cast<DATATYPE *>(ttkUtils::GetVoidPointer(inputScalarField)), \
106 static_cast<DATATYPE *>(ttkUtils::GetVoidPointer(outputScalarField)), \
107 *inpTri); \
108 } \
109 break; \
110 }
111
112 auto outputScalarField
113 = AllocateScalarField(inputScalarField, outPointsNumber);
114 if(outputScalarField == nullptr) {
115 return -3;
116 }
117
118 // only for scalar fields
119 switch(inputScalarField->GetDataType()) {
120 DISPATCH_INTERPOLATE_DIS(VTK_CHAR, char);
121 DISPATCH_INTERPOLATE_DIS(VTK_INT, int);
122 DISPATCH_INTERPOLATE_DIS(VTK_LONG, long);
123 DISPATCH_INTERPOLATE_DIS(VTK_ID_TYPE, vtkIdType);
124 DISPATCH_INTERPOLATE_CONT(VTK_FLOAT, float);
125 DISPATCH_INTERPOLATE_CONT(VTK_DOUBLE, double);
126 }
127 output->GetPointData()->AddArray(outputScalarField);
128 }
129
130 const auto outCellsNumber = this->getNumberOfTriangles();
131
132 for(size_t i = 0; i < ncelldata; ++i) {
133 auto inputScalarField = input->GetCellData()->GetArray(i);
134 if(inputScalarField == nullptr) {
135 return -2;
136 }
137
138 auto outputScalarField
139 = AllocateScalarField(inputScalarField, outCellsNumber);
140 if(outputScalarField == nullptr) {
141 return -3;
142 }
143
144 // only for scalar fields
145 switch(inputScalarField->GetDataType()) {
146 vtkTemplateMacro(this->interpolateCellDataField<VTK_TT>(
147 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(inputScalarField)),
148 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(outputScalarField))));
149 }
150 output->GetCellData()->AddArray(outputScalarField);
151 }
152
153 return 0;
154}
155
157 vtkInformationVector **inputVector,
158 vtkInformationVector *outputVector) {
159
160 ttk::Timer tm;
161
162 auto input = vtkDataSet::GetData(inputVector[0]);
163 auto output = vtkUnstructuredGrid::GetData(outputVector);
164
165 auto triangulation = ttkAlgorithm::GetTriangulation(input);
166 ttk::ExplicitTriangulation triangulationSubdivision{};
167
168 if(triangulation == nullptr) {
169 printMsg("Error, internal triangulation is empty.");
170 return 0;
171 }
172
173 // early return: copy input if no subdivision
174 if(SubdivisionLevel == 0) {
175 output->ShallowCopy(input);
176 return 0;
177 }
178
179 this->preconditionTriangulation(triangulation);
180
181 // first iteration: generate the new triangulation
182 int ret = this->execute(*triangulation, triangulationSubdivision);
183 if(ret != 0) {
184 this->printErr("Could not subdivide input mesh");
185 return 0;
186 }
187
188 // first iteration: interpolate input scalar fields
189 ret = InterpolateScalarFields(input, output, *triangulation);
190 if(ret != 0) {
191 this->printErr("Error interpolating input data array(s)");
192 return 0;
193 }
194
195 for(unsigned int i = 1; i < SubdivisionLevel; ++i) {
196 // move previous points to temp vector
197 decltype(points_) tmpPoints{};
198 std::swap(points_, tmpPoints);
199
200 // move previous triangulation cells to temp vector
201 decltype(cells_connectivity_) tmpCellsCo{};
202 std::swap(cells_connectivity_, tmpCellsCo);
203 decltype(cells_offsets_) tmpCellsOff{};
204 std::swap(cells_offsets_, tmpCellsOff);
205
206 // move previous triangulation to temp triangulation
207 decltype(triangulationSubdivision) tmpTr{};
208 std::swap(triangulationSubdivision, tmpTr);
209
210#ifdef TTK_CELL_ARRAY_NEW
211 tmpTr.setInputCells(
212 tmpCellsOff.size() - 1, tmpCellsCo.data(), tmpCellsOff.data());
213#else
214 ttk::LongSimplexId *tmpCells = nullptr;
215 ttk::CellArray::TranslateToFlatLayout(tmpCellsCo, tmpCellsOff, tmpCells);
216 tmpTr.setInputCells(tmpCellsCo.size() - 1, tmpCells);
217#endif
218 tmpTr.setInputPoints(tmpPoints.size() / 3, tmpPoints.data());
219 this->preconditionTriangulation(&tmpTr);
220
221 // generate the new triangulation
222 this->execute(*triangulation, triangulationSubdivision);
223
224 // interpolate output scalar fields
225 InterpolateScalarFields(output, output, *triangulation);
226 }
227
228 // generated 3D coordinates
229 auto points = vtkSmartPointer<vtkPoints>::New();
230 for(size_t i = 0; i < points_.size() / 3; i++) {
231 points->InsertNextPoint(&points_[3 * i]);
232 }
233 output->SetPoints(points);
234
235 // generated triangles
237 for(size_t i = 0; i < cells_offsets_.size() - 1; i++) {
238 cells->InsertNextCell(3, &cells_connectivity_[cells_offsets_[i]]);
239 }
240 output->SetCells(VTK_TRIANGLE, cells);
241
242 // cell id
244 cellId->SetName("CellId");
245 ttkUtils::SetVoidArray(cellId, pointId_.data(), pointId_.size(), 1);
246 output->GetPointData()->AddArray(cellId);
247
248 // cell dimension
250 cellDim->SetName("CellDimension");
251 ttkUtils::SetVoidArray(cellDim, pointDim_.data(), pointDim_.size(), 1);
252 output->GetPointData()->AddArray(cellDim);
253
254 // shallow copy input field data
255 output->GetFieldData()->ShallowCopy(input->GetFieldData());
256
257 this->printMsg("Complete", 1.0, tm.getElapsedTime(), this->threadNumber_);
258
259 return 1;
260}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
TTK VTK-filter that wraps the ttk::BarycentricSubdivision processing package.
vtkSmartPointer< vtkDataArray > AllocateScalarField(vtkDataArray *const inputScalarField, int ntuples) const
Allocate an output array of same type that input array.
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int InterpolateScalarFields(vtkDataSet *const input, vtkUnstructuredGrid *const output, ttk::Triangulation &inputTriangulation) const
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.cpp:226
static void SetVoidArray(vtkDataArray *array, void *data, vtkIdType size, int save)
Definition ttkUtils.cpp:280
SimplexId getNumberOfVertices() const
Return the number of vertices in the output triangulation.
std::vector< LongSimplexId > cells_connectivity_
void preconditionTriangulation(AbstractTriangulation *const triangulation)
int execute(const triangulationType &inputTriangl, ExplicitTriangulation &outputTriangl)
std::vector< SimplexId > pointId_
SimplexId getNumberOfTriangles() const
Return the number of triangles in the output triangulation.
std::vector< LongSimplexId > cells_offsets_
std::vector< SimplexId > pointDim_
static void TranslateToFlatLayout(std::vector< LongSimplexId > &connectivity, std::vector< LongSimplexId > &offset, LongSimplexId *&singleArray)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
ExplicitTriangulation is a class that provides time efficient traversal methods on triangulations of ...
double getElapsedTime()
Definition Timer.h:15
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
long long int LongSimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:15
#define DISPATCH_INTERPOLATE_DIS(CASE, TYPE)
vtkStandardNewMacro(ttkBarycentricSubdivision)
#define DISPATCH_INTERPOLATE_CONT(CASE, TYPE)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)