diff --git a/external/poly2tri/common/dll_symbol.h b/external/poly2tri/common/dll_symbol.h new file mode 100644 index 00000000000..8e06ab6574e --- /dev/null +++ b/external/poly2tri/common/dll_symbol.h @@ -0,0 +1,32 @@ +/* + * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors + * https://github.com/jhasse/poly2tri + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define P2T_DLL_SYMBOL diff --git a/external/poly2tri/common/shapes.cc b/external/poly2tri/common/shapes.cc index ed821752aab..d4bd6e03add 100644 --- a/external/poly2tri/common/shapes.cc +++ b/external/poly2tri/common/shapes.cc @@ -40,44 +40,44 @@ Point::Point(double x, double y) : x(x), y(y) } std::ostream& operator<<(std::ostream& out, const Point& point) { - return out << point.x << "," << point.y; + return out << point.x << "," << point.y; } Triangle::Triangle(Point& a, Point& b, Point& c) { - points_[0] = &a; points_[1] = &b; points_[2] = &c; - neighbors_[0] = nullptr; neighbors_[1] = nullptr; neighbors_[2] = nullptr; - constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; - delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; - interior_ = false; + points_[0] = &a; points_[1] = &b; points_[2] = &c; + neighbors_[0] = nullptr; neighbors_[1] = nullptr; neighbors_[2] = nullptr; + constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; + interior_ = false; } // Update neighbor pointers void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) { - if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) - neighbors_[0] = t; - else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) - neighbors_[1] = t; - else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) - neighbors_[2] = t; - else - assert(0); + if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) + neighbors_[0] = t; + else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) + neighbors_[1] = t; + else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) + neighbors_[2] = t; + else + assert(0); } // Exhaustive search to update neighbor pointers void Triangle::MarkNeighbor(Triangle& t) { - if (t.Contains(points_[1], points_[2])) { - neighbors_[0] = &t; - t.MarkNeighbor(points_[1], points_[2], this); - } else if (t.Contains(points_[0], points_[2])) { - neighbors_[1] = &t; - t.MarkNeighbor(points_[0], points_[2], this); - } else if (t.Contains(points_[0], points_[1])) { - neighbors_[2] = &t; - t.MarkNeighbor(points_[0], points_[1], this); - } + if (t.Contains(points_[1], points_[2])) { + neighbors_[0] = &t; + t.MarkNeighbor(points_[1], points_[2], this); + } else if (t.Contains(points_[0], points_[2])) { + neighbors_[1] = &t; + t.MarkNeighbor(points_[0], points_[2], this); + } else if (t.Contains(points_[0], points_[1])) { + neighbors_[2] = &t; + t.MarkNeighbor(points_[0], points_[1], this); + } } /** @@ -86,12 +86,10 @@ void Triangle::MarkNeighbor(Triangle& t) void Triangle::Clear() { Triangle *t; - for( int i=0; i<3; i++ ) - { - t = neighbors_[i]; - if( t != nullptr ) - { - t->ClearNeighbor( this ); + for (auto& neighbor : neighbors_) { + t = neighbor; + if (t != nullptr) { + t->ClearNeighbor(this); } } ClearNeighbors(); @@ -116,298 +114,298 @@ void Triangle::ClearNeighbor(const Triangle *triangle ) void Triangle::ClearNeighbors() { - neighbors_[0] = nullptr; - neighbors_[1] = nullptr; - neighbors_[2] = nullptr; + neighbors_[0] = nullptr; + neighbors_[1] = nullptr; + neighbors_[2] = nullptr; } void Triangle::ClearDelunayEdges() { - delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; } Point* Triangle::OppositePoint(Triangle& t, const Point& p) { - Point *cw = t.PointCW(p); - return PointCW(*cw); + Point *cw = t.PointCW(p); + return PointCW(*cw); } // Legalized triangle by rotating clockwise around point(0) void Triangle::Legalize(Point& point) { - points_[1] = points_[0]; - points_[0] = points_[2]; - points_[2] = &point; + points_[1] = points_[0]; + points_[0] = points_[2]; + points_[2] = &point; } // Legalize triagnle by rotating clockwise around oPoint void Triangle::Legalize(Point& opoint, Point& npoint) { - if (&opoint == points_[0]) { - points_[1] = points_[0]; - points_[0] = points_[2]; - points_[2] = &npoint; - } else if (&opoint == points_[1]) { - points_[2] = points_[1]; - points_[1] = points_[0]; - points_[0] = &npoint; - } else if (&opoint == points_[2]) { - points_[0] = points_[2]; - points_[2] = points_[1]; - points_[1] = &npoint; - } else { - assert(0); - } + if (&opoint == points_[0]) { + points_[1] = points_[0]; + points_[0] = points_[2]; + points_[2] = &npoint; + } else if (&opoint == points_[1]) { + points_[2] = points_[1]; + points_[1] = points_[0]; + points_[0] = &npoint; + } else if (&opoint == points_[2]) { + points_[0] = points_[2]; + points_[2] = points_[1]; + points_[1] = &npoint; + } else { + assert(0); + } } int Triangle::Index(const Point* p) { - if (p == points_[0]) { - return 0; - } else if (p == points_[1]) { - return 1; - } else if (p == points_[2]) { - return 2; - } - assert(0); - return -1; + if (p == points_[0]) { + return 0; + } else if (p == points_[1]) { + return 1; + } else if (p == points_[2]) { + return 2; + } + assert(0); + return -1; } int Triangle::EdgeIndex(const Point* p1, const Point* p2) { - if (points_[0] == p1) { - if (points_[1] == p2) { - return 2; - } else if (points_[2] == p2) { - return 1; + if (points_[0] == p1) { + if (points_[1] == p2) { + return 2; + } else if (points_[2] == p2) { + return 1; + } + } else if (points_[1] == p1) { + if (points_[2] == p2) { + return 0; + } else if (points_[0] == p2) { + return 2; + } + } else if (points_[2] == p1) { + if (points_[0] == p2) { + return 1; + } else if (points_[1] == p2) { + return 0; + } } - } else if (points_[1] == p1) { - if (points_[2] == p2) { - return 0; - } else if (points_[0] == p2) { - return 2; - } - } else if (points_[2] == p1) { - if (points_[0] == p2) { - return 1; - } else if (points_[1] == p2) { - return 0; - } - } - return -1; + return -1; } void Triangle::MarkConstrainedEdge(int index) { - constrained_edge[index] = true; + constrained_edge[index] = true; } void Triangle::MarkConstrainedEdge(Edge& edge) { - MarkConstrainedEdge(edge.p, edge.q); + MarkConstrainedEdge(edge.p, edge.q); } // Mark edge as constrained void Triangle::MarkConstrainedEdge(Point* p, Point* q) { - if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { - constrained_edge[2] = true; - } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { - constrained_edge[1] = true; - } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { - constrained_edge[0] = true; - } + if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { + constrained_edge[2] = true; + } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { + constrained_edge[1] = true; + } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { + constrained_edge[0] = true; + } } // The point counter-clockwise to given point Point* Triangle::PointCW(const Point& point) { - if (&point == points_[0]) { - return points_[2]; - } else if (&point == points_[1]) { - return points_[0]; - } else if (&point == points_[2]) { - return points_[1]; - } - assert(0); - return nullptr; + if (&point == points_[0]) { + return points_[2]; + } else if (&point == points_[1]) { + return points_[0]; + } else if (&point == points_[2]) { + return points_[1]; + } + assert(0); + return nullptr; } // The point counter-clockwise to given point Point* Triangle::PointCCW(const Point& point) { - if (&point == points_[0]) { - return points_[1]; - } else if (&point == points_[1]) { - return points_[2]; - } else if (&point == points_[2]) { - return points_[0]; - } - assert(0); - return nullptr; + if (&point == points_[0]) { + return points_[1]; + } else if (&point == points_[1]) { + return points_[2]; + } else if (&point == points_[2]) { + return points_[0]; + } + assert(0); + 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]; + 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) { - if (&point == points_[0]) { - return neighbors_[1]; - } else if (&point == points_[1]) { - return neighbors_[2]; - } - return neighbors_[0]; + if (&point == points_[0]) { + return neighbors_[1]; + } else if (&point == points_[1]) { + return neighbors_[2]; + } + return neighbors_[0]; } // The neighbor counter-clockwise to given point Triangle* Triangle::NeighborCCW(const Point& point) { - if (&point == points_[0]) { - return neighbors_[2]; - } else if (&point == points_[1]) { - return neighbors_[0]; - } - return neighbors_[1]; + if (&point == points_[0]) { + return neighbors_[2]; + } else if (&point == points_[1]) { + return neighbors_[0]; + } + return neighbors_[1]; } bool Triangle::GetConstrainedEdgeCCW(const Point& p) { - if (&p == points_[0]) { - return constrained_edge[2]; - } else if (&p == points_[1]) { - return constrained_edge[0]; - } - return constrained_edge[1]; + if (&p == points_[0]) { + return constrained_edge[2]; + } else if (&p == points_[1]) { + return constrained_edge[0]; + } + return constrained_edge[1]; } bool Triangle::GetConstrainedEdgeCW(const Point& p) { - if (&p == points_[0]) { - return constrained_edge[1]; - } else if (&p == points_[1]) { - return constrained_edge[2]; - } - return constrained_edge[0]; + if (&p == points_[0]) { + return constrained_edge[1]; + } else if (&p == points_[1]) { + return constrained_edge[2]; + } + return constrained_edge[0]; } void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce) { - if (&p == points_[0]) { - constrained_edge[2] = ce; - } else if (&p == points_[1]) { - constrained_edge[0] = ce; - } else { - constrained_edge[1] = ce; - } + if (&p == points_[0]) { + constrained_edge[2] = ce; + } else if (&p == points_[1]) { + constrained_edge[0] = ce; + } else { + constrained_edge[1] = ce; + } } void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce) { - if (&p == points_[0]) { - constrained_edge[1] = ce; - } else if (&p == points_[1]) { - constrained_edge[2] = ce; - } else { - constrained_edge[0] = ce; - } + if (&p == points_[0]) { + constrained_edge[1] = ce; + } else if (&p == points_[1]) { + constrained_edge[2] = ce; + } else { + constrained_edge[0] = ce; + } } bool Triangle::GetDelunayEdgeCCW(const Point& p) { - if (&p == points_[0]) { - return delaunay_edge[2]; - } else if (&p == points_[1]) { - return delaunay_edge[0]; - } - return delaunay_edge[1]; + if (&p == points_[0]) { + return delaunay_edge[2]; + } else if (&p == points_[1]) { + return delaunay_edge[0]; + } + return delaunay_edge[1]; } bool Triangle::GetDelunayEdgeCW(const Point& p) { - if (&p == points_[0]) { - return delaunay_edge[1]; - } else if (&p == points_[1]) { - return delaunay_edge[2]; - } - return delaunay_edge[0]; + if (&p == points_[0]) { + return delaunay_edge[1]; + } else if (&p == points_[1]) { + return delaunay_edge[2]; + } + return delaunay_edge[0]; } void Triangle::SetDelunayEdgeCCW(const Point& p, bool e) { - if (&p == points_[0]) { - delaunay_edge[2] = e; - } else if (&p == points_[1]) { - delaunay_edge[0] = e; - } else { - delaunay_edge[1] = e; - } + if (&p == points_[0]) { + delaunay_edge[2] = e; + } else if (&p == points_[1]) { + delaunay_edge[0] = e; + } else { + delaunay_edge[1] = e; + } } void Triangle::SetDelunayEdgeCW(const Point& p, bool e) { - if (&p == points_[0]) { - delaunay_edge[1] = e; - } else if (&p == points_[1]) { - delaunay_edge[2] = e; - } else { - delaunay_edge[0] = e; - } + if (&p == points_[0]) { + delaunay_edge[1] = e; + } else if (&p == points_[1]) { + delaunay_edge[2] = e; + } else { + delaunay_edge[0] = e; + } } void Triangle::DebugPrint() { - std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl; + std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl; } bool Triangle::CircumcicleContains(const Point& point) const { - assert(IsCounterClockwise()); - const double dx = points_[0]->x - point.x; - const double dy = points_[0]->y - point.y; - const double ex = points_[1]->x - point.x; - const double ey = points_[1]->y - point.y; - const double fx = points_[2]->x - point.x; - const double fy = points_[2]->y - point.y; + assert(IsCounterClockwise()); + const double dx = points_[0]->x - point.x; + const double dy = points_[0]->y - point.y; + const double ex = points_[1]->x - point.x; + const double ey = points_[1]->y - point.y; + const double fx = points_[2]->x - point.x; + const double fy = points_[2]->y - point.y; - const double ap = dx * dx + dy * dy; - const double bp = ex * ex + ey * ey; - const double cp = fx * fx + fy * fy; + const double ap = dx * dx + dy * dy; + const double bp = ex * ex + ey * ey; + const double cp = fx * fx + fy * fy; - return (dx * (fy * bp - cp * ey) - dy * (fx * bp - cp * ex) + ap * (fx * ey - fy * ex)) < 0; + return (dx * (fy * bp - cp * ey) - dy * (fx * bp - cp * ex) + ap * (fx * ey - fy * ex)) < 0; } bool Triangle::IsCounterClockwise() const { - return (points_[1]->x - points_[0]->x) * (points_[2]->y - points_[0]->y) - - (points_[2]->x - points_[0]->x) * (points_[1]->y - points_[0]->y) > - 0; + return (points_[1]->x - points_[0]->x) * (points_[2]->y - points_[0]->y) - + (points_[2]->x - points_[0]->x) * (points_[1]->y - points_[0]->y) > + 0; } bool IsDelaunay(const std::vector& triangles) { - for (const auto triangle : triangles) { - for (const auto other : triangles) { - if (triangle == other) { - continue; - } - for (int i = 0; i < 3; ++i) { - if (triangle->CircumcicleContains(*other->GetPoint(i))) { - return false; + for (const auto triangle : triangles) { + for (const auto other : triangles) { + if (triangle == other) { + continue; + } + for (int i = 0; i < 3; ++i) { + if (triangle->CircumcicleContains(*other->GetPoint(i))) { + return false; + } + } } - } } - } - return true; + return true; } -} +} // namespace p2t diff --git a/external/poly2tri/common/shapes.h b/external/poly2tri/common/shapes.h index 5bf8c8fb483..334fc2e0b93 100644 --- a/external/poly2tri/common/shapes.h +++ b/external/poly2tri/common/shapes.h @@ -29,9 +29,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Include guard -#ifndef SHAPES_H -#define SHAPES_H +#pragma once + +#include "dll_symbol.h" #include #include @@ -42,290 +42,288 @@ namespace p2t { struct Edge; -struct Point { +struct P2T_DLL_SYMBOL Point { - double x, y; + double x, y; - /// Default constructor does nothing (for performance). - Point() - { - x = 0.0; - y = 0.0; - } + /// Default constructor does nothing (for performance). + Point() + { + x = 0.0; + y = 0.0; + } - /// The edges this point constitutes an upper ending point - std::vector edge_list; + /// The edges this point constitutes an upper ending point + std::vector edge_list; - /// Construct using coordinates. - Point(double x, double y); + /// Construct using coordinates. + Point(double x, double y); - /// Set this point to all zeros. - void set_zero() - { - x = 0.0; - y = 0.0; - } + /// Set this point to all zeros. + void set_zero() + { + x = 0.0; + y = 0.0; + } - /// Set this point to some specified coordinates. - void set(double x_, double y_) - { - x = x_; - y = y_; - } + /// Set this point to some specified coordinates. + void set(double x_, double y_) + { + x = x_; + y = y_; + } - /// Negate this point. - Point operator -() const - { - Point v; - v.set(-x, -y); - return v; - } + /// Negate this point. + Point operator -() const + { + Point v; + v.set(-x, -y); + return v; + } - /// Add a point to this point. - void operator +=(const Point& v) - { - x += v.x; - y += v.y; - } + /// Add a point to this point. + void operator +=(const Point& v) + { + x += v.x; + y += v.y; + } - /// Subtract a point from this point. - void operator -=(const Point& v) - { - x -= v.x; - y -= v.y; - } + /// Subtract a point from this point. + void operator -=(const Point& v) + { + x -= v.x; + y -= v.y; + } - /// Multiply this point by a scalar. - void operator *=(double a) - { - x *= a; - y *= a; - } + /// Multiply this point by a scalar. + void operator *=(double a) + { + x *= a; + y *= a; + } - /// Get the length of this point (the norm). - double Length() const - { - return sqrt(x * x + y * y); - } + /// Get the length of this point (the norm). + double Length() const + { + return sqrt(x * x + y * y); + } - /// Convert this point into a unit point. Returns the Length. - double Normalize() - { - const double len = Length(); - x /= len; - y /= len; - return len; - } + /// Convert this point into a unit point. Returns the Length. + double Normalize() + { + const double len = Length(); + x /= len; + y /= len; + return len; + } }; -std::ostream& operator<<(std::ostream&, const Point&); +P2T_DLL_SYMBOL std::ostream& operator<<(std::ostream&, const Point&); // Represents a simple polygon's edge -struct Edge { +struct P2T_DLL_SYMBOL Edge { - Point* p, *q; + Point* p, *q; - /// Constructor - Edge(Point& p1, Point& p2) : p(&p1), q(&p2) - { - if (p1.y > p2.y) { - q = &p1; - p = &p2; - } else if (p1.y == p2.y) { - if (p1.x > p2.x) { - q = &p1; - p = &p2; - } else if (p1.x == p2.x) { - // Repeat points - throw std::runtime_error("Edge::Edge: p1 == p2"); - } + /// Constructor + Edge(Point& p1, Point& p2) : p(&p1), q(&p2) + { + if (p1.y > p2.y) { + q = &p1; + p = &p2; + } else if (p1.y == p2.y) { + if (p1.x > p2.x) { + q = &p1; + p = &p2; + } else if (p1.x == p2.x) { + // Repeat points + throw std::runtime_error("Edge::Edge: p1 == p2"); + } + } + + q->edge_list.push_back(this); } - - q->edge_list.push_back(this); - } }; // Triangle-based data structures are know to have better performance than quad-edge structures // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // "Triangulations in CGAL" -class Triangle { +class P2T_DLL_SYMBOL Triangle { public: -/// Constructor -Triangle(Point& a, Point& b, Point& c); + /// Constructor + Triangle(Point& a, Point& b, Point& c); -/// Flags to determine if an edge is a Constrained edge -bool constrained_edge[3]; -/// Flags to determine if an edge is a Delauney edge -bool delaunay_edge[3]; + /// Flags to determine if an edge is a Constrained edge + bool constrained_edge[3]; + /// Flags to determine if an edge is a Delauney edge + bool delaunay_edge[3]; -Point* GetPoint(int index); -Point* PointCW(const Point& point); -Point* PointCCW(const Point& point); -Point* OppositePoint(Triangle& t, const Point& p); + Point* GetPoint(int index); + Point* PointCW(const Point& point); + Point* PointCCW(const Point& point); + Point* OppositePoint(Triangle& t, const Point& p); -Triangle* GetNeighbor(int index); -void MarkNeighbor(Point* p1, Point* p2, Triangle* t); -void MarkNeighbor(Triangle& t); + Triangle* GetNeighbor(int index); + void MarkNeighbor(Point* p1, Point* p2, Triangle* t); + void MarkNeighbor(Triangle& t); -void MarkConstrainedEdge(int index); -void MarkConstrainedEdge(Edge& edge); -void MarkConstrainedEdge(Point* p, Point* q); + void MarkConstrainedEdge(int index); + void MarkConstrainedEdge(Edge& edge); + void MarkConstrainedEdge(Point* p, Point* q); -int Index(const Point* p); -int EdgeIndex(const Point* p1, const Point* p2); + 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); -bool GetConstrainedEdgeCW(const Point& p); -void SetConstrainedEdgeCCW(const Point& p, bool ce); -void SetConstrainedEdgeCW(const Point& p, bool ce); -bool GetDelunayEdgeCCW(const Point& p); -bool GetDelunayEdgeCW(const Point& p); -void SetDelunayEdgeCCW(const Point& p, bool e); -void SetDelunayEdgeCW(const Point& p, bool e); + Triangle* NeighborAcross(const Point& point); + Triangle* NeighborCW(const Point& point); + Triangle* NeighborCCW(const Point& point); + bool GetConstrainedEdgeCCW(const Point& p); + bool GetConstrainedEdgeCW(const Point& p); + void SetConstrainedEdgeCCW(const Point& p, bool ce); + void SetConstrainedEdgeCW(const Point& p, bool ce); + bool GetDelunayEdgeCCW(const Point& p); + bool GetDelunayEdgeCW(const Point& p); + void SetDelunayEdgeCCW(const Point& p, bool e); + void SetDelunayEdgeCW(const Point& p, bool e); -bool Contains(const Point* p); -bool Contains(const Edge& e); -bool Contains(const Point* p, const Point* q); -void Legalize(Point& point); -void Legalize(Point& opoint, Point& npoint); -/** + bool Contains(const Point* p); + bool Contains(const Edge& e); + bool Contains(const Point* p, const Point* q); + void Legalize(Point& point); + void Legalize(Point& opoint, Point& npoint); + /** * Clears all references to all other triangles and points */ -void Clear(); -void ClearNeighbor(const Triangle *triangle); -void ClearNeighbors(); -void ClearDelunayEdges(); + void Clear(); + void ClearNeighbor(const Triangle *triangle); + void ClearNeighbors(); + void ClearDelunayEdges(); -inline bool IsInterior(); -inline void IsInterior(bool b); + inline bool IsInterior(); + inline void IsInterior(bool b); -void DebugPrint(); + void DebugPrint(); -bool CircumcicleContains(const Point&) const; + bool CircumcicleContains(const Point&) const; private: -bool IsCounterClockwise() const; + bool IsCounterClockwise() const; -/// Triangle points -Point* points_[3]; -/// Neighbor list -Triangle* neighbors_[3]; + /// Triangle points + Point* points_[3]; + /// Neighbor list + Triangle* neighbors_[3]; -/// Has this triangle been marked as an interior triangle? -bool interior_; + /// Has this triangle been marked as an interior triangle? + bool interior_; }; inline bool cmp(const Point* a, const Point* b) { - if (a->y < b->y) { - return true; - } else if (a->y == b->y) { - // Make sure q is point with greater x value - if (a->x < b->x) { - return true; + if (a->y < b->y) { + return true; + } else if (a->y == b->y) { + // Make sure q is point with greater x value + if (a->x < b->x) { + return true; + } } - } - return false; + return false; } /// Add two points_ component-wise. inline Point operator +(const Point& a, const Point& b) { - return Point(a.x + b.x, a.y + b.y); + return Point(a.x + b.x, a.y + b.y); } /// Subtract two points_ component-wise. inline Point operator -(const Point& a, const Point& b) { - return Point(a.x - b.x, a.y - b.y); + return Point(a.x - b.x, a.y - b.y); } /// Multiply point by scalar inline Point operator *(double s, const Point& a) { - return Point(s * a.x, s * a.y); + return Point(s * a.x, s * a.y); } inline bool operator ==(const Point& a, const Point& b) { - return a.x == b.x && a.y == b.y; + return a.x == b.x && a.y == b.y; } inline bool operator !=(const Point& a, const Point& b) { - return !(a.x == b.x) || !(a.y == b.y); + return !(a.x == b.x) || !(a.y == b.y); } /// Peform the dot product on two vectors. inline double Dot(const Point& a, const Point& b) { - return a.x * b.x + a.y * b.y; + return a.x * b.x + a.y * b.y; } /// Perform the cross product on two vectors. In 2D this produces a scalar. inline double Cross(const Point& a, const Point& b) { - return a.x * b.y - a.y * b.x; + return a.x * b.y - a.y * b.x; } /// Perform the cross product on a point and a scalar. In 2D this produces /// a point. inline Point Cross(const Point& a, double s) { - return Point(s * a.y, -s * a.x); + return Point(s * a.y, -s * a.x); } /// Perform the cross product on a scalar and a point. In 2D this produces /// a point. inline Point Cross(double s, const Point& a) { - return Point(-s * a.y, s * a.x); + return Point(-s * a.y, s * a.x); } inline Point* Triangle::GetPoint(int index) { - return points_[index]; + return points_[index]; } inline Triangle* Triangle::GetNeighbor(int index) { - return neighbors_[index]; + return neighbors_[index]; } inline bool Triangle::Contains(const Point* p) { - return p == points_[0] || p == points_[1] || p == points_[2]; + return p == points_[0] || p == points_[1] || p == points_[2]; } inline bool Triangle::Contains(const Edge& e) { - return Contains(e.p) && Contains(e.q); + return Contains(e.p) && Contains(e.q); } inline bool Triangle::Contains(const Point* p, const Point* q) { - return Contains(p) && Contains(q); + return Contains(p) && Contains(q); } inline bool Triangle::IsInterior() { - return interior_; + return interior_; } inline void Triangle::IsInterior(bool b) { - interior_ = b; + interior_ = b; } /// Is this set a valid delaunay triangulation? -bool IsDelaunay(const std::vector&); +P2T_DLL_SYMBOL bool IsDelaunay(const std::vector&); } - -#endif diff --git a/external/poly2tri/common/utils.h b/external/poly2tri/common/utils.h index b4b78bf0be0..3734ce87c33 100644 --- a/external/poly2tri/common/utils.h +++ b/external/poly2tri/common/utils.h @@ -29,13 +29,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef UTILS_H -#define UTILS_H +#pragma once // Otherwise #defines like M_PI are undeclared under Visual Studio -#ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES -#endif #include "shapes.h" @@ -67,15 +64,19 @@ enum Orientation { CW, CCW, COLLINEAR }; */ Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc) { - double detleft = (pa.x - pc.x) * (pb.y - pc.y); - double detright = (pa.y - pc.y) * (pb.x - pc.x); - double val = detleft - detright; - if (val > -EPSILON && val < EPSILON) { - return COLLINEAR; - } else if (val > 0) { - return CCW; - } - return CW; + double detleft = (pa.x - pc.x) * (pb.y - pc.y); + double detright = (pa.y - pc.y) * (pb.x - pc.x); + double val = detleft - detright; + + // Using a tolerance here fails on concave-by-subepsilon boundaries + // if (val > -EPSILON && val < EPSILON) { + // Using == on double makes -Wfloat-equal warnings yell at us + if (std::fpclassify(val) == FP_ZERO) { + return COLLINEAR; + } else if (val > 0) { + return CCW; + } + return CW; } /* @@ -114,18 +115,16 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point& pd) { - double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y); - if (oadb >= -EPSILON) { - return false; - } + double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y); + if (oadb >= -EPSILON) { + return false; + } - double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y); - if (oadc <= EPSILON) { - return false; - } - return true; + double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y); + if (oadc <= EPSILON) { + return false; + } + return true; } } - -#endif diff --git a/external/poly2tri/sweep/advancing_front.cc b/external/poly2tri/sweep/advancing_front.cc index b8e9609efcd..170dc86ebcd 100644 --- a/external/poly2tri/sweep/advancing_front.cc +++ b/external/poly2tri/sweep/advancing_front.cc @@ -36,75 +36,75 @@ namespace p2t { AdvancingFront::AdvancingFront(Node& head, Node& tail) { - head_ = &head; - tail_ = &tail; - search_node_ = &head; + head_ = &head; + tail_ = &tail; + search_node_ = &head; } Node* AdvancingFront::LocateNode(double x) { - Node* node = search_node_; + Node* node = search_node_; - if (x < node->value) { - while ((node = node->prev) != nullptr) { - if (x >= node->value) { - search_node_ = node; - return node; - } + if (x < node->value) { + while ((node = node->prev) != nullptr) { + if (x >= node->value) { + search_node_ = node; + return node; + } + } + } else { + while ((node = node->next) != nullptr) { + if (x < node->value) { + search_node_ = node->prev; + return node->prev; + } + } } - } else { - while ((node = node->next) != nullptr) { - if (x < node->value) { - search_node_ = node->prev; - return node->prev; - } - } - } - return nullptr; + return nullptr; } Node* AdvancingFront::FindSearchNode(double x) { - (void)x; // suppress compiler warnings "unused parameter 'x'" - // TODO: implement BST index - return search_node_; + (void)x; // suppress compiler warnings "unused parameter 'x'" + // TODO: implement BST index + return search_node_; } Node* AdvancingFront::LocatePoint(const Point* point) { - const double px = point->x; - Node* node = FindSearchNode(px); - const double nx = node->point->x; + const double px = point->x; + Node* node = FindSearchNode(px); + const double nx = node->point->x; - if (px == nx) { - if (point != node->point) { - // We might have two nodes with same x value for a short time - if (point == node->prev->point) { - node = node->prev; - } else if (point == node->next->point) { - node = node->next; - } else { - assert(0); - } + if (px == nx) { + if (point != node->point) { + // We might have two nodes with same x value for a short time + if (point == node->prev->point) { + node = node->prev; + } else if (point == node->next->point) { + node = node->next; + } else { + assert(0); + } + } + } else if (px < nx) { + while ((node = node->prev) != nullptr) { + if (point == node->point) { + break; + } + } + } else { + while ((node = node->next) != nullptr) { + if (point == node->point) + break; + } } - } else if (px < nx) { - while ((node = node->prev) != nullptr) { - if (point == node->point) { - break; - } - } - } else { - while ((node = node->next) != nullptr) { - if (point == node->point) - break; - } - } - if(node) search_node_ = node; - return node; + if(node) search_node_ = node; + return node; } AdvancingFront::~AdvancingFront() { } -} +} // namespace p2t diff --git a/external/poly2tri/sweep/advancing_front.h b/external/poly2tri/sweep/advancing_front.h index 3de07082434..fe171132836 100644 --- a/external/poly2tri/sweep/advancing_front.h +++ b/external/poly2tri/sweep/advancing_front.h @@ -29,8 +29,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ADVANCED_FRONT_H -#define ADVANCED_FRONT_H +#pragma once #include "../common/shapes.h" @@ -40,21 +39,21 @@ struct Node; // Advancing front node struct Node { - Point* point; - Triangle* triangle; + Point* point; + Triangle* triangle; - Node* next; - Node* prev; + Node* next; + Node* prev; - double value; + double value; - Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x) - { - } + Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x) + { + } - Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x) - { - } + Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x) + { + } }; @@ -62,57 +61,55 @@ struct Node { class AdvancingFront { public: -AdvancingFront(Node& head, Node& tail); -// Destructor -~AdvancingFront(); + AdvancingFront(Node& head, Node& tail); + // Destructor + ~AdvancingFront(); -Node* head(); -void set_head(Node* node); -Node* tail(); -void set_tail(Node* node); -Node* search(); -void set_search(Node* node); + Node* head(); + void set_head(Node* node); + Node* tail(); + void set_tail(Node* node); + Node* search(); + void set_search(Node* node); -/// Locate insertion point along advancing front -Node* LocateNode(double x); + /// Locate insertion point along advancing front + Node* LocateNode(double x); -Node* LocatePoint(const Point* point); + Node* LocatePoint(const Point* point); private: -Node* head_, *tail_, *search_node_; + Node* head_, *tail_, *search_node_; -Node* FindSearchNode(double x); + Node* FindSearchNode(double x); }; inline Node* AdvancingFront::head() { - return head_; + return head_; } inline void AdvancingFront::set_head(Node* node) { - head_ = node; + head_ = node; } inline Node* AdvancingFront::tail() { - return tail_; + return tail_; } inline void AdvancingFront::set_tail(Node* node) { - tail_ = node; + tail_ = node; } inline Node* AdvancingFront::search() { - return search_node_; + return search_node_; } inline void AdvancingFront::set_search(Node* node) { - search_node_ = node; + search_node_ = node; } } - -#endif diff --git a/external/poly2tri/sweep/cdt.cc b/external/poly2tri/sweep/cdt.cc index 4dfe6a6419e..a242c28873e 100644 --- a/external/poly2tri/sweep/cdt.cc +++ b/external/poly2tri/sweep/cdt.cc @@ -34,38 +34,38 @@ namespace p2t { CDT::CDT(const std::vector& polyline) { - sweep_context_ = new SweepContext(polyline); - sweep_ = new Sweep; + sweep_context_ = new SweepContext(polyline); + sweep_ = new Sweep; } void CDT::AddHole(const std::vector& polyline) { - sweep_context_->AddHole(polyline); + sweep_context_->AddHole(polyline); } void CDT::AddPoint(Point* point) { - sweep_context_->AddPoint(point); + sweep_context_->AddPoint(point); } void CDT::Triangulate() { - sweep_->Triangulate(*sweep_context_); + sweep_->Triangulate(*sweep_context_); } std::vector CDT::GetTriangles() { - return sweep_context_->GetTriangles(); + return sweep_context_->GetTriangles(); } std::list CDT::GetMap() { - return sweep_context_->GetMap(); + return sweep_context_->GetMap(); } CDT::~CDT() { - delete sweep_context_; - delete sweep_; + delete sweep_context_; + delete sweep_; } } // namespace p2t diff --git a/external/poly2tri/sweep/cdt.h b/external/poly2tri/sweep/cdt.h index efeeda38897..e0678359546 100644 --- a/external/poly2tri/sweep/cdt.h +++ b/external/poly2tri/sweep/cdt.h @@ -29,13 +29,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CDT_H -#define CDT_H +#pragma once #include "advancing_front.h" #include "sweep_context.h" #include "sweep.h" +#include "../common/dll_symbol.h" + /** * * @author Mason Green @@ -44,62 +45,60 @@ namespace p2t { -class CDT +class P2T_DLL_SYMBOL CDT { public: - /** + /** * Constructor - add polyline with non repeating points * * @param polyline */ - CDT(const std::vector& polyline); + CDT(const std::vector& polyline); - /** + /** * Destructor - clean up memory */ - ~CDT(); + ~CDT(); - /** + /** * Add a hole * * @param polyline */ - void AddHole(const std::vector& polyline); + void AddHole(const std::vector& polyline); - /** + /** * Add a steiner point * * @param point */ - void AddPoint(Point* point); + void AddPoint(Point* point); - /** + /** * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points */ - void Triangulate(); + void Triangulate(); - /** + /** * Get CDT triangles */ - std::vector GetTriangles(); + std::vector GetTriangles(); - /** + /** * Get triangle map */ - std::list GetMap(); + std::list GetMap(); - private: +private: - /** + /** * Internals */ - SweepContext* sweep_context_; - Sweep* sweep_; + SweepContext* sweep_context_; + Sweep* sweep_; }; } - -#endif diff --git a/external/poly2tri/sweep/sweep.cc b/external/poly2tri/sweep/sweep.cc index 3267a41774f..ed23044b6de 100644 --- a/external/poly2tri/sweep/sweep.cc +++ b/external/poly2tri/sweep/sweep.cc @@ -41,260 +41,297 @@ namespace p2t { // Triangulate simple polygon with holes void Sweep::Triangulate(SweepContext& tcx) { - tcx.InitTriangulation(); - tcx.CreateAdvancingFront(); - // Sweep points; build mesh - SweepPoints(tcx); - // Clean up - FinalizationPolygon(tcx); + tcx.InitTriangulation(); + tcx.CreateAdvancingFront(); + // Sweep points; build mesh + SweepPoints(tcx); + // Clean up + FinalizationPolygon(tcx); } void Sweep::SweepPoints(SweepContext& tcx) { - for (size_t i = 1; i < tcx.point_count(); i++) { - Point& point = *tcx.GetPoint(i); - Node* node = &PointEvent(tcx, point); - for (unsigned int j = 0; j < point.edge_list.size(); j++) { - EdgeEvent(tcx, point.edge_list[j], node); + for (size_t i = 1; i < tcx.point_count(); i++) { + Point& point = *tcx.GetPoint(i); + Node* node = &PointEvent(tcx, point); + for (auto& j : point.edge_list) { + EdgeEvent(tcx, j, node); + } } - } } void Sweep::FinalizationPolygon(SweepContext& tcx) { - // Get an Internal triangle to start with - Triangle* t = tcx.front()->head()->next->triangle; - Point* p = tcx.front()->head()->next->point; - while (t && !t->GetConstrainedEdgeCW(*p)) { - t = t->NeighborCCW(*p); - } + // Get an Internal triangle to start with + Triangle* t = tcx.front()->head()->next->triangle; + Point* p = tcx.front()->head()->next->point; + while (t && !t->GetConstrainedEdgeCW(*p)) { + t = t->NeighborCCW(*p); + } - // Collect interior triangles constrained by edges - if (t) { - tcx.MeshClean(*t); - } + // Collect interior triangles constrained by edges + if (t) { + tcx.MeshClean(*t); + } } Node& Sweep::PointEvent(SweepContext& tcx, Point& point) { - Node* node_ptr = tcx.LocateNode(point); - if (!node_ptr || !node_ptr->point || !node_ptr->next || !node_ptr->next->point) - { - throw std::runtime_error("PointEvent - null node"); - } + Node* node_ptr = tcx.LocateNode(point); + if (!node_ptr || !node_ptr->point || !node_ptr->next || !node_ptr->next->point) + { + throw std::runtime_error("PointEvent - null node"); + } - Node& node = *node_ptr; - Node& new_node = NewFrontTriangle(tcx, point, node); + Node& node = *node_ptr; + Node& new_node = NewFrontTriangle(tcx, point, node); - // Only need to check +epsilon since point never have smaller - // x value than node due to how we fetch nodes from the front - if (point.x <= node.point->x + EPSILON) { - Fill(tcx, node); - } + // Only need to check +epsilon since point never have smaller + // x value than node due to how we fetch nodes from the front + if (point.x <= node.point->x + EPSILON) { + Fill(tcx, node); + } - //tcx.AddNode(new_node); + //tcx.AddNode(new_node); - FillAdvancingFront(tcx, new_node); - return new_node; + FillAdvancingFront(tcx, new_node); + return new_node; } void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - tcx.edge_event.constrained_edge = edge; - tcx.edge_event.right = (edge->p->x > edge->q->x); + tcx.edge_event.constrained_edge = edge; + tcx.edge_event.right = (edge->p->x > edge->q->x); - if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { - return; - } + if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { + return; + } - // For now we will do all needed filling - // TODO: integrate with flip process might give some better performance - // but for now this avoid the issue with cases that needs both flips and fills - FillEdgeEvent(tcx, edge, node); - EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); + // For now we will do all needed filling + // TODO: integrate with flip process might give some better performance + // but for now this avoid the issue with cases that needs both flips and fills + FillEdgeEvent(tcx, edge, node); + EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); } 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; - } - - Point* p1 = triangle->PointCCW(point); - Orientation o1 = Orient2d(eq, *p1, ep); - if (o1 == COLLINEAR) { - 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); - } else { - throw std::runtime_error("EdgeEvent - collinear points not supported"); + if (triangle == nullptr) { + throw std::runtime_error("EdgeEvent - null triangle"); } - return; - } - - Point* p2 = triangle->PointCW(point); - Orientation o2 = Orient2d(eq, *p2, ep); - if (o2 == COLLINEAR) { - 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); - } else { - throw std::runtime_error("EdgeEvent - collinear points not supported"); + if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { + return; } - return; - } - if (o1 == o2) { - // Need to decide if we are rotating CW or CCW to get to a triangle - // that will cross edge - if (o1 == CW) { - triangle = triangle->NeighborCCW(point); - } else { - triangle = triangle->NeighborCW(point); + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { + 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); + } else { + throw std::runtime_error("EdgeEvent - collinear points not supported"); + } + return; + } + + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { + 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); + } else { + throw std::runtime_error("EdgeEvent - collinear points not supported"); + } + return; + } + + if (o1 == o2) { + // Need to decide if we are rotating CW or CCW to get to a triangle + // that will cross edge + if (o1 == CW) { + triangle = triangle->NeighborCCW(point); + } 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); } - EdgeEvent(tcx, ep, eq, triangle, point); - } else { - // This triangle crosses constraint so lets flippin start! - assert(triangle); - FlipEdgeEvent(tcx, ep, eq, triangle, point); - } } bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) { - const int index = triangle.EdgeIndex(&ep, &eq); + const int index = triangle.EdgeIndex(&ep, &eq); - if (index != -1) { - triangle.MarkConstrainedEdge(index); - Triangle* t = triangle.GetNeighbor(index); - if (t) { - t->MarkConstrainedEdge(&ep, &eq); + if (index != -1) { + triangle.MarkConstrainedEdge(index); + Triangle* t = triangle.GetNeighbor(index); + if (t) { + t->MarkConstrainedEdge(&ep, &eq); + } + return true; } - return true; - } - return false; + return false; } Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node) { - Triangle* triangle = new Triangle(point, *node.point, *node.next->point); + Triangle* triangle = new Triangle(point, *node.point, *node.next->point); - triangle->MarkNeighbor(*node.triangle); - tcx.AddToMap(triangle); + triangle->MarkNeighbor(*node.triangle); + tcx.AddToMap(triangle); - Node* new_node = new Node(point); - nodes_.push_back(new_node); + Node* new_node = new Node(point); + nodes_.push_back(new_node); - new_node->next = node.next; - new_node->prev = &node; - node.next->prev = new_node; - node.next = new_node; + new_node->next = node.next; + new_node->prev = &node; + node.next->prev = new_node; + node.next = new_node; - if (!Legalize(tcx, *triangle)) { - tcx.MapTriangleToNodes(*triangle); - } + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } - return *new_node; + return *new_node; } void Sweep::Fill(SweepContext& tcx, Node& node) { - Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); + Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); - // TODO: should copy the constrained_edge value from neighbor triangles - // for now constrained_edge values are copied during the legalize - triangle->MarkNeighbor(*node.prev->triangle); - triangle->MarkNeighbor(*node.triangle); + // TODO: should copy the constrained_edge value from neighbor triangles + // for now constrained_edge values are copied during the legalize + triangle->MarkNeighbor(*node.prev->triangle); + triangle->MarkNeighbor(*node.triangle); - tcx.AddToMap(triangle); + tcx.AddToMap(triangle); - // Update the advancing front - node.prev->next = node.next; - node.next->prev = node.prev; + // Update the advancing front + node.prev->next = node.next; + node.next->prev = node.prev; - // If it was legalized the triangle has already been mapped - if (!Legalize(tcx, *triangle)) { - tcx.MapTriangleToNodes(*triangle); - } + // If it was legalized the triangle has already been mapped + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } } void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) { - // Fill right holes - Node* node = n.next; + // Fill right holes + Node* node = n.next; - while (node && node->next) { - // if HoleAngle exceeds 90 degrees then break. - if (LargeHole_DontFill(node)) break; - Fill(tcx, *node); - node = node->next; - } - - // Fill left holes - node = n.prev; - - while (node && node->prev) { - // if HoleAngle exceeds 90 degrees then break. - if (LargeHole_DontFill(node)) break; - Fill(tcx, *node); - node = node->prev; - } - - // Fill right basins - if (n.next && n.next->next) { - const double angle = BasinAngle(n); - if (angle < PI_3div4) { - FillBasin(tcx, n); + while (node && node->next) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->next; + } + + // Fill left holes + node = n.prev; + + while (node && node->prev) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->prev; + } + + // Fill right basins + if (n.next && n.next->next) { + const double angle = BasinAngle(n); + if (angle < PI_3div4) { + FillBasin(tcx, n); + } } - } } // True if HoleAngle exceeds 90 degrees. +// LargeHole_DontFill checks if the advancing front has a large hole. +// A "Large hole" is a triangle formed by a sequence of points in the advancing +// front where three neighbor points form a triangle. +// And angle between left-top, bottom, and right-top points is more than 90 degrees. +// The first part of the algorithm reviews only three neighbor points, e.g. named A, B, C. +// Additional part of this logic reviews a sequence of 5 points - +// additionally reviews one point before and one after the sequence of three (A, B, C), +// e.g. named X and Y. +// In this case, angles are XBC and ABY and this if angles are negative or more +// than 90 degrees LargeHole_DontFill returns true. +// But there is a configuration when ABC has a negative angle but XBC or ABY is less +// than 90 degrees and positive. +// Then function LargeHole_DontFill return false and initiates filling. +// This filling creates a triangle ABC and adds it to the advancing front. +// But in the case when angle ABC is negative this triangle goes inside the advancing front +// and can intersect previously created triangles. +// This triangle leads to making wrong advancing front and problems in triangulation in the future. +// Looks like such a triangle should not be created. +// The simplest way to check and fix it is to check an angle ABC. +// If it is negative LargeHole_DontFill should return true and +// not initiate creating the ABC triangle in the advancing front. +// X______A Y +// \ / +// \ / +// \ B / +// | / +// | / +// |/ +// C bool Sweep::LargeHole_DontFill(const Node* node) const { - const Node* nextNode = node->next; - const Node* prevNode = node->prev; - if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) - return false; + const Node* nextNode = node->next; + const Node* prevNode = node->prev; + if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) + return false; - // Check additional points on front. - const Node* next2Node = nextNode->next; - // "..Plus.." because only want angles on same side as point being added. - if ((next2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) - return false; + if (AngleIsNegative(node->point, nextNode->point, prevNode->point)) + return true; - const Node* prev2Node = prevNode->prev; - // "..Plus.." because only want angles on same side as point being added. - if ((prev2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) - return false; + // Check additional points on front. + const Node* next2Node = nextNode->next; + // "..Plus.." because only want angles on same side as point being added. + if ((next2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) + return false; - return true; + const Node* prev2Node = prevNode->prev; + // "..Plus.." because only want angles on same side as point being added. + if ((prev2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) + return false; + + return true; +} + +bool Sweep::AngleIsNegative(const Point* origin, const Point* pa, const Point* pb) const { + const double angle = Angle(origin, pa, pb); + return angle < 0; } bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const { - const double angle = Angle(origin, pa, pb); - return ((angle > PI_div2) || (angle < -PI_div2)); + const double angle = Angle(origin, pa, pb); + return ((angle > PI_div2) || (angle < -PI_div2)); } bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const { - const double angle = Angle(origin, pa, pb); - return (angle > PI_div2) || (angle < 0); + const double angle = Angle(origin, pa, pb); + return (angle > PI_div2) || (angle < 0); } double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const { - /* Complex plane + /* Complex plane * ab = cosA +i*sinA * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) * atan2(y,x) computes the principal value of the argument function @@ -302,27 +339,27 @@ double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const * Where x = ax*bx + ay*by * y = ax*by - ay*bx */ - const double px = origin->x; - const double py = origin->y; - const double ax = pa->x - px; - const double ay = pa->y - py; - const double bx = pb->x - px; - const double by = pb->y - py; - const double x = ax * by - ay * bx; - const double y = ax * bx + ay * by; - return atan2(x, y); + const double px = origin->x; + const double py = origin->y; + const double ax = pa->x - px; + const double ay = pa->y - py; + const double bx = pb->x - px; + const double by = pb->y - py; + const double x = ax * by - ay * bx; + const double y = ax * bx + ay * by; + return atan2(x, y); } double Sweep::BasinAngle(const Node& node) const { - const double ax = node.point->x - node.next->next->point->x; - const double ay = node.point->y - node.next->next->point->y; - return atan2(ay, ax); + const double ax = node.point->x - node.next->next->point->x; + const double ay = node.point->y - node.next->next->point->y; + return atan2(ay, ax); } double Sweep::HoleAngle(const Node& node) const { - /* Complex plane + /* Complex plane * ab = cosA +i*sinA * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) * atan2(y,x) computes the principal value of the argument function @@ -330,495 +367,494 @@ double Sweep::HoleAngle(const Node& node) const * Where x = ax*bx + ay*by * y = ax*by - ay*bx */ - const double ax = node.next->point->x - node.point->x; - const double ay = node.next->point->y - node.point->y; - const double bx = node.prev->point->x - node.point->x; - const double by = node.prev->point->y - node.point->y; - return atan2(ax * by - ay * bx, ax * bx + ay * by); + const double ax = node.next->point->x - node.point->x; + const double ay = node.next->point->y - node.point->y; + const double bx = node.prev->point->x - node.point->x; + const double by = node.prev->point->y - node.point->y; + return atan2(ax * by - ay * bx, ax * bx + ay * by); } bool Sweep::Legalize(SweepContext& tcx, Triangle& t) { - // To legalize a triangle we start by finding if any of the three edges - // violate the Delaunay condition - for (int i = 0; i < 3; i++) { - if (t.delaunay_edge[i]) - continue; + // To legalize a triangle we start by finding if any of the three edges + // violate the Delaunay condition + for (int i = 0; i < 3; i++) { + if (t.delaunay_edge[i]) + continue; - Triangle* ot = t.GetNeighbor(i); + Triangle* ot = t.GetNeighbor(i); - if (ot) { - Point* p = t.GetPoint(i); - Point* op = ot->OppositePoint(t, *p); - int oi = ot->Index(op); + if (ot) { + Point* p = t.GetPoint(i); + Point* op = ot->OppositePoint(t, *p); + int oi = ot->Index(op); - // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) - // then we should not try to legalize - if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { - t.constrained_edge[i] = ot->constrained_edge[oi]; - continue; - } + // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) + // then we should not try to legalize + if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { + t.constrained_edge[i] = ot->constrained_edge[oi]; + continue; + } - bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); + bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); - if (inside) { - // Lets mark this shared edge as Delaunay - t.delaunay_edge[i] = true; - ot->delaunay_edge[oi] = true; + if (inside) { + // Lets mark this shared edge as Delaunay + t.delaunay_edge[i] = true; + ot->delaunay_edge[oi] = true; - // Lets rotate shared edge one vertex CW to legalize it - RotateTrianglePair(t, *p, *ot, *op); + // Lets rotate shared edge one vertex CW to legalize it + RotateTrianglePair(t, *p, *ot, *op); - // We now got one valid Delaunay Edge shared by two triangles - // This gives us 4 new edges to check for Delaunay + // We now got one valid Delaunay Edge shared by two triangles + // This gives us 4 new edges to check for Delaunay - // Make sure that triangle to node mapping is done only one time for a specific triangle - bool not_legalized = !Legalize(tcx, t); - if (not_legalized) { - tcx.MapTriangleToNodes(t); + // Make sure that triangle to node mapping is done only one time for a specific triangle + bool not_legalized = !Legalize(tcx, t); + if (not_legalized) { + tcx.MapTriangleToNodes(t); + } + + not_legalized = !Legalize(tcx, *ot); + if (not_legalized) + tcx.MapTriangleToNodes(*ot); + + // Reset the Delaunay edges, since they only are valid Delaunay edges + // until we add a new triangle or point. + // XXX: need to think about this. Can these edges be tried after we + // return to previous recursive level? + t.delaunay_edge[i] = false; + ot->delaunay_edge[oi] = false; + + // If triangle have been legalized no need to check the other edges since + // the recursive legalization will handles those so we can end here. + return true; + } } - - not_legalized = !Legalize(tcx, *ot); - if (not_legalized) - tcx.MapTriangleToNodes(*ot); - - // Reset the Delaunay edges, since they only are valid Delaunay edges - // until we add a new triangle or point. - // XXX: need to think about this. Can these edges be tried after we - // return to previous recursive level? - t.delaunay_edge[i] = false; - ot->delaunay_edge[oi] = false; - - // If triangle have been legalized no need to check the other edges since - // the recursive legalization will handles those so we can end here. - return true; - } } - } - return false; + return false; } bool Sweep::Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const { - const double adx = pa.x - pd.x; - const double ady = pa.y - pd.y; - const double bdx = pb.x - pd.x; - const double bdy = pb.y - pd.y; + const double adx = pa.x - pd.x; + const double ady = pa.y - pd.y; + const double bdx = pb.x - pd.x; + const double bdy = pb.y - pd.y; - const double adxbdy = adx * bdy; - const double bdxady = bdx * ady; - const double oabd = adxbdy - bdxady; + const double adxbdy = adx * bdy; + const double bdxady = bdx * ady; + const double oabd = adxbdy - bdxady; - if (oabd <= 0) - return false; + if (oabd <= 0) + return false; - const double cdx = pc.x - pd.x; - const double cdy = pc.y - pd.y; + const double cdx = pc.x - pd.x; + const double cdy = pc.y - pd.y; - const double cdxady = cdx * ady; - const double adxcdy = adx * cdy; - const double ocad = cdxady - adxcdy; + const double cdxady = cdx * ady; + const double adxcdy = adx * cdy; + const double ocad = cdxady - adxcdy; - if (ocad <= 0) - return false; + if (ocad <= 0) + return false; - const double bdxcdy = bdx * cdy; - const double cdxbdy = cdx * bdy; + const double bdxcdy = bdx * cdy; + const double cdxbdy = cdx * bdy; - const double alift = adx * adx + ady * ady; - const double blift = bdx * bdx + bdy * bdy; - const double clift = cdx * cdx + cdy * cdy; + const double alift = adx * adx + ady * ady; + const double blift = bdx * bdx + bdy * bdy; + const double clift = cdx * cdx + cdy * cdy; - const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; + const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; - return det > 0; + return det > 0; } void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const { - Triangle* n1, *n2, *n3, *n4; - n1 = t.NeighborCCW(p); - n2 = t.NeighborCW(p); - n3 = ot.NeighborCCW(op); - n4 = ot.NeighborCW(op); + Triangle* n1, *n2, *n3, *n4; + n1 = t.NeighborCCW(p); + n2 = t.NeighborCW(p); + n3 = ot.NeighborCCW(op); + n4 = ot.NeighborCW(op); - bool ce1, ce2, ce3, ce4; - ce1 = t.GetConstrainedEdgeCCW(p); - ce2 = t.GetConstrainedEdgeCW(p); - ce3 = ot.GetConstrainedEdgeCCW(op); - ce4 = ot.GetConstrainedEdgeCW(op); + bool ce1, ce2, ce3, ce4; + ce1 = t.GetConstrainedEdgeCCW(p); + ce2 = t.GetConstrainedEdgeCW(p); + ce3 = ot.GetConstrainedEdgeCCW(op); + ce4 = ot.GetConstrainedEdgeCW(op); - bool de1, de2, de3, de4; - de1 = t.GetDelunayEdgeCCW(p); - de2 = t.GetDelunayEdgeCW(p); - de3 = ot.GetDelunayEdgeCCW(op); - de4 = ot.GetDelunayEdgeCW(op); + bool de1, de2, de3, de4; + de1 = t.GetDelunayEdgeCCW(p); + de2 = t.GetDelunayEdgeCW(p); + de3 = ot.GetDelunayEdgeCCW(op); + de4 = ot.GetDelunayEdgeCW(op); - t.Legalize(p, op); - ot.Legalize(op, p); + t.Legalize(p, op); + ot.Legalize(op, p); - // Remap delaunay_edge - ot.SetDelunayEdgeCCW(p, de1); - t.SetDelunayEdgeCW(p, de2); - t.SetDelunayEdgeCCW(op, de3); - ot.SetDelunayEdgeCW(op, de4); + // Remap delaunay_edge + ot.SetDelunayEdgeCCW(p, de1); + t.SetDelunayEdgeCW(p, de2); + t.SetDelunayEdgeCCW(op, de3); + ot.SetDelunayEdgeCW(op, de4); - // Remap constrained_edge - ot.SetConstrainedEdgeCCW(p, ce1); - t.SetConstrainedEdgeCW(p, ce2); - t.SetConstrainedEdgeCCW(op, ce3); - ot.SetConstrainedEdgeCW(op, ce4); + // Remap constrained_edge + ot.SetConstrainedEdgeCCW(p, ce1); + t.SetConstrainedEdgeCW(p, ce2); + t.SetConstrainedEdgeCCW(op, ce3); + ot.SetConstrainedEdgeCW(op, ce4); - // Remap neighbors - // XXX: might optimize the markNeighbor by keeping track of - // what side should be assigned to what neighbor after the - // rotation. Now mark neighbor does lots of testing to find - // the right side. - t.ClearNeighbors(); - ot.ClearNeighbors(); - if (n1) ot.MarkNeighbor(*n1); - if (n2) t.MarkNeighbor(*n2); - if (n3) t.MarkNeighbor(*n3); - if (n4) ot.MarkNeighbor(*n4); - t.MarkNeighbor(ot); + // Remap neighbors + // XXX: might optimize the markNeighbor by keeping track of + // what side should be assigned to what neighbor after the + // rotation. Now mark neighbor does lots of testing to find + // the right side. + t.ClearNeighbors(); + ot.ClearNeighbors(); + if (n1) ot.MarkNeighbor(*n1); + if (n2) t.MarkNeighbor(*n2); + if (n3) t.MarkNeighbor(*n3); + if (n4) ot.MarkNeighbor(*n4); + t.MarkNeighbor(ot); } void Sweep::FillBasin(SweepContext& tcx, Node& node) { - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - tcx.basin.left_node = node.next->next; - } else { - tcx.basin.left_node = node.next; - } + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + tcx.basin.left_node = node.next->next; + } else { + tcx.basin.left_node = node.next; + } - // Find the bottom and right node - tcx.basin.bottom_node = tcx.basin.left_node; - while (tcx.basin.bottom_node->next - && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { - tcx.basin.bottom_node = tcx.basin.bottom_node->next; - } - if (tcx.basin.bottom_node == tcx.basin.left_node) { - // No valid basin - return; - } + // Find the bottom and right node + tcx.basin.bottom_node = tcx.basin.left_node; + while (tcx.basin.bottom_node->next + && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { + tcx.basin.bottom_node = tcx.basin.bottom_node->next; + } + if (tcx.basin.bottom_node == tcx.basin.left_node) { + // No valid basin + return; + } - tcx.basin.right_node = tcx.basin.bottom_node; - while (tcx.basin.right_node->next - && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { - tcx.basin.right_node = tcx.basin.right_node->next; - } - if (tcx.basin.right_node == tcx.basin.bottom_node) { - // No valid basins - return; - } + tcx.basin.right_node = tcx.basin.bottom_node; + while (tcx.basin.right_node->next + && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { + tcx.basin.right_node = tcx.basin.right_node->next; + } + if (tcx.basin.right_node == tcx.basin.bottom_node) { + // No valid basins + return; + } - tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; - tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; + tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; + tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; - FillBasinReq(tcx, tcx.basin.bottom_node); + FillBasinReq(tcx, tcx.basin.bottom_node); } void Sweep::FillBasinReq(SweepContext& tcx, Node* node) { - // if shallow stop filling - if (IsShallow(tcx, *node)) { - return; - } - - Fill(tcx, *node); - - if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { - return; - } else if (node->prev == tcx.basin.left_node) { - Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); - if (o == CW) { - return; + // if shallow stop filling + if (IsShallow(tcx, *node)) { + return; } - node = node->next; - } else if (node->next == tcx.basin.right_node) { - Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); - if (o == CCW) { - return; - } - node = node->prev; - } else { - // Continue with the neighbor node with lowest Y value - if (node->prev->point->y < node->next->point->y) { - node = node->prev; + + Fill(tcx, *node); + + if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { + return; + } else if (node->prev == tcx.basin.left_node) { + Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); + if (o == CW) { + return; + } + node = node->next; + } else if (node->next == tcx.basin.right_node) { + Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); + if (o == CCW) { + return; + } + node = node->prev; } else { - node = node->next; + // Continue with the neighbor node with lowest Y value + if (node->prev->point->y < node->next->point->y) { + node = node->prev; + } else { + node = node->next; + } } - } - FillBasinReq(tcx, node); + FillBasinReq(tcx, node); } bool Sweep::IsShallow(SweepContext& tcx, Node& node) { - double height; + double height; - if (tcx.basin.left_highest) { - height = tcx.basin.left_node->point->y - node.point->y; - } else { - height = tcx.basin.right_node->point->y - node.point->y; - } + if (tcx.basin.left_highest) { + height = tcx.basin.left_node->point->y - node.point->y; + } else { + height = tcx.basin.right_node->point->y - node.point->y; + } - // if shallow stop filling - if (tcx.basin.width > height) { - return true; - } - return false; + // if shallow stop filling + if (tcx.basin.width > height) { + return true; + } + return false; } void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - if (tcx.edge_event.right) { - FillRightAboveEdgeEvent(tcx, edge, node); - } else { - FillLeftAboveEdgeEvent(tcx, edge, node); - } + if (tcx.edge_event.right) { + FillRightAboveEdgeEvent(tcx, edge, node); + } else { + FillLeftAboveEdgeEvent(tcx, edge, node); + } } void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - while (node->next->point->x < edge->p->x) { - // Check if next node is below the edge - if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { - FillRightBelowEdgeEvent(tcx, edge, *node); - } else { - node = node->next; + while (node->next->point->x < edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { + FillRightBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->next; + } } - } } void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - if (node.point->x < edge->p->x) { - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else { - // Convex - FillRightConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillRightBelowEdgeEvent(tcx, edge, node); + if (node.point->x < edge->p->x) { + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillRightConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillRightBelowEdgeEvent(tcx, edge, node); + } } - } } void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - Fill(tcx, *node.next); - if (node.next->point != edge->p) { - // Next above or below edge? - if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { - // Below - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Next is concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else { - // Next is convex - } + Fill(tcx, *node.next); + if (node.next->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { + // Below + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Next is concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } } - } } void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - // Next concave or convex? - if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, *node.next); - } else { - // Convex - // Next above or below edge? - if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { - // Below - FillRightConvexEdgeEvent(tcx, edge, *node.next); + // Next concave or convex? + if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, *node.next); } else { - // Above + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { + // Below + FillRightConvexEdgeEvent(tcx, edge, *node.next); + } else { + // Above + } } - } } void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - while (node->prev->point->x > edge->p->x) { - // Check if next node is below the edge - if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { - FillLeftBelowEdgeEvent(tcx, edge, *node); - } else { - node = node->prev; + while (node->prev->point->x > edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { + FillLeftBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->prev; + } } - } } void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - if (node.point->x > edge->p->x) { - if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else { - // Convex - FillLeftConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillLeftBelowEdgeEvent(tcx, edge, node); + if (node.point->x > edge->p->x) { + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillLeftConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillLeftBelowEdgeEvent(tcx, edge, node); + } } - } } void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - // Next concave or convex? - if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); - } else { - // Convex - // Next above or below edge? - if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { - // Below - FillLeftConvexEdgeEvent(tcx, edge, *node.prev); + // Next concave or convex? + if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); } else { - // Above + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { + // Below + FillLeftConvexEdgeEvent(tcx, edge, *node.prev); + } else { + // Above + } } - } } void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - Fill(tcx, *node.prev); - if (node.prev->point != edge->p) { - // Next above or below edge? - if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { - // Below - if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Next is concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else { - // Next is convex - } + Fill(tcx, *node.prev); + if (node.prev->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { + // Below + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Next is concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } } - } } void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& 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)) { - // Lets rotate shared edge one vertex CW - RotateTrianglePair(*t, p, ot, op); - tcx.MapTriangleToNodes(*t); - tcx.MapTriangleToNodes(ot); - - if (p == eq && op == ep) { - if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { - t->MarkConstrainedEdge(&ep, &eq); - ot.MarkConstrainedEdge(&ep, &eq); - Legalize(tcx, *t); - Legalize(tcx, ot); - } else { - // XXX: I think one of the triangles should be legalized here? - } - } else { - Orientation o = Orient2d(eq, op, ep); - t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); - FlipEdgeEvent(tcx, ep, eq, t, 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)) { + // Lets rotate shared edge one vertex CW + RotateTrianglePair(*t, p, ot, op); + tcx.MapTriangleToNodes(*t); + tcx.MapTriangleToNodes(ot); + + if (p == eq && op == ep) { + if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { + t->MarkConstrainedEdge(&ep, &eq); + ot.MarkConstrainedEdge(&ep, &eq); + Legalize(tcx, *t); + Legalize(tcx, ot); + } else { + // XXX: I think one of the triangles should be legalized here? + } + } else { + Orientation o = Orient2d(eq, op, ep); + t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); + FlipEdgeEvent(tcx, ep, eq, t, p); + } + } else { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); + EdgeEvent(tcx, ep, eq, t, p); } - } else { - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); - EdgeEvent(tcx, ep, eq, t, p); - } } Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) { - if (o == CCW) { - // ot is not crossing edge after flip - int edge_index = ot.EdgeIndex(&p, &op); - ot.delaunay_edge[edge_index] = true; - Legalize(tcx, ot); - ot.ClearDelunayEdges(); - return t; - } + if (o == CCW) { + // ot is not crossing edge after flip + int edge_index = ot.EdgeIndex(&p, &op); + ot.delaunay_edge[edge_index] = true; + Legalize(tcx, ot); + ot.ClearDelunayEdges(); + return t; + } - // t is not crossing edge after flip - int edge_index = t.EdgeIndex(&p, &op); + // t is not crossing edge after flip + int edge_index = t.EdgeIndex(&p, &op); - t.delaunay_edge[edge_index] = true; - Legalize(tcx, t); - t.ClearDelunayEdges(); - return ot; + t.delaunay_edge[edge_index] = true; + Legalize(tcx, t); + t.ClearDelunayEdges(); + return ot; } Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) { - Orientation o2d = Orient2d(eq, op, ep); - if (o2d == CW) { - // Right - return *ot.PointCCW(op); - } else if (o2d == CCW) { - // Left - return *ot.PointCW(op); - } - throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); + Orientation o2d = Orient2d(eq, op, ep); + if (o2d == CW) { + // Right + return *ot.PointCCW(op); + } else if (o2d == CCW) { + // Left + return *ot.PointCW(op); + } + throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); } void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p) { - Triangle* ot_ptr = t.NeighborAcross(p); - if (ot_ptr == nullptr) { - throw std::runtime_error("FlipScanEdgeEvent - null neighbor across"); - } + Triangle* ot_ptr = t.NeighborAcross(p); + if (ot_ptr == nullptr) { + throw std::runtime_error("FlipScanEdgeEvent - null neighbor across"); + } - Point* op_ptr = ot_ptr->OppositePoint(t, p); - if (op_ptr == nullptr) { - throw std::runtime_error("FlipScanEdgeEvent - null opposing point"); - } + Point* op_ptr = ot_ptr->OppositePoint(t, p); + if (op_ptr == nullptr) { + throw std::runtime_error("FlipScanEdgeEvent - null opposing point"); + } - Point* p1 = flip_triangle.PointCCW(eq); - Point* p2 = flip_triangle.PointCW(eq); - if (p1 == nullptr || p2 == nullptr) { - throw std::runtime_error("FlipScanEdgeEvent - null on either of points"); - } + Point* p1 = flip_triangle.PointCCW(eq); + Point* p2 = flip_triangle.PointCW(eq); + if (p1 == nullptr || p2 == nullptr) { + throw std::runtime_error("FlipScanEdgeEvent - null on either of points"); + } - Triangle& ot = *ot_ptr; - Point& op = *op_ptr; + Triangle& ot = *ot_ptr; + Point& op = *op_ptr; - if (InScanArea(eq, *p1, *p2, op)) { - // flip with new edge op->eq - FlipEdgeEvent(tcx, eq, op, &ot, op); - // TODO: Actually I just figured out that it should be possible to - // improve this by getting the next ot and op before the the above - // flip and continue the flipScanEdgeEvent here - // set new ot and op here and loop back to inScanArea test - // 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 { - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); - } + if (InScanArea(eq, *p1, *p2, op)) { + // flip with new edge op->eq + FlipEdgeEvent(tcx, eq, op, &ot, op); + // TODO: Actually I just figured out that it should be possible to + // improve this by getting the next ot and op before the the above + // flip and continue the flipScanEdgeEvent here + // set new ot and op here and loop back to inScanArea test + // 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 { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); + } } Sweep::~Sweep() { // Clean up memory - for(size_t i = 0; i < nodes_.size(); i++) { - delete nodes_[i]; + for (auto& node : nodes_) { + delete node; } - } } // namespace p2t diff --git a/external/poly2tri/sweep/sweep.h b/external/poly2tri/sweep/sweep.h index cd9ce926650..02431fc5d9a 100644 --- a/external/poly2tri/sweep/sweep.h +++ b/external/poly2tri/sweep/sweep.h @@ -36,8 +36,7 @@ * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com */ -#ifndef SWEEP_H -#define SWEEP_H +#pragma once #include @@ -53,28 +52,28 @@ class Sweep { public: - /** + /** * Triangulate * * @param tcx */ - void Triangulate(SweepContext& tcx); + void Triangulate(SweepContext& tcx); - /** + /** * Destructor - clean up memory */ - ~Sweep(); + ~Sweep(); private: - /** + /** * Start sweeping the Y-sorted point set from bottom to top * * @param tcx */ - void SweepPoints(SweepContext& tcx); + void SweepPoints(SweepContext& tcx); - /** + /** * Find closes node to the left of the new point and * create a new triangle. If needed new holes and basins * will be filled to. @@ -83,20 +82,20 @@ private: * @param point * @return */ - Node& PointEvent(SweepContext& tcx, Point& point); + Node& PointEvent(SweepContext& tcx, Point& point); - /** + /** * * * @param tcx * @param edge * @param node */ - void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); + void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); - /** + /** * Creates a new front triangle and legalize it * * @param tcx @@ -104,21 +103,21 @@ private: * @param node * @return */ - Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); + Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); - /** + /** * Adds a triangle to the advancing front to fill a hole. * @param tcx * @param node - middle node, that is the bottom of the hole */ - void Fill(SweepContext& tcx, Node& node); + void Fill(SweepContext& tcx, Node& node); - /** + /** * Returns true if triangle was legalized */ - bool Legalize(SweepContext& tcx, Triangle& t); + bool Legalize(SweepContext& tcx, Triangle& t); - /** + /** * Requirement:
* 1. a,b and c form a triangle.
* 2. a and d is know to be on opposite side of bc
@@ -142,9 +141,9 @@ private: * @param d - point opposite a * @return true if d is inside circle, false if on circle edge */ - bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const; + bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const; - /** + /** * Rotates a triangle pair one vertex CW *
    *       n2                    n2
@@ -158,37 +157,38 @@ private:
    *       n4                    n4
    * 
*/ - void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const; + void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const; - /** + /** * Fills holes in the Advancing Front * * * @param tcx * @param n */ - void FillAdvancingFront(SweepContext& tcx, Node& n); + void FillAdvancingFront(SweepContext& tcx, Node& n); - // Decision-making about when to Fill hole. - // Contributed by ToolmakerSteve2 - bool LargeHole_DontFill(const Node* node) const; - bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const; - bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const; - double Angle(const Point* origin, const Point* pa, const Point* pb) const; + // Decision-making about when to Fill hole. + // Contributed by ToolmakerSteve2 + bool LargeHole_DontFill(const Node* node) const; + bool AngleIsNegative(const Point* origin, const Point* pa, const Point* pb) const; + bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const; + bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const; + double Angle(const Point* origin, const Point* pa, const Point* pb) const; - /** + /** * * @param node - middle node * @return the angle between 3 front nodes */ - double HoleAngle(const Node& node) const; + double HoleAngle(const Node& node) const; - /** + /** * The basin angle is decided against the horizontal line [1,0] */ - double BasinAngle(const Node& node) const; + double BasinAngle(const Node& node) const; - /** + /** * Fills a basin that has formed on the Advancing Front to the right * of given node.
* First we decide a left,bottom and right node that forms the @@ -197,42 +197,42 @@ private: * @param tcx * @param node - starting node, this or next node will be left node */ - void FillBasin(SweepContext& tcx, Node& node); + void FillBasin(SweepContext& tcx, Node& node); - /** + /** * Recursive algorithm to fill a Basin with triangles * * @param tcx * @param node - bottom_node * @param cnt - counter used to alternate on even and odd numbers */ - void FillBasinReq(SweepContext& tcx, Node* node); + void FillBasinReq(SweepContext& tcx, Node* node); - bool IsShallow(SweepContext& tcx, Node& node); + bool IsShallow(SweepContext& tcx, Node& node); - bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); + bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); - void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p); + void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p); - /** + /** * After a flip we have two triangles and know that only one will still be * intersecting the edge. So decide which to contiune with and legalize the other * @@ -244,9 +244,9 @@ private: * @param op - another point shared by both triangles * @return returns the triangle still intersecting the edge */ - Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); + Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); - /** + /** * When we need to traverse from one triangle to the next we need * the point in current triangle that is the opposite point to the next * triangle. @@ -257,9 +257,9 @@ private: * @param op * @return */ - Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); + Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); - /** + /** * Scan part of the FlipScan algorithm
* When a triangle pair isn't flippable we will scan for the next * point that is inside the flip triangle scan area. When found @@ -272,14 +272,12 @@ private: * @param t * @param p */ - void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); + void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); - void FinalizationPolygon(SweepContext& tcx); + void FinalizationPolygon(SweepContext& tcx); - std::vector nodes_; + std::vector nodes_; }; } - -#endif diff --git a/external/poly2tri/sweep/sweep_context.cc b/external/poly2tri/sweep/sweep_context.cc index 79bc5e7e355..14bcb9e69cc 100644 --- a/external/poly2tri/sweep/sweep_context.cc +++ b/external/poly2tri/sweep/sweep_context.cc @@ -1,5 +1,5 @@ /* - * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors + * Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors * https://github.com/jhasse/poly2tri * * All rights reserved. @@ -34,152 +34,152 @@ namespace p2t { -SweepContext::SweepContext(const std::vector& polyline) : points_(polyline), - front_(nullptr), - head_(nullptr), - tail_(nullptr), - af_head_(nullptr), - af_middle_(nullptr), - af_tail_(nullptr) +SweepContext::SweepContext(std::vector polyline) : points_(std::move(polyline)), + front_(nullptr), + head_(nullptr), + tail_(nullptr), + af_head_(nullptr), + af_middle_(nullptr), + af_tail_(nullptr) { - InitEdges(points_); + InitEdges(points_); } void SweepContext::AddHole(const std::vector& polyline) { - InitEdges(polyline); - for(unsigned int i = 0; i < polyline.size(); i++) { - points_.push_back(polyline[i]); - } + InitEdges(polyline); + for (auto i : polyline) { + points_.push_back(i); + } } void SweepContext::AddPoint(Point* point) { - points_.push_back(point); + points_.push_back(point); } std::vector &SweepContext::GetTriangles() { - return triangles_; + return triangles_; } std::list &SweepContext::GetMap() { - return map_; + return map_; } void SweepContext::InitTriangulation() { - double xmax(points_[0]->x), xmin(points_[0]->x); - double ymax(points_[0]->y), ymin(points_[0]->y); + double xmax(points_[0]->x), xmin(points_[0]->x); + double ymax(points_[0]->y), ymin(points_[0]->y); - // Calculate bounds. - for (unsigned int i = 0; i < points_.size(); i++) { - Point& p = *points_[i]; - if (p.x > xmax) - xmax = p.x; - if (p.x < xmin) - xmin = p.x; - if (p.y > ymax) - ymax = p.y; - if (p.y < ymin) - ymin = p.y; - } + // Calculate bounds. + for (auto& point : points_) { + Point& p = *point; + if (p.x > xmax) + xmax = p.x; + if (p.x < xmin) + xmin = p.x; + if (p.y > ymax) + ymax = p.y; + if (p.y < ymin) + ymin = p.y; + } - double dx = kAlpha * (xmax - xmin); - double dy = kAlpha * (ymax - ymin); - head_ = new Point(xmin - dx, ymin - dy); - tail_ = new Point(xmax + dx, ymin - dy); + double dx = kAlpha * (xmax - xmin); + double dy = kAlpha * (ymax - ymin); + head_ = new Point(xmin - dx, ymin - dy); + tail_ = new Point(xmax + dx, ymin - dy); - // Sort points along y-axis - std::sort(points_.begin(), points_.end(), cmp); + // Sort points along y-axis + std::sort(points_.begin(), points_.end(), cmp); } void SweepContext::InitEdges(const std::vector& polyline) { - size_t num_points = polyline.size(); - for (size_t i = 0; i < num_points; i++) { - size_t j = i < num_points - 1 ? i + 1 : 0; - edge_list.push_back(new Edge(*polyline[i], *polyline[j])); - } + size_t num_points = polyline.size(); + for (size_t i = 0; i < num_points; i++) { + size_t j = i < num_points - 1 ? i + 1 : 0; + edge_list.push_back(new Edge(*polyline[i], *polyline[j])); + } } Point* SweepContext::GetPoint(size_t index) { - return points_[index]; + return points_[index]; } void SweepContext::AddToMap(Triangle* triangle) { - map_.push_back(triangle); + map_.push_back(triangle); } Node* SweepContext::LocateNode(const Point& point) { - // TODO implement search tree - return front_->LocateNode(point.x); + // TODO implement search tree + return front_->LocateNode(point.x); } void SweepContext::CreateAdvancingFront() { - // Initial triangle - Triangle* triangle = new Triangle(*points_[0], *head_, *tail_); + // Initial triangle + Triangle* triangle = new Triangle(*points_[0], *head_, *tail_); - map_.push_back(triangle); + map_.push_back(triangle); - af_head_ = new Node(*triangle->GetPoint(1), *triangle); - af_middle_ = new Node(*triangle->GetPoint(0), *triangle); - af_tail_ = new Node(*triangle->GetPoint(2)); - front_ = new AdvancingFront(*af_head_, *af_tail_); + af_head_ = new Node(*triangle->GetPoint(1), *triangle); + af_middle_ = new Node(*triangle->GetPoint(0), *triangle); + af_tail_ = new Node(*triangle->GetPoint(2)); + front_ = new AdvancingFront(*af_head_, *af_tail_); - // TODO: More intuitive if head is middles next and not previous? - // so swap head and tail - af_head_->next = af_middle_; - af_middle_->next = af_tail_; - af_middle_->prev = af_head_; - af_tail_->prev = af_middle_; + // TODO: More intuitive if head is middles next and not previous? + // so swap head and tail + af_head_->next = af_middle_; + af_middle_->next = af_tail_; + af_middle_->prev = af_head_; + af_tail_->prev = af_middle_; } void SweepContext::RemoveNode(Node* node) { - delete node; + delete node; } void SweepContext::MapTriangleToNodes(Triangle& t) { - for (int i = 0; i < 3; i++) { - if (!t.GetNeighbor(i)) { - Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); - if (n) - n->triangle = &t; + for (int i = 0; i < 3; i++) { + if (!t.GetNeighbor(i)) { + Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); + if (n) + n->triangle = &t; + } } - } } void SweepContext::RemoveFromMap(Triangle* triangle) { - map_.remove(triangle); + map_.remove(triangle); } void SweepContext::MeshClean(Triangle& triangle) { - std::vector triangles; - triangles.push_back(&triangle); + std::vector triangles; + triangles.push_back(&triangle); - while(!triangles.empty()){ - Triangle *t = triangles.back(); - triangles.pop_back(); + while(!triangles.empty()){ + Triangle *t = triangles.back(); + triangles.pop_back(); - if (t != nullptr && !t->IsInterior()) { - t->IsInterior(true); - triangles_.push_back(t); - for (int i = 0; i < 3; i++) { - if (!t->constrained_edge[i]) - triangles.push_back(t->GetNeighbor(i)); - } + if (t != nullptr && !t->IsInterior()) { + t->IsInterior(true); + triangles_.push_back(t); + for (int i = 0; i < 3; i++) { + if (!t->constrained_edge[i]) + triangles.push_back(t->GetNeighbor(i)); + } + } } - } } SweepContext::~SweepContext() @@ -194,17 +194,13 @@ SweepContext::~SweepContext() delete af_middle_; delete af_tail_; - typedef std::list type_list; - - for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) { - Triangle* ptr = *iter; + for (auto ptr : map_) { delete ptr; } - for(unsigned int i = 0; i < edge_list.size(); i++) { - delete edge_list[i]; + for (auto& i : edge_list) { + delete i; } - } } // namespace p2t diff --git a/external/poly2tri/sweep/sweep_context.h b/external/poly2tri/sweep/sweep_context.h index 47d970b7bcf..b2b60715cae 100644 --- a/external/poly2tri/sweep/sweep_context.h +++ b/external/poly2tri/sweep/sweep_context.h @@ -1,5 +1,5 @@ /* - * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors + * Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors * https://github.com/jhasse/poly2tri * * All rights reserved. @@ -29,8 +29,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SWEEP_CONTEXT_H -#define SWEEP_CONTEXT_H +#pragma once #include #include @@ -51,136 +50,135 @@ class AdvancingFront; class SweepContext { public: -/// Constructor -SweepContext(const std::vector& polyline); -/// Destructor -~SweepContext(); + /// Constructor + explicit SweepContext(std::vector polyline); + /// Destructor + ~SweepContext(); -void set_head(Point* p1); + void set_head(Point* p1); -Point* head() const; + Point* head() const; -void set_tail(Point* p1); + void set_tail(Point* p1); -Point* tail() const; + Point* tail() const; -size_t point_count() const; + size_t point_count() const; -Node* LocateNode(const Point& point); + Node* LocateNode(const Point& point); -void RemoveNode(Node* node); + void RemoveNode(Node* node); -void CreateAdvancingFront(); + void CreateAdvancingFront(); -/// Try to map a node to all sides of this triangle that don't have a neighbor -void MapTriangleToNodes(Triangle& t); + /// Try to map a node to all sides of this triangle that don't have a neighbor + void MapTriangleToNodes(Triangle& t); -void AddToMap(Triangle* triangle); + void AddToMap(Triangle* triangle); -Point* GetPoint(size_t index); + Point* GetPoint(size_t index); -Point* GetPoints(); + Point* GetPoints(); -void RemoveFromMap(Triangle* triangle); + void RemoveFromMap(Triangle* triangle); -void AddHole(const std::vector& polyline); + void AddHole(const std::vector& polyline); -void AddPoint(Point* point); + void AddPoint(Point* point); -AdvancingFront* front() const; + AdvancingFront* front() const; -void MeshClean(Triangle& triangle); + void MeshClean(Triangle& triangle); -std::vector &GetTriangles(); -std::list &GetMap(); + std::vector &GetTriangles(); + std::list &GetMap(); -std::vector edge_list; + std::vector edge_list; -struct Basin { - Node* left_node; - Node* bottom_node; - Node* right_node; - double width; - bool left_highest; + struct Basin { + Node* left_node; + Node* bottom_node; + Node* right_node; + double width; + bool left_highest; - Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) - { - } + Basin() + : left_node(nullptr), bottom_node(nullptr), right_node(nullptr), width(0.0), left_highest(false) + { + } - void Clear() - { - left_node = NULL; - bottom_node = NULL; - right_node = NULL; - width = 0.0; - left_highest = false; - } -}; + void Clear() + { + left_node = nullptr; + bottom_node = nullptr; + right_node = nullptr; + width = 0.0; + left_highest = false; + } + }; -struct EdgeEvent { - Edge* constrained_edge; - bool right; + struct EdgeEvent { + Edge* constrained_edge; + bool right; - EdgeEvent() : constrained_edge(NULL), right(false) - { - } -}; + EdgeEvent() : constrained_edge(NULL), right(false) + { + } + }; -Basin basin; -EdgeEvent edge_event; + Basin basin; + EdgeEvent edge_event; private: -friend class Sweep; + friend class Sweep; -std::vector triangles_; -std::list map_; -std::vector points_; + std::vector triangles_; + std::list map_; + std::vector points_; -// Advancing front -AdvancingFront* front_; -// head point used with advancing front -Point* head_; -// tail point used with advancing front -Point* tail_; + // Advancing front + AdvancingFront* front_; + // head point used with advancing front + Point* head_; + // tail point used with advancing front + Point* tail_; -Node *af_head_, *af_middle_, *af_tail_; + Node *af_head_, *af_middle_, *af_tail_; -void InitTriangulation(); -void InitEdges(const std::vector& polyline); + void InitTriangulation(); + void InitEdges(const std::vector& polyline); }; inline AdvancingFront* SweepContext::front() const { - return front_; + return front_; } inline size_t SweepContext::point_count() const { - return points_.size(); + return points_.size(); } inline void SweepContext::set_head(Point* p1) { - head_ = p1; + head_ = p1; } inline Point* SweepContext::head() const { - return head_; + return head_; } inline void SweepContext::set_tail(Point* p1) { - tail_ = p1; + tail_ = p1; } inline Point* SweepContext::tail() const { - return tail_; + return tail_; } } - -#endif