TTK
Loading...
Searching...
No Matches
ttkFiberSurface.cpp
Go to the documentation of this file.
1#include <vtkCellArray.h>
2#include <vtkCellData.h>
3#include <vtkDoubleArray.h>
4#include <vtkInformation.h>
5#include <vtkNew.h>
6#include <vtkObjectFactory.h>
7#include <vtkPointData.h>
8#include <vtkPolyData.h>
9#include <vtkUnstructuredGrid.h>
10#include <vtkVersionMacros.h>
11
12#include <ttkFiberSurface.h>
13#include <ttkMacros.h>
14#include <ttkUtils.h>
15
17
19 this->SetNumberOfInputPorts(2);
20 this->SetNumberOfOutputPorts(1);
21}
22
23int ttkFiberSurface::FillInputPortInformation(int port, vtkInformation *info) {
24 if(port == 0) {
25 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
26 return 1;
27 } else if(port == 1) {
28 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid");
29 return 1;
30 }
31 return 0;
32}
33
34int ttkFiberSurface::FillOutputPortInformation(int port, vtkInformation *info) {
35 if(port == 0) {
36 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData");
37 return 1;
38 }
39 return 0;
40}
41
42template <typename VTK_T1, typename VTK_T2>
44
45#ifdef TTK_ENABLE_FIBER_SURFACE_WITH_RANGE_OCTREE
46 if(RangeOctree) {
47 ttkTemplateMacro(triangulation->getType(),
48 (this->buildOctree<VTK_T1, VTK_T2>(
49 static_cast<TTK_TT *>(triangulation->getData()))));
50 }
51#endif // TTK_ENABLE_FIBER_SURFACE_WITH_RANGE_OCTREE
52
53 ttkTemplateMacro(triangulation->getType(),
54 (this->computeSurface<VTK_T1, VTK_T2>(
55 static_cast<TTK_TT *>(triangulation->getData()))));
56 return 0;
57}
58
59int ttkFiberSurface::RequestData(vtkInformation *ttkNotUsed(request),
60 vtkInformationVector **inputVector,
61 vtkInformationVector *outputVector) {
62
63 using ttk::SimplexId;
64 ttk::Timer const t;
65
66 const auto input = vtkDataSet::GetData(inputVector[0]);
67 const auto polygon = vtkUnstructuredGrid::GetData(inputVector[1]);
68 auto output = vtkPolyData::GetData(outputVector);
69
70 const auto dataUfield = this->GetInputArrayToProcess(0, input);
71 const auto dataVfield = this->GetInputArrayToProcess(1, input);
72 const auto polygonUfield = this->GetInputArrayToProcess(2, polygon);
73 const auto polygonVfield = this->GetInputArrayToProcess(3, polygon);
74
75 if(dataUfield == nullptr || dataVfield == nullptr || polygonUfield == nullptr
76 || polygonVfield == nullptr) {
77 this->printErr("Could not find data array");
78 return -1;
79 }
80
81 if(!(input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID
82 || input->GetDataObjectType() == VTK_IMAGE_DATA)) {
83 this->printErr("Unsupported VTK data structure");
84 return -5;
85 }
86
87 auto triangulation = ttkAlgorithm::GetTriangulation(input);
88 if(triangulation == nullptr) {
89 return -1;
90 }
91
92 this->preconditionTriangulation(triangulation);
93 outputVertexList_.clear();
94 this->setGlobalVertexList(&outputVertexList_);
95 this->setInputField(
96 ttkUtils::GetVoidPointer(dataUfield), ttkUtils::GetVoidPointer(dataVfield));
97 this->setPolygonEdgeNumber(polygon->GetNumberOfCells());
98 threadedTriangleList_.resize(polygon->GetNumberOfCells());
99 threadedVertexList_.resize(polygon->GetNumberOfCells());
100 this->setPolygon(&inputPolygon_);
101
102 this->setPointMerging(PointMerge);
103 this->setPointMergingThreshold(PointMergeDistanceThreshold);
104
105#ifdef TTK_ENABLE_FIBER_SURFACE_WITH_RANGE_OCTREE
106 if((!RangeOctree) || (dataUfield->GetMTime() > GetMTime())
107 || (dataVfield->GetMTime() > GetMTime())) {
108
109 this->printMsg("Resetting octree...");
110
111 this->flushOctree();
112 Modified();
113 }
114#endif
115
116 inputPolygon_.clear();
117
118 SimplexId const cellNumber = polygon->GetNumberOfCells();
119 vtkCellArray *connectivity = polygon->GetCells();
120
121#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 6, 1)
122 if(connectivity->GetConnectivityArray()->GetNumberOfTuples() < cellNumber) {
123#else
124 if(connectivity->GetData()->GetNumberOfTuples() < 3 * cellNumber) {
125#endif
126 this->printErr("Error: ill-defined range polygon.");
127 return 0;
128 }
129
130#if !defined(_WIN32) || defined(_WIN32) && defined(VTK_USE_64BIT_IDS)
131#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 6, 1)
132 vtkNew<vtkIdTypeArray> legacyFormat;
133 connectivity->ExportLegacyFormat(legacyFormat);
134 const long long int *cellArray
135 = (const long long int *)legacyFormat->GetPointer(0);
136#else
137 const long long int *cellArray = connectivity->GetData()->GetPointer(0);
138#endif
139#else
140 int *pt = connectivity->GetPointer();
141 long long extra_pt = *pt;
142 const long long int *cellArray = &extra_pt;
143#endif
144
145 SimplexId vertexId0, vertexId1;
146 std::pair<std::pair<double, double>, std::pair<double, double>> rangeEdge;
147
148 for(SimplexId i = 0; i < cellNumber; i++) {
149
150 vertexId0 = cellArray[3 * i + 1];
151 vertexId1 = cellArray[3 * i + 2];
152
153 rangeEdge.first.first = polygonUfield->GetTuple1(vertexId0);
154 rangeEdge.first.second = polygonVfield->GetTuple1(vertexId0);
155
156 rangeEdge.second.first = polygonUfield->GetTuple1(vertexId1);
157 rangeEdge.second.second = polygonVfield->GetTuple1(vertexId1);
158
159 inputPolygon_.push_back(rangeEdge);
160 }
161
162 for(size_t i = 0; i < threadedTriangleList_.size(); i++) {
163 threadedTriangleList_[i].clear();
164 this->setTriangleList(i, &(threadedTriangleList_[i]));
165 threadedVertexList_[i].clear();
166 this->setVertexList(i, &(threadedVertexList_[i]));
167 }
168
169#ifndef TTK_ENABLE_DOUBLE_TEMPLATING
170 if(dataUfield->GetDataType() != dataVfield->GetDataType()) {
171 this->printErr(
172 "Scalar fields should have same input type. Use TTKPointDataConverter or "
173 "TTKArrayEditor to convert array types.");
174 return 0;
175 }
176 switch(dataUfield->GetDataType()) {
177 vtkTemplateMacro((dispatch<VTK_TT, VTK_TT>(triangulation)));
178 }
179#else
180 switch(vtkTemplate2PackMacro(
181 dataUfield->GetDataType(), dataVfield->GetDataType())) {
182 vtkTemplate2Macro((dispatch<VTK_T1, VTK_T2>(triangulation)));
183 }
184#endif // TTK_ENABLE_DOUBLE_TEMPLATING
185
186 // prepare the VTK output
187 // NOTE: right now, there is a copy of the output data. this is no good.
188 // to fix.
189
190 size_t triangleNumber = 0;
191
192 for(size_t i = 0; i < threadedTriangleList_.size(); i++) {
193 triangleNumber += threadedTriangleList_[i].size();
194 }
195
196 vtkNew<vtkPoints> outputVertexList{};
197 vtkNew<vtkDoubleArray> outputU{};
198 vtkNew<vtkDoubleArray> outputV{};
199 vtkNew<vtkDoubleArray> outputParameterization{};
200 vtkNew<vtkCellArray> outputTriangleList{};
201 vtkNew<ttkSimplexIdTypeArray> outputEdgeIds{};
202 vtkNew<ttkSimplexIdTypeArray> outputTetIds{};
203 vtkNew<ttkSimplexIdTypeArray> outputCaseIds{};
204
205 if(RangeCoordinates) {
206 outputU->SetName(dataUfield->GetName());
207 outputU->SetNumberOfTuples(outputVertexList_.size());
208
209 outputV->SetName(dataVfield->GetName());
210 outputV->SetNumberOfTuples(outputVertexList_.size());
211 }
212
213 if(EdgeParameterization) {
214 outputParameterization->SetName("EdgeParameterization");
215 outputParameterization->SetNumberOfTuples(outputVertexList_.size());
216 }
217
218 outputVertexList->SetNumberOfPoints(outputVertexList_.size());
219 output->SetPoints(outputVertexList);
220
221#ifdef TTK_ENABLE_OPENMP
222#pragma omp parallel for num_threads(threadNumber_)
223#endif
224 for(size_t i = 0; i < outputVertexList_.size(); i++) {
225 outputVertexList->SetPoint(i, outputVertexList_[i].p_[0],
226 outputVertexList_[i].p_[1],
227 outputVertexList_[i].p_[2]);
228 if(RangeCoordinates) {
229 outputU->SetTuple1(i, outputVertexList_[i].uv_.first);
230 outputV->SetTuple1(i, outputVertexList_[i].uv_.second);
231 }
232 if(EdgeParameterization) {
233 outputParameterization->SetTuple1(i, outputVertexList_[i].t_);
234 }
235 }
236 if(RangeCoordinates) {
237 output->GetPointData()->AddArray(outputU);
238 output->GetPointData()->AddArray(outputV);
239 } else {
240 output->GetPointData()->RemoveArray(dataUfield->GetName());
241 output->GetPointData()->RemoveArray(dataVfield->GetName());
242 }
243 if(EdgeParameterization) {
244 output->GetPointData()->AddArray(outputParameterization);
245 } else {
246 output->GetPointData()->RemoveArray("EdgeParameterization");
247 }
248
249 if(EdgeIds) {
250 outputEdgeIds->SetName("EdgeIds");
251 outputEdgeIds->SetNumberOfTuples(triangleNumber);
252 }
253
254 if(TetIds) {
255 outputTetIds->SetName("TetIds");
256 outputTetIds->SetNumberOfTuples(triangleNumber);
257 }
258
259 if(CaseIds) {
260 outputCaseIds->SetName("CaseIds");
261 outputCaseIds->SetNumberOfTuples(triangleNumber);
262 }
263
264 vtkNew<vtkIdList> idList{};
265 idList->SetNumberOfIds(3);
266
267 triangleNumber = 0;
268 for(size_t i = 0; i < threadedTriangleList_.size(); i++) {
269 for(size_t j = 0; j < threadedTriangleList_[i].size(); j++) {
270 for(int k = 0; k < 3; k++) {
271 idList->SetId(k, threadedTriangleList_[i][j].vertexIds_[k]);
272 }
273 outputTriangleList->InsertNextCell(idList);
274 if(EdgeIds) {
275 outputEdgeIds->SetTuple1(triangleNumber, i);
276 }
277 if(TetIds) {
278 outputTetIds->SetTuple1(
279 triangleNumber, threadedTriangleList_[i][j].tetId_);
280 }
281 if(CaseIds) {
282 outputCaseIds->SetTuple1(
283 triangleNumber, threadedTriangleList_[i][j].caseId_);
284 }
285 triangleNumber++;
286 }
287 }
288 output->SetPolys(outputTriangleList);
289 if(EdgeIds) {
290 output->GetCellData()->AddArray(outputEdgeIds);
291 } else {
292 output->GetCellData()->RemoveArray("EdgeIds");
293 }
294 if(TetIds) {
295 output->GetCellData()->AddArray(outputTetIds);
296 } else {
297 output->GetCellData()->RemoveArray("TetIds");
298 }
299 if(CaseIds) {
300 output->GetCellData()->AddArray(outputCaseIds);
301 } else {
302 output->GetCellData()->RemoveArray("CaseIds");
303 }
304
305 return 1;
306}
#define ttkTemplateMacro(triangulationType, call)
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
TTK VTK-filter that computes fiber surfaces.
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int dispatch(ttk::Triangulation *const triangulation)
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.cpp:228
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
int setGlobalVertexList(std::vector< Vertex > *globalList)
int setInputField(const void *uField, const void *vField)
int setPolygonEdgeNumber(const SimplexId &polygonEdgeNumber)
int setPointMerging(const bool &onOff)
int setPointMergingThreshold(const double &threshold)
int setPolygon(const std::vector< std::pair< std::pair< double, double >, std::pair< double, double > > > *polygon)
int setVertexList(const SimplexId &polygonEdgeId, std::vector< Vertex > *vertexList)
int setTriangleList(const SimplexId &polygonEdgeId, std::vector< Triangle > *triangleList)
void preconditionTriangulation(AbstractTriangulation *triangulation)
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
AbstractTriangulation * getData()
Triangulation::Type getType() const
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
vtkStandardNewMacro(ttkFiberSurface)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)