15 #include <vtkIdList.h> 16 #include <vtkIntArray.h> 17 #include <vtkIsotropicDiscreteRemeshing.h> 18 #include <vtkMultiThreader.h> 19 #include <vtkPolyData.h> 20 #include <vtkPolyDataNormals.h> 21 #include <vtkSmartPointer.h> 22 #include <vtkSurface.h> 24 struct ClustersQuadrics
26 explicit ClustersQuadrics(
int size) : Elements(new double *[size]), Size(size)
28 for (
int i = 0; i < size; ++i)
30 Elements[i] =
new double[9];
32 for (
int j = 0; j < 9; ++j)
39 for (
int i = 0; i < Size; ++i)
49 ClustersQuadrics(
const ClustersQuadrics &);
50 ClustersQuadrics &operator=(
const ClustersQuadrics &);
56 mitkThrow() <<
"Input surface is nullptr!";
58 if (t >= surface->GetSizeOfPolyDataSeries())
59 mitkThrow() <<
"Input surface doesn't have data at time step " << t <<
"!";
61 vtkPolyData *polyData =
const_cast<mitk::Surface *
>(surface.GetPointer())->GetVtkPolyData(t);
63 if (polyData ==
nullptr)
64 mitkThrow() <<
"PolyData of input surface at time step " << t <<
" is nullptr!";
66 if (polyData->GetNumberOfPolys() == 0)
67 mitkThrow() <<
"Input surface has no polygons at time step " << t <<
"!";
76 int optimizationLevel,
84 vtkSmartPointer<vtkPolyData> surfacePolyData = vtkSmartPointer<vtkPolyData>::New();
85 surfacePolyData->DeepCopy(const_cast<Surface *>(surface.GetPointer())->GetVtkPolyData(t));
87 vtkSmartPointer<vtkSurface> mesh = vtkSmartPointer<vtkSurface>::New();
89 mesh->CreateFromPolyData(surfacePolyData);
90 mesh->GetCellData()->Initialize();
91 mesh->GetPointData()->Initialize();
93 mesh->DisplayMeshProperties();
96 numVertices = surfacePolyData->GetNumberOfPoints();
98 if (edgeSplitting != 0.0)
99 mesh->SplitLongEdges(edgeSplitting);
101 vtkSmartPointer<vtkIsotropicDiscreteRemeshing> remesher = vtkSmartPointer<vtkIsotropicDiscreteRemeshing>::New();
103 remesher->GetMetric()->SetGradation(gradation);
104 remesher->SetBoundaryFixing(boundaryFixing);
105 remesher->SetConsoleOutput(1);
106 remesher->SetForceManifold(forceManifold);
107 remesher->SetInput(mesh);
108 remesher->SetNumberOfClusters(numVertices);
109 remesher->SetNumberOfThreads(vtkMultiThreader::GetGlobalDefaultNumberOfThreads());
110 remesher->SetSubsamplingThreshold(subsampling);
115 if (optimizationLevel != 0)
117 ClustersQuadrics clustersQuadrics(numVertices);
119 vtkSmartPointer<vtkIdList> faceList = vtkSmartPointer<vtkIdList>::New();
120 vtkSmartPointer<vtkIntArray> clustering = remesher->GetClustering();
121 vtkSmartPointer<vtkSurface> remesherInput = remesher->GetInput();
122 int clusteringType = remesher->GetClusteringType();
123 int numItems = remesher->GetNumberOfItems();
124 int numMisclassifiedItems = 0;
126 for (
int i = 0; i < numItems; ++i)
128 int cluster = clustering->GetValue(i);
130 if (cluster >= 0 && cluster < numVertices)
132 if (clusteringType != 0)
134 remesherInput->GetVertexNeighbourFaces(i, faceList);
135 int numIds =
static_cast<int>(faceList->GetNumberOfIds());
137 for (
int j = 0; j < numIds; ++j)
138 vtkQuadricTools::AddTriangleQuadric(
139 clustersQuadrics.Elements[cluster], remesherInput, faceList->GetId(j),
false);
143 vtkQuadricTools::AddTriangleQuadric(clustersQuadrics.Elements[cluster], remesherInput, i,
false);
148 ++numMisclassifiedItems;
152 if (numMisclassifiedItems != 0)
153 std::cout << numMisclassifiedItems <<
" items with wrong cluster association" << std::endl;
155 vtkSmartPointer<vtkSurface> remesherOutput = remesher->GetOutput();
158 for (
int i = 0; i < numVertices; ++i)
160 remesherOutput->GetPoint(i, point);
161 vtkQuadricTools::ComputeRepresentativePoint(clustersQuadrics.Elements[i], point, optimizationLevel);
162 remesherOutput->SetPointCoordinates(i, point);
165 std::cout <<
"After quadrics post-processing:" << std::endl;
166 remesherOutput->DisplayMeshProperties();
169 vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
171 normals->SetInputData(remesher->GetOutput());
172 normals->AutoOrientNormalsOn();
173 normals->ComputeCellNormalsOff();
174 normals->ComputePointNormalsOn();
175 normals->ConsistencyOff();
176 normals->FlipNormalsOff();
177 normals->NonManifoldTraversalOff();
178 normals->SplittingOff();
183 remeshedSurface->SetVtkPolyData(normals->GetOutput());
187 return remeshedSurface;
190 mitk::ACVD::RemeshFilter::RemeshFilter()
195 m_EdgeSplitting(0.0),
196 m_OptimizationLevel(1),
197 m_ForceManifold(
false),
198 m_BoundaryFixing(
false)
201 this->SetNthOutput(0, output);
204 mitk::ACVD::RemeshFilter::~RemeshFilter()
219 this->SetNthOutput(0, output);
MITKREMESHING_EXPORT Surface::Pointer Remesh(Surface::ConstPointer surface, unsigned int t, int numVertices, double gradation, int subsampling=10, double edgeSplitting=0.0, int optimizationLevel=1, bool forceManifold=false, bool boundaryFixing=false)
Remesh a surface and store the result in a new surface.
Class for storing surfaces (vtkPolyData).
static void ValidateSurface(mitk::Surface::ConstPointer surface, unsigned int t)
void GenerateData() override