Commit dc80f419 authored by T.J. Corona's avatar T.J. Corona
Browse files

Correct and augment the behavior of vtkPolygonBuilder

This fix is in reference to bug report 0015582. vtkPolygonBuilder manifested
two problems: triangles that were not adjacent to any triangles that were
previously added to the builder were discarded, and polygons with internal
vertices resulted in overlapping cells (the class was explicitly not designed
to handle polygons with internal vertices). The new version fixes these two
issues, and test TestCutter has been added to check these issues as well.
parent 2e0acc8d
......@@ -12,11 +12,11 @@
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkSmartPointer.h"
#include "vtkIdList.h"
#include "vtkNew.h"
#include "vtkPoints.h"
#include "vtkPolygonBuilder.h"
#include "vtkIdList.h"
#include "vtkSmartPointer.h"
int TestPolygonBuilder(int, char* [])
{
......@@ -25,25 +25,20 @@ int TestPolygonBuilder(int, char* [])
vtkIdType b = points->InsertNextPoint(1,0,0);
vtkIdType c = points->InsertNextPoint(0,1,0);
vtkIdType d = points->InsertNextPoint(1,1,0);
vtkIdType e = points->InsertNextPoint(0.5,0.5,0);
vtkPolygonBuilder builder;
vtkIdType corner[4] = {a,b,c,d};
vtkIdType abc[3]={a,b,c};
if(builder.InsertTriangle(abc)==false)
{
return EXIT_FAILURE;
}
vtkPolygonBuilder builder;
vtkIdType bcd[3]={b,c,d}; //invalid triangle
if(builder.InsertTriangle(bcd)==true) //check whether we correctly fail
{
return EXIT_FAILURE;
}
vtkIdType p[3];
p[0] = e;
vtkIdType cbd[3]={c,b,d};
if(builder.InsertTriangle(cbd)==false)
for (size_t i=0;i<4;i++)
{
return EXIT_FAILURE;
p[1] = corner[i];
p[2] = corner[(i+1)%4];
builder.InsertTriangle(p);
}
vtkNew<vtkIdList> poly;
......@@ -53,14 +48,5 @@ int TestPolygonBuilder(int, char* [])
{
return EXIT_FAILURE;
}
vtkIdType expected[4]= {0,1,3,2};
for(size_t i =0 ;i<4; i++)
{
if(poly->GetId(i)!=expected[i])
{
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
......@@ -19,78 +19,84 @@ vtkPolygonBuilder::vtkPolygonBuilder()
{
}
void vtkPolygonBuilder::Reset()
{
this->Poly.clear();
}
bool vtkPolygonBuilder::InsertTriangle(vtkIdType* abc)
void vtkPolygonBuilder::InsertTriangle(vtkIdType* abc)
{
if(this->Poly.size()==0)
{
this->Insert(0, abc[0]);
this->Insert(0, abc[1]);
this->Insert(1, abc[2]);
return true;
}
// For each triangle edge, and for each direction (clockwise and
// counterclockwise): the number of instances of each edge are recorded, and
// edges with exactly one instance are stored
int i;
VertexRef v(0);
for(i=0; i<3; i++)
for (int i=0;i<3;i++)
{
if(FindEdge(abc[(i+1)%3],abc[(i+2)%3],v))
for (int j=1;j>=-1;j-=2)
{
break;
}
}
Edge edge(abc[i],abc[(i+j+3)%3]);
size_t nInstances = ++(this->EdgeCounter[edge]);
if(i==3)
{
return false;
}
if (nInstances == 1)
{
this->Edges.insert(std::make_pair(edge.first,edge.second));
}
else if (nInstances == 2)
{
std::pair<EdgeMap::iterator, EdgeMap::iterator> range = Edges.equal_range(edge.first);
this->Insert(v, abc[i]);
return true;
EdgeMap::iterator it = range.first;
for (; it != range.second; ++it)
{
if (it->second == edge.second)
{
Edges.erase(it);
break;
}
}
}
}
}
return;
}
void vtkPolygonBuilder::GetPolygon(vtkIdList* poly) const
void vtkPolygonBuilder::GetPolygon(vtkIdList* poly)
{
poly->Reset();
if(this->Poly.size()==0)
// We now have exactly two instances of each outer edge, corresponding to a
// clockwise and counterclockwise traversal
if (this->Edges.size()<6)
{
return;
}
VertexRef v = 0;
do
{
poly->InsertNextId(this->GetVertexId(v));
v = this->GetNextVertex(v);
}while(v!=0);
}
bool vtkPolygonBuilder::FindEdge(vtkIdType a, vtkIdType b, VertexRef& v) const
{
v = 0;
do
EdgeMap::iterator edgeIt = this->Edges.begin();
vtkIdType firstVtx,vtx1,vtx2;
firstVtx = vtx1 = (*edgeIt).first;
poly->InsertNextId(vtx1);
vtx2 = (*edgeIt).second;
while (vtx2 != firstVtx)
{
VertexRef u = this->GetNextVertex(v);
if( this->GetVertexId(u)==a && this->GetVertexId(v)==b )
poly->InsertNextId(vtx2);
// we will find either the inverse to our current edge, or the next edge
// in the path.
edgeIt = this->Edges.find(vtx2);
if ((*edgeIt).second == vtx1)
{
return true;
// we have found the inverse. Remove it and look agian.
this->Edges.erase(edgeIt);
edgeIt = this->Edges.find(vtx2);
}
v = u;
}while(v!=0);
return false;
vtx1 = vtx2;
vtx2 = edgeIt->second;
}
this->Reset();
}
vtkPolygonBuilder::VertexRef vtkPolygonBuilder::Insert(VertexRef i, vtkIdType vertexId)
void vtkPolygonBuilder::Reset()
{
//Allocate a vertex that points to itself
VertexRef j = this->Poly.size();
this->Poly.push_back(Vertex(j,vertexId));
//splice the cycle
this->Poly[j].Next = this->Poly[i].Next;
this->Poly[i].Next = j;
return j;
this->EdgeCounter.clear();
this->Edges.clear();
}
......@@ -16,18 +16,16 @@
//
// .SECTION Description
// The polygon output is the boundary of the union of the triangles.
// It is assumed that the input triangles form a simple polygon without
// internal vertices.
// The algorithm is quadratic to the input size, but
// can be sped up easily by improving the FindEdge() function. It is
// currently used to compute polygon for slicing.
// It is assumed that the input triangles form a simple polygon. It is
// currently used to compute polygons for slicing.
//
#ifndef vtkPolygonBuilder_h
#define vtkPolygonBuilder_h
#include "vtkCommonMiscModule.h" // For export macro
#include <vector> //for private data members
#include <map> //for private data members
#include <utility> //for private data members
#include "vtkType.h" //for basic types
#include <cstddef> //for size_t
#include "vtkObject.h"
......@@ -37,25 +35,17 @@ class VTKCOMMONMISC_EXPORT vtkPolygonBuilder
{
public:
vtkPolygonBuilder();
void InsertTriangle(vtkIdType* abc);
void GetPolygon(vtkIdList* poly);
void Reset();
bool InsertTriangle(vtkIdType* abc);
void GetPolygon(vtkIdList* poly) const;
private:
typedef size_t VertexRef;
struct Vertex
{
VertexRef Next;
vtkIdType Vert;
Vertex(VertexRef next, vtkIdType vert):Next(next), Vert(vert){}
};
bool FindEdge(vtkIdType a, vtkIdType b, VertexRef& v) const;
VertexRef Insert(VertexRef i, vtkIdType vertexId);
vtkIdType GetVertexId(VertexRef i) const { return this->Poly[i].Vert;}
VertexRef GetNextVertex(VertexRef i) const { return this->Poly[i].Next;}
std::vector<Vertex> Poly;
typedef std::pair<vtkIdType,vtkIdType> Edge;
typedef std::map<Edge,size_t> EdgeHistogram;
typedef std::multimap<vtkIdType,vtkIdType> EdgeMap;
EdgeHistogram EdgeCounter;
EdgeMap Edges;
};
#endif
......
......@@ -35,6 +35,7 @@ vtk_add_test_python(
contourQuadraticTetra.py,NO_RT
createBFont.py
cutLoop.py
cutter.py
dispPlot.py
fieldToPolyData.py
fieldToRGrid.py
......
import vtk
from vtk.util.misc import vtkGetDataRoot
ren1 = vtk.vtkRenderer()
ren2 = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
renWin.AddRenderer(ren2)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
xmlReader = vtk.vtkXMLUnstructuredGridReader()
xmlReader.SetFileName( vtkGetDataRoot() + '/Data/cuttertest.vtu' )
plane = vtk.vtkPlane()
plane.SetOrigin( 50,0,405 )
plane.SetNormal( 0,0,1 )
# pipeline for cutter producing triangles
triCutter = vtk.vtkCutter()
triCutter.SetInputConnection( xmlReader.GetOutputPort() )
triCutter.SetCutFunction( plane )
triMapper = vtk.vtkPolyDataMapper()
triMapper.SetInputConnection( triCutter.GetOutputPort() )
triMapper.ScalarVisibilityOff()
triActor = vtk.vtkActor()
triActor.SetMapper( triMapper )
triActor.GetProperty().SetColor( 1,0,0 )
triActor.GetProperty().EdgeVisibilityOn()
triActor.GetProperty().SetEdgeColor( 1,1,1 )
ren1.AddViewProp( triActor )
ren1.SetViewport( 0,0,0.5,1.0)
# pipeline for cutter producing polygons
polyCutter = vtk.vtkCutter()
polyCutter.GenerateTrianglesOff()
polyCutter.SetInputConnection( xmlReader.GetOutputPort() )
polyCutter.SetCutFunction( plane )
polyMapper = vtk.vtkPolyDataMapper()
polyMapper.SetInputConnection( polyCutter.GetOutputPort() )
polyMapper.ScalarVisibilityOff()
polyActor = vtk.vtkActor()
polyActor.SetMapper( polyMapper )
polyActor.GetProperty().SetColor( 0,0,1 )
polyActor.GetProperty().EdgeVisibilityOn()
polyActor.GetProperty().SetEdgeColor( 1,1,1 )
ren2.AddViewProp( polyActor )
ren2.SetViewport( 0.5,0,1.0,1.0 )
# the render window
renWin.SetSize(600,500)
iren.Initialize()
40f219d1bfbedc7bdfb94f7a9cf4e8d5
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment