1#include <vtkCellData.h>
3#include <vtkDoubleArray.h>
4#include <vtkFloatArray.h>
5#include <vtkIdTypeArray.h>
6#include <vtkInformation.h>
8#include <vtkPointData.h>
9#include <vtkPolyData.h>
10#include <vtkSignedCharArray.h>
11#include <vtkSmartPointer.h>
12#include <vtkUnsignedCharArray.h>
21 SetNumberOfInputPorts(1);
22 SetNumberOfOutputPorts(1);
26 vtkInformation *info) {
28 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(),
"vtkDataSet");
35 vtkInformation *info) {
37 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkPolyData");
43template <
typename triangulationType>
44int ttkPersistentGenerators::dispatch(vtkPolyData *output,
45 vtkDataArray *
const inputScalarsArray,
46 const SimplexId *
const inputOrder,
47 const triangulationType &triangulation) {
50 inputScalarsArray->GetMTime(), inputOrder, triangulation);
51 std::vector<GeneratorType> cycles{};
52 std::vector<std::vector<SimplexId>> connComps{};
54 cycles, connComps, inputOrder, triangulation);
56 const SimplexId numberOfVertices = triangulation.getNumberOfVertices();
57 std::vector<SimplexId> isVisited(numberOfVertices, -1);
58 std::vector<SimplexId> visitedIds{};
60 vtkNew<vtkPoints> points{};
61 vtkNew<vtkCellArray> cells{};
63 vtkNew<ttkSimplexIdTypeArray> cycleId{};
64 cycleId->SetName(
"CycleId");
65 vtkNew<ttkSimplexIdTypeArray> edgeId{};
66 edgeId->SetName(
"EdgeId");
67 vtkNew<ttkSimplexIdTypeArray> birthId{};
68 birthId->SetName(
"BirthId");
69 vtkNew<ttkSimplexIdTypeArray> deathId{};
70 deathId->SetName(
"DeathId");
71 vtkNew<ttkSimplexIdTypeArray> ccId{};
72 ccId->SetName(
"ComponentId");
73 vtkNew<vtkUnsignedCharArray> iFin{};
77 vtkNew<vtkSignedCharArray> mask{};
79 vtkNew<ttkSimplexIdTypeArray> vertsId{};
82 sf->SetName(inputScalarsArray->GetName());
83 vtkNew<vtkSignedCharArray> nbOnBoundary{};
84 nbOnBoundary->SetNumberOfComponents(1);
87 const auto addVertex = [&](
const SimplexId v) {
91 std::array<float, 3> p{};
92 triangulation.getVertexPoint(v, p[0], p[1], p[2]);
93 return points->InsertNextPoint(p.data());
96 const auto addEdge = [&](
const SimplexId e) {
97 std::array<vtkIdType, 2> pts{};
98 for(
int i = 0; i < 2; ++i) {
100 triangulation.getEdgeVertex(e, i, v);
101 if(isVisited[v] == -1) {
102 pts[i] = addVertex(v);
103 isVisited[v] = pts[i];
104 visitedIds.emplace_back(v);
106 pts[i] = isVisited[v];
109 cells->InsertNextCell(2, pts.data());
112 for(
size_t i = 0; i < cycles.size(); ++i) {
113 if(cycles[i].boundary.empty()) {
117 const auto &cycle{cycles[i]};
118 const auto cbirth{cycle.boundary[0]};
119 const auto cdeath{cycle.critTriangleId};
120 const auto cpers{inputScalarsArray->GetTuple1(cycle.critVertsIds[0])
121 - inputScalarsArray->GetTuple1(cycle.critVertsIds[1])};
123 for(
const auto e : cycle.boundary) {
125 cycleId->InsertNextTuple1(i);
126 edgeId->InsertNextTuple1(e);
127 birthId->InsertNextTuple1(cbirth);
128 deathId->InsertNextTuple1(cdeath);
129 pers->InsertNextTuple1(cpers);
130 iFin->InsertNextTuple1(cdeath != -1);
131 nbOnBoundary->InsertNextTuple1(
132 triangulation.isEdgeOnBoundary(cbirth)
133 + (cdeath != -1 && triangulation.getDimensionality() == 3
134 ? triangulation.isTriangleOnBoundary(cdeath)
137 for(
const auto cc : connComps[i]) {
138 ccId->InsertNextTuple1(cc);
142 for(
const auto v : visitedIds) {
143 vertsId->InsertNextTuple1(v);
144 sf->InsertNextTuple1(inputScalarsArray->GetTuple1(v));
145 mask->InsertNextTuple1(1);
150 triangulation.getEdgeVertex(cbirth, 0, v0);
151 triangulation.getEdgeVertex(cbirth, 1, v1);
152 mask->SetTuple1(isVisited[v0], 0);
153 mask->SetTuple1(isVisited[v1], 0);
156 for(
const auto v : visitedIds) {
162 output->SetPoints(points);
163 output->GetPointData()->AddArray(sf);
164 output->GetPointData()->AddArray(mask);
165 output->GetPointData()->AddArray(vertsId);
166 output->SetLines(cells);
167 output->GetCellData()->AddArray(cycleId);
168 output->GetCellData()->AddArray(edgeId);
169 output->GetCellData()->AddArray(birthId);
170 output->GetCellData()->AddArray(deathId);
171 output->GetCellData()->AddArray(ccId);
172 output->GetCellData()->AddArray(iFin);
173 output->GetCellData()->AddArray(pers);
174 output->GetCellData()->AddArray(nbOnBoundary);
180 vtkInformationVector **inputVector,
181 vtkInformationVector *outputVector) {
183 auto *input = vtkDataSet::GetData(inputVector[0]);
184 auto *output = vtkPolyData::GetData(outputVector, 0);
187 if(triangulation ==
nullptr) {
188 this->
printErr(
"Wrong triangulation");
193 vtkDataArray *inputScalars = this->GetInputArrayToProcess(0, inputVector);
194 if(inputScalars ==
nullptr) {
195 this->
printErr(
"Wrong input scalars");
200 input, 0, triangulation,
false, 1, ForceInputOffsetScalarField);
201 if(offsetField ==
nullptr) {
202 this->
printErr(
"Wrong input offsets");
208 this->dispatch(output, inputScalars,
209 ttkUtils::GetPointer<SimplexId>(offsetField),
210 *
static_cast<TTK_TT *
>(triangulation->
getData())));
#define ttkTemplateMacro(triangulationType, call)
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
vtkDataArray * GetOrderArray(vtkDataSet *const inputData, const int scalarArrayIdx, ttk::Triangulation *triangulation, const bool getGlobalOrder=false, const int orderArrayIdx=0, const bool enforceOrderArrayIdx=false)
TTK VTK-filter for the computation of persistent generators.
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
ttkPersistentGenerators()
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
void setDebugMsgPrefix(const std::string &prefix)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void preconditionTriangulation(AbstractTriangulation *const data)
int buildGradient(const void *const scalars, const size_t scalarsMTime, const SimplexId *const offsets, const triangulationType &triangulation, const std::vector< bool > *updateMask=nullptr)
int computePersistentGenerators(std::vector< GeneratorType > &generators, std::vector< std::vector< SimplexId > > &connComps, const SimplexId *const offsets, const triangulationType &triangulation)
Compute the persistence generators from the discrete gradient.
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
AbstractTriangulation * getData()
Triangulation::Type getType() const
const char PersistenceName[]
const char MorseSmaleCriticalPointsOnBoundaryName[]
const char PersistenceIsFinite[]
const char VertexScalarFieldName[]
default name for vertex scalar field
const char MaskScalarFieldName[]
default name for mask scalar field
int SimplexId
Identifier type for simplices of any dimension.
vtkStandardNewMacro(ttkPersistentGenerators)