mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-12-28 13:43:30 +01:00
Triangle::NeighborAcross to return a pointer
Same as Triangle::NeighborCW and Triangle::NeighborCCW
This commit is contained in:
parent
35b2fa916a
commit
1054475eeb
@ -243,6 +243,17 @@ Point* Triangle::PointCCW(const Point& point)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The neighbor across to given point
|
||||
Triangle* Triangle::NeighborAcross(const Point& point)
|
||||
{
|
||||
if (&point == points_[0]) {
|
||||
return neighbors_[0];
|
||||
} else if (&point == points_[1]) {
|
||||
return neighbors_[1];
|
||||
}
|
||||
return neighbors_[2];
|
||||
}
|
||||
|
||||
// The neighbor clockwise to given point
|
||||
Triangle* Triangle::NeighborCW(const Point& point)
|
||||
{
|
||||
@ -349,23 +360,6 @@ void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
|
||||
}
|
||||
}
|
||||
|
||||
// The neighbor across to given point
|
||||
Triangle& Triangle::NeighborAcross(const Point& opoint)
|
||||
{
|
||||
Triangle* neighbor = nullptr;
|
||||
if (&opoint == points_[0]) {
|
||||
neighbor = neighbors_[0];
|
||||
} else if (&opoint == points_[1]) {
|
||||
neighbor = neighbors_[1];
|
||||
} else {
|
||||
neighbor = neighbors_[2];
|
||||
}
|
||||
if (neighbor == nullptr) {
|
||||
throw std::runtime_error("NeighborAcross - null neighbor");
|
||||
}
|
||||
return *neighbor;
|
||||
}
|
||||
|
||||
void Triangle::DebugPrint()
|
||||
{
|
||||
std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl;
|
||||
|
@ -176,6 +176,7 @@ void MarkConstrainedEdge(Point* p, Point* q);
|
||||
int Index(const Point* p);
|
||||
int EdgeIndex(const Point* p1, const Point* p2);
|
||||
|
||||
Triangle* NeighborAcross(const Point& point);
|
||||
Triangle* NeighborCW(const Point& point);
|
||||
Triangle* NeighborCCW(const Point& point);
|
||||
bool GetConstrainedEdgeCCW(const Point& p);
|
||||
@ -203,8 +204,6 @@ void ClearDelunayEdges();
|
||||
inline bool IsInterior();
|
||||
inline void IsInterior(bool b);
|
||||
|
||||
Triangle& NeighborAcross(const Point& opoint);
|
||||
|
||||
void DebugPrint();
|
||||
|
||||
bool CircumcicleContains(const Point&) const;
|
||||
|
@ -108,6 +108,9 @@ void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
|
||||
|
||||
void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)
|
||||
{
|
||||
if (triangle == nullptr) {
|
||||
throw std::runtime_error("EdgeEvent - null triangle");
|
||||
}
|
||||
if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {
|
||||
return;
|
||||
}
|
||||
@ -115,13 +118,13 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
|
||||
Point* p1 = triangle->PointCCW(point);
|
||||
Orientation o1 = Orient2d(eq, *p1, ep);
|
||||
if (o1 == COLLINEAR) {
|
||||
if( triangle->Contains(&eq, p1)) {
|
||||
triangle->MarkConstrainedEdge(&eq, p1 );
|
||||
if (triangle->Contains(&eq, p1)) {
|
||||
triangle->MarkConstrainedEdge(&eq, p1);
|
||||
// We are modifying the constraint maybe it would be better to
|
||||
// not change the given constraint and just keep a variable for the new constraint
|
||||
tcx.edge_event.constrained_edge->q = p1;
|
||||
triangle = &triangle->NeighborAcross(point);
|
||||
EdgeEvent( tcx, ep, *p1, triangle, *p1 );
|
||||
triangle = triangle->NeighborAcross(point);
|
||||
EdgeEvent(tcx, ep, *p1, triangle, *p1);
|
||||
} else {
|
||||
throw std::runtime_error("EdgeEvent - collinear points not supported");
|
||||
}
|
||||
@ -131,13 +134,13 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
|
||||
Point* p2 = triangle->PointCW(point);
|
||||
Orientation o2 = Orient2d(eq, *p2, ep);
|
||||
if (o2 == COLLINEAR) {
|
||||
if( triangle->Contains(&eq, p2)) {
|
||||
triangle->MarkConstrainedEdge(&eq, p2 );
|
||||
if (triangle->Contains(&eq, p2)) {
|
||||
triangle->MarkConstrainedEdge(&eq, p2);
|
||||
// We are modifying the constraint maybe it would be better to
|
||||
// not change the given constraint and just keep a variable for the new constraint
|
||||
tcx.edge_event.constrained_edge->q = p2;
|
||||
triangle = &triangle->NeighborAcross(point);
|
||||
EdgeEvent( tcx, ep, *p2, triangle, *p2 );
|
||||
triangle = triangle->NeighborAcross(point);
|
||||
EdgeEvent(tcx, ep, *p2, triangle, *p2);
|
||||
} else {
|
||||
throw std::runtime_error("EdgeEvent - collinear points not supported");
|
||||
}
|
||||
@ -149,12 +152,13 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
|
||||
// that will cross edge
|
||||
if (o1 == CW) {
|
||||
triangle = triangle->NeighborCCW(point);
|
||||
} else{
|
||||
} else {
|
||||
triangle = triangle->NeighborCW(point);
|
||||
}
|
||||
EdgeEvent(tcx, ep, eq, triangle, point);
|
||||
} else {
|
||||
// This triangle crosses constraint so lets flippin start!
|
||||
assert(triangle);
|
||||
FlipEdgeEvent(tcx, ep, eq, triangle, point);
|
||||
}
|
||||
}
|
||||
@ -215,7 +219,6 @@ void Sweep::Fill(SweepContext& tcx, Node& node)
|
||||
if (!Legalize(tcx, *triangle)) {
|
||||
tcx.MapTriangleToNodes(*triangle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
|
||||
@ -293,7 +296,7 @@ double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const
|
||||
*/
|
||||
const double px = origin->x;
|
||||
const double py = origin->y;
|
||||
const double ax = pa->x- px;
|
||||
const double ax = pa->x - px;
|
||||
const double ay = pa->y - py;
|
||||
const double bx = pb->x - px;
|
||||
const double by = pb->y - py;
|
||||
@ -586,7 +589,7 @@ void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
|
||||
if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
|
||||
// Concave
|
||||
FillRightConcaveEdgeEvent(tcx, edge, node);
|
||||
} else{
|
||||
} else {
|
||||
// Convex
|
||||
FillRightConvexEdgeEvent(tcx, edge, node);
|
||||
// Retry this one
|
||||
@ -610,7 +613,6 @@ void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
|
||||
@ -619,13 +621,13 @@ void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
|
||||
if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) {
|
||||
// Concave
|
||||
FillRightConcaveEdgeEvent(tcx, edge, *node.next);
|
||||
} else{
|
||||
} else {
|
||||
// Convex
|
||||
// Next above or below edge?
|
||||
if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) {
|
||||
// Below
|
||||
FillRightConvexEdgeEvent(tcx, edge, *node.next);
|
||||
} else{
|
||||
} else {
|
||||
// Above
|
||||
}
|
||||
}
|
||||
@ -664,13 +666,13 @@ void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
|
||||
if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {
|
||||
// Concave
|
||||
FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);
|
||||
} else{
|
||||
} else {
|
||||
// Convex
|
||||
// Next above or below edge?
|
||||
if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) {
|
||||
// Below
|
||||
FillLeftConvexEdgeEvent(tcx, edge, *node.prev);
|
||||
} else{
|
||||
} else {
|
||||
// Above
|
||||
}
|
||||
}
|
||||
@ -686,17 +688,22 @@ void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
|
||||
if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
|
||||
// Next is concave
|
||||
FillLeftConcaveEdgeEvent(tcx, edge, node);
|
||||
} else{
|
||||
} else {
|
||||
// Next is convex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)
|
||||
{
|
||||
Triangle& ot = t->NeighborAcross(p);
|
||||
assert(t);
|
||||
Triangle* ot_ptr = t->NeighborAcross(p);
|
||||
if (ot_ptr == nullptr)
|
||||
{
|
||||
throw std::runtime_error("FlipEdgeEvent - null neighbor across");
|
||||
}
|
||||
Triangle& ot = *ot_ptr;
|
||||
Point& op = *ot.OppositePoint(*t, p);
|
||||
|
||||
if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
|
||||
@ -762,7 +769,11 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
|
||||
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
|
||||
Triangle& t, Point& p)
|
||||
{
|
||||
Triangle& ot = t.NeighborAcross(p);
|
||||
Triangle* ot_ptr = t.NeighborAcross(p);
|
||||
if (ot_ptr == nullptr) {
|
||||
throw std::runtime_error("FlipScanEdgeEvent - null neighbor across");
|
||||
}
|
||||
Triangle& ot = *ot_ptr;
|
||||
Point& op = *ot.OppositePoint(t, p);
|
||||
|
||||
if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {
|
||||
@ -775,7 +786,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
|
||||
// also need to set a new flip_triangle first
|
||||
// Turns out at first glance that this is somewhat complicated
|
||||
// so it will have to wait.
|
||||
} else{
|
||||
} else {
|
||||
Point& newP = NextFlipPoint(ep, eq, ot, op);
|
||||
FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP);
|
||||
}
|
||||
@ -790,5 +801,4 @@ Sweep::~Sweep() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace p2t
|
||||
|
@ -21,7 +21,7 @@ BOOST_AUTO_TEST_CASE(BasicTest)
|
||||
new p2t::Point(1, 1),
|
||||
};
|
||||
p2t::CDT cdt{ polyline };
|
||||
cdt.Triangulate();
|
||||
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
||||
const auto result = cdt.GetTriangles();
|
||||
BOOST_REQUIRE_EQUAL(result.size(), 1);
|
||||
BOOST_CHECK_EQUAL(*result[0]->GetPoint(0), *polyline[0]);
|
||||
@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(QuadTest)
|
||||
std::vector<p2t::Point*> polyline{ new p2t::Point(0, 0), new p2t::Point(0, 1),
|
||||
new p2t::Point(1, 1), new p2t::Point(1, 0) };
|
||||
p2t::CDT cdt{ polyline };
|
||||
cdt.Triangulate();
|
||||
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
||||
const auto result = cdt.GetTriangles();
|
||||
BOOST_REQUIRE_EQUAL(result.size(), 2);
|
||||
BOOST_CHECK(p2t::IsDelaunay(result));
|
||||
@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(QuadTest)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(QuadTestThrow)
|
||||
BOOST_AUTO_TEST_CASE(NarrowQuadTest)
|
||||
{
|
||||
// Very narrow quad that demonstrates a failure case during triangulation
|
||||
std::vector<p2t::Point*> polyline {
|
||||
@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(TestbedFilesTest)
|
||||
polyline.push_back(new p2t::Point(x, y));
|
||||
}
|
||||
p2t::CDT cdt{ polyline };
|
||||
cdt.Triangulate();
|
||||
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
||||
const auto result = cdt.GetTriangles();
|
||||
BOOST_REQUIRE(result.size() * 3 > polyline.size());
|
||||
BOOST_CHECK_MESSAGE(p2t::IsDelaunay(result), filename + std::to_string(polyline.size()));
|
||||
|
Loading…
Reference in New Issue
Block a user