All–
I’m getting some non-intuitive behavior (I don’t feel confident calling it a bug) when decimating a mesh which has point and cell data assigned. Say that I assign point data and cell data to a coarse mesh, and then decimate it. The point data behaves as I would expect–as points are removed from the mesh during decimation, the associated point data is also removed. The cell data, however, is not removed, and the data becomes disassociated with the cells of the decimated mesh.
I realize that this may not be a trivial problem to solve depending on how the decimation algorithm works (i.e., if the decimation algorithm involves more than simply deleting and repositioning existing faces); however, the problem seems analogous to decimating a mesh with materials applied to the faces, which behaves more-or-less as expected in software such as Blender.
What would be the best way of achieving this? I’ve had a look through the source code to see if there is an obvious place where I could, for example, delete the cell data as cells are deleted, but the Quad Edge Mesh code is a bit dense and I’m having trouble isolating the spot.
Here’s a minimally compilable example showing the behavior.
Best, and thanks as always,
–Davis
#include <itkQuadEdgeMesh.h>
#include <itkRegularSphereMeshSource.h>
#include <itkQuadEdgeMeshDecimationCriteria.h>
#include <itkSquaredEdgeLengthDecimationQuadEdgeMeshFilter.h>
const unsigned int Dimension = 3;
using TCoordinate = float;
using TMesh = itk::QuadEdgeMesh<TCoordinate, Dimension>;
using TCriterion = itk::NumberOfFacesCriterion< TMesh >;
using TDecimation = itk::SquaredEdgeLengthDecimationQuadEdgeMeshFilter< TMesh,
TMesh,
TCriterion >;
using TSphereSource = itk::RegularSphereMeshSource<TMesh>;
int main( int argc, char ** argv )
{
const auto source = TSphereSource::New();
source->Update();
const auto mesh = TMesh::New();
mesh->Graft( source->GetOutput() );
mesh->DisconnectPipeline();
// Assign Labels to Points
for (auto it = mesh->GetPoints()->Begin();
it != mesh->GetPoints()->End();
++it)
{
mesh->SetPointData( it.Index(), it.Index() % 2 );
}
// Assign Labels to Faces
for (auto it = mesh->GetCells()->Begin();
it != mesh->GetCells()->End();
++it)
{
mesh->SetCellData( it.Index(), it.Index() % 2);
}
std::cout << "Original Mesh:" << '\n';
std::cout << "Points: " << mesh->GetNumberOfPoints() << '\n';
std::cout << "Point Data: " << mesh->GetPointData()->Size() << '\n';
std::cout << "Cells: " << mesh->GetNumberOfCells() << '\n';
std::cout << "Cell Data: " << mesh->GetCellData()->Size() << "\n\n";
// Original Mesh:
// Points: 66
// Point Data: 66
// Cells: 128
// Cell Data: 128
const auto criterion = TCriterion::New();
criterion->SetTopologicalChange( true );
criterion->SetNumberOfElements( 50 );
const auto decimate = TDecimation::New();
decimate->SetInput( mesh );
decimate->SetCriterion( criterion );
decimate->Update();
const auto decimated_mesh = TMesh::New();
decimated_mesh->Graft( decimate->GetOutput() );
decimated_mesh->DisconnectPipeline();
std::cout << "Decimated Mesh:" << '\n';
std::cout << "Points: " << decimated_mesh->GetNumberOfPoints() << '\n';
std::cout << "Point Data: " << decimated_mesh->GetPointData()->Size() << '\n';
std::cout << "Cells: " << decimated_mesh->GetNumberOfCells() << '\n';
std::cout << "Cell Data: " << decimated_mesh->GetCellData()->Size() << '\n';
// Decimated Mesh:
// Points: 27
// Point Data: 27
// Cells: 50
// Cell Data: 128 <== Intuitively, I expect this to be 50
return EXIT_SUCCESS;
}