42 vtkInformationVector **inputVector,
43 vtkInformationVector *outputVector) {
48 auto input = vtkUnstructuredGrid::GetData(inputVector[0]);
49 auto output = vtkUnstructuredGrid::GetData(outputVector);
53 if(triangulation ==
nullptr) {
58 triangulation->preconditionBoundaryVertices();
61 SimplexId
const vertexNumber = input->GetNumberOfPoints();
62 std::vector<SimplexId> candidateVertices;
65 for(SimplexId i = 0; i < vertexNumber; i++) {
66 if(triangulation->isVertexOnBoundary(i)) {
67 candidateVertices.push_back(i);
71 candidateVertices.resize(vertexNumber);
72 for(SimplexId i = 0; i < vertexNumber; i++)
73 candidateVertices[i] = i;
76 std::vector<std::vector<SimplexId>> closePoints(vertexNumber);
78 this->
printMsg(
"Computing pointwise distances with "
79 + std::to_string(candidateVertices.size()) +
" candidates");
81#ifdef TTK_ENABLE_OPENMP
82#pragma omp parallel for num_threads(threadNumber_)
84 for(SimplexId i = 0; i < (SimplexId)candidateVertices.size(); i++) {
86 std::array<double, 3> p0{};
88 SimplexId
const vertexId0 = candidateVertices[i];
90 input->GetPoint(vertexId0, p0.data());
91 for(SimplexId j = 0; j < (SimplexId)candidateVertices.size(); j++) {
93 std::array<double, 3> p1{};
94 SimplexId
const vertexId1 = candidateVertices[j];
95 input->GetPoint(vertexId1, p1.data());
97 if(distance < DistanceThreshold) {
98 closePoints[vertexId0].push_back(vertexId1);
104 this->
printMsg(
"Merging points...");
106 std::vector<double> minMergeDistance(vertexNumber, -1);
107 std::vector<double> maxMergeDistance(vertexNumber, -1);
108 std::vector<SimplexId> mergeCount(vertexNumber, 0);
109 std::vector<SimplexId> mergeMap(vertexNumber, -1);
111 for(SimplexId i = 0; i < vertexNumber; i++) {
112 if(closePoints[i].size()) {
114 SimplexId targetVertexId = i;
116 SimplexId nextTargetVertexId = targetVertexId;
117 for(SimplexId j = 0; j < (SimplexId)closePoints[targetVertexId].size();
119 if(closePoints[targetVertexId][j] < nextTargetVertexId)
120 nextTargetVertexId = closePoints[targetVertexId][j];
122 targetVertexId = nextTargetVertexId;
123 mergeMap[i] = targetVertexId;
124 }
while(mergeMap[targetVertexId] != targetVertexId);
125 mergeCount[targetVertexId]++;
127 if(i != targetVertexId) {
128 std::array<double, 3> p0{}, p1{};
129 input->GetPoint(i, p0.data());
130 input->GetPoint(targetVertexId, p1.data());
132 if((minMergeDistance[targetVertexId] == -1)
133 || (distance < minMergeDistance[targetVertexId])) {
134 minMergeDistance[targetVertexId] = distance;
136 if((maxMergeDistance[targetVertexId] == -1)
137 || (distance > maxMergeDistance[targetVertexId])) {
138 maxMergeDistance[targetVertexId] = distance;
146 SimplexId vertexIdGen = 0;
147 std::vector<SimplexId> old2new(vertexNumber, 0);
148 std::vector<SimplexId> new2old;
149 for(SimplexId i = 0; i < vertexNumber; i++) {
150 if(mergeMap[i] == i) {
151 old2new[i] = vertexIdGen;
153 new2old.push_back(i);
155 old2new[i] = old2new[mergeMap[i]];
160 vtkNew<vtkPoints> pointSet{};
161 pointSet->SetNumberOfPoints(vertexIdGen);
163 vtkNew<vtkIdTypeArray> mergeCountArray{};
164 mergeCountArray->SetNumberOfTuples(vertexIdGen);
165 mergeCountArray->SetName(
"VertexMergeCount");
167 vtkNew<vtkDoubleArray> minDistanceArray{};
168 minDistanceArray->SetNumberOfTuples(vertexIdGen);
169 minDistanceArray->SetName(
"MinMergeDistance");
171 vtkNew<vtkDoubleArray> maxDistanceArray{};
172 maxDistanceArray->SetNumberOfTuples(vertexIdGen);
173 maxDistanceArray->SetName(
"MaxMergeDistance");
175 std::vector<vtkNew<vtkDoubleArray>> pointData{};
176 pointData.resize(input->GetPointData()->GetNumberOfArrays());
177 for(
size_t i = 0; i < pointData.size(); i++) {
178 pointData[i]->SetName(input->GetPointData()->GetArray(i)->GetName());
179 pointData[i]->SetNumberOfComponents(
180 input->GetPointData()->GetArray(i)->GetNumberOfComponents());
181 pointData[i]->SetNumberOfTuples(vertexIdGen);
184#ifdef TTK_ENABLE_OPENMP
185#pragma omp parallel for num_threads(threadNumber_)
187 for(SimplexId i = 0; i < vertexIdGen; i++) {
188 std::array<double, 3> p{};
189 input->GetPoint(new2old[i], p.data());
190 pointSet->SetPoint(i, p.data());
192 mergeCountArray->SetTuple1(i, mergeCount[new2old[i]]);
193 minDistanceArray->SetTuple1(i, minMergeDistance[new2old[i]]);
194 maxDistanceArray->SetTuple1(i, maxMergeDistance[new2old[i]]);
196 for(
size_t j = 0; j < pointData.size(); j++) {
197 std::vector<double> data(pointData[j]->GetNumberOfComponents());
198 input->GetPointData()->GetArray(j)->GetTuple(new2old[i], data.data());
199 pointData[j]->SetTuple(i, data.data());
203 output->SetPoints(pointSet);
204 for(
size_t i = 0; i < pointData.size(); i++) {
205 output->GetPointData()->AddArray(pointData[i]);
207 output->GetPointData()->AddArray(mergeCountArray);
208 output->GetPointData()->AddArray(minDistanceArray);
209 output->GetPointData()->AddArray(maxDistanceArray);
213 std::vector<vtkNew<vtkDoubleArray>> cellData{};
214 cellData.resize(input->GetCellData()->GetNumberOfArrays());
215 for(
size_t i = 0; i < cellData.size(); i++) {
216 cellData[i]->SetName(input->GetCellData()->GetArray(i)->GetName());
217 cellData[i]->SetNumberOfComponents(
218 input->GetCellData()->GetArray(i)->GetNumberOfComponents());
221 for(SimplexId i = 0; i < input->GetNumberOfCells(); i++) {
222 vtkNew<vtkGenericCell> c{};
223 input->GetCell(i, c);
225 std::vector<SimplexId> newVertexIds;
226 for(
int j = 0; j < c->GetNumberOfPoints(); j++) {
227 SimplexId
const vertexId = old2new[c->GetPointId(j)];
229 for(SimplexId k = 0; k < (SimplexId)newVertexIds.size(); k++) {
230 if(newVertexIds[k] == vertexId) {
236 newVertexIds.push_back(vertexId);
240 vtkNew<vtkIdList> idList{};
241 idList->SetNumberOfIds(newVertexIds.size());
242 for(
size_t j = 0; j < newVertexIds.size(); j++) {
243 idList->SetId(j, newVertexIds[j]);
246 vtkIdType cellId = -1;
248 if((c->GetCellDimension() == 1) && (newVertexIds.size() == 2)) {
249 cellId = output->InsertNextCell(VTK_LINE, idList);
251 if(c->GetCellDimension() == 2) {
252 if(newVertexIds.size() > 2) {
253 cellId = output->InsertNextCell(VTK_POLYGON, idList);
256 if(c->GetCellDimension() == 3) {
257 if(newVertexIds.size() == 4) {
258 cellId = output->InsertNextCell(VTK_TETRA, idList);
260 if(newVertexIds.size() == 8) {
261 cellId = output->InsertNextCell(VTK_HEXAHEDRON, idList);
263 this->
printWrn(
"Ill-defined cell type for cell #" + std::to_string(i)
264 +
" (" + std::to_string(newVertexIds.size())
271 for(
size_t j = 0; j < cellData.size(); j++) {
272 std::vector<double> data(cellData[j]->GetNumberOfComponents());
273 input->GetCellData()->GetArray(j)->GetTuple(i, data.data());
274 cellData[j]->InsertNextTuple(data.data());
278 for(
size_t i = 0; i < cellData.size(); i++)
279 output->GetCellData()->AddArray(cellData[i]);