diff --git a/benchmarks/ClassSizes.cpp b/benchmarks/ClassSizes.cpp index 015be2138f..d4fe96bdfb 100644 --- a/benchmarks/ClassSizes.cpp +++ b/benchmarks/ClassSizes.cpp @@ -40,6 +40,9 @@ #include #include #include +#include +#include +#include using namespace std; using namespace geos; @@ -71,6 +74,9 @@ main() check(geom::CoordinateArraySequence); check(geom::FixedSizeCoordinateSequence<1>); check(geom::FixedSizeCoordinateSequence<2>); + check(triangulate::quadedge::QuadEdge); + check(triangulate::quadedge::QuadEdgeQuartet); + check(triangulate::quadedge::Vertex); check(int64); } diff --git a/include/geos/triangulate/quadedge/Makefile.am b/include/geos/triangulate/quadedge/Makefile.am index 2d48754ac0..1c05bedfbe 100644 --- a/include/geos/triangulate/quadedge/Makefile.am +++ b/include/geos/triangulate/quadedge/Makefile.am @@ -11,6 +11,7 @@ geos_HEADERS = \ QuadEdge.h \ Vertex.h \ TrianglePredicate.h \ + QuadEdgeQuartet.h \ QuadEdgeSubdivision.h \ QuadEdgeLocator.h \ LastFoundQuadEdgeLocator.h \ diff --git a/include/geos/triangulate/quadedge/QuadEdge.h b/include/geos/triangulate/quadedge/QuadEdge.h index 0a464dc708..51513bbe44 100644 --- a/include/geos/triangulate/quadedge/QuadEdge.h +++ b/include/geos/triangulate/quadedge/QuadEdge.h @@ -4,6 +4,7 @@ * http://geos.osgeo.org * * Copyright (C) 2012 Excensus LLC. + * Copyright (C) 2019 Daniel Baston * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Licence as published @@ -28,6 +29,9 @@ namespace geos { namespace triangulate { //geos.triangulate namespace quadedge { //geos.triangulate.quadedge + +class GEOS_DLL QuadEdgeQuartet; + /** \brief * A class that represents the edge data structure which implements the quadedge algebra. * @@ -35,8 +39,7 @@ namespace quadedge { //geos.triangulate.quadedge * "Primitives for the manipulation of general subdivisions and the computation of Voronoi diagrams", * *ACM Transactions on Graphics*, 4(2), 1985, 75-123. * - * Each edge object is part of a quartet of 4 edges, linked via their `_rot` references. - * Any edge in the group may be accessed using a series of {@link #rot()} operations. + * Each edge object is part of a QuadEdgeQuartet of 4 edges, linked via relative memory addresses. * Quadedges in a subdivision are linked together via their `next` references. * The linkage between the quadedge quartets determines the topology * of the subdivision. @@ -49,16 +52,17 @@ namespace quadedge { //geos.triangulate.quadedge * @author Benjamin Campbell * */ class GEOS_DLL QuadEdge { + friend class QuadEdgeQuartet; public: /** \brief * Creates a new QuadEdge quartet from {@link Vertex} o to {@link Vertex} d. * * @param o the origin Vertex * @param d the destination Vertex - * @return the new QuadEdge* The caller is reponsible for - * freeing the returned pointer + * @param edges a container in which to store the newly created quartet + * @return the new QuadEdge*, */ - static std::unique_ptr makeEdge(const Vertex& o, const Vertex& d); + static QuadEdge* makeEdge(const Vertex& o, const Vertex & d, std::deque & edges); /** \brief * Creates a new QuadEdge connecting the destination of a to the origin of @@ -67,10 +71,9 @@ class GEOS_DLL QuadEdge { * * Additionally, the data pointers of the new edge are set. * - * @return the new QuadEdge* The caller is reponsible for - * freeing the returned pointer + * @return the new QuadEdge* */ - static std::unique_ptr connect(QuadEdge& a, QuadEdge& b); + static QuadEdge* connect(QuadEdge& a, QuadEdge& b, std::deque & edges); /** \brief * Splices two edges together or apart. @@ -97,31 +100,26 @@ class GEOS_DLL QuadEdge { private: //// the dual of this edge, directed from right to left - QuadEdge* _rot; - Vertex vertex; // The vertex that this edge represents - QuadEdge* next; // A reference to a connected edge - void* data; + Vertex vertex; // The vertex that this edge represents + QuadEdge* next; // A reference to a connected edge + + int8_t num; // the position of the QuadEdge in the quartet (0-3) + bool isAlive; bool visited; /** - * Quadedges must be made using {@link makeEdge}, + * Quadedges must be made using {@link QuadEdgeQuartet::makeEdge}, * to ensure proper construction. */ - QuadEdge(); + explicit QuadEdge(int8_t _num) : + next(nullptr), + num(_num), + isAlive(true), + visited(false) { + } public: - virtual ~QuadEdge(); - - /** \brief - * Free the QuadEdge quartet associated with this QuadEdge by a connect() - * or makeEdge() call. - * - * @note DO NOT call this function on a QuadEdge that was not returned - * by connect() or makeEdge(). - */ - virtual void free(); - /** \brief * Gets the primary edge of this quadedge and its `sym`. * @@ -131,21 +129,7 @@ class GEOS_DLL QuadEdge { * * @return the primary quadedge */ - const QuadEdge& getPrimary() const; - - /** \brief - * Sets the external data value for this edge. - * - * @param data an object containing external data - */ - virtual void setData(void* data); - - /** \brief - * Gets the external data value for this edge. - * - * @return the data object - */ - virtual void* getData(); + const QuadEdge& getPrimary(); /** \brief * Marks this quadedge as being deleted. @@ -203,10 +187,16 @@ class GEOS_DLL QuadEdge { * * @return the rotated edge */ - inline QuadEdge& + inline const QuadEdge& rot() const { - return *_rot; + return (num < 3) ? *(this + 1) : *(this - 3); + } + + inline QuadEdge& + rot() + { + return (num < 3) ? *(this + 1) : *(this - 3); } /** \brief @@ -214,10 +204,16 @@ class GEOS_DLL QuadEdge { * * @return the inverse rotated edge. */ - inline QuadEdge& + inline const QuadEdge& invRot() const { - return rot().sym(); + return (num > 0) ? *(this - 1) : *(this + 3); + } + + inline QuadEdge& + invRot() + { + return (num > 0) ? *(this - 1) : *(this + 3); } /** \brief @@ -225,10 +221,16 @@ class GEOS_DLL QuadEdge { * * @return the sym of the edge */ - inline QuadEdge& + inline const QuadEdge& sym() const { - return rot().rot(); + return (num < 2) ? *(this + 2) : *(this - 2); + } + + inline QuadEdge& + sym() + { + return (num < 2) ? *(this + 2) : *(this - 2); } /** \brief @@ -236,29 +238,41 @@ class GEOS_DLL QuadEdge { * * @return the next linked edge. */ - inline QuadEdge& + inline const QuadEdge& oNext() const { return *next; } + inline QuadEdge& + oNext() + { + return *next; + } + /** \brief * Gets the next CW edge around (from) the origin of this edge. * * @return the previous edge. */ - inline QuadEdge& + inline const QuadEdge& oPrev() const { return rot().oNext().rot(); } + inline QuadEdge& + oPrev() + { + return rot().oNext().rot(); + } + /** \brief * Gets the next CCW edge around (into) the destination of this edge. * * @return the next destination edge. */ - inline QuadEdge& + inline const QuadEdge& dNext() const { return sym().oNext().sym(); @@ -269,41 +283,59 @@ class GEOS_DLL QuadEdge { * * @return the previous destination edge. */ - inline QuadEdge& + inline const QuadEdge& dPrev() const { return invRot().oNext().invRot(); } + inline QuadEdge& + dPrev() + { + return invRot().oNext().invRot(); + } + /** \brief * Gets the CCW edge around the left face following this edge. * * @return the next left face edge. */ - inline QuadEdge& + inline const QuadEdge& lNext() const { return invRot().oNext().rot(); } + inline QuadEdge& + lNext() + { + return invRot().oNext().rot(); + } + /** \brief * Gets the CCW edge around the left face before this edge. * * @return the previous left face edge. */ - inline QuadEdge& + inline const QuadEdge& lPrev() const { return oNext().sym(); } + inline QuadEdge& + lPrev() + { + return oNext().sym(); + } + /** \brief * Gets the edge around the right face ccw following this edge. * * @return the next right face edge. */ - inline QuadEdge& - rNext() + inline const QuadEdge& + rNext() const { return rot().oNext().invRot(); } @@ -313,8 +345,8 @@ class GEOS_DLL QuadEdge { * * @return the previous right face edge. */ - inline QuadEdge& - rPrev() + inline const QuadEdge& + rPrev() const { return sym().oNext(); } @@ -404,9 +436,10 @@ class GEOS_DLL QuadEdge { std::unique_ptr toLineSegment() const; }; + } //namespace geos.triangulate.quadedge } //namespace geos.triangulate -} //namespace goes +} //namespace geos #endif //GEOS_TRIANGULATE_QUADEDGE_QUADEDGE_H diff --git a/include/geos/triangulate/quadedge/QuadEdgeQuartet.h b/include/geos/triangulate/quadedge/QuadEdgeQuartet.h new file mode 100644 index 0000000000..30817d942f --- /dev/null +++ b/include/geos/triangulate/quadedge/QuadEdgeQuartet.h @@ -0,0 +1,67 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2019 Daniel Baston + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#ifndef GEOS_TRIANGULATE_QUADEDGE_QUADEDGEQUARTET_H +#define GEOS_TRIANGULATE_QUADEDGE_QUADEDGEQUARTET_H + +#include + + +namespace geos { +namespace triangulate { +namespace quadedge { + +class GEOS_DLL QuadEdgeQuartet { + +public: + QuadEdgeQuartet() : e{QuadEdge(0), QuadEdge(1), QuadEdge(2), QuadEdge(3)} { + e[0].next = &(e[0]); + e[1].next = &(e[3]); + e[2].next = &(e[2]); + e[3].next = &(e[1]); + }; + + static QuadEdge& makeEdge(const Vertex& o, const Vertex & d, std::deque & edges) { + edges.emplace_back(); + auto& qe = edges.back(); + qe.base().setOrig(o); + qe.base().setDest(d); + + return qe.base(); + } + + QuadEdge& base() { + return e[0]; + } + + const QuadEdge& base() const { + return e[0]; + } + + void setVisited(bool status) { + for (auto& edge : e) { + edge.setVisited(status); + } + } + +private: + std::array e; +}; + +} +} +} + + +#endif diff --git a/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h b/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h index f8df4882e0..e3b5c889a8 100644 --- a/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h +++ b/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h @@ -4,6 +4,7 @@ * http://geos.osgeo.org * * Copyright (C) 2012 Excensus LLC. + * Copyright (C) 2019 Daniel Baston * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Licence as published @@ -26,7 +27,9 @@ #include #include +#include #include +#include #include namespace geos { @@ -45,7 +48,6 @@ class Envelope; namespace triangulate { //geos.triangulate namespace quadedge { //geos.triangulate.quadedge -class QuadEdge; class TriangleVisitor; const double EDGE_COINCIDENCE_TOL_FACTOR = 1000; @@ -91,12 +93,11 @@ class GEOS_DLL QuadEdgeSubdivision { const QuadEdge* triEdge[3]); private: - QuadEdgeList quadEdges; - QuadEdgeList createdEdges; - QuadEdge* startingEdges[3]; + std::deque quadEdges; + std::array startingEdges; double tolerance; double edgeCoincidenceTolerance; - Vertex frameVertex[3]; + std::array frameVertex; geom::Envelope frameEnv; std::unique_ptr locator; bool visit_state_clean; @@ -112,12 +113,12 @@ class GEOS_DLL QuadEdgeSubdivision { */ QuadEdgeSubdivision(const geom::Envelope& env, double tolerance); - virtual ~QuadEdgeSubdivision(); + virtual ~QuadEdgeSubdivision() = default; private: virtual void createFrame(const geom::Envelope& env); - virtual void initSubdiv(QuadEdge* initEdges[3]); + virtual void initSubdiv(); public: /** \brief @@ -148,8 +149,8 @@ class GEOS_DLL QuadEdgeSubdivision { * * @return a QuadEdgeList */ - inline const QuadEdgeList& - getEdges() const + inline std::deque& + getEdges() { return quadEdges; } @@ -192,8 +193,7 @@ class GEOS_DLL QuadEdgeSubdivision { * Deletes a quadedge from the subdivision. Linked quadedges are updated to * reflect the deletion. * - * @param e - * the quadedge to delete + * @param e the quadedge to delete */ void remove(QuadEdge& e); diff --git a/include/geos/triangulate/quadedge/TrianglePredicate.h b/include/geos/triangulate/quadedge/TrianglePredicate.h index 8742fc1298..a1a7f9f48c 100644 --- a/include/geos/triangulate/quadedge/TrianglePredicate.h +++ b/include/geos/triangulate/quadedge/TrianglePredicate.h @@ -19,6 +19,8 @@ #ifndef GEOS_TRIANGULATE_QUADEDGE_TRIANGLEPREDICATE_H #define GEOS_TRIANGULATE_QUADEDGE_TRIANGLEPREDICATE_H +#include + namespace geos { namespace geom { // geos.geom @@ -39,7 +41,7 @@ class Coordinate; * @author Benjamin Campbell * */ -class TrianglePredicate { +class GEOS_DLL TrianglePredicate { public: /** * Tests if a point is inside the circle defined by diff --git a/include/geos/triangulate/quadedge/Vertex.h b/include/geos/triangulate/quadedge/Vertex.h index b08f4dd50b..334ced8f8d 100644 --- a/include/geos/triangulate/quadedge/Vertex.h +++ b/include/geos/triangulate/quadedge/Vertex.h @@ -24,6 +24,7 @@ #include #include +#include //fwd declarations @@ -76,7 +77,7 @@ class GEOS_DLL Vertex { Vertex(const geom::Coordinate& _p); Vertex(); - virtual ~Vertex() {}; + ~Vertex() {}; inline double getX() const @@ -126,7 +127,7 @@ class GEOS_DLL Vertex { return false; } - virtual int classify(const Vertex& p0, const Vertex& p1); + int classify(const Vertex& p0, const Vertex& p1); /** * Computes the cross product k = u X v. @@ -206,7 +207,9 @@ class GEOS_DLL Vertex { * @param c a vertex of the triangle * @return true if this vertex is in the circumcircle of (a,b,c) */ - virtual bool isInCircle(const Vertex& a, const Vertex& b, const Vertex& c) const; + bool isInCircle(const Vertex& a, const Vertex& b, const Vertex& c) const { + return geom::TrianglePredicate::isInCircleRobust(a.p, b.p, c.p, this->p); + } /** * Tests whether the triangle formed by this vertex and two @@ -248,7 +251,7 @@ class GEOS_DLL Vertex { * @param c third vertex of the triangle * @return ratio of circumradius to shortest edge. */ - virtual double circumRadiusRatio(const Vertex& b, const Vertex& c); + double circumRadiusRatio(const Vertex& b, const Vertex& c); /** * returns a new vertex that is mid-way between this vertex and another end point. @@ -256,7 +259,7 @@ class GEOS_DLL Vertex { * @param a the other end point. * @return the point mid-way between this and that. */ - virtual std::unique_ptr midPoint(const Vertex& a); + std::unique_ptr midPoint(const Vertex& a); /** * Computes the centre of the circumcircle of this vertex and two others. @@ -265,14 +268,13 @@ class GEOS_DLL Vertex { * @param c * @return the Coordinate which is the circumcircle of the 3 points. */ - virtual std::unique_ptr circleCenter(const Vertex& b, const Vertex& c) const; + std::unique_ptr circleCenter(const Vertex& b, const Vertex& c) const; /** - * For this vertex enclosed in a triangle defined by three verticies v0, v1 and v2, interpolate + * For this vertex enclosed in a triangle defined by three vertices v0, v1 and v2, interpolate * a z value from the surrounding vertices. */ - virtual double interpolateZValue(const Vertex& v0, const Vertex& v1, - const Vertex& v2) const; + double interpolateZValue(const Vertex& v0, const Vertex& v1, const Vertex& v2) const; /** * Interpolates the Z-value (height) of a point enclosed in a triangle diff --git a/src/triangulate/IncrementalDelaunayTriangulator.cpp b/src/triangulate/IncrementalDelaunayTriangulator.cpp index 7becab84e7..d20421dcc1 100644 --- a/src/triangulate/IncrementalDelaunayTriangulator.cpp +++ b/src/triangulate/IncrementalDelaunayTriangulator.cpp @@ -54,7 +54,7 @@ IncrementalDelaunayTriangulator::insertSite(const Vertex& v) QuadEdge* e = subdiv->locate(v); if(!e) { - throw LocateFailureException(""); + throw LocateFailureException("Could not locate vertex."); } if(subdiv->isVertexOfEdge(*e, v)) { diff --git a/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp b/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp index 12b2c0c148..782c2d13cf 100644 --- a/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp +++ b/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp @@ -38,7 +38,7 @@ QuadEdge* LastFoundQuadEdgeLocator::findEdge() { // assume there is an edge - return *(subdiv->getEdges().begin()); + return &(subdiv->getEdges()[0].base()); } QuadEdge* diff --git a/src/triangulate/quadedge/LocateFailureException.cpp b/src/triangulate/quadedge/LocateFailureException.cpp index 3c0d75f7da..7bbb3c134b 100644 --- a/src/triangulate/quadedge/LocateFailureException.cpp +++ b/src/triangulate/quadedge/LocateFailureException.cpp @@ -22,10 +22,9 @@ namespace geos { namespace triangulate { //geos.triangulate namespace quadedge { //geos.triangulate.quadedge -LocateFailureException::LocateFailureException(std::string const& msg) -{ - util::GEOSException("LocateFailureException", msg); -} +LocateFailureException::LocateFailureException(std::string const& msg) : + util::GEOSException("LocateFailureException", msg) +{} } //namespace geos.triangulate.quadedge } //namespace geos.triangulate diff --git a/src/triangulate/quadedge/QuadEdge.cpp b/src/triangulate/quadedge/QuadEdge.cpp index b48e136847..344c6ecca8 100644 --- a/src/triangulate/quadedge/QuadEdge.cpp +++ b/src/triangulate/quadedge/QuadEdge.cpp @@ -4,6 +4,7 @@ * http://geos.osgeo.org * * Copyright (C) 2012 Excensus LLC. + * Copyright (C) 2019 Daniel Baston * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Licence as published @@ -17,6 +18,7 @@ **********************************************************************/ #include +#include namespace geos { namespace triangulate { //geos.triangulate @@ -24,36 +26,14 @@ namespace quadedge { //geos.triangulate.quadedge using namespace geos::geom; -std::unique_ptr -QuadEdge::makeEdge(const Vertex& o, const Vertex& d) -{ - QuadEdge* q0 = new QuadEdge(); - //q1-q3 are free()'d by q0 - QuadEdge* q1 = new QuadEdge(); - QuadEdge* q2 = new QuadEdge(); - QuadEdge* q3 = new QuadEdge(); - - q0->_rot = q1; - q1->_rot = q2; - q2->_rot = q3; - q3->_rot = q0; - - q0->setNext(q0); - q1->setNext(q3); - q2->setNext(q2); - q3->setNext(q1); - - QuadEdge* base = q0; - base->setOrig(o); - base->setDest(d); - - return std::unique_ptr(base); +QuadEdge* QuadEdge::makeEdge(const Vertex& o, const Vertex& d, std::deque & edges) { + return &QuadEdgeQuartet::makeEdge(o, d, edges); } -std::unique_ptr -QuadEdge::connect(QuadEdge& a, QuadEdge& b) +QuadEdge* +QuadEdge::connect(QuadEdge& a, QuadEdge& b, std::deque & edges) { - std::unique_ptr q0 = makeEdge(a.dest(), b.orig()); + QuadEdge* q0 = makeEdge(a.dest(), b.orig(), edges); splice(*q0, a.lNext()); splice(q0->sym(), b); return q0; @@ -89,32 +69,8 @@ QuadEdge::swap(QuadEdge& e) e.setDest(b.dest()); } -QuadEdge::QuadEdge() : _rot(nullptr), vertex(), next(nullptr), data(nullptr), isAlive(true), visited(false) -{ } - -QuadEdge::~QuadEdge() -{ -} - -void -QuadEdge::free() -{ - if(_rot) { - if(_rot->_rot) { - if(_rot->_rot->_rot) { - delete _rot->_rot->_rot; - _rot->_rot->_rot = nullptr; - } - delete _rot->_rot; - _rot->_rot = nullptr; - } - delete _rot; - _rot = nullptr; - } -} - const QuadEdge& -QuadEdge::getPrimary() const +QuadEdge::getPrimary() { if(orig().getCoordinate().compareTo(dest().getCoordinate()) <= 0) { return *this; @@ -124,18 +80,6 @@ QuadEdge::getPrimary() const } } -void -QuadEdge::setData(void* p_data) -{ - this->data = p_data; -} - -void* -QuadEdge::getData() -{ - return data; -} - void QuadEdge::remove() { diff --git a/src/triangulate/quadedge/QuadEdgeSubdivision.cpp b/src/triangulate/quadedge/QuadEdgeSubdivision.cpp index 6c57f47a02..bc4a1ba5c8 100644 --- a/src/triangulate/quadedge/QuadEdgeSubdivision.cpp +++ b/src/triangulate/quadedge/QuadEdgeSubdivision.cpp @@ -4,6 +4,7 @@ * http://geos.osgeo.org * * Copyright (C) 2012 Excensus LLC. + * Copyright (C) 2019 Daniel Baston * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Licence as published @@ -67,21 +68,7 @@ QuadEdgeSubdivision::QuadEdgeSubdivision(const geom::Envelope& env, double p_tol { edgeCoincidenceTolerance = tolerance / EDGE_COINCIDENCE_TOL_FACTOR; createFrame(env); - initSubdiv(startingEdges); - quadEdges.push_back(startingEdges[0]); - createdEdges.push_back(startingEdges[0]); - quadEdges.push_back(startingEdges[1]); - createdEdges.push_back(startingEdges[1]); - quadEdges.push_back(startingEdges[2]); - createdEdges.push_back(startingEdges[2]); -} - -QuadEdgeSubdivision::~QuadEdgeSubdivision() -{ - for(QuadEdgeList::iterator iter = createdEdges.begin(); iter != createdEdges.end(); ++iter) { - (*iter)->free(); - delete *iter; - } + initSubdiv(); } void @@ -107,51 +94,32 @@ QuadEdgeSubdivision::createFrame(const geom::Envelope& env) frameEnv.expandToInclude(frameVertex[2].getCoordinate()); } void -QuadEdgeSubdivision::initSubdiv(QuadEdge* initEdges[3]) +QuadEdgeSubdivision::initSubdiv() { - std::unique_ptr tmp_ptr; - // build initial subdivision from frame - tmp_ptr = QuadEdge::makeEdge(frameVertex[0], frameVertex[1]); - initEdges[0] = tmp_ptr.get(); - tmp_ptr.release(); - + assert(quadEdges.empty()); - tmp_ptr = QuadEdge::makeEdge(frameVertex[1], frameVertex[2]); - initEdges[1] = tmp_ptr.get(); - tmp_ptr.release(); - - QuadEdge::splice(initEdges[0]->sym(), *initEdges[1]); - - tmp_ptr = QuadEdge::makeEdge(frameVertex[2], frameVertex[0]); - initEdges[2] = tmp_ptr.get(); - tmp_ptr.release(); + // build initial subdivision from frame + startingEdges[0] = QuadEdge::makeEdge(frameVertex[0], frameVertex[1], quadEdges); + startingEdges[1] = QuadEdge::makeEdge(frameVertex[1], frameVertex[2], quadEdges); + QuadEdge::splice(startingEdges[0]->sym(), *startingEdges[1]); - QuadEdge::splice(initEdges[1]->sym(), *initEdges[2]); - QuadEdge::splice(initEdges[2]->sym(), *initEdges[0]); + startingEdges[2] = QuadEdge::makeEdge(frameVertex[2], frameVertex[0], quadEdges); + QuadEdge::splice(startingEdges[1]->sym(), *startingEdges[2]); + QuadEdge::splice(startingEdges[2]->sym(), *startingEdges[0]); } QuadEdge& QuadEdgeSubdivision::makeEdge(const Vertex& o, const Vertex& d) { - std::unique_ptr q0 = QuadEdge::makeEdge(o, d); - QuadEdge* q0_ptr = q0.get(); - q0.release(); - - createdEdges.push_back(q0_ptr); - quadEdges.push_back(q0_ptr); - return *q0_ptr; + QuadEdge* e = QuadEdge::makeEdge(o, d, quadEdges); + return *e; } QuadEdge& QuadEdgeSubdivision::connect(QuadEdge& a, QuadEdge& b) { - std::unique_ptr q0 = QuadEdge::connect(a, b); - QuadEdge* q0_ptr = q0.get(); - q0.release(); - - createdEdges.push_back(q0_ptr); - quadEdges.push_back(q0_ptr); - return *q0_ptr; + QuadEdge* e = QuadEdge::connect(a, b, quadEdges); + return *e; } void @@ -160,8 +128,11 @@ QuadEdgeSubdivision::remove(QuadEdge& e) QuadEdge::splice(e, e.oPrev()); QuadEdge::splice(e.sym(), e.sym().oPrev()); - // this is inefficient on a std::vector, but this method should be called infrequently - quadEdges.erase(std::remove(quadEdges.begin(), quadEdges.end(), &e), quadEdges.end()); + // this is inefficient but this should be called infrequently + quadEdges.erase( + std::remove_if(quadEdges.begin(), quadEdges.end(), + [&e](QuadEdgeQuartet& es) { return &es.base() == &e; }), + quadEdges.end()); //mark these edges as removed e.remove(); @@ -191,7 +162,7 @@ QuadEdgeSubdivision::locateFromEdge(const Vertex& v, * since the orientation predicates may experience precision failures. */ if(iter > maxIter) { - throw LocateFailureException(""); + throw LocateFailureException("Could not locate vertex."); } if((v.equals(e->orig())) || (v.equals(e->dest()))) { @@ -403,7 +374,7 @@ class visit(QuadEdge* triEdges[3]) override { auto coordSeq = coordSeqFact.create(4, 0); - for(int i = 0; i < 3; i++) { + for(size_t i = 0; i < 3; i++) { Vertex v = triEdges[i]->orig(); coordSeq->setAt(v.getCoordinate(), i); } @@ -447,7 +418,7 @@ void QuadEdgeSubdivision::prepareVisit() { if (!visit_state_clean) { for (auto& qe : quadEdges) { - qe->setVisited(false); + qe.setVisited(false); } } @@ -633,7 +604,8 @@ QuadEdgeSubdivision::getVertexUniqueEdges(bool includeFrame) auto edges = detail::make_unique(); std::set visitedVertices; // TODO unordered_set of Vertex* ? - for(QuadEdge* qe : quadEdges) { + for(auto& quartet : quadEdges) { + QuadEdge* qe = &quartet.base(); const Vertex& v = qe->orig(); if(visitedVertices.find(v) == visitedVertices.end()) { //if v not found diff --git a/src/triangulate/quadedge/Vertex.cpp b/src/triangulate/quadedge/Vertex.cpp index 3d8980b848..8f74ea0d75 100644 --- a/src/triangulate/quadedge/Vertex.cpp +++ b/src/triangulate/quadedge/Vertex.cpp @@ -77,14 +77,6 @@ Vertex::classify(const Vertex& p0, const Vertex& p1) } } -bool -Vertex::isInCircle(const Vertex& a, const Vertex& b, const Vertex& c) const -{ - return TrianglePredicate::isInCircleRobust(a.p, b.p, c.p, this->p); - // non-robust - best to not use - //return TrianglePredicate.isInCircle(a.p, b.p, c.p, this->p); -} - bool Vertex::rightOf(const QuadEdge& e) const { diff --git a/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp b/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp index 1079b093fa..c6f877731a 100644 --- a/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp +++ b/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp @@ -6,6 +6,7 @@ // geos #include #include +#include // std #include @@ -39,31 +40,26 @@ template<> void object::test<1> () { + std::deque edges; + Vertex v1(0, 0); Vertex v2(0, 1); Vertex v3(1, 0); Vertex v4(1, 1); - std::unique_ptr q0; - std::unique_ptr r0; - std::unique_ptr s0; + auto q0 = QuadEdge::makeEdge(v1, v2, edges); + auto r0 = QuadEdge::makeEdge(v3, v4, edges); - q0 = QuadEdge::makeEdge(v1, v2); - r0 = QuadEdge::makeEdge(v3, v4); - s0 = QuadEdge::connect(*q0, *r0); + auto s0 = QuadEdge::connect(*q0, *r0, edges); //verify properties ensured by connect() //the new edge connects q0->orig() and r0->dest() ensure(s0->orig().equals(q0->dest())); ensure(s0->dest().equals(r0->orig())); //q0, r0, and s0 should have the same left face - ensure(&q0->lNext() == s0.get()); - ensure(&s0->lNext() == r0.get()); - - q0->free(); - r0->free(); - s0->free(); + ensure(&q0->lNext() == s0); + ensure(&s0->lNext() == r0); } // 2 - QuadEdge::connect(), causing a loop @@ -72,31 +68,25 @@ template<> void object::test<2> () { + std::deque edges; + Vertex v1(0, 0); Vertex v2(0, 1); Vertex v3(1, 0); Vertex v4(1, 1); - std::unique_ptr q0; - std::unique_ptr r0; - std::unique_ptr s0; - - q0 = QuadEdge::makeEdge(v1, v2); - r0 = QuadEdge::makeEdge(v2, v3); - s0 = QuadEdge::connect(*q0, *r0); + auto q0 = QuadEdge::makeEdge(v1, v2, edges); + auto r0 = QuadEdge::makeEdge(v2, v3, edges); + auto s0 = QuadEdge::connect(*q0, *r0, edges); //verify properties ensured by connect() //the new edge connects q0->orig() and r0->dest() ensure(s0->orig().equals(q0->dest())); ensure(s0->dest().equals(r0->orig())); //q0, r0, and s0 should have the same left face - ensure(&q0->lNext() == s0.get()); - ensure(&s0->lNext() == r0.get()); - - q0->free(); - r0->free(); - s0->free(); + ensure(&q0->lNext() == s0); + ensure(&s0->lNext() == r0); } // 3 - QuadEdge::swap() @@ -105,23 +95,20 @@ template<> void object::test<3> () { + std::deque edges; + Vertex v1(0, 0); Vertex v2(0, 1); Vertex v3(1, 0); Vertex v4(1, 1); - std::unique_ptr q0; - std::unique_ptr r0; - std::unique_ptr s0; - std::unique_ptr t0; - std::unique_ptr u0; - //make a quadilateral - q0 = QuadEdge::makeEdge(v1, v2); - r0 = QuadEdge::makeEdge(v4, v3); - s0 = QuadEdge::connect(*q0, *r0); - t0 = QuadEdge::connect(*r0, *q0); + auto q0 = QuadEdge::makeEdge(v1, v2, edges); + auto r0 = QuadEdge::makeEdge(v4, v3, edges); + + QuadEdge::connect(*q0, *r0, edges); + auto t0 = QuadEdge::connect(*r0, *q0, edges); //printf("\n=====================\n"); //printf("r0->orig(): %f %f\n", r0->orig().getX(), r0->orig().getY()); @@ -130,7 +117,7 @@ void object::test<3> //printf("s0->dest(): %f %f\n", s0->dest().getX(), s0->dest().getY()); //add an interior edge to make 2 triangles - u0 = QuadEdge::connect(*t0, *r0); + auto u0 = QuadEdge::connect(*t0, *r0, edges); //printf("\n=====================\n"); //printf("q0->orig(): %f %f\n", q0->orig().getX(), q0->orig().getY()); //printf("q0->dest(): %f %f\n", q0->dest().getX(), q0->dest().getY()); @@ -160,12 +147,6 @@ void object::test<3> //printf("u0->dest(): %f %f\n", u0->dest().getX(), u0->dest().getY()); ensure(r0->dest().equals(u0->dest())); ensure(u0->orig().equals(q0->dest())); - - q0->free(); - r0->free(); - s0->free(); - t0->free(); - u0->free(); } } // namespace tut