[vtkusers] Using vtkTriangleFilter to reduce concave polygons to convex
Alex Southern
mrapsouthern at gmail.com
Mon Jul 2 05:50:50 EDT 2012
Hi, Thank you for your suggestions, I figured it out below. For some
reason, which one of you is probably aware of, the vtkTriangleFilter
does not behave in an intuitive way when you provide only one polygon.
An example of this is given by the original code I posted.
Bill's suggestion of randomly perturbing the points in each axial
direction by a small amount, although I have not tried it, I am safe to
assume it works. Presumably this is related to the fact that the points
are no longer in the same axial plane. I also tried using a
vtkTriangleFilter on a more complex 3D model that was defined by both
convex (not triangles) and concave polygons, using Paraview to apply the
Triangulate filter (vtkTriangleFilter), it worked perfectly well.
For my needs I want to triangulate a single potentially "bad"polygon and
keep track of which triangles belonged to which polygon. As I explained,
vtkTriangleFilter did not behave well under these conditions. Therefore,
replacing vtkTriangleFilter with vtkDelaunay2D does the trick.
This was probably already known or obvious to most, in any case, there
it is.
Thanks for you time.
A.
#include <vtkVersion.h>
#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkCubeSource.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
using namespace std;
int main()
{
vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> cellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkDelaunay2D> triFilter = vtkSmartPointer<vtkDelaunay2D>::New();
vtkSmartPointer<vtkPolyData> pd1 = vtkSmartPointer<vtkPolyData>::New();
vtkPolyData *pd2;
// Generate a concave polygon that is NOT flat (in one plane)
pts->InsertNextPoint( 1.00, 2.48, 0.00 );
pts->InsertNextPoint( 1.00, 0.00, 0.00 );
pts->InsertNextPoint( 1.00, 1.24, 0.29 );
pts->InsertNextPoint( 0.00, 0.00, 0.00 );
pts->InsertNextPoint( 0.00, 2.48, 0.00 );
int p[5] = {0, 1, 2, 3, 4};
cellArray->InsertNextCell(5,p);
pd1->SetPoints( pts );
pd1->SetPolys( cellArray );
triFilter->SetInput( pd1 );
triFilter->Update();
pd2 = triFilter->GetOutput();
// // Create a renderer, render window, and interactor
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindow->AddRenderer(renderer);
renderWindowInteractor->SetRenderWindow(renderWindow);
// map filtered data
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
mapper->SetInput( pd2 ); // change to pd1 to see bad polygon
actor->SetMapper( mapper );
renderer->AddActor( actor );
renderer->SetBackground(.5, .1, .1);
//// Render and interact
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
On 6/30/2012 7:07 PM, Bill Lorensen wrote:
> Here's a not so elegant solution. It perturbs each point by a small
> random number, does the triangulation and then reassigns the original
> points to the polydata.
>
> #include <vtkVersion.h>
> #include <vtkSmartPointer.h>
> #include <vtkActor.h>
> #include <vtkCubeSource.h>
> #include <vtkPolyData.h>
> #include <vtkCellArray.h>
> #include <vtkPolyDataMapper.h>
> #include <vtkRenderWindow.h>
> #include <vtkRenderWindowInteractor.h>
> #include <vtkRenderer.h>
> #include <vtkPointData.h>
> #include <vtkTriangleFilter.h>
> #include <vtkMath.h>
>
> using namespace std;
>
> int main()
> {
> vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
> vtkSmartPointer<vtkPoints> ptsDelta = vtkSmartPointer<vtkPoints>::New();
> vtkSmartPointer<vtkCellArray> cellArray =
> vtkSmartPointer<vtkCellArray>::New();
>
> vtkSmartPointer<vtkTriangleFilter> triFilter =
> vtkSmartPointer<vtkTriangleFilter>::New();
> vtkSmartPointer<vtkPolyData> pd1 = vtkSmartPointer<vtkPolyData>::New();
> vtkPolyData *pd2;
>
> // Generate a concave polygon that is NOT flat (i.e. not in one plane)
> pts->InsertNextPoint( 1.00, 2.48, 0.00 );
> pts->InsertNextPoint( 1.00, 0.00, 0.00 );
> pts->InsertNextPoint( 1.00, 1.24, 0.29 );
> pts->InsertNextPoint( 0.00, 0.00, 0.00 );
> pts->InsertNextPoint( 0.00, 2.4801, 0.00 );
> int p[5] = {0, 1, 2, 3, 4};
> cellArray->InsertNextCell(5,p);
>
> for (unsigned int i = 0; i < pts->GetNumberOfPoints(); ++i)
> {
> double x, y, z;
> x = pts->GetPoint(i)[0] + vtkMath::Random(0.0, .00001);
> y = pts->GetPoint(i)[1] + vtkMath::Random(0.0, .00001);
> z = pts->GetPoint(i)[2] + vtkMath::Random(0.0, .00001);
> ptsDelta->InsertNextPoint(x, y, z);
> }
> pd1->SetPoints( ptsDelta );
> pd1->SetPolys( cellArray );
>
>
>
> #if VTK_MAJOR_VERSION <= 5
> triFilter->SetInput( pd1 );
> #else
> triFilter->SetInputData( pd1 );
> #endif
> triFilter->Update();
> pd2 = triFilter->GetOutput();
> pd2->SetPoints(pts);
>
> // Create a renderer, render window, and interactor
> vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
> vtkSmartPointer<vtkRenderWindow> renderWindow =
> vtkSmartPointer<vtkRenderWindow>::New();
> vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
> vtkSmartPointer<vtkRenderWindowInteractor>::New();
>
> renderWindow->AddRenderer(renderer);
> renderWindowInteractor->SetRenderWindow(renderWindow);
>
> // map filtered data
> vtkSmartPointer<vtkPolyDataMapper> mapper =
> vtkSmartPointer<vtkPolyDataMapper>::New();
> vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
>
> #if VTK_MAJOR_VERSION <= 5
> mapper->SetInput( pd2 ); // change to pd1 to see bad polygon
> #else
> mapper->SetInputData( pd2 ); // change to pd1 to see bad polygon
> #endif
> actor->SetMapper( mapper );
> renderer->AddActor( actor );
>
> renderer->SetBackground(.5, .1, .1);
>
> //// Render and interact
> renderWindow->Render();
> renderWindowInteractor->Start();
>
> return 0;
> }
More information about the vtkusers
mailing list