Commit c70d60fe authored by T.J. Corona's avatar T.J. Corona Committed by Kitware Robot
Browse files

Merge topic 'delaunay-updates'

d26946ae

 Delaunay: fixes to the extension.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !541
parents 9526bca6 d26946ae
......@@ -48,7 +48,7 @@ std::vector<Delaunay::Shape::Point> ExportDelaunayMesh::operator()(
start_off = tess->nextCellOffset(start_off))
{
tess->vertexIdsOfCell(start_off, cell_conn);
for (std::size_t j = 0; j < cell_conn.size() - 1; j++)
for (std::size_t j = 0; j < cell_conn.size(); j++)
{
pointsForEdge.push_back(
Delaunay::Shape::Point(tess->coords()[cell_conn[j]*3 + 0],
......@@ -58,17 +58,18 @@ std::vector<Delaunay::Shape::Point> ExportDelaunayMesh::operator()(
}
// We transplant the edge's points into the global point vector according to
// the edge use's orientation.
// the edge use's orientation. We skip the first point, as it is always a
// duplicate of the last point in the global vector.
if (eu.orientation() == 1)
{
for (auto p = pointsForEdge.begin(); p != pointsForEdge.end(); ++p)
for (auto p = pointsForEdge.begin() + 1; p != pointsForEdge.end(); ++p)
{
points.push_back(Delaunay::Shape::Point(p->x,p->y));
}
}
else
{
for (auto p = pointsForEdge.rbegin(); p != pointsForEdge.rend(); ++p)
for (auto p = pointsForEdge.rbegin() + 1; p != pointsForEdge.rend(); ++p)
{
points.push_back(Delaunay::Shape::Point(p->x,p->y));
}
......@@ -76,12 +77,6 @@ std::vector<Delaunay::Shape::Point> ExportDelaunayMesh::operator()(
pointsForEdge.clear();
}
// Delaunay polygons do not use a repeated point to denote a loop.
if (points.front() == points.back())
{
points.pop_back();
}
return points;
}
......
......@@ -11,6 +11,8 @@
//=============================================================================
#include "smtk/extension/delaunay/operators/TessellateFace.h"
#include "smtk/attribute/VoidItem.h"
#include "smtk/extension/delaunay/io/ImportDelaunayMesh.h"
#include "smtk/extension/delaunay/io/ExportDelaunayMesh.h"
......@@ -27,6 +29,7 @@
#include "Shape/Point.hh"
#include "Shape/Polygon.hh"
#include "Shape/PolygonUtilities.hh"
#include "Validation/IsValidPolygon.hh"
#include <algorithm>
......@@ -40,7 +43,7 @@ TessellateFace::TessellateFace()
bool TessellateFace::ableToOperate()
{
smtk::model::EntityRef eRef =
this->specification()->findModelEntity("face")->value();
this->specification()->associations()->value();
return
this->Superclass::ableToOperate() &&
......@@ -51,10 +54,11 @@ bool TessellateFace::ableToOperate()
OperatorResult TessellateFace::operateInternal()
{
smtk::model::Face face =
this->specification()->findModelEntity("face")->
smtk::model::Face face = this->specification()->associations()->
value().as<smtk::model::Face>();
bool validatePolygons = this->findVoid("validate polygons")->isEnabled();
// get the face use for the face
smtk::model::FaceUse fu = face.positiveUse();
......@@ -62,7 +66,7 @@ OperatorResult TessellateFace::operateInternal()
smtk::model::Loops exteriorLoops = fu.loops();
if (exteriorLoops.size() == 0)
{
// if we don't have loops we are bailing out!
// if we don't have loops, there is nothing to mesh
smtkErrorMacro(this->log(), "No loops associated with this face.");
return this->createResult(OPERATION_FAILED);
}
......@@ -75,6 +79,9 @@ OperatorResult TessellateFace::operateInternal()
std::vector<Delaunay::Shape::Point> points =
exportToDelaunayMesh(exteriorLoop);
// make a polygon validator
Delaunay::Validation::IsValidPolygon isValidPolygon;
Delaunay::Shape::Polygon p(points);
// if the orientation is not ccw, flip the orientation
if (Delaunay::Shape::Orientation(p) != 1)
......@@ -82,6 +89,13 @@ OperatorResult TessellateFace::operateInternal()
p = Delaunay::Shape::Polygon(points.rbegin(), points.rend());
}
if (validatePolygons && !isValidPolygon(p))
{
// the polygon is invalid, so we exit with failure
smtkErrorMacro(this->log(), "Outer boundary polygon is invalid.");
return this->createResult(OPERATION_FAILED);
}
// discretize the polygon
Delaunay::Discretization::ConstrainedDelaunayMesh discretize;
Delaunay::Mesh::Mesh mesh;
......@@ -99,6 +113,14 @@ OperatorResult TessellateFace::operateInternal()
{
p_sub = Delaunay::Shape::Polygon(points_sub.rbegin(), points_sub.rend());
}
if (validatePolygons && !isValidPolygon(p_sub))
{
// the polygon is invalid, so we exit with failure
smtkErrorMacro(this->log(), "Inner boundary polygon is invalid.");
return this->createResult(OPERATION_FAILED);
}
excise(p_sub, mesh);
}
......
......@@ -9,10 +9,19 @@
Tessellate a model face using Delaunay.
This operation updates the smtk::mesh::Tessellation associated with an
smtk::mesh::Face using Delaunay.
smtk::mesh::Face using Delaunay. The resulting tessellation is
composed only of the boundary points.
</DetailedDescription>
<AssociationsDef Name="face" NumberOfRequiredValues="1">
<MembershipMask>face</MembershipMask>
<BriefDescription>The face to tessellate.</BriefDescription>
</AssociationsDef>
<ItemDefinitions>
<ModelEntity Name="face" NumberOfRequiredValues="1"/>
<Void Name="validate polygons" Label="Validate Polygons prior to Tessellation"
Optional="true" AdvanceLevel="1">
<BriefDescription>Ensure the polygons describing the
boundaries are valid before tessellating the face.</BriefDescription>
</Void>
</ItemDefinitions>
</AttDef>
<!-- Result -->
......
......@@ -11,6 +11,8 @@
//=============================================================================
#include "smtk/extension/delaunay/operators/TriangulateFace.h"
#include "smtk/attribute/VoidItem.h"
#include "smtk/extension/delaunay/io/ImportDelaunayMesh.h"
#include "smtk/extension/delaunay/io/ExportDelaunayMesh.h"
......@@ -27,6 +29,7 @@
#include "Shape/Point.hh"
#include "Shape/Polygon.hh"
#include "Shape/PolygonUtilities.hh"
#include "Validation/IsValidPolygon.hh"
#include <algorithm>
......@@ -40,7 +43,7 @@ TriangulateFace::TriangulateFace()
bool TriangulateFace::ableToOperate()
{
smtk::model::EntityRef eRef =
this->specification()->findModelEntity("face")->value();
this->specification()->associations()->value();
return
this->Superclass::ableToOperate() &&
......@@ -51,10 +54,11 @@ bool TriangulateFace::ableToOperate()
OperatorResult TriangulateFace::operateInternal()
{
smtk::model::Face face =
this->specification()->findModelEntity("face")->
smtk::model::Face face = this->specification()->associations()->
value().as<smtk::model::Face>();
bool validatePolygons = this->findVoid("validate polygons")->isEnabled();
// get the face use for the face
smtk::model::FaceUse fu = face.positiveUse();
......@@ -62,7 +66,7 @@ OperatorResult TriangulateFace::operateInternal()
smtk::model::Loops exteriorLoops = fu.loops();
if (exteriorLoops.size() == 0)
{
// if we don't have loops we are bailing out!
// if we don't have loops, there is nothing to mesh
smtkErrorMacro(this->log(), "No loops associated with this face.");
return this->createResult(OPERATION_FAILED);
}
......@@ -75,6 +79,9 @@ OperatorResult TriangulateFace::operateInternal()
std::vector<Delaunay::Shape::Point> points =
exportToDelaunayMesh(exteriorLoop);
// make a polygon validator
Delaunay::Validation::IsValidPolygon isValidPolygon;
Delaunay::Shape::Polygon p(points);
// if the orientation is not ccw, flip the orientation
if (Delaunay::Shape::Orientation(p) != 1)
......@@ -82,6 +89,13 @@ OperatorResult TriangulateFace::operateInternal()
p = Delaunay::Shape::Polygon(points.rbegin(), points.rend());
}
if (validatePolygons && !isValidPolygon(p))
{
// the polygon is invalid, so we exit with failure
smtkErrorMacro(this->log(), "Outer boundary polygon is invalid.");
return this->createResult(OPERATION_FAILED);
}
// discretize the polygon
Delaunay::Discretization::ConstrainedDelaunayMesh discretize;
Delaunay::Mesh::Mesh mesh;
......@@ -99,6 +113,14 @@ OperatorResult TriangulateFace::operateInternal()
{
p_sub = Delaunay::Shape::Polygon(points_sub.rbegin(), points_sub.rend());
}
if (validatePolygons && !isValidPolygon(p_sub))
{
// the polygon is invalid, so we exit with failure
smtkErrorMacro(this->log(), "Inner boundary polygon is invalid.");
return this->createResult(OPERATION_FAILED);
}
excise(p_sub, mesh);
}
......
......@@ -9,13 +9,20 @@
Triangulate a model face into a mesh using Delaunay.
This operation creates an smtk::mesh::MeshSet associated with an
smtk::mesh::Face using Delaunay. The MeshSet resides in the
smtk::mesh::Collection with the same UUID as the Face's model. If this
collection does not yet exist during the construction of the mesh, it is
created and populated with the MeshSet.
smtk::mesh::Face using Delaunay. The MeshSet resides in a new
smtk::mesh::Collection associated with the face's model. The
resulting triangulation is composed only of the boundary points.
</DetailedDescription>
<AssociationsDef Name="face" NumberOfRequiredValues="1">
<MembershipMask>face</MembershipMask>
<BriefDescription>The face to triangulate.</BriefDescription>
</AssociationsDef>
<ItemDefinitions>
<ModelEntity Name="face" NumberOfRequiredValues="1"/>
<Void Name="validate polygons" Label="Validate Polygons prior to Triangulation"
Optional="true" AdvanceLevel="1">
<BriefDescription>Ensure the polygons describing the
boundaries are valid before triangulating the face.</BriefDescription>
</Void>
</ItemDefinitions>
</AttDef>
<!-- Result -->
......
......@@ -123,9 +123,7 @@ int UnitTestTessellateFace(int, char** const)
std::cerr << "No tessellate face operator\n";
return 1;
}
tessellateFace->specification()->associateEntity(model);
tessellateFace->specification()->findModelEntity("face")->
setValue(face);
tessellateFace->specification()->associateEntity(face);
if (!tessellateFace->ableToOperate())
{
......
......@@ -123,9 +123,7 @@ int UnitTestTriangulateFace(int, char** const)
std::cerr << "No triangulate face operator\n";
return 1;
}
triangulateFace->specification()->associateEntity(model);
triangulateFace->specification()->findModelEntity("face")->
setValue(face);
triangulateFace->specification()->associateEntity(face);
if (!triangulateFace->ableToOperate())
{
......
......@@ -39,8 +39,7 @@ class UnitTessellateFace(smtk.testing.TestCase):
else:
face = self.mgr.findEntitiesOfType(smtk.model.FACE, True)[0]
tessellateFace = self.sess.op('tessellate face')
tessellateFace.specification().associateEntity(self.model)
tessellateFace.specification().findModelEntity("face").setValue(face)
tessellateFace.specification().associateEntity(face)
result = tessellateFace.operate()
tessellatedFace = face.hasTessellation()
assert(len(tessellatedFace.coords()) == 8*3)
......
......@@ -39,8 +39,7 @@ class UnitTriangulateFace(smtk.testing.TestCase):
else:
face = self.mgr.findEntitiesOfType(smtk.model.FACE, True)[0]
triangulateFace = self.sess.op('triangulate face')
triangulateFace.specification().associateEntity(self.model)
triangulateFace.specification().findModelEntity("face").setValue(face)
triangulateFace.specification().associateEntity(face)
result = triangulateFace.operate()
triangulatedFace = self.mgr.meshes().associatedCollections(face)[0]
assert(triangulatedFace.points().size() == 8)
......
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