TTK
Loading...
Searching...
No Matches
ttkContourAroundPoint.cpp
Go to the documentation of this file.
2
3#include <ttkMacros.h>
4#include <ttkUtils.h>
5
6#include <vtkInformation.h>
7#include <vtkInformationVector.h>
8#include <vtkVersion.h>
9
10#include <vtkCellData.h>
11#include <vtkDataSet.h>
12#include <vtkUnstructuredGrid.h>
13#include <vtkVersionMacros.h>
14
15#include <vtkFloatArray.h>
16#include <vtkIdTypeArray.h>
17
18#include <cassert>
19
21
22//----------------------------------------------------------------------------//
23
25 vtkInformation *info) {
26 switch(port) {
27 case 0:
28 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
29 return 1;
30 case 1:
31 case 2:
32 info->Set(
33 vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid");
34 return 1;
35 }
36 return 0;
37}
38
40 vtkInformation *info) {
41 switch(port) {
42 case 0:
43 case 1:
44 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid");
45 return 1;
46 }
47 return 0;
48}
49
50//----------------------------------------------------------------------------//
51
53 vtkInformationVector **iVec,
54 vtkInformationVector *oVec) {
55
56 _outFld = vtkUnstructuredGrid::GetData(oVec, 0);
57 _outPts = vtkUnstructuredGrid::GetData(oVec, 1);
58
59 if(!preprocessFld(vtkDataSet::GetData(iVec[0])))
60 return 0;
61 if(!preprocessPts(vtkUnstructuredGrid::GetData(iVec[1]),
62 vtkUnstructuredGrid::GetData(iVec[2])))
63 return 0;
64 if(!process())
65 return 0;
66 if(!postprocess())
67 return 0;
68
69 return 1;
70}
71
72//----------------------------------------------------------------------------//
73
74bool ttkContourAroundPoint::preprocessFld(vtkDataSet *dataset) {
75 ttk::Triangulation *triangulation = ttkAlgorithm::GetTriangulation(dataset);
76 if(!triangulation)
77 return false;
78
79 auto scalars = GetInputArrayToProcess(0, dataset);
80 if(!scalars)
81 return false;
82
83 const double radius = ui_spherical ? -1. : 0.;
84
85 const auto errorCode = this->setInputField(
86 triangulation, ttkUtils::GetVoidPointer(scalars), ui_sizeFilter, radius);
87 if(errorCode < 0) {
88 printErr("super->setInputField failed with code "
89 + std::to_string(errorCode));
90 return false;
91 }
92
93 _triangTypeCode = triangulation->getType();
94 _scalarTypeCode = scalars->GetDataType();
95 _scalarsName = scalars->GetName();
96
97 std::ostringstream stream;
98 stream << "Scalar type: " << scalars->GetDataTypeAsString() << " (code "
99 << _scalarTypeCode << ")";
101
102 return true;
103}
104
105//----------------------------------------------------------------------------//
106
107bool ttkContourAroundPoint::preprocessPts(vtkUnstructuredGrid *nodes,
108 vtkUnstructuredGrid *arcs) {
109 // ---- Point data ---- //
110
111 auto points = nodes->GetPoints();
112 if(points->GetDataType() != VTK_FLOAT) {
113 printErr("The point coordinates must be of type float");
114 return false;
115 }
116 auto coords
117 = reinterpret_cast<float *>(ttkUtils::GetVoidPointer(points->GetData()));
118
119 auto pData = nodes->GetPointData();
120 auto scalarBuf = getBuffer<float>(pData, "Scalar", VTK_FLOAT, "float");
121 auto codeBuf = getBuffer<int>(pData, "CriticalType", VTK_INT, "int");
122 if(!scalarBuf || !codeBuf)
123 return false;
124
125 // ---- Cell data ---- //
126
127#ifndef NDEBUG // each arc should of course be defined by exactly two vertices
128 auto cells = arcs->GetCells();
129 const auto maxNvPerC = cells->GetMaxCellSize();
130 if(maxNvPerC != 2) {
131 printErr(
132 "The points must come in pairs but there is at least one cell with "
133 + std::to_string(maxNvPerC) + " points");
134 return false;
135 }
136 // NOTE Ideally check for minNvPerC != 2
137#endif
138
139 auto cData = arcs->GetCellData();
140 auto c2p = getBuffer<int>(cData, "upNodeId", VTK_INT, "int");
141 auto c2q = getBuffer<int>(cData, "downNodeId", VTK_INT, "int");
142 if(!c2p || !c2q)
143 return false;
144
145 // ---- Loop over pairs ---- //
146
147 static constexpr int minCode = 0;
148 static constexpr int maxCode = 3;
149 const double sadFac = ui_extension * 0.01; // saddle or mean of min and max
150 const double extFac = 1 - sadFac; // factor for the extreme point
151
152 _coords.resize(0);
153 _scalars.resize(0);
154 _isovals.resize(0);
155 _flags.resize(0);
156
157 auto addPoint = [this, coords, scalarBuf](int p, float isoval, int code) {
158 const auto point = &coords[p * 3];
159 _coords.push_back(point[0]);
160 _coords.push_back(point[1]);
161 _coords.push_back(point[2]);
162 _scalars.push_back(scalarBuf[p]);
163 _isovals.push_back(isoval);
164 _flags.push_back(code == minCode ? 0 : 1);
165 };
166
167 const vtkIdType nc = arcs->GetNumberOfCells();
168 for(vtkIdType c = 0; c < nc; ++c) {
169 const auto p = c2p[c];
170 const auto q = c2q[c];
171 const auto pCode = codeBuf[p];
172 const auto qCode = codeBuf[q];
173
174 const bool pIsSad = pCode != minCode && pCode != maxCode;
175 const bool qIsSad = qCode != minCode && qCode != maxCode;
176 if(pIsSad || qIsSad) {
177 if(pIsSad && qIsSad) // two saddles
178 continue;
179 // extremum and saddle
180 const auto ext = pIsSad ? q : p;
181 const auto sad = pIsSad ? p : q;
182 const float isoval = scalarBuf[ext] * extFac + scalarBuf[sad] * sadFac;
183 addPoint(ext, isoval, codeBuf[ext]);
184 } else { // min-max pair
185 printWrn("Arc " + std::to_string(c) + " joins a minimum and a maximum");
186 const auto pVal = scalarBuf[p];
187 const auto qVal = scalarBuf[q];
188 const auto cVal = (pVal + qVal) / 2;
189 addPoint(p, pVal * extFac + cVal * sadFac, pCode);
190 addPoint(q, qVal * extFac + cVal * sadFac, qCode);
191 }
192 }
193
194 auto np = _scalars.size();
195 const auto errorCode = this->setInputPoints(
196 _coords.data(), _scalars.data(), _isovals.data(), _flags.data(), np);
197 if(errorCode < 0) {
198 printErr("setInputPoints failed with code " + std::to_string(errorCode));
199 return false;
200 }
201 return true;
202}
203
204//----------------------------------------------------------------------------//
205
207 int errorCode = 0;
208 switch(_scalarTypeCode) {
209 vtkTemplateMacro((errorCode = this->execute<VTK_TT>()));
210 }
211 // ttkVtkTemplateMacro(
212 // _scalarTypeCode, _triangTypeCode,
213 // (errorCode = this->execute<VTK_TT, TTK_TT>())
214 // )
215 if(errorCode < 0) { // In TTK, negative is bad.
216 printErr("super->execute failed with code " + std::to_string(errorCode));
217 return false;
218 }
219 return true;
220}
221
222//----------------------------------------------------------------------------//
223
226 if(nc == 0) // very fine area filter
227 return true;
228
229 // ---- Cell data (output 0) ---- //
230
231 std::vector<int> ctypes(nc);
232
233 vtkIdType cinfoCounter = 0;
234 for(ttk::SimplexId c = 0; c < nc; ++c) {
235 const auto nvOfCell = _outContoursCinfos[cinfoCounter];
236 assert(nvOfCell >= 2 && nvOfCell <= 3); // ensured in super class
237 ctypes[c] = nvOfCell == 2 ? VTK_LINE : VTK_TRIANGLE;
238 cinfoCounter += nvOfCell + 1;
239 }
240
242 auto cinfoArr = vtkSmartPointer<vtkIdTypeArray>::New();
244 cinfoArr, _outContoursCinfos.data(), _outContoursCinfos.size(), 1);
245#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 6, 1)
246 cells->ImportLegacyFormat(cinfoArr);
247#else
248 cells->SetCells(nc, cinfoArr);
249#endif
250 _outFld->SetCells(ctypes.data(), cells);
251
252 // ---- Point data (output 0) ---- //
253
254 if(vtkSmartPointer<vtkPoints>::New()->GetDataType() != VTK_FLOAT) {
255 printErr("The API has changed! We have expected the default "
256 "coordinate type to be float");
257 return false;
258 }
259
260 auto points = vtkSmartPointer<vtkPoints>::New();
261 auto coordArr = vtkSmartPointer<vtkFloatArray>::New();
262 coordArr->SetNumberOfComponents(3);
264 coordArr, _outContoursCoords.data(), _outContoursCoords.size(), 1);
265 points->SetData(coordArr);
266 _outFld->SetPoints(points);
267
268 auto scalarArr = vtkFloatArray::New();
270 scalarArr, _outContoursScalars.data(), _outContoursScalars.size(), 1);
271 scalarArr->SetName(_scalarsName);
272 _outFld->GetPointData()->AddArray(scalarArr);
273
274 auto flagArr = vtkIntArray::New();
276 flagArr, _outContoursFlags.data(), _outContoursFlags.size(), 1);
277 flagArr->SetName("isMax");
278 _outFld->GetPointData()->AddArray(flagArr);
279
280 // ---- Output 1 (added in a later revision of the algo) ---- //
281
284 coordArr->SetNumberOfComponents(3);
286 coordArr, _outCentroidsCoords.data(), _outCentroidsCoords.size(), 1);
287 points->SetData(coordArr);
288 _outPts->SetPoints(points);
289
290 scalarArr = vtkFloatArray::New();
292 scalarArr, _outCentroidsScalars.data(), _outCentroidsScalars.size(), 1);
293 scalarArr->SetName(_scalarsName);
294 _outPts->GetPointData()->AddArray(scalarArr);
295
296 flagArr = vtkIntArray::New();
298 flagArr, _outCentroidsFlags.data(), _outCentroidsFlags.size(), 1);
299 flagArr->SetName("isMax");
300 _outPts->GetPointData()->AddArray(flagArr);
301
302 return true;
303}
#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 contourAroundPoint processing package.
bool postprocess()
Assemble the output object from the results of the TTK module.
T * getBuffer(vtkFieldData *data, const std::string &varName, int typeCode, const std::string &typeName)
int RequestData(vtkInformation *request, vtkInformationVector **iVec, vtkInformationVector *oVec) override
bool preprocessPts(vtkUnstructuredGrid *nodes, vtkUnstructuredGrid *arcs)
int FillOutputPortInformation(int port, vtkInformation *info) override
bool preprocessFld(vtkDataSet *dataset)
int FillInputPortInformation(int port, vtkInformation *info) override
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.cpp:228
static void SetVoidArray(vtkDataArray *array, void *data, vtkIdType size, int save)
Definition ttkUtils.cpp:282
int setInputField(triangulationType *triangulation, void *scalars, double sizeFilter, double radius=0.)
std::vector< float > _outCentroidsCoords
std::vector< float > _outContoursScalars
std::vector< float > _outContoursCoords
std::vector< int > _outCentroidsFlags
std::vector< float > _outCentroidsScalars
std::vector< LongSimplexId > _outContoursCinfos
int setInputPoints(float *coords, float *scalars, float *isovals, int *flags, std::size_t np)
std::vector< int > _outContoursFlags
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
Triangulation::Type getType() const
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
vtkStandardNewMacro(ttkContourAroundPoint)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)