[geos-commits] [SCM] GEOS branch master updated. eb4da1440836fedf503e1eb2c245595a0f33db5e

git at osgeo.org git at osgeo.org
Wed Oct 23 18:15:40 PDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, master has been updated
       via  eb4da1440836fedf503e1eb2c245595a0f33db5e (commit)
       via  8b433f0887633e320053e169e5bf71c5bbaecb1f (commit)
      from  26c0b56ee17672617a4eeec4635ef644c33380f8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit eb4da1440836fedf503e1eb2c245595a0f33db5e
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Oct 18 12:21:40 2019 -0400

    Minor optimization to Vertex::isCCW
    
    Verified w/godbolt that this removes a couple of instructions.

diff --git a/include/geos/triangulate/quadedge/Vertex.h b/include/geos/triangulate/quadedge/Vertex.h
index 334ced8..808bf0e 100644
--- a/include/geos/triangulate/quadedge/Vertex.h
+++ b/include/geos/triangulate/quadedge/Vertex.h
@@ -222,10 +222,9 @@ public:
     inline bool
     isCCW(const Vertex& b, const Vertex& c) const
     {
-        // is equal to the signed area of the triangle
-
+        // check if signed area is positive
         return (b.p.x - p.x) * (c.p.y - p.y)
-               - (b.p.y - p.y) * (c.p.x - p.x) > 0;
+               > (b.p.y - p.y) * (c.p.x - p.x);
     }
 
     bool rightOf(const QuadEdge& e) const;

commit 8b433f0887633e320053e169e5bf71c5bbaecb1f
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Oct 16 21:20:53 2019 -0400

    Improve Delaunay/Voronoi performance
    
    - Introduce a QuadEdgeQuartet structure to store four QuadEdges. This
    reduces the number of memory allocations needed to create the QuadEdges,
    and allows them to refer to each other by their relative memory
    addresses. (This follows the Graphics Gems implementation.) For now, we
    still require QuadEdgeQuartets to have stable addresses, so we store
    them in a std::deque. If this requirement can be relaxed, better
    performance may come from using a std::vector.
    - Reduce the size of a Vertex and a QuadEdge by eliminating unnecessary
    virtual methods and associated vtable storage.
    
    Overall performance improvement of about 25% observed on benchmark.

diff --git a/benchmarks/ClassSizes.cpp b/benchmarks/ClassSizes.cpp
index 015be21..d4fe96b 100644
--- a/benchmarks/ClassSizes.cpp
+++ b/benchmarks/ClassSizes.cpp
@@ -40,6 +40,9 @@
 #include <geos/constants.h>
 #include <iostream>
 #include <geos/geomgraph/index/SweepLineEvent.h>
+#include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeQuartet.h>
+#include <geos/triangulate/quadedge/Vertex.h>
 
 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 2d48754..1c05bed 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 0a464dc..51513bb 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<QuadEdge> makeEdge(const Vertex& o, const Vertex& d);
+    static QuadEdge* makeEdge(const Vertex& o, const Vertex & d, std::deque<QuadEdgeQuartet> & edges);
 
     /** \brief
      * Creates a new QuadEdge connecting the destination of a to the origin of
@@ -67,10 +71,9 @@ public:
      *
      * 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<QuadEdge> connect(QuadEdge& a, QuadEdge& b);
+    static QuadEdge* connect(QuadEdge& a, QuadEdge& b, std::deque<QuadEdgeQuartet> & edges);
 
     /** \brief
      * Splices two edges together or apart.
@@ -97,31 +100,26 @@ public:
 
 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 @@ public:
      *
      * @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 @@ public:
      *
      * @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 @@ public:
      *
      * @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 @@ public:
      *
      * @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 @@ public:
      *
      * @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 @@ public:
      *
      * @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 @@ public:
      *
      * @return the previous right face edge.
      */
-    inline QuadEdge&
-    rPrev()
+    inline const QuadEdge&
+    rPrev() const
     {
         return sym().oNext();
     }
@@ -404,9 +436,10 @@ public:
     std::unique_ptr<geom::LineSegment> 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 0000000..30817d9
--- /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 <geos/triangulate/quadedge/QuadEdge.h>
+
+
+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<QuadEdgeQuartet> & 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<QuadEdge, 4> e;
+};
+
+}
+}
+}
+
+
+#endif
diff --git a/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h b/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h
index f8df488..e3b5c88 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 <vector>
 
 #include <geos/geom/MultiLineString.h>
+#include <geos/triangulate/quadedge/QuadEdge.h>
 #include <geos/triangulate/quadedge/QuadEdgeLocator.h>
+#include <geos/triangulate/quadedge/QuadEdgeQuartet.h>
 #include <geos/triangulate/quadedge/Vertex.h>
 
 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 @@ public:
                                  const QuadEdge* triEdge[3]);
 
 private:
-    QuadEdgeList quadEdges;
-    QuadEdgeList createdEdges;
-    QuadEdge* startingEdges[3];
+    std::deque<QuadEdgeQuartet> quadEdges;
+    std::array<QuadEdge*, 3> startingEdges;
     double tolerance;
     double edgeCoincidenceTolerance;
-    Vertex frameVertex[3];
+    std::array<Vertex, 3> frameVertex;
     geom::Envelope frameEnv;
     std::unique_ptr<QuadEdgeLocator> locator;
     bool visit_state_clean;
@@ -112,12 +113,12 @@ public:
      */
     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 @@ public:
      *
      * @return a QuadEdgeList
      */
-    inline const QuadEdgeList&
-    getEdges() const
+    inline std::deque<QuadEdgeQuartet>&
+    getEdges()
     {
         return quadEdges;
     }
@@ -192,8 +193,7 @@ public:
      * 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 8742fc1..a1a7f9f 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 <geos/export.h>
+
 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 b08f4dd..334ced8 100644
--- a/include/geos/triangulate/quadedge/Vertex.h
+++ b/include/geos/triangulate/quadedge/Vertex.h
@@ -24,6 +24,7 @@
 
 #include <geos/geom/Coordinate.h>
 #include <geos/algorithm/HCoordinate.h>
+#include <geos/triangulate/quadedge/TrianglePredicate.h>
 
 
 //fwd declarations
@@ -76,7 +77,7 @@ public:
     Vertex(const geom::Coordinate& _p);
 
     Vertex();
-    virtual ~Vertex() {};
+    ~Vertex() {};
 
     inline double
     getX() const
@@ -126,7 +127,7 @@ public:
         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 @@ public:
      * @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 @@ private:
      * @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 @@ private:
      * @param a the other end point.
      * @return the point mid-way between this and that.
      */
-    virtual std::unique_ptr<Vertex> midPoint(const Vertex& a);
+    std::unique_ptr<Vertex> midPoint(const Vertex& a);
 
     /**
      * Computes the centre of the circumcircle of this vertex and two others.
@@ -265,14 +268,13 @@ private:
      * @param c
      * @return the Coordinate which is the circumcircle of the 3 points.
      */
-    virtual std::unique_ptr<Vertex> circleCenter(const Vertex& b, const Vertex& c) const;
+    std::unique_ptr<Vertex> 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 7becab8..d20421d 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 12b2c0c..782c2d1 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 3c0d75f..7bbb3c1 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 b48e136..344c6ec 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 <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeQuartet.h>
 
 namespace geos {
 namespace triangulate { //geos.triangulate
@@ -24,36 +26,14 @@ namespace quadedge { //geos.triangulate.quadedge
 
 using namespace geos::geom;
 
-std::unique_ptr<QuadEdge>
-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<QuadEdge>(base);
+QuadEdge* QuadEdge::makeEdge(const Vertex& o, const Vertex& d, std::deque<QuadEdgeQuartet> & edges) {
+    return &QuadEdgeQuartet::makeEdge(o, d, edges);
 }
 
-std::unique_ptr<QuadEdge>
-QuadEdge::connect(QuadEdge& a, QuadEdge& b)
+QuadEdge*
+QuadEdge::connect(QuadEdge& a, QuadEdge& b, std::deque<QuadEdgeQuartet> & edges)
 {
-    std::unique_ptr<QuadEdge> 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;
@@ -125,18 +81,6 @@ QuadEdge::getPrimary() const
 }
 
 void
-QuadEdge::setData(void* p_data)
-{
-    this->data = p_data;
-}
-
-void*
-QuadEdge::getData()
-{
-    return data;
-}
-
-void
 QuadEdge::remove()
 {
     rot().rot().rot().isAlive = false;
diff --git a/src/triangulate/quadedge/QuadEdgeSubdivision.cpp b/src/triangulate/quadedge/QuadEdgeSubdivision.cpp
index 6c57f47..bc4a1ba 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<QuadEdge> 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<QuadEdge> 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<QuadEdge> 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 @@ public:
     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<QuadEdgeList>();
     std::set<Vertex> 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 3d8980b..8f74ea0 100644
--- a/src/triangulate/quadedge/Vertex.cpp
+++ b/src/triangulate/quadedge/Vertex.cpp
@@ -78,14 +78,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
 {
     return isCCW(e.dest(), e.orig());
diff --git a/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp b/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp
index 1079b09..c6f8777 100644
--- a/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp
+++ b/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp
@@ -6,6 +6,7 @@
 // geos
 #include <geos/triangulate/quadedge/Vertex.h>
 #include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeQuartet.h>
 // std
 #include <stdio.h>
 
@@ -39,31 +40,26 @@ template<>
 void object::test<1>
 ()
 {
+    std::deque<QuadEdgeQuartet> edges;
+
     Vertex v1(0, 0);
     Vertex v2(0, 1);
 
     Vertex v3(1, 0);
     Vertex v4(1, 1);
 
-    std::unique_ptr<QuadEdge> q0;
-    std::unique_ptr<QuadEdge> r0;
-    std::unique_ptr<QuadEdge> 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<QuadEdgeQuartet> edges;
+
     Vertex v1(0, 0);
     Vertex v2(0, 1);
 
     Vertex v3(1, 0);
     Vertex v4(1, 1);
 
-    std::unique_ptr<QuadEdge> q0;
-    std::unique_ptr<QuadEdge> r0;
-    std::unique_ptr<QuadEdge> 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<QuadEdgeQuartet> edges;
+
     Vertex v1(0, 0);
     Vertex v2(0, 1);
 
     Vertex v3(1, 0);
     Vertex v4(1, 1);
 
-    std::unique_ptr<QuadEdge> q0;
-    std::unique_ptr<QuadEdge> r0;
-    std::unique_ptr<QuadEdge> s0;
-    std::unique_ptr<QuadEdge> t0;
-    std::unique_ptr<QuadEdge> 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
 

-----------------------------------------------------------------------

Summary of changes:
 benchmarks/ClassSizes.cpp                          |   6 +
 include/geos/triangulate/quadedge/Makefile.am      |   1 +
 include/geos/triangulate/quadedge/QuadEdge.h       | 147 +++++++++++++--------
 .../geos/triangulate/quadedge/QuadEdgeQuartet.h    |  67 ++++++++++
 .../triangulate/quadedge/QuadEdgeSubdivision.h     |  22 +--
 .../geos/triangulate/quadedge/TrianglePredicate.h  |   4 +-
 include/geos/triangulate/quadedge/Vertex.h         |  25 ++--
 .../IncrementalDelaunayTriangulator.cpp            |   2 +-
 .../quadedge/LastFoundQuadEdgeLocator.cpp          |   2 +-
 .../quadedge/LocateFailureException.cpp            |   7 +-
 src/triangulate/quadedge/QuadEdge.cpp              |  72 ++--------
 src/triangulate/quadedge/QuadEdgeSubdivision.cpp   |  78 ++++-------
 src/triangulate/quadedge/Vertex.cpp                |   8 --
 tests/unit/triangulate/quadedge/QuadEdgeTest.cpp   |  65 ++++-----
 14 files changed, 252 insertions(+), 254 deletions(-)
 create mode 100644 include/geos/triangulate/quadedge/QuadEdgeQuartet.h


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list