6#include <vtkCallbackCommand.h>
7#include <vtkCellData.h>
8#include <vtkCellTypes.h>
10#include <vtkImageData.h>
11#include <vtkPointData.h>
12#include <vtkPolyData.h>
13#include <vtkUnstructuredGrid.h>
14#include <vtkVersionMacros.h>
16static vtkCellArray *GetCells(vtkDataSet *dataSet) {
17 switch(dataSet->GetDataObjectType()) {
18 case VTK_UNSTRUCTURED_GRID: {
19 auto dataSetAsUG =
static_cast<vtkUnstructuredGrid *
>(dataSet);
20 return dataSetAsUG->GetCells();
23 auto dataSetAsPD =
static_cast<vtkPolyData *
>(dataSet);
24 return dataSetAsPD->GetNumberOfPolys() > 0 ? dataSetAsPD->GetPolys()
25 : dataSetAsPD->GetNumberOfLines() > 0 ? dataSetAsPD->GetLines()
26 : dataSetAsPD->GetVerts();
32static int checkCellTypes(vtkPointSet *
object) {
36#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 2, 0)
37 if(object->GetDataObjectType() == VTK_UNSTRUCTURED_GRID) {
38 auto objectAsUG = vtkUnstructuredGrid::SafeDownCast(
object);
39 auto distinctCellTypes = objectAsUG->GetDistinctCellTypesArray();
40 nTypes = distinctCellTypes->GetNumberOfTuples();
45#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 6, 1)
46 object->GetDistinctCellTypes(cellTypes);
48 object->GetCellTypes(cellTypes);
50 nTypes = cellTypes->GetNumberOfTypes();
63 const auto &cellType =
object->GetCellType(0);
64 if(cellType != VTK_VERTEX && cellType != VTK_LINE
65 && cellType != VTK_TRIANGLE && cellType != VTK_TETRA)
81 void Init(vtkDataSet *dataSet) {
84 if(dataSet->IsA(
"vtkPointSet"))
85 this->observee =
static_cast<vtkObject *
>(GetCells(dataSet));
87 this->observee =
static_cast<vtkObject *
>(dataSet);
89 this->observee->AddObserver(vtkCommand::DeleteEvent,
this, 1);
96 this->observee->RemoveObserver(
this);
100 if(instance->registry.empty()) {
104 auto it = instance->registry.find(this->key);
105 if(it != instance->registry.end()) {
106 instance->registry.erase(it);
108 instance->printMsg(
"# Registered Triangulations: "
109 + std::to_string(instance->registry.size()),
118 auto cells = GetCells(dataSet);
122 if(dataSet->IsA(
"vtkImageData")) {
123 auto image =
static_cast<vtkImageData *
>(dataSet);
124 image->GetExtent(this->
extent);
125 image->GetOrigin(this->
origin);
126 image->GetSpacing(this->
spacing);
131 onDelete->Init(dataSet);
135 auto cells = GetCells(dataSet);
139 if(dataSet->IsA(
"vtkImageData")) {
140 auto image =
static_cast<vtkImageData *
>(dataSet);
147 image->GetExtent(extent_);
148 image->GetOrigin(origin_);
149 image->GetSpacing(spacing_);
150 image->GetDimensions(dimensions_);
157 for(
int i = 0; i < 6; i++)
158 if(this->
extent[i] != extent_[i])
160 for(
int i = 0; i < 3; i++)
161 if(this->
origin[i] != origin_[i] || this->
spacing[i] != spacing_[i]
171ttkTriangulationFactory::ttkTriangulationFactory() {
176 ttkTriangulationFactory::CreateImplicitTriangulation(vtkImageData *image) {
178 this->
printMsg(
"Initializing Implicit Triangulation", 0, 0,
181 auto triangulation = std::make_unique<ttk::Triangulation>();
184 image->GetExtent(extent);
187 image->GetOrigin(origin);
190 image->GetSpacing(spacing);
193 if(!spacing[1] && !spacing[2])
199 image->GetDimensions(dimensions);
201 double firstPoint[3];
202 firstPoint[0] = origin[0] + extent[0] * spacing[0];
203 firstPoint[1] = origin[1] + extent[2] * spacing[1];
204 firstPoint[2] = origin[2] + extent[4] * spacing[2];
206 triangulation->setInputGrid(firstPoint[0], firstPoint[1], firstPoint[2],
207 spacing[0], spacing[1], spacing[2], dimensions[0],
208 dimensions[1], dimensions[2]);
210 this->
printMsg(
"Initializing Implicit Triangulation", 1,
214 return triangulation;
218 ttkTriangulationFactory::CreateExplicitTriangulation(vtkPointSet *pointSet) {
221 auto points = pointSet->GetPoints();
223 this->
printErr(
"DataSet has uninitialized `vtkPoints`.");
227 auto cells = GetCells(pointSet);
229 this->
printErr(
"DataSet has uninitialized `vtkCellArray`.");
233 auto triangulation = std::make_unique<ttk::Triangulation>();
234 int const hasIndexArray
238 this->
printMsg(
"Initializing Compact Triangulation", 0, 0,
241 this->
printMsg(
"Initializing Explicit Triangulation", 0, 0,
247 auto pointDataType = points->GetDataType();
248 if(pointDataType != VTK_FLOAT && pointDataType != VTK_DOUBLE) {
249 this->
printErr(
"Unable to initialize 'ttk::Triangulation' for point "
250 "precision other than 'float' or 'double'.");
256 vtkAbstractArray *indexArray = pointSet->GetPointData()->GetAbstractArray(
258 triangulation->setStellarInputPoints(
259 points->GetNumberOfPoints(), pointDataArray,
260 (
int *)indexArray->GetVoidPointer(0), pointDataType == VTK_DOUBLE);
262 triangulation->setInputPoints(points->GetNumberOfPoints(), pointDataArray,
263 pointDataType == VTK_DOUBLE);
268 int const cellTypeStatus = checkCellTypes(pointSet);
269 if(cellTypeStatus == -1) {
270 this->
printWrn(
"Inhomogeneous cell dimensions detected.");
272 "Consider using `ttkExtract` to extract cells of a given dimension.");
274 }
else if(cellTypeStatus == -2) {
275 this->
printWrn(
"Cells are not simplices.");
276 this->
printWrn(
"Consider using `vtkTetrahedralize` in pre-processing.");
281 int const nCells = cells->GetNumberOfCells();
283 if(!cells->IsStorage64Bit()) {
284 if(cells->CanConvertTo64BitStorage()) {
285 this->
printWrn(
"Converting the cell array to 64-bit storage");
286 bool const success = cells->ConvertTo64BitStorage();
289 "Error converting the provided cell array to 64-bit storage");
294 "Cannot convert the provided cell array to 64-bit storage");
298 auto connectivity =
static_cast<vtkIdType *
>(
300 auto offsets =
static_cast<vtkIdType *
>(
306 = triangulation->setStellarInputCells(nCells, connectivity, offsets);
308 status = triangulation->setInputCells(nCells, connectivity, offsets);
313 "Run the `vtkTetrahedralize` filter to resolve the issue.");
319 this->
printMsg(
"Initializing Compact Triangulation", 1,
323 this->
printMsg(
"Initializing Explicit Triangulation", 1,
328 return triangulation;
332 ttkTriangulationFactory::CreateTriangulation(vtkDataSet *dataSet) {
333 switch(dataSet->GetDataObjectType()) {
334 case VTK_UNSTRUCTURED_GRID:
335 case VTK_POLY_DATA: {
336 return this->CreateExplicitTriangulation(
337 static_cast<vtkPointSet *
>(dataSet));
339 case VTK_IMAGE_DATA: {
340 return this->CreateImplicitTriangulation((vtkImageData *)dataSet);
343 this->
printErr(
"Unable to triangulate `"
344 + std::string(dataSet->GetClassName()) +
"`");
352 int debugLevel,
float cacheRatio, vtkDataSet *
object) {
354 instance->setDebugLevel(debugLevel);
359 auto it = instance->registry.find(key);
360 if(it != instance->registry.end()) {
362 if(it->second.isValid(
object)) {
365 triangulation = it->second.triangulation.get();
369 instance->registry.erase(key);
373 if(!triangulation && object->IsA(
"vtkImageData")) {
374 instance->FindImplicitTriangulation(
375 triangulation,
static_cast<vtkImageData *
>(
object));
377 instance->printMsg(
"Retrieving Equivalent Implicit-Triangulation",
382 triangulation = instance->CreateTriangulation(
object).release();
384 instance->registry.emplace(std::piecewise_construct,
385 std::forward_as_tuple(key),
386 std::forward_as_tuple(
object, triangulation));
391 "# Registered Triangulations: " + std::to_string(instance->registry.size()),
399 return triangulation;
402int ttkTriangulationFactory::FindImplicitTriangulation(
405 for(
const auto &it : this->
registry) {
406 if(it.second.owner->IsA(
"vtkImageData")) {
407 if(it.second.isValid(image)) {
408 triangulation = it.second.triangulation.get();
418 switch(dataSet->GetDataObjectType()) {
419 case VTK_IMAGE_DATA: {
423 auto cells = GetCells(dataSet);
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
static RegistryKey GetKey(vtkDataSet *dataSet)
static ttk::Triangulation * GetTriangulation(int debugLevel, float cacheRatio, vtkDataSet *object)
static ttkTriangulationFactory Instance
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void setDebugMsgPrefix(const std::string &prefix)
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
int setDebugLevel(const int &debugLevel) override
Tune the debug level (default: 0).
int setCacheSize(const float &ratio)
const char compactTriangulationIndex[]
bool isValid(vtkDataSet *dataSet) const
RegistryValue(vtkDataSet *dataSet, ttk::Triangulation *triangulation_)
RegistryTriangulation triangulation
void Execute(vtkObject *, unsigned long ttkNotUsed(eventId), void *ttkNotUsed(callData)) override
static ttkOnDeleteCommand * New()
void Init(vtkDataSet *dataSet)
std::unique_ptr< ttk::Triangulation > RegistryTriangulation
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)