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 object->GetCellTypes(cellTypes);
46 nTypes = cellTypes->GetNumberOfTypes();
59 const auto &cellType =
object->GetCellType(0);
60 if(cellType != VTK_VERTEX && cellType != VTK_LINE
61 && cellType != VTK_TRIANGLE && cellType != VTK_TETRA)
77 void Init(vtkDataSet *dataSet) {
80 if(dataSet->IsA(
"vtkPointSet"))
81 this->observee =
static_cast<vtkObject *
>(GetCells(dataSet));
83 this->observee =
static_cast<vtkObject *
>(dataSet);
85 this->observee->AddObserver(vtkCommand::DeleteEvent,
this, 1);
92 this->observee->RemoveObserver(
this);
96 if(instance->registry.empty()) {
100 auto it = instance->
registry.find(this->key);
101 if(it != instance->registry.end()) {
102 instance->registry.erase(it);
104 instance->printMsg(
"# Registered Triangulations: "
105 + std::to_string(instance->registry.size()),
113 : triangulation(triangulation_), owner(dataSet) {
114 auto cells = GetCells(dataSet);
118 if(dataSet->IsA(
"vtkImageData")) {
119 auto image =
static_cast<vtkImageData *
>(dataSet);
120 image->GetExtent(this->
extent);
121 image->GetOrigin(this->
origin);
122 image->GetSpacing(this->
spacing);
127 onDelete->Init(dataSet);
131 auto cells = GetCells(dataSet);
135 if(dataSet->IsA(
"vtkImageData")) {
136 auto image =
static_cast<vtkImageData *
>(dataSet);
143 image->GetExtent(extent_);
144 image->GetOrigin(origin_);
145 image->GetSpacing(spacing_);
146 image->GetDimensions(dimensions_);
153 for(
int i = 0; i < 6; i++)
154 if(this->
extent[i] != extent_[i])
156 for(
int i = 0; i < 3; i++)
157 if(this->
origin[i] != origin_[i] || this->
spacing[i] != spacing_[i]
167ttkTriangulationFactory::ttkTriangulationFactory() {
172 ttkTriangulationFactory::CreateImplicitTriangulation(vtkImageData *image) {
174 this->
printMsg(
"Initializing Implicit Triangulation", 0, 0,
177 auto triangulation = std::make_unique<ttk::Triangulation>();
180 image->GetExtent(extent);
183 image->GetOrigin(origin);
186 image->GetSpacing(spacing);
189 image->GetDimensions(dimensions);
191 double firstPoint[3];
192 firstPoint[0] = origin[0] + extent[0] * spacing[0];
193 firstPoint[1] = origin[1] + extent[2] * spacing[1];
194 firstPoint[2] = origin[2] + extent[4] * spacing[2];
196 triangulation->setInputGrid(firstPoint[0], firstPoint[1], firstPoint[2],
197 spacing[0], spacing[1], spacing[2], dimensions[0],
198 dimensions[1], dimensions[2]);
200 this->
printMsg(
"Initializing Implicit Triangulation", 1,
204 return triangulation;
208 ttkTriangulationFactory::CreateExplicitTriangulation(vtkPointSet *pointSet) {
211 auto points = pointSet->GetPoints();
213 this->
printErr(
"DataSet has uninitialized `vtkPoints`.");
217 auto cells = GetCells(pointSet);
219 this->
printErr(
"DataSet has uninitialized `vtkCellArray`.");
223 auto triangulation = std::make_unique<ttk::Triangulation>();
224 int const hasIndexArray
228 this->
printMsg(
"Initializing Compact Triangulation", 0, 0,
231 this->
printMsg(
"Initializing Explicit Triangulation", 0, 0,
237 auto pointDataType = points->GetDataType();
238 if(pointDataType != VTK_FLOAT && pointDataType != VTK_DOUBLE) {
239 this->
printErr(
"Unable to initialize 'ttk::Triangulation' for point "
240 "precision other than 'float' or 'double'.");
246 vtkAbstractArray *indexArray = pointSet->GetPointData()->GetAbstractArray(
248 triangulation->setStellarInputPoints(
249 points->GetNumberOfPoints(), pointDataArray,
250 (
int *)indexArray->GetVoidPointer(0), pointDataType == VTK_DOUBLE);
252 triangulation->setInputPoints(points->GetNumberOfPoints(), pointDataArray,
253 pointDataType == VTK_DOUBLE);
258 int const cellTypeStatus = checkCellTypes(pointSet);
259 if(cellTypeStatus == -1) {
260 this->
printWrn(
"Inhomogeneous cell dimensions detected.");
262 "Consider using `ttkExtract` to extract cells of a given dimension.");
264 }
else if(cellTypeStatus == -2) {
265 this->
printWrn(
"Cells are not simplices.");
266 this->
printWrn(
"Consider using `vtkTetrahedralize` in pre-processing.");
271 int const nCells = cells->GetNumberOfCells();
273 if(!cells->IsStorage64Bit()) {
274 if(cells->CanConvertTo64BitStorage()) {
275 this->
printWrn(
"Converting the cell array to 64-bit storage");
276 bool const success = cells->ConvertTo64BitStorage();
279 "Error converting the provided cell array to 64-bit storage");
284 "Cannot convert the provided cell array to 64-bit storage");
288 auto connectivity =
static_cast<vtkIdType *
>(
290 auto offsets =
static_cast<vtkIdType *
>(
296 = triangulation->setStellarInputCells(nCells, connectivity, offsets);
298 status = triangulation->setInputCells(nCells, connectivity, offsets);
303 "Run the `vtkTetrahedralize` filter to resolve the issue.");
309 this->
printMsg(
"Initializing Compact Triangulation", 1,
313 this->
printMsg(
"Initializing Explicit Triangulation", 1,
318 return triangulation;
322 ttkTriangulationFactory::CreateTriangulation(vtkDataSet *dataSet) {
323 switch(dataSet->GetDataObjectType()) {
324 case VTK_UNSTRUCTURED_GRID:
325 case VTK_POLY_DATA: {
326 return this->CreateExplicitTriangulation(
327 static_cast<vtkPointSet *
>(dataSet));
329 case VTK_IMAGE_DATA: {
330 return this->CreateImplicitTriangulation((vtkImageData *)dataSet);
333 this->
printErr(
"Unable to triangulate `"
334 + std::string(dataSet->GetClassName()) +
"`");
342 int debugLevel,
float cacheRatio, vtkDataSet *
object) {
349 auto it = instance->registry.find(key);
350 if(it != instance->registry.end()) {
352 if(it->second.isValid(
object)) {
355 triangulation = it->second.triangulation.get();
359 instance->registry.erase(key);
363 if(!triangulation && object->IsA(
"vtkImageData")) {
364 instance->FindImplicitTriangulation(
365 triangulation,
static_cast<vtkImageData *
>(
object));
367 instance->printMsg(
"Retrieving Equivalent Implicit-Triangulation",
372 triangulation = instance->CreateTriangulation(
object).release();
374 instance->registry.emplace(std::piecewise_construct,
375 std::forward_as_tuple(key),
376 std::forward_as_tuple(
object, triangulation));
381 "# Registered Triangulations: " + std::to_string(instance->registry.size()),
385 triangulation->setDebugLevel(debugLevel);
386 triangulation->setCacheSize(cacheRatio);
389 return triangulation;
392int ttkTriangulationFactory::FindImplicitTriangulation(
395 for(
const auto &it : this->
registry) {
396 if(it.second.owner->IsA(
"vtkImageData")) {
397 if(it.second.isValid(image)) {
398 triangulation = it.second.triangulation.get();
408 switch(dataSet->GetDataObjectType()) {
409 case VTK_IMAGE_DATA: {
413 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)
virtual int setDebugLevel(const int &debugLevel)
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 ...
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)