How to decimate a PolyData without changing pointData’s scalar’s position? Two classes vtkQuadricDecimation and vtkDecimatePro are worth discussing.

vtkQuadricDecimation can decimate pointdata’s scalar.
We have to set AttributeErrorMetric true to handle it.

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkCamera.h>
#include <vtkActor2D.h>
#include <vtkLineSource.h>
#include <vtkAppendPolyData.h>
#include <vtkPointData.h>
#include <vtkFloatArray.h>
#include <vtkQuadricDecimation.h>
#include <vtkTriangleFilter.h>
#include <vtkPlaneSource.h>

using namespace std;

int main()
{
    vtkSmartPointer<vtkSphereSource> sphereSource =
            vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->SetPhiResolution( 50 );
    sphereSource->SetThetaResolution( 50 );
    sphereSource->Update();

    vtkPolyData *spherePd = sphereSource->GetOutput();
    vtkFloatArray *sphereScalars = vtkFloatArray::New();
    for( int i = 0; i < spherePd->GetNumberOfPoints(); ++i )
    {
        sphereScalars->InsertNextTuple1( 1.0 * i / spherePd->GetNumberOfPoints() );
    }
    spherePd->GetPointData()->SetScalars( sphereScalars );
    sphereScalars->FastDelete();

    vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereMapper->SetInputData( spherePd );

    vtkSmartPointer<vtkActor> sphereActor =
            vtkSmartPointer<vtkActor>::New();
    sphereActor->SetMapper( sphereMapper );

    // Define viewport ranges
    // (xmin, ymin, xmax, ymax) left-top and right-bottom point
    double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
    double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};

    // Setup renderers
    vtkSmartPointer<vtkRenderer> leftRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    leftRenderer->SetViewport(leftViewport);
    leftRenderer->SetBackground(0, 0, 0);

    vtkSmartPointer<vtkRenderer> rightRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    rightRenderer->SetViewport(rightViewport);
    rightRenderer->SetBackground(0, 0, 0);

    leftRenderer->AddActor( sphereActor );

    vtkSmartPointer<vtkQuadricDecimation> decimation
            = vtkSmartPointer<vtkQuadricDecimation>::New();
    decimation->SetTargetReduction( 0.3 );
    decimation->AttributeErrorMetricOn();
    decimation->ScalarsAttributeOn();

    decimation->SetInputData( sphereActor->GetMapper()->GetInput() );
    decimation->Update();
    vtkSmartPointer<vtkPolyDataMapper> decimatedSphereMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    decimatedSphereMapper->SetInputData( decimation->GetOutput() );
    vtkSmartPointer<vtkActor> decimatedSphereActor =
            vtkSmartPointer<vtkActor>::New();
    decimatedSphereActor->SetMapper( decimatedSphereMapper );

    rightRenderer->AddActor( decimatedSphereActor );

    leftRenderer->ResetCamera();
    rightRenderer->ResetCamera();

    vtkSmartPointer<vtkRenderWindow> renderWindow =
            vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize(600, 300);
    renderWindow->AddRenderer( leftRenderer );
    renderWindow->AddRenderer( rightRenderer );

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow( renderWindow );

    renderWindow->Render();
    renderWindowInteractor->Start();
    return 0;
}

Display:



But I found the scalar may change pointData’s scalar’s position in the way.

 double decimatePercent = 0.5;
 vtkSmartPointer<vtkQuadricDecimation> decimation
     = vtkSmartPointer<vtkQuadricDecimation>::New();
 decimation->SetTargetReduction( decimatePercent );
 decimation->AttributeErrorMetricOn();
 decimation->ScalarsAttributeOn();
 decimation->SetInputData( polydata );
 decimation->Update();



I can’t just change attributes’ proportion such as ScalarsWeight or VectorsWeight to fix the issue.
Then I find vtkDecimatePro may help me to get what I want.

 double decimatePercent = 0.5;
 vtkSmartPointer<vtkDecimatePro> decimation =
   vtkSmartPointer<vtkDecimatePro>::New();
 decimation->SetTargetReduction( decimatePercent );
 decimation->PreserveTopologyOn();
 decimation->SetInputData( polydata );
 decimation->Update();



Test code:
actorCollection

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkCamera.h>
#include <vtkActor2D.h>
#include <vtkLineSource.h>
#include <vtkAppendPolyData.h>
#include <vtkPointData.h>
#include <vtkFloatArray.h>
#include <vtkCamera.h>
#include <vtkSTLReader.h>
#include <vtkDecimatePro.h>
#include <vtkFloatArray.h>

#include "vtkSetGet.h"
#include "myQuadricDecimation.h"
#include "UMacroDefinition.h"

#include <vtkTriangleFilter.h>
#include <vtkPlaneSource.h>
#include <vtkQuadricDecimation.h>
#include <QString>

using namespace std;

bool LoadOldArchdataFile( vtkPolyData *archData )
{
    QString filePath = "/Users/weiyang/Desktop/archData_l.ad";

    ifstream iStream;
    iStream.open(filePath.toStdString(), ios::binary);

    if (iStream.is_open() == false)
        return false;
    int archType;
    iStream.read((char*)&archType, sizeof(archType));

    vtkIdType numberOfPoints;
    char cNumberOfPoints[8];
    iStream.read(cNumberOfPoints, sizeof(cNumberOfPoints));
    BYTEARRAY_TO_VTKIDTYPE(cNumberOfPoints, numberOfPoints);

    vSPNew(points, vtkPoints);
    for (vtkIdType i = 0; i < numberOfPoints; i++)
    {
        double pointPos[3];
        iStream.read((char*)pointPos, sizeof(pointPos));
        points->InsertNextPoint(pointPos);
    }

    char cNumberOfCells[8];
    iStream.read(cNumberOfCells, sizeof(cNumberOfCells));
    vtkIdType numberOfCells;
    BYTEARRAY_TO_VTKIDTYPE(cNumberOfCells, numberOfCells);

    vSPNew(cells, vtkCellArray);
    for (vtkIdType i = 0; i < numberOfCells; i++)
    {
        vtkIdType nPoints;
        char cNPoints[8];
        iStream.read(cNPoints, sizeof(cNPoints));
        BYTEARRAY_TO_VTKIDTYPE(cNPoints, nPoints);

        vtkIdType *pts = new vtkIdType[nPoints];
        for (vtkIdType j = 0; j < nPoints; j++)
        {
            char cPts[8];
            iStream.read(cPts, sizeof(cPts));
            BYTEARRAY_TO_VTKIDTYPE(cPts, pts[j]);
        }
        cells->InsertNextCell(nPoints);
        for (int j = 0; j < nPoints; j++)
            cells->InsertCellPoint(pts[j]);

        delete[]pts;
    }

    vtkIdType numberOfPointTypeArray = 0;
    char cNumberOfPointTypeArray[8];
    iStream.read(cNumberOfPointTypeArray, sizeof(cNumberOfPointTypeArray));
    BYTEARRAY_TO_VTKIDTYPE(cNumberOfPointTypeArray, numberOfPointTypeArray);
    if (numberOfPointTypeArray == 0)
    {
        iStream.close();
        return false;
    }

    vSPNew(pointTypeArray, vtkIntArray);
    for (vtkIdType i = 0; i < numberOfPointTypeArray; i++)
    {
        int pointType;
        iStream.read((char*)&pointType, sizeof(pointType));
        pointTypeArray->InsertNextValue(pointType);
    }

    vSPNew( floatArray, vtkIntArray ); //vtkFloatArray);
    for (vtkIdType i = 0; i < numberOfPointTypeArray; i++)
    {
        int value = pointTypeArray->GetValue( i );
        value = value % 3;
        floatArray->InsertNextValue( value ); //1.0 * value / 13
    }

    archData->SetPoints(points);
    archData->SetPolys(cells);
    //archData->GetPointData()->SetScalars( pointTypeArray );
    archData->GetPointData()->SetScalars( floatArray );
    archData->Modified();
    archData->BuildCells();
    archData->BuildLinks();

    vtkIdType numberOfSeedPointList;
    char cNumberOfSeedPointList[8];
    iStream.read(cNumberOfSeedPointList, sizeof(cNumberOfSeedPointList));
    BYTEARRAY_TO_VTKIDTYPE(cNumberOfSeedPointList, numberOfSeedPointList);
    vSP<vtkIdList> seedPointList = vSP<vtkIdList>::New(); //m_ZipsAndEMs->Getm_SeedPointList();
    seedPointList->Reset();
    for (vtkIdType i = 0; i < numberOfSeedPointList; i++)
    {
        vtkIdType pointId;
        char cPointId[8];
        iStream.read(cPointId, sizeof(cPointId));
        BYTEARRAY_TO_VTKIDTYPE(cPointId, pointId);
        seedPointList->InsertNextId(pointId);
    }
    iStream.close();
    return true;
}

int main()
{
    setbuf( stdout, nullptr );

    double decimatePercent = 0.5;
    /*
    vtkSmartPointer<vtkSphereSource> sphereSource =
            vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->SetPhiResolution( 50 );
    sphereSource->SetThetaResolution( 50 );
    sphereSource->Update();
    */

    //vtkPolyData *spherePd = stlReader->GetOutput(); //sphereSource->GetOutput();
    vSPNew( spherePd, vtkPolyData );
    LoadOldArchdataFile( spherePd );
/*    vtkFloatArray *sphereScalars = vtkFloatArray::New();
    for( int i = 0; i < spherePd->GetNumberOfPoints(); ++i )
    {
        sphereScalars->InsertNextTuple1( 1.0 * i / spherePd->GetNumberOfPoints() );
    }
    spherePd->GetPointData()->SetScalars( sphereScalars );
    sphereScalars->FastDelete(); */

    vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereMapper->SetInputData( spherePd );

    vtkSmartPointer<vtkActor> sphereActor =
            vtkSmartPointer<vtkActor>::New();
    sphereActor->SetMapper( sphereMapper );

    // Define viewport ranges
    // (xmin, ymin, xmax, ymax) left-top and right-bottom point
    double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
    double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};

    // Setup renderers
    vtkSmartPointer<vtkRenderer> leftRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    leftRenderer->SetViewport(leftViewport);
    leftRenderer->SetBackground(0, 0, 0);

    vtkSmartPointer<vtkRenderer> rightRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    rightRenderer->SetViewport(rightViewport);
    rightRenderer->SetBackground(0, 0, 0);

    leftRenderer->AddActor( sphereActor );

//    vtkSmartPointer<vtkQuadricDecimation> decimation
//            = vtkSmartPointer<vtkQuadricDecimation>::New();
//    decimation->SetTargetReduction( decimatePercent );
//    decimation->AttributeErrorMetricOn();
//    decimation->ScalarsAttributeOn();

    vtkSmartPointer<vtkDecimatePro> decimation =
      vtkSmartPointer<vtkDecimatePro>::New();
    //decimation->SetInputData(inputPolyData);
    decimation->SetTargetReduction( decimatePercent );
    //decimation->PreserveTopologyOn();

    decimation->SetInputData( sphereActor->GetMapper()->GetInput() );
    decimation->Update();
    decimation->PrintSelf( std::cout, *vtkIndent::New() );
    vtkSmartPointer<vtkPolyDataMapper> decimatedSphereMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    decimatedSphereMapper->SetInputData( decimation->GetOutput() );
    vtkSmartPointer<vtkActor> decimatedSphereActor =
            vtkSmartPointer<vtkActor>::New();
    decimatedSphereActor->SetMapper( decimatedSphereMapper );

    rightRenderer->AddActor( decimatedSphereActor );

    vtkSmartPointer<vtkCamera> camera =
            vtkSmartPointer<vtkCamera>::New();
    leftRenderer->SetActiveCamera( camera );
    rightRenderer->SetActiveCamera( camera );
    leftRenderer->ResetCamera();
    rightRenderer->ResetCamera();

    vtkSmartPointer<vtkRenderWindow> renderWindow =
            vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize(600, 300);
    renderWindow->AddRenderer( leftRenderer );
    renderWindow->AddRenderer( rightRenderer );

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow( renderWindow );

    renderWindow->Render();
    renderWindowInteractor->Start();
    return 0;
}

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You cannot copy content of this page