Here is a way to remesh 3D model, for every triangle cell we can add a center point and create 3 new small cells. The old big triangle will be removed from the model.
You can read other relative posts about remesh model, VTK – Remesh Model By Flip Operation and VTK – Delete Cells And Create Model Without Invalid Points.
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkXMLPolyDataWriter.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkSTLWriter.h>
#include <vtkPlane.h>
#include <vtkImplicitPolyDataDistance.h>
#include <vtkProperty.h>
#include <vtkSelectEnclosedPoints.h>
#include <vtkTriangleFilter.h>
#include <vtkSTLReader.h>
#include <vtkPointData.h>
#include <vtkColorTransferFunction.h>
#include <vtkPolyDataConnectivityFilter.h>
#include <vtkLinearSubdivisionFilter.h>
#include <vtkButterflySubdivisionFilter.h>
#include <vtkNamedColors.h>
#include <vtkClipPolyData.h>
#include <map>
#include "point.hpp"
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
using namespace std;
bool SubdivideCell(vtkSPtr<vtkPolyData> data, int cellId, double edgeLenMax)
{
vtkIdType nPoints;
vtkIdType const *__pts;
data->GetCellPoints(cellId, nPoints, __pts);
vtkIdType pts[3] = { __pts[0], __pts[1], __pts[2] };
cout << "\ncellId: " << cellId << ", cell count: " << data->GetNumberOfCells() << endl;
cout << "pts: " << pts[0] << ", " << pts[1] << ", " << pts[2] << endl;
if (nPoints != 3)
return false;
double totalDistance = 0.0;
for (int j = 0; j < 3; j++)
{
double nextPos[3], curPos[3];
data->GetPoint(pts[j], curPos);
int nextId = pts[(j + 1) % 3];
data->GetPoint(nextId, nextPos);
double distance = sqrt(vtkMath::Distance2BetweenPoints(curPos, nextPos));
totalDistance += distance;
}
double average = totalDistance / 3;
if (average > edgeLenMax)
{
double cellCenterPos[3] = { 0, 0, 0 };
for (int j = 0; j < 3; j++)
{
double curPos[3];
data->GetPoint(pts[j], curPos);
vtkMath::Add(cellCenterPos, curPos, cellCenterPos);
}
vtkMath::MultiplyScalar(cellCenterPos, 1.0/3);
vtkIdType cellCenterPointId = data->InsertNextLinkedPoint(cellCenterPos, 3);
vtkIdType tri[3] = { pts[0], pts[1], cellCenterPointId };
data->RemoveReferenceToCell(pts[2], cellId); // redefine the old cell
data->ReplaceCell( cellId, 3, tri );
data->ResizeCellList( cellCenterPointId, 1 );
data->AddReferenceToCell(cellCenterPointId, cellId);
vtkIdType tri1[3] = { pts[1], pts[2], cellCenterPointId };
int cellId1 = data->InsertNextLinkedCell(VTK_TRIANGLE, 3, tri1);
vtkIdType tri2[3] = { pts[2], pts[0], cellCenterPointId };
int cellId2 = data->InsertNextLinkedCell(VTK_TRIANGLE, 3, tri2);
data->Modified();
return true;
}
return false;
}
int main()
{
vtkSPtrNew( source, vtkSphereSource );
source->SetRadius(3);
source->Update();
auto data = source->GetOutput();
data->BuildCells();
data->BuildLinks();
int oldCellCount = data->GetNumberOfCells();
for( int i = 0; i < oldCellCount; ++i )
{
SubdivideCell( data, i, 1 );
}
vtkSPtrNew( mapper0, vtkPolyDataMapper );
mapper0->SetInputData( data );
vtkSPtrNew( actor0, vtkActor );
actor0->SetMapper( mapper0 );
vtkSPtrNew( renderer, vtkRenderer );
renderer->AddActor( actor0 );
vtkSPtrNew( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
Compare the old model, the left one, and the handled model, the right one.