We have a model looks like in the following scene. It has been cut by a plane but the shape changed after that. So its surface become not flat.

I got the cut plane information and planed to project all points on the cut part to the plane.

The code snippet:

UPolyDataSurfaceToPlane.h

#pragma once

#include <vtkPolyDataAlgorithm.h>
#include <vtkPlane.h>
#include <vtkCell.h>
#include <vtkPlane.h>

class CUPolyDataSurfaceToPlane : public vtkPolyDataAlgorithm
{
public:
  vtkTypeMacro(CUPolyDataSurfaceToPlane, vtkPolyDataAlgorithm);
  static CUPolyDataSurfaceToPlane* New();
  void SetClipPlane(vtkPlane *plane);

protected:
  CUPolyDataSurfaceToPlane(vtkPlane* cf = nullptr);
  ~CUPolyDataSurfaceToPlane() override;
  vtkSmartPointer<vtkPlane> GetCellPlane(vtkSmartPointer<vtkCell> cell, bool &outOfPlane);
  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;

  vtkPlane* m_ClipFunction;

private:
  CUPolyDataSurfaceToPlane(const CUPolyDataSurfaceToPlane&) = delete;
  void operator=(const CUPolyDataSurfaceToPlane&) = delete;
};

UPolyDataSurfaceToPlane.cpp

#include "UPolyDataSurfaceToPlane.h"
#include "tool.h"

#include <vtkInformationVector.h>
#include <vtkInformation.h>
#include <vtkMath.h>

vtkStandardNewMacro(CUPolyDataSurfaceToPlane);

CUPolyDataSurfaceToPlane::CUPolyDataSurfaceToPlane(vtkPlane *cf)
{
    m_ClipFunction = cf;
}

CUPolyDataSurfaceToPlane::~CUPolyDataSurfaceToPlane()
{
    m_ClipFunction = nullptr;
}

void CUPolyDataSurfaceToPlane::SetClipPlane(vtkPlane *plane)
{
    m_ClipFunction = plane;
}

vtkSmartPointer<vtkPlane> CUPolyDataSurfaceToPlane::GetCellPlane(vtkSmartPointer<vtkCell> cell, bool &outOfPlane)
{
    auto points = cell->GetPoints();
    if( points->GetNumberOfPoints() != 3 )
    {
        cout << "not triangle!\n";
        return nullptr;
    }

    PointStruct center, pts[3];
    outOfPlane = false;
    for( int i = 0; i < points->GetNumberOfPoints(); ++i )
    {
        PointStruct pt( points->GetPoint( i ) );
        center = center + pt;
        pts[i] = pt;

        if( m_ClipFunction->EvaluateFunction(pt.point) < 0 )
        {
            outOfPlane = true;
        }
    }
    center /= 3;
    PointStruct normal = ( pts[0] - pts[1] ) ^ ( pts[0] - pts[2] );
    normal.Unit();
    vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
    plane->SetOrigin( center.point );
    plane->SetNormal( normal.point );

    return plane;
}

int CUPolyDataSurfaceToPlane::RequestData
    (
    vtkInformation* vtkNotUsed(request),
    vtkInformationVector** inputVector,
    vtkInformationVector* outputVector
    )
{
    // get the info objects
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
    vtkInformation* outInfo = outputVector->GetInformationObject(0);

    // get the input and output
    vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
    vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
    double funcValueLimit = 1, normalAngleDiffLimit = 10;
    vtkSmartPointer<vtkIdList> surfaceCells = vtkSmartPointer<vtkIdList>::New();
    PointStruct clipNormal( m_ClipFunction->GetNormal() );
    cout << "clipNormal: " << clipNormal[0] << ", " << clipNormal[1] <<  ", " << clipNormal[2] << endl;
    for( int i = 0; i < input->GetNumberOfCells(); ++i )
    {
        vtkSmartPointer<vtkCell> cell = input->GetCell( i );
        bool outOfPlane;
        auto cellPlane = GetCellPlane( cell, outOfPlane );
        PointStruct cellNormal( cellPlane->GetNormal() );
        auto normalAngle = vtkMath::AngleBetweenVectors( clipNormal.point, cellNormal.point );
        auto funcValue = m_ClipFunction->EvaluateFunction( cellPlane->GetOrigin() );
         if( outOfPlane ||
            ( fabs( funcValue ) < funcValueLimit && fabs( normalAngle ) < normalAngleDiffLimit )
          )
        {
            surfaceCells->InsertNextId( i );
        }
    }

    vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
    newPoints->DeepCopy( input->GetPoints() );
    for( int i = 0; i < surfaceCells->GetNumberOfIds(); ++i )
    {
        auto cellId = surfaceCells->GetId( i );
        vtkIdType npts;
        vtkIdType *pts;
        input->GetCell( cellId, pts );
        for( int j = 0; j < 3; ++j )
        {
            PointStruct pt( input->GetPoint( pts[j] ) );
            m_ClipFunction->ProjectPoint( pt.point, pt.point );
            newPoints->SetPoint( pts[j], pt.point );
        }
    }

    vtkSmartPointer<vtkCellArray> newCells = vtkSmartPointer<vtkCellArray>::New();
    newCells->DeepCopy( input->GetPolys() );

    output->SetPoints( newPoints );
    output->SetPolys( newCells );

    return 1;
}

main.cpp

#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSTLReader.h>
#include <vtkTransform.h>
#include <vtkPlaneSource.h>
#include <string>
#include <iostream>
#include <vtkProperty.h>

#include "tool.h"
#include "UPolyDataSurfaceToPlane.h"

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

using namespace std;

void ShowBigPlane(vtkSPtr<vtkRenderer> renderer, vtkSPtr<vtkPlane> plane)
{
    vtkSmartPointer<vtkPlaneSource> planeSource =
        vtkSmartPointer<vtkPlaneSource>::New();
    planeSource->SetCenter( plane->GetOrigin() );
    planeSource->SetNormal( plane->GetNormal() );
    planeSource->Update();

    vtkSmartPointer<vtkPolyDataMapper> planeMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    planeMapper->SetInputData( planeSource->GetOutput() );
    planeMapper->Update();

    int scaleValue = 40;
    vtkSmartPointer<vtkActor> planeActor =
        vtkSmartPointer<vtkActor>::New();
    planeActor->SetMapper( planeMapper );
    planeActor->GetProperty()->SetColor( 0, 1, 1 );

    PointStruct originPt( plane->GetOrigin() );
    vtkSPtrNew( trans, vtkTransform );
    trans->Translate( originPt.point );
    trans->Scale( scaleValue, scaleValue, scaleValue );
    trans->Translate( (-originPt).point );
    planeActor->SetUserTransform( trans );

    renderer->AddActor( planeActor );
}

int main()
{
    std::string filePath = "origin_surface.stl";
    vtkSPtrNew( reader, vtkSTLReader );
    reader->SetFileName( filePath.c_str() );
    reader->Update();

    auto data = reader->GetOutput();

    PointStruct origin( -1.78958, -22.5648, 20.2123 );
    PointStruct normal( 0.00056659, -0.10854, -0.994092 );

    vtkSmartPointer<vtkPlane> cutPlane = vtkSmartPointer<vtkPlane>::New();
    cutPlane->SetOrigin( origin.point );
    cutPlane->SetNormal( normal.point );

    vtkSmartPointer<CUPolyDataSurfaceToPlane> surfaceToPlane = vtkSmartPointer<CUPolyDataSurfaceToPlane>::New();
    surfaceToPlane->SetInputData( data );
    surfaceToPlane->SetClipPlane( cutPlane );
    surfaceToPlane->Update();

    vtkSPtrNew( mapper, vtkPolyDataMapper );
    mapper->SetInputData( surfaceToPlane->GetOutput() );

    vtkSPtrNew( actor, vtkActor );
    actor->SetMapper( mapper );

    vtkSPtrNew( mapper0, vtkPolyDataMapper );
    mapper0->SetInputData( data );

    vtkSPtrNew( actor0, vtkActor );
    actor0->SetMapper( mapper0 );
    actor0->GetProperty()->SetColor( 1, 0, 0 );

    vtkSPtrNew( renderer, vtkRenderer );
    renderer->AddActor( actor );
    //renderer->AddActor( actor0 );
    renderer->SetBackground( 0, 0, 0 );

    ShowBigPlane( renderer, cutPlane );

    vtkSPtrNew( renderWindow, vtkRenderWindow );
    renderWindow->AddRenderer( renderer );

    vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
    renderWindowInteractor->SetRenderWindow( renderWindow );

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

STL File:
origin_surface.stl

Output:

Categories: VTK

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

3D Model Viewer: add grid plane and convex hull.

X
A prohibited operation
0
Would love your thoughts, please comment.x
()
x