[geos-commits] r3693 - in trunk: . include/geos include/geos/triangulate include/geos/triangulate/quadedge src src/triangulate src/triangulate/quadedge tests/unit tests/unit/triangulate tests/unit/triangulate/quadedge
svn_geos at osgeo.org
svn_geos at osgeo.org
Tue Jun 26 10:11:33 PDT 2012
Author: strk
Date: 2012-06-26 10:11:33 -0700 (Tue, 26 Jun 2012)
New Revision: 3693
Added:
trunk/include/geos/triangulate/
trunk/include/geos/triangulate/DelaunayTriangulationBuilder.h
trunk/include/geos/triangulate/IncrementalDelaunayTriangulator.h
trunk/include/geos/triangulate/Makefile.am
trunk/include/geos/triangulate/quadedge/
trunk/include/geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h
trunk/include/geos/triangulate/quadedge/LocateFailureException.h
trunk/include/geos/triangulate/quadedge/Makefile.am
trunk/include/geos/triangulate/quadedge/QuadEdge.h
trunk/include/geos/triangulate/quadedge/QuadEdgeLocator.h
trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h
trunk/include/geos/triangulate/quadedge/TrianglePredicate.h
trunk/include/geos/triangulate/quadedge/TriangleVisitor.h
trunk/include/geos/triangulate/quadedge/Vertex.h
trunk/src/triangulate/
trunk/src/triangulate/DelaunayTriangulationBuilder.cpp
trunk/src/triangulate/IncrementalDelaunayTriangulator.cpp
trunk/src/triangulate/Makefile.am
trunk/src/triangulate/quadedge/
trunk/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp
trunk/src/triangulate/quadedge/LocateFailureException.cpp
trunk/src/triangulate/quadedge/Makefile.am
trunk/src/triangulate/quadedge/QuadEdge.cpp
trunk/src/triangulate/quadedge/QuadEdgeLocator.cpp
trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp
trunk/src/triangulate/quadedge/TrianglePredicate.cpp
trunk/src/triangulate/quadedge/TriangleVisitor.cpp
trunk/src/triangulate/quadedge/Vertex.cpp
trunk/tests/unit/triangulate/
trunk/tests/unit/triangulate/DelaunayTest.cpp
trunk/tests/unit/triangulate/quadedge/
trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
trunk/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp
Modified:
trunk/NEWS
trunk/configure.in
trunk/src/Makefile.am
trunk/tests/unit/Makefile.am
Log:
Port Delaunay Triangulation API from JTS (#487)
Work contributed by Benjamin Campbell
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2012-06-25 23:31:38 UTC (rev 3692)
+++ trunk/NEWS 2012-06-26 17:11:33 UTC (rev 3693)
@@ -2,6 +2,7 @@
????-??-??
- New things:
+ - Delaunay Triangulation API (#487)
- Interruptibility API (C and C++)
- CAPI: GEOSNode (#496) - PHP: Geometry->node
- GeometryPrecisionReducer class
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2012-06-25 23:31:38 UTC (rev 3692)
+++ trunk/configure.in 2012-06-26 17:11:33 UTC (rev 3693)
@@ -465,6 +465,8 @@
include/geos/planargraph/algorithm/Makefile
include/geos/precision/Makefile
include/geos/simplify/Makefile
+ include/geos/triangulate/Makefile
+ include/geos/triangulate/quadedge/Makefile
include/geos/util/Makefile
include/geos/version.h
src/index/Makefile
@@ -492,6 +494,8 @@
src/planargraph/Makefile
src/precision/Makefile
src/simplify/Makefile
+ src/triangulate/Makefile
+ src/triangulate/quadedge/Makefile
src/util/Makefile
swig/geos.i
swig/Makefile
Added: trunk/include/geos/triangulate/DelaunayTriangulationBuilder.h
===================================================================
--- trunk/include/geos/triangulate/DelaunayTriangulationBuilder.h (rev 0)
+++ trunk/include/geos/triangulate/DelaunayTriangulationBuilder.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,144 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/DelaunayTriangulationBuilder.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_DELAUNAYTRIANGULATIONBUILDER_H
+#define GEOS_TRIANGULATE_DELAUNAYTRIANGULATIONBUILDER_H
+
+#include <geos/triangulate/IncrementalDelaunayTriangulator.h>
+
+
+namespace geos {
+namespace geom{
+ class CoordinateSequence;
+ class Geometry;
+ class MultiLineString;
+ class GeometryCollection;
+ class GeometryFactory;
+}
+
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+class QuadEdgeSubdivision;
+
+/**
+ * A utility class which creates Delaunay Trianglulations
+ * from collections of points and extract the resulting
+ * triangulation edges or triangles as geometries.
+ *
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ *
+ */
+class GEOS_DLL DelaunayTriangulationBuilder
+{
+public:
+ /**
+ * Extracts the unique {@link Coordinate}s from the given {@link Geometry}.
+ * @param geom the geometry to extract from
+ * @return a List of the unique Coordinates. Caller takes ownership of the returned object.
+ */
+ static geom::CoordinateSequence* extractUniqueCoordinates(const geom::Geometry& geom);
+
+ static void unique(geom::CoordinateSequence& coords);
+
+ /**
+ * Converts all {@link Coordinate}s in a collection to {@link Vertex}es.
+ * @param coords the coordinates to convert
+ * @return a List of Vertex objects. Call takes ownership of returned object.
+ */
+ static IncrementalDelaunayTriangulator::VertexList* toVertices(const geom::CoordinateSequence &coords);
+
+private:
+ geom::CoordinateSequence* siteCoords;
+ double tolerance;
+ QuadEdgeSubdivision *subdiv;
+
+public:
+ /**
+ * Creates a new triangulation builder.
+ *
+ */
+ DelaunayTriangulationBuilder();
+
+ ~DelaunayTriangulationBuilder();
+
+ /**
+ * Sets the sites (vertices) which will be triangulated.
+ * All vertices of the given geometry will be used as sites.
+ *
+ * @param geom the geometry from which the sites will be extracted.
+ */
+ void setSites(const geom::Geometry& geom);
+
+ /**
+ * Sets the sites (vertices) which will be triangulated
+ * from a collection of {@link Coordinate}s.
+ *
+ * @param geom a CoordinateSequence.
+ */
+ void setSites(const geom::CoordinateSequence& coords);
+
+ /**
+ * Sets the snapping tolerance which will be used
+ * to improved the robustness of the triangulation computation.
+ * A tolerance of 0.0 specifies that no snapping will take place.
+ *
+ * @param tolerance the tolerance distance to use
+ */
+ inline void setTolerance(double tolerance)
+ {
+ this->tolerance = tolerance;
+ }
+
+private:
+ void create();
+
+public:
+ /**
+ * Gets the {@link QuadEdgeSubdivision} which models the computed triangulation.
+ *
+ * @return the subdivision containing the triangulation
+ */
+ QuadEdgeSubdivision& getSubdivision();
+
+ /**
+ * Gets the edges of the computed triangulation as a {@link MultiLineString}.
+ *
+ * @param geomFact the geometry factory to use to create the output
+ * @return the edges of the triangulation. The caller takes ownership of the returned object.
+ */
+ std::auto_ptr<geom::MultiLineString> getEdges(geom::GeometryFactory &geomFact);
+
+ /**
+ * Gets the faces of the computed triangulation as a {@link GeometryCollection}
+ * of {@link Polygon}.
+ *
+ * @param geomFact the geometry factory to use to create the output
+ * @return the faces of the triangulation. The caller takes ownership of the returned object.
+ */
+ std::auto_ptr<geom::GeometryCollection> getTriangles(geom::GeometryFactory& geomFact);
+
+};
+
+}//namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_DELAUNAYTRIANGULATIONBUILDER_H
+
Added: trunk/include/geos/triangulate/IncrementalDelaunayTriangulator.h
===================================================================
--- trunk/include/geos/triangulate/IncrementalDelaunayTriangulator.h (rev 0)
+++ trunk/include/geos/triangulate/IncrementalDelaunayTriangulator.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,87 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/IncrementalDelaunayTriangulator.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_INCREMENTALDELAUNAYTRIANGULATOR_H
+#define GEOS_TRIANGULATE_INCREMENTALDELAUNAYTRIANGULATOR_H
+
+#include <list>
+
+#include <geos/triangulate/quadedge/Vertex.h>
+
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+
+namespace quadedge {
+ class QuadEdge;
+ class QuadEdgeSubdivision;
+}
+
+/**
+ * Computes a Delauanay Triangulation of a set of {@link Vertex}es, using an
+ * incrementatal insertion algorithm.
+ *
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ */
+class GEOS_DLL IncrementalDelaunayTriangulator
+{
+private:
+ quadedge::QuadEdgeSubdivision *subdiv;
+ bool isUsingTolerance;
+
+public:
+ /**
+ * Creates a new triangulator using the given {@link QuadEdgeSubdivision}.
+ * The triangulator uses the tolerance of the supplied subdivision.
+ *
+ * @param subdiv
+ * a subdivision in which to build the TIN
+ */
+ IncrementalDelaunayTriangulator(quadedge::QuadEdgeSubdivision *subdiv);
+
+ typedef std::list<quadedge::Vertex> VertexList;
+
+ /**
+ * Inserts all sites in a collection. The inserted vertices <b>MUST</b> be
+ * unique up to the provided tolerance value. (i.e. no two vertices should be
+ * closer than the provided tolerance value). They do not have to be rounded
+ * to the tolerance grid, however.
+ *
+ * @param vertices a Collection of Vertex
+ *
+ * @throws LocateFailureException if the location algorithm fails to converge in a reasonable number of iterations
+ */
+ void insertSites(const VertexList& vertices);
+
+ /**
+ * Inserts a new point into a subdivision representing a Delaunay
+ * triangulation, and fixes the affected edges so that the result is still a
+ * Delaunay triangulation.
+ * <p>
+ *
+ * @return a quadedge containing the inserted vertex
+ */
+ quadedge::QuadEdge& insertSite(const quadedge::Vertex &v);
+};
+
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_INCREMENTALDELAUNAYTRIANGULATOR_H
+
Added: trunk/include/geos/triangulate/Makefile.am
===================================================================
--- trunk/include/geos/triangulate/Makefile.am (rev 0)
+++ trunk/include/geos/triangulate/Makefile.am 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,13 @@
+#
+# This file is part of project GEOS (http://trac.osgeo.org/geos/)
+#
+SUBDIRS = \
+ quadedge
+
+EXTRA_DIST =
+
+geosdir = $(includedir)/geos/triangulate
+
+geos_HEADERS = \
+ IncrementalDelaunayTriangulator.h \
+ DelaunayTriangulationBuilder.h
Added: trunk/include/geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,68 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/LastFoundQuadEdgeLocator.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_LASTFOUNDQUADEDGELOCATOR_H
+#define GEOS_TRIANGULATE_QUADEDGE_LASTFOUNDQUADEDGELOCATOR_H
+
+#include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeLocator.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+//fwd declarations
+class QuadEdgeSubdivision;
+
+/**
+* Locates {@link QuadEdge}s in a {@link QuadEdgeSubdivision},
+* optimizing the search by starting in the
+* locality of the last edge found.
+*
+* @author JTS: Martin Davis
+* @author Benjamin Campbell
+*/
+
+class LastFoundQuadEdgeLocator : public QuadEdgeLocator {
+private:
+ QuadEdgeSubdivision* subdiv;
+ QuadEdge* lastEdge;
+
+public:
+ LastFoundQuadEdgeLocator(QuadEdgeSubdivision *subdiv);
+
+private:
+ virtual void init();
+
+ virtual QuadEdge* findEdge();
+
+public:
+ /**
+ * Locates an edge e, such that either v is on e, or e is an edge of a triangle containing v.
+ * The search starts from the last located edge amd proceeds on the general direction of v.
+ * @return The caller _does not_ take ownership of the returned object.
+ */
+ virtual QuadEdge* locate(const Vertex &v);
+};
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif // GEOS_TRIANGULATE_QUADEDGE_LASTFOUNDQUADEDGELOCATOR_H
+
Added: trunk/include/geos/triangulate/quadedge/LocateFailureException.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/LocateFailureException.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/LocateFailureException.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,40 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/LocateFailureException.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_LOCATEFAILUREEXCEPTION_H
+#define GEOS_TRIANGULATE_QUADEDGE_LOCATEFAILUREEXCEPTION_H
+
+#include <string>
+
+#include <geos/util.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+class GEOS_DLL LocateFailureException : public geos::util::GEOSException {
+public:
+ LocateFailureException(std::string const&msg);
+};
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_LOCATEFAILUREEXCEPTION_H
+
Added: trunk/include/geos/triangulate/quadedge/Makefile.am
===================================================================
--- trunk/include/geos/triangulate/quadedge/Makefile.am (rev 0)
+++ trunk/include/geos/triangulate/quadedge/Makefile.am 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,18 @@
+#
+# This file is part of project GEOS (http://trac.osgeo.org/geos/)
+#
+SUBDIRS =
+
+EXTRA_DIST =
+
+geosdir = $(includedir)/geos/triangulate/quadedge
+
+geos_HEADERS = \
+ QuadEdge.h \
+ Vertex.h \
+ TrianglePredicate.h \
+ QuadEdgeSubdivision.h \
+ QuadEdgeLocator.h \
+ LastFoundQuadEdgeLocator.h \
+ LocateFailureException.h \
+ TriangleVisitor.h
Added: trunk/include/geos/triangulate/quadedge/QuadEdge.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/QuadEdge.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/QuadEdge.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,360 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/QuadEdge.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_QUADEDGE_H
+#define GEOS_TRIANGULATE_QUADEDGE_QUADEDGE_H
+
+#include <memory>
+
+#include <geos/triangulate/quadedge/Vertex.h>
+#include <geos/geom/LineSegment.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+/**
+ * A class that represents the edge data structure which implements the quadedge algebra.
+ * The quadedge algebra was described in a well-known paper by Guibas and Stolfi,
+ * "Primitives for the manipulation of general subdivisions and the computation of Voronoi diagrams",
+ * <i>ACM Transactions on Graphics</i>, 4(2), 1985, 75-123.
+ * <p>
+ * Each edge object is part of a quartet of 4 edges,
+ * linked via their <tt>_rot</tt> references.
+ * Any edge in the group may be accessed using a series of {@link #rot()} operations.
+ * Quadedges in a subdivision are linked together via their <tt>next</tt> references.
+ * The linkage between the quadedge quartets determines the topology
+ * of the subdivision.
+ * <p>
+ * The edge class does not contain separate information for vertice or faces; a vertex is implicitly
+ * defined as a ring of edges (created using the <tt>next</tt> field).
+ *
+ * @author JTS: David Skea
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ * */
+class GEOS_DLL QuadEdge {
+public:
+ /**
+ * 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
+ */
+ static std::auto_ptr<QuadEdge> makeEdge(const Vertex &o, const Vertex &d);
+
+ /**
+ * Creates a new QuadEdge connecting the destination of a to the origin of
+ * b, in such a way that all three have the same left face after the
+ * connection is complete. Additionally, the data pointers of the new edge
+ * are set.
+ *
+ * @return the new QuadEdge* The caller is reponsible for
+ * freeing the returned pointer
+ */
+ static std::auto_ptr<QuadEdge> connect(QuadEdge &a, QuadEdge &b);
+
+ /**
+ * Splices two edges together or apart.
+ * Splice affects the two edge rings around the origins of a and b, and, independently, the two
+ * edge rings around the left faces of <tt>a</tt> and <tt>b</tt>.
+ * In each case, (i) if the two rings are distinct,
+ * Splice will combine them into one, or (ii) if the two are the same ring, Splice will break it
+ * into two separate pieces. Thus, Splice can be used both to attach the two edges together, and
+ * to break them apart.
+ *
+ * @param a an edge to splice
+ * @param b an edge to splice
+ *
+ */
+ static void splice(QuadEdge &a, QuadEdge &b);
+
+ /**
+ * Turns an edge counterclockwise inside its enclosing quadrilateral.
+ *
+ * @param e the quadedge to turn
+ */
+ static void swap(QuadEdge &e);
+
+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;
+ bool isAlive;
+
+ /**
+ * Quadedges must be made using {@link makeEdge},
+ * to ensure proper construction.
+ */
+ QuadEdge();
+
+public:
+ ~QuadEdge();
+
+ /**
+ * Free the QuadEdge quartet associated with this QuadEdge by a connect()
+ * or makeEdge() call.
+ * DO NOT call this function on a QuadEdge that was not returned
+ * by connect() or makeEdge().
+ */
+ virtual void free();
+
+ /**
+ * Gets the primary edge of this quadedge and its <tt>sym</tt>.
+ * The primary edge is the one for which the origin
+ * and destination coordinates are ordered
+ * according to the standard {@link Coordinate} ordering
+ *
+ * @return the primary quadedge
+ */
+ const QuadEdge& getPrimary() const;
+
+ /**
+ * Sets the external data value for this edge.
+ *
+ * @param data an object containing external data
+ */
+ virtual void setData(void* data);
+
+ /**
+ * Gets the external data value for this edge.
+ *
+ * @return the data object
+ */
+ virtual void* getData();
+
+ /**
+ * Marks this quadedge as being deleted.
+ * This does not free the memory used by
+ * this quadedge quartet, but indicates
+ * that this quadedge quartet no longer participates
+ * in a subdivision.
+ *
+ */
+ void remove();
+
+ /**
+ * Tests whether this edge has been deleted.
+ *
+ * @return true if this edge has not been deleted.
+ */
+ inline bool isLive() {
+ return isAlive;
+ }
+
+
+ /**
+ * Sets the connected edge
+ *
+ * @param nextEdge edge
+ */
+ inline void setNext(QuadEdge *next) {
+ this->next = next;
+ }
+
+ /***************************************************************************
+ * QuadEdge Algebra
+ ***************************************************************************
+ */
+
+ /**
+ * Gets the dual of this edge, directed from its right to its left.
+ *
+ * @return the rotated edge
+ */
+ inline QuadEdge& rot() const {
+ return *_rot;
+ }
+
+ /**
+ * Gets the dual of this edge, directed from its left to its right.
+ *
+ * @return the inverse rotated edge.
+ */
+ inline QuadEdge& invRot() const {
+ return rot().sym();
+ }
+
+ /**
+ * Gets the edge from the destination to the origin of this edge.
+ *
+ * @return the sym of the edge
+ */
+ inline QuadEdge& sym() const {
+ return rot().rot();
+ }
+
+ /**
+ * Gets the next CCW edge around the origin of this edge.
+ *
+ * @return the next linked edge.
+ */
+ inline QuadEdge& oNext() const {
+ return *next;
+ }
+
+ /**
+ * Gets the next CW edge around (from) the origin of this edge.
+ *
+ * @return the previous edge.
+ */
+ inline QuadEdge& oPrev() const {
+ return rot().oNext().rot();
+ }
+
+ /**
+ * Gets the next CCW edge around (into) the destination of this edge.
+ *
+ * @return the next destination edge.
+ */
+ inline QuadEdge& dNext() const {
+ return sym().oNext().sym();
+ }
+
+ /**
+ * Gets the next CW edge around (into) the destination of this edge.
+ *
+ * @return the previous destination edge.
+ */
+ inline QuadEdge& dPrev() const {
+ return invRot().oNext().invRot();
+ }
+
+ /**
+ * Gets the CCW edge around the left face following this edge.
+ *
+ * @return the next left face edge.
+ */
+ inline QuadEdge& lNext() const {
+ return invRot().oNext().rot();
+ }
+
+ /**
+ * Gets the CCW edge around the left face before this edge.
+ *
+ * @return the previous left face edge.
+ */
+ inline QuadEdge& lPrev() const {
+ return oNext().sym();
+ }
+
+ /**
+ * Gets the edge around the right face ccw following this edge.
+ *
+ * @return the next right face edge.
+ */
+ inline QuadEdge& rNext() {
+ return rot().oNext().invRot();
+ }
+
+ /**
+ * Gets the edge around the right face ccw before this edge.
+ *
+ * @return the previous right face edge.
+ */
+ inline QuadEdge& rPrev() {
+ return sym().oNext();
+ }
+
+ /***********************************************************************************************
+ * Data Access
+ **********************************************************************************************/
+ /**
+ * Sets the vertex for this edge's origin
+ *
+ * @param o the origin vertex
+ */
+ inline void setOrig(const Vertex &o) {
+ vertex = o;
+ }
+
+ /**
+ * Sets the vertex for this edge's destination
+ *
+ * @param d the destination vertex
+ */
+ inline void setDest(const Vertex &d) {
+ sym().setOrig(d);
+ }
+
+ /**
+ * Gets the vertex for the edge's origin
+ *
+ * @return the origin vertex
+ */
+ const Vertex& orig() const {
+ return vertex;
+ }
+
+ /**
+ * Gets the vertex for the edge's destination
+ *
+ * @return the destination vertex
+ */
+ const Vertex& dest() const {
+ return sym().orig();
+ }
+
+ /**
+ * Gets the length of the geometry of this quadedge.
+ *
+ * @return the length of the quadedge
+ */
+ inline double getLength() const {
+ return orig().getCoordinate().distance(dest().getCoordinate());
+ }
+
+ /**
+ * Tests if this quadedge and another have the same line segment geometry,
+ * regardless of orientation.
+ *
+ * @param qe a quadege
+ * @return true if the quadedges are based on the same line segment regardless of orientation
+ */
+ bool equalsNonOriented(const QuadEdge &qe) const;
+
+ /**
+ * Tests if this quadedge and another have the same line segment geometry
+ * with the same orientation.
+ *
+ * @param qe a quadege
+ * @return true if the quadedges are based on the same line segment
+ */
+ bool equalsOriented(const QuadEdge &qe) const;
+
+ /**
+ * Creates a {@link LineSegment} representing the
+ * geometry of this edge.
+ *
+ * @return a LineSegment
+ */
+ std::auto_ptr<geom::LineSegment> toLineSegment() const;
+};
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_QUADEDGE_H
+
Added: trunk/include/geos/triangulate/quadedge/QuadEdgeLocator.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/QuadEdgeLocator.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/QuadEdgeLocator.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,49 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/QuadEdgeLocator.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_QUADEDGELOCATOR_H
+#define GEOS_TRIANGULATE_QUADEDGE_QUADEDGELOCATOR_H
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+class Vertex;
+class QuadEdge;
+
+/**
+ * An interface for classes which locate an edge in a {@link QuadEdgeSubdivision}
+ * which either contains a given {@link Vertex} V
+ * or is an edge of a triangle which contains V.
+ * Implementors may utilized different strategies for
+ * optimizing locating containing edges/triangles.
+ *
+ * @author JTS: Martin Davis
+ * @author Ben Campbell
+ */
+class QuadEdgeLocator {
+public:
+ virtual ~QuadEdgeLocator() = 0; //not implemented
+ virtual QuadEdge* locate(const Vertex &v) = 0; //not implemented
+};
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_QUADEDGELOCATOR_H
Added: trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,402 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/QuadEdgeSubdivision.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_QUADEDGESUBDIVISION_H
+#define GEOS_TRIANGULATE_QUADEDGE_QUADEDGESUBDIVISION_H
+
+#include <memory>
+#include <list>
+#include <stack>
+#include <set>
+
+#include <geos/geom/Envelope.h>
+#include <geos/geom/MultiLineString.h>
+#include <geos/triangulate/quadedge/QuadEdgeLocator.h>
+#include <geos/triangulate/quadedge/Vertex.h>
+
+namespace geos {
+
+namespace geom {
+
+ class CoordinateSequence;
+ class GeometryCollection;
+ class GeometryFactory;
+ class Coordinate;
+}
+
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+class QuadEdge;
+class TriangleVisitor;
+
+const double EDGE_COINCIDENCE_TOL_FACTOR = 1000;
+
+/**
+ * A class that contains the {@link QuadEdge}s representing a planar
+ * subdivision that models a triangulation.
+ * The subdivision is constructed using the
+ * quadedge algebra defined in the classs {@link QuadEdge}.
+ * All metric calculations
+ * are done in the {@link Vertex} class.
+ * In addition to a triangulation, subdivisions
+ * support extraction of Voronoi diagrams.
+ * This is easily accomplished, since the Voronoi diagram is the dual
+ * of the Delaunay triangulation.
+ * <p>
+ * Subdivisions can be provided with a tolerance value. Inserted vertices which
+ * are closer than this value to vertices already in the subdivision will be
+ * ignored. Using a suitable tolerance value can prevent robustness failures
+ * from happening during Delaunay triangulation.
+ * <p>
+ * Subdivisions maintain a <b>frame</b> triangle around the client-created
+ * edges. The frame is used to provide a bounded "container" for all edges
+ * within a TIN. Normally the frame edges, frame connecting edges, and frame
+ * triangles are not included in client processing.
+ *
+ * @author JTS: David Skea
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ */
+class GEOS_DLL QuadEdgeSubdivision {
+public:
+ typedef std::list<QuadEdge*> QuadEdgeList;
+
+ /**
+ * Gets the edges for the triangle to the left of the given {@link QuadEdge}.
+ *
+ * @param startQE
+ * @param triEdge
+ *
+ * @throws IllegalArgumentException
+ * if the edges do not form a triangle
+ */
+ static void getTriangleEdges(const QuadEdge &startQE,
+ const QuadEdge* triEdge[3]);
+
+private:
+ QuadEdgeList quadEdges;
+ QuadEdgeList removedEdges;
+ QuadEdge* startingEdges[3];
+ double tolerance;
+ double edgeCoincidenceTolerance;
+ Vertex frameVertex[3];
+ geom::Envelope frameEnv;
+ std::auto_ptr<QuadEdgeLocator> locator;
+
+public:
+ /**
+ * Creates a new instance of a quad-edge subdivision based on a frame triangle
+ * that encloses a supplied bounding box. A new super-bounding box that
+ * contains the triangle is computed and stored.
+ *
+ * @param env
+ * the bouding box to surround
+ * @param tolerance
+ * the tolerance value for determining if two sites are equal
+ */
+ QuadEdgeSubdivision(const geom::Envelope &env, double tolerance);
+
+ ~QuadEdgeSubdivision();
+
+private:
+ virtual void createFrame(const geom::Envelope &env);
+
+ virtual void initSubdiv(QuadEdge* initEdges[3]);
+
+public:
+ /**
+ * Gets the vertex-equality tolerance value
+ * used in this subdivision
+ *
+ * @return the tolerance value
+ */
+ inline double getTolerance() const {
+ return tolerance;
+ }
+
+ /**
+ * Gets the envelope of the Subdivision (including the frame).
+ *
+ * @return the envelope
+ */
+ inline const geom::Envelope& getEnvelope() const {
+ return frameEnv;
+ }
+
+ /**
+ * Gets the collection of base {@link QuadEdge}s (one for every pair of
+ * vertices which is connected).
+ *
+ * @return a QuadEdgeList
+ */
+ inline const QuadEdgeList& getEdges() const {
+ return quadEdges;
+ }
+
+ /**
+ * Sets the {@link QuadEdgeLocator} to use for locating containing triangles
+ * in this subdivision.
+ *
+ * @param locator
+ * a QuadEdgeLocator
+ */
+ inline void setLocator(std::auto_ptr<QuadEdgeLocator> locator) {
+ this->locator = locator;
+ }
+
+ /**
+ * Creates a new quadedge, recording it in the edges list.
+ *
+ * @param o
+ * @param d
+ * @return
+ */
+ virtual QuadEdge& makeEdge(const Vertex &o, const Vertex &d);
+
+ /**
+ * Creates a new QuadEdge connecting the destination of a to the origin of b,
+ * in such a way that all three have the same left face after the connection
+ * is complete. The quadedge is recorded in the edges list.
+ *
+ * @param a
+ * @param b
+ * @return
+ */
+ virtual QuadEdge& connect(QuadEdge &a, QuadEdge &b);
+
+ /**
+ * Deletes a quadedge from the subdivision. Linked quadedges are updated to
+ * reflect the deletion.
+ *
+ * @param e
+ * the quadedge to delete
+ */
+ void remove(QuadEdge &e);
+
+ /**
+ * Locates an edge of a triangle which contains a location
+ * specified by a Vertex v.
+ * The edge returned has the
+ * property that either v is on e, or e is an edge of a triangle containing v.
+ * The search starts from startEdge amd proceeds on the general direction of v.
+ * <p>
+ * This locate algorithm relies on the subdivision being Delaunay. For
+ * non-Delaunay subdivisions, this may loop for ever.
+ *
+ * @param v the location to search for
+ * @param startEdge an edge of the subdivision to start searching at
+ * @returns a QuadEdge which contains v, or is on the edge of a triangle containing v
+ * @throws LocateFailureException
+ * if the location algorithm fails to converge in a reasonable
+ * number of iterations. The returned pointer should not be
+ * freed be the caller.
+ */
+ QuadEdge* locateFromEdge(const Vertex &v,
+ const QuadEdge &startEdge) const;
+
+ /**
+ * Finds a quadedge of a triangle containing a location
+ * specified by a {@link Vertex}, if one exists.
+ *
+ * @param x the vertex to locate
+ * @return a quadedge on the edge of a triangle which touches or contains the location
+ * @return null if no such triangle exists. The returned pointer should not be
+ * freed be the caller.
+ */
+ inline QuadEdge* locate(const Vertex &v) const {
+ return locator->locate(v);
+ }
+
+ /**
+ * Finds a quadedge of a triangle containing a location
+ * specified by a {@link Coordinate}, if one exists.
+ *
+ * @param p the Coordinate to locate
+ * @return a quadedge on the edge of a triangle which touches or contains the location
+ * @return null if no such triangle exists. The returned pointer should not be
+ * freed be the caller.
+ */
+ inline QuadEdge* locate(const geom::Coordinate &p) {
+ return locator->locate(Vertex(p));
+ }
+
+ /**
+ * Locates the edge between the given vertices, if it exists in the
+ * subdivision.
+ *
+ * @param p0 a coordinate
+ * @param p1 another coordinate
+ * @return the edge joining the coordinates, if present
+ * @return null if no such edge exists
+ * @return the caller _should not_ free the returned pointer
+ */
+ QuadEdge* locate(const geom::Coordinate &p0, const geom::Coordinate &p1);
+
+ /**
+ * Inserts a new site into the Subdivision, connecting it to the vertices of
+ * the containing triangle (or quadrilateral, if the split point falls on an
+ * existing edge).
+ * <p>
+ * This method does NOT maintain the Delaunay condition. If desired, this must
+ * be checked and enforced by the caller.
+ * <p>
+ * This method does NOT check if the inserted vertex falls on an edge. This
+ * must be checked by the caller, since this situation may cause erroneous
+ * triangulation
+ *
+ * @param v
+ * the vertex to insert
+ * @return a new quad edge terminating in v
+ */
+ QuadEdge& insertSite(const Vertex &v);
+
+ /**
+ * Tests whether a QuadEdge is an edge incident on a frame triangle vertex.
+ *
+ * @param e
+ * the edge to test
+ * @return true if the edge is connected to the frame triangle
+ */
+ bool isFrameEdge(const QuadEdge &e) const;
+
+ /**
+ * Tests whether a QuadEdge is an edge on the border of the frame facets and
+ * the internal facets. E.g. an edge which does not itself touch a frame
+ * vertex, but which touches an edge which does.
+ *
+ * @param e
+ * the edge to test
+ * @return true if the edge is on the border of the frame
+ */
+ bool isFrameBorderEdge(const QuadEdge &e) const;
+
+ /**
+ * Tests whether a vertex is a vertex of the outer triangle.
+ *
+ * @param v
+ * the vertex to test
+ * @return true if the vertex is an outer triangle vertex
+ */
+ bool isFrameVertex(const Vertex &v) const;
+
+
+ /**
+ * Tests whether a {@link Coordinate} lies on a {@link QuadEdge}, up to a
+ * tolerance determined by the subdivision tolerance.
+ *
+ * @param e
+ * a QuadEdge
+ * @param p
+ * a point
+ * @return true if the vertex lies on the edge
+ */
+ bool isOnEdge(const QuadEdge &e, const geom::Coordinate &p) const;
+
+ /**
+ * Tests whether a {@link Vertex} is the start or end vertex of a
+ * {@link QuadEdge}, up to the subdivision tolerance distance.
+ *
+ * @param e
+ * @param v
+ * @return true if the vertex is a endpoint of the edge
+ */
+ bool isVertexOfEdge(const QuadEdge &e, const Vertex &v) const;
+
+ /**
+ * Gets all primary quadedges in the subdivision.
+ * A primary edge is a {@link QuadEdge}
+ * which occupies the 0'th position in its array of associated quadedges.
+ * These provide the unique geometric edges of the triangulation.
+ *
+ * @param includeFrame true if the frame edges are to be included
+ * @return a List of QuadEdges. The caller takes ownership of the returned QuadEdgeList but not the
+ * items it contains.
+ */
+ std::auto_ptr<QuadEdgeList> getPrimaryEdges(bool includeFrame);
+
+ /*****************************************************************************
+ * Visitors
+ ****************************************************************************/
+
+ void visitTriangles(TriangleVisitor *triVisitor, bool includeFrame);
+
+private:
+ typedef std::stack<QuadEdge*> QuadEdgeStack;
+ typedef std::set<QuadEdge*> QuadEdgeSet;
+ typedef std::list< geom::CoordinateSequence*> TriList;
+
+ /**
+ * The quadedges forming a single triangle.
+ * Only one visitor is allowed to be active at a
+ * time, so this is safe.
+ */
+ QuadEdge* triEdges[3];
+
+ /**
+ * Stores the edges for a visited triangle. Also pushes sym (neighbour) edges
+ * on stack to visit later.
+ *
+ * @param edge
+ * @param edgeStack
+ * @param includeFrame
+ * @return the visited triangle edges
+ * @return null if the triangle should not be visited (for instance, if it is
+ * outer)
+ */
+ QuadEdge** fetchTriangleToVisit(QuadEdge *edge, QuadEdgeStack &edgeStack, bool includeFrame,
+ QuadEdgeSet &visitedEdges);
+
+ /**
+ * Gets the coordinates for each triangle in the subdivision as an array.
+ *
+ * @param includeFrame
+ * true if the frame triangles should be included
+ * @param triList a list of Coordinate[4] representing each triangle
+ */
+ void getTriangleCoordinates(TriList* triList, bool includeFrame);
+
+private:
+ class TriangleCoordinatesVisitor;
+
+public:
+ /**
+ * Gets the geometry for the edges in the subdivision as a {@link MultiLineString}
+ * containing 2-point lines.
+ *
+ * @param geomFact the GeometryFactory to use
+ * @return a MultiLineString. The caller takes ownership of the returned object.
+ */
+ std::auto_ptr<geom::MultiLineString> getEdges(const geom::GeometryFactory& geomFact);
+
+ /**
+ * Gets the geometry for the triangles in a triangulated subdivision as a {@link GeometryCollection}
+ * of triangular {@link Polygon}s.
+ *
+ * @param geomFact the GeometryFactory to use
+ * @return a GeometryCollection of triangular Polygons. The caller takes ownership of the returned object.
+ */
+ std::auto_ptr<geom::GeometryCollection> getTriangles(const geom::GeometryFactory &geomFact);
+
+};
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_QUADEDGESUBDIVISION_H
Added: trunk/include/geos/triangulate/quadedge/TrianglePredicate.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/TrianglePredicate.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/TrianglePredicate.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,114 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/TrianglePredicate.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_TRIANGLEPREDICATE_H
+#define GEOS_TRIANGULATE_QUADEDGE_TRIANGLEPREDICATE_H
+
+namespace geos {
+namespace geom { // geos.geom
+
+class Coordinate;
+
+/**
+ * Algorithms for computing values and predicates
+ * associated with triangles.
+ * For some algorithms extended-precision
+ * implementations are provided, which are more robust
+ * (i.e. they produce correct answers in more cases).
+ * Also, some more robust formulations of
+ * some algorithms are provided, which utilize
+ * normalization to the origin.
+ *
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ *
+ */
+class TrianglePredicate
+{
+public:
+ /**
+ * Tests if a point is inside the circle defined by
+ * the triangle with vertices a, b, c (oriented counter-clockwise).
+ * This test uses simple
+ * double-precision arithmetic, and thus may not be robust.
+ *
+ * @param a a vertex of the triangle
+ * @param b a vertex of the triangle
+ * @param c a vertex of the triangle
+ * @param P the point to test
+ * @return true if this point is inside the circle defined by the points a, b, c
+ */
+ static bool isInCircleNonRobust(
+ const Coordinate &a, const Coordinate &b, const Coordinate &c,
+ const Coordinate &p);
+
+ /**
+ * Tests if a point is inside the circle defined by
+ * the triangle with vertices a, b, c (oriented counter-clockwise).
+ * This test uses simple
+ * double-precision arithmetic, and thus is not 10% robust.
+ * However, by using normalization to the origin
+ * it provides improved robustness and increased performance.
+ * <p>
+ * Based on code by J.R.Shewchuk.
+ *
+ *
+ * @param a a vertex of the triangle
+ * @param b a vertex of the triangle
+ * @param c a vertex of the triangle
+ * @param P the point to test
+ * @return true if this point is inside the circle defined by the points a, b, c
+ */
+ static bool isInCircleNormalized(
+ const Coordinate &a, const Coordinate &b, const Coordinate &c,
+ const Coordinate &p);
+
+private:
+ /**
+ * Computes twice the area of the oriented triangle (a, b, c), i.e., the area is positive if the
+ * triangle is oriented counterclockwise.
+ *
+ * @param a a vertex of the triangle
+ * @param b a vertex of the triangle
+ * @param c a vertex of the triangle
+ */
+ static double triArea(const Coordinate &a,
+ const Coordinate &b, const Coordinate &c);
+
+public:
+ /**
+ * Tests if a point is inside the circle defined by
+ * the triangle with vertices a, b, c (oriented counter-clockwise).
+ * This method uses more robust computation.
+ *
+ * @param a a vertex of the triangle
+ * @param b a vertex of the triangle
+ * @param c a vertex of the triangle
+ * @param P the point to test
+ * @return true if this point is inside the circle defined by the points a, b, c
+ */
+ static bool isInCircleRobust(
+ const Coordinate &a, const Coordinate &b, const Coordinate &c,
+ const Coordinate &p);
+} ;
+
+} // namespace geos.geom
+} // namespace geos
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_TRIANGLEPREDICATE_H
+
Added: trunk/include/geos/triangulate/quadedge/TriangleVisitor.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/TriangleVisitor.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/TriangleVisitor.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,50 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/TriangleVisitor.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_TRIANGLEVISITOR_H
+#define GEOS_TRIANGULATE_QUADEDGE_TRIANGLEVISITOR_H
+
+#include <geos/triangulate/quadedge/QuadEdge.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+/**
+ * An interface for algorithms which process the triangles in a {@link QuadEdgeSubdivision}.
+ *
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ */
+class GEOS_DLL TriangleVisitor {
+public:
+ /**
+ * Visits the {@link QuadEdge}s of a triangle.
+ *
+ * @param triEdges an array of the 3 quad edges in a triangle (in CCW order)
+ */
+ virtual void visit(QuadEdge* triEdges[3]) = 0;
+ virtual ~TriangleVisitor() = 0 ;
+private:
+} ;
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
+#endif // GEOS_TRIANGULATE_QUADEDGE_TRIANGLEVISITOR_H
Added: trunk/include/geos/triangulate/quadedge/Vertex.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/Vertex.h (rev 0)
+++ trunk/include/geos/triangulate/quadedge/Vertex.h 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,273 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/Vertex.java rev. r524
+ *
+ **********************************************************************/
+
+#ifndef GEOS_TRIANGULATE_QUADEDGE_VERTEX_H
+#define GEOS_TRIANGULATE_QUADEDGE_VERTEX_H
+
+#include <math.h>
+#include <memory>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/algorithm/HCoordinate.h>
+
+
+//fwd declarations
+namespace geos {
+namespace triangulate {
+namespace quadedge {
+ class QuadEdge;
+}
+}
+}
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+/**
+ * Models a site (node) in a {@link QuadEdgeSubdivision}.
+ * The sites can be points on a line string representing a
+ * linear site.
+ * <p>
+ * The vertex can be considered as a vector with a norm, length, inner product, cross
+ * product, etc. Additionally, point relations (e.g., is a point to the left of a line, the circle
+ * defined by this point and two others, etc.) are also defined in this class.
+ * <p>
+ * It is common to want to attach user-defined data to
+ * the vertices of a subdivision.
+ * One way to do this is to subclass <tt>Vertex</tt>
+ * to carry any desired information (see {@link ConstraintVertex}.
+ *
+ * @author JTS: David Skea
+ * @author JTS: Martin Davis
+ * @author Benjamin Campbell
+ * */
+
+class GEOS_DLL Vertex {
+public:
+ static const int LEFT = 0;
+ static const int RIGHT = 1;
+ static const int BEYOND = 2;
+ static const int BEHIND = 3;
+ static const int BETWEEN = 4;
+ static const int ORIGIN = 5;
+ static const int DESTINATION = 6;
+private:
+ geom::Coordinate p;
+
+public:
+ Vertex(double _x, double _y);
+
+ Vertex(double _x, double _y, double _z);
+
+ Vertex(const geom::Coordinate &_p);
+
+ Vertex();
+
+ inline double getX() const {
+ return p.x;
+ }
+
+ inline double getY() const {
+ return p.y;
+ }
+
+ inline double getZ() const {
+ return p.z;
+ }
+
+ inline void setZ(double _z) {
+ p.z = _z;
+ }
+
+ inline const geom::Coordinate& getCoordinate() const {
+ return p;
+ }
+
+ inline bool equals(const Vertex &_x) const
+ {
+ if (p.x == _x.getX() && p.y == _x.getY())
+ return true;
+ return false;
+ }
+
+ inline bool equals(const Vertex &_x, double tolerance) const
+ {
+ if (p.distance(_x.getCoordinate()) < tolerance)
+ return true;
+ return false;
+ }
+
+ virtual int classify(const Vertex &p0, const Vertex &p1);
+
+ /**
+ * Computes the cross product k = u X v.
+ *
+ * @param v a vertex
+ * @return returns the magnitude of u X v
+ */
+ inline double crossProduct(const Vertex &v) const
+ {
+ return (p.x * v.getY() - p.y * v.getX());
+ }
+
+ /**
+ * Computes the inner or dot product
+ *
+ * @param v, a vertex
+ * @return returns the dot product u.v
+ */
+ inline double dot(Vertex v) const
+ {
+ return (p.x * v.getX() + p.y * v.getY());
+ }
+
+ /**
+ * Computes the scalar product c(v)
+ *
+ * @param v, a vertex
+ * @return returns the scaled vector
+ */
+ inline std::auto_ptr<Vertex> times(double c) const {
+ return std::auto_ptr<Vertex>(new Vertex(c * p.x, c * p.y));
+ }
+
+ /* Vector addition */
+ inline std::auto_ptr<Vertex> sum(Vertex v) const {
+ return std::auto_ptr<Vertex>(new Vertex(p.x + v.getX(), p.y + v.getY()));
+ }
+
+ /* and subtraction */
+ inline std::auto_ptr<Vertex> sub(const Vertex &v) const {
+ return std::auto_ptr<Vertex>(new Vertex(p.x - v.getX(), p.y - v.getY()));
+ }
+
+ /* magnitude of vector */
+ inline double magn() const {
+ return (sqrt(p.x * p.x + p.y * p.y));
+ }
+
+ /* returns k X v (cross product). this is a vector perpendicular to v */
+ inline std::auto_ptr<Vertex> cross() const {
+ return std::auto_ptr<Vertex>(new Vertex(p.y, -p.x));
+ }
+
+ /** ************************************************************* */
+ /***********************************************************************************************
+ * Geometric primitives /
+ **********************************************************************************************/
+
+ /**
+ * Tests if the vertex is inside the circle defined by
+ * the triangle with vertices a, b, c (oriented counter-clockwise).
+ *
+ * @param a a vertex of the triangle
+ * @param b a vertex of the triangle
+ * @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;
+
+ /**
+ * Tests whether the triangle formed by this vertex and two
+ * other vertices is in CCW orientation.
+ *
+ * @param b a vertex
+ * @param c a vertex
+ * @returns true if the triangle is oriented CCW
+ */
+ inline bool isCCW(const Vertex &b, const Vertex &c) const
+ {
+ // is equal to the signed area of the triangle
+
+ return (b.p.x - p.x) * (c.p.y - p.y)
+ - (b.p.y - p.y) * (c.p.x - p.x) > 0;
+ }
+
+ bool rightOf(const QuadEdge &e) const;
+ bool leftOf(const QuadEdge &e) const;
+
+private:
+ static std::auto_ptr<algorithm::HCoordinate> bisector(const Vertex &a, const Vertex &b);
+
+ inline double distance(const Vertex &v1, const Vertex &v2)
+ {
+ return sqrt(pow(v2.getX() - v1.getX(), 2.0)
+ + pow(v2.getY() - v1.getY(), 2.0));
+ }
+
+ /**
+ * Computes the value of the ratio of the circumradius to shortest edge. If smaller than some
+ * given tolerance B, the associated triangle is considered skinny. For an equal lateral
+ * triangle this value is 0.57735. The ratio is related to the minimum triangle angle theta by:
+ * circumRadius/shortestEdge = 1/(2sin(theta)).
+ *
+ * @param b second vertex of the triangle
+ * @param c third vertex of the triangle
+ * @return ratio of circumradius to shortest edge.
+ */
+ virtual double circumRadiusRatio(const Vertex &b, const Vertex &c);
+
+ /**
+ * returns a new vertex that is mid-way between this vertex and another end point.
+ *
+ * @param a the other end point.
+ * @return the point mid-way between this and that.
+ */
+ virtual std::auto_ptr<Vertex> midPoint(const Vertex &a);
+
+ /**
+ * Computes the centre of the circumcircle of this vertex and two others.
+ *
+ * @param b
+ * @param c
+ * @return the Coordinate which is the circumcircle of the 3 points.
+ */
+ virtual std::auto_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
+ * a z value from the surrounding vertices.
+ */
+ virtual double interpolateZValue(const Vertex &v0, const Vertex &v1,
+ const Vertex &v2) const;
+
+ /**
+ * Interpolates the Z value of a point enclosed in a 3D triangle.
+ */
+ static double interpolateZ(const geom::Coordinate &p, const geom::Coordinate &v0,
+ const geom::Coordinate &v1, const geom::Coordinate &v2);
+
+ /**
+ * Computes the interpolated Z-value for a point p lying on the segment p0-p1
+ *
+ * @param p
+ * @param p0
+ * @param p1
+ * @return
+ */
+ static double interpolateZ(const geom::Coordinate &p, const geom::Coordinate &p0,
+ const geom::Coordinate &p1);
+};
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace geos
+
+#endif //GEOS_TRIANGULATE_QUADEDGE_VERTEX_H
+
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2012-06-25 23:31:38 UTC (rev 3692)
+++ trunk/src/Makefile.am 2012-06-26 17:11:33 UTC (rev 3693)
@@ -13,6 +13,7 @@
geomgraph \
precision \
simplify \
+ triangulate \
util
EXTRA_DIST = Makefile.vc dirlist.mk CMakeLists.txt info.plist.in
@@ -44,4 +45,5 @@
planargraph/libplanargraph.la \
precision/libprecision.la \
simplify/libsimplify.la \
+ triangulate/libtriangulate.la \
util/libutil.la
Added: trunk/src/triangulate/DelaunayTriangulationBuilder.cpp
===================================================================
--- trunk/src/triangulate/DelaunayTriangulationBuilder.cpp (rev 0)
+++ trunk/src/triangulate/DelaunayTriangulationBuilder.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,132 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/DelaunayTriangulationBuilder.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/DelaunayTriangulationBuilder.h>
+
+#include <algorithm>
+
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/triangulate/IncrementalDelaunayTriangulator.h>
+#include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+using namespace geos::geom;
+
+CoordinateSequence* DelaunayTriangulationBuilder::extractUniqueCoordinates(
+ const Geometry& geom)
+{
+ geom::CoordinateSequence *coords = geom.getCoordinates();
+ unique(*coords);
+ return coords;
+}
+
+void DelaunayTriangulationBuilder::unique(CoordinateSequence& coords)
+{
+ std::vector<Coordinate> coordVector;
+ coords.toVector(coordVector);
+ std::sort(coordVector.begin(), coordVector.end(), geos::geom::CoordinateLessThen());
+ coords.setPoints(coordVector);
+ coords.removeRepeatedPoints();
+}
+
+IncrementalDelaunayTriangulator::VertexList* DelaunayTriangulationBuilder::toVertices(
+ const CoordinateSequence &coords)
+{
+ IncrementalDelaunayTriangulator::VertexList* vertexList =
+ new IncrementalDelaunayTriangulator::VertexList();
+
+ for(size_t iter=0; iter < coords.size(); ++iter)
+ {
+ vertexList->push_back(Vertex(coords.getAt(iter)));
+ }
+ return vertexList;
+}
+
+DelaunayTriangulationBuilder::DelaunayTriangulationBuilder() :
+ siteCoords(NULL), tolerance(0.0), subdiv(NULL)
+{
+}
+
+DelaunayTriangulationBuilder::~DelaunayTriangulationBuilder()
+{
+ if(siteCoords)
+ delete siteCoords;
+ if(subdiv)
+ delete subdiv;
+}
+
+void DelaunayTriangulationBuilder::setSites(const Geometry& geom)
+{
+ if(siteCoords)
+ delete siteCoords;
+ // remove any duplicate points (they will cause the triangulation to fail)
+ siteCoords = extractUniqueCoordinates(geom);
+}
+
+void DelaunayTriangulationBuilder::setSites(const CoordinateSequence& coords)
+{
+ if(siteCoords)
+ delete siteCoords;
+ siteCoords = coords.clone();
+ // remove any duplicate points (they will cause the triangulation to fail)
+ unique(*siteCoords);
+}
+
+void DelaunayTriangulationBuilder::create()
+{
+ if(subdiv != NULL || siteCoords == NULL)
+ return;
+
+ Envelope siteEnv;
+ siteCoords ->expandEnvelope(siteEnv);
+ IncrementalDelaunayTriangulator::VertexList* vertices = toVertices(*siteCoords);
+ subdiv = new QuadEdgeSubdivision(siteEnv, tolerance);
+ IncrementalDelaunayTriangulator triangulator = IncrementalDelaunayTriangulator(subdiv);
+ triangulator.insertSites(*vertices);
+ delete vertices;
+}
+
+QuadEdgeSubdivision& DelaunayTriangulationBuilder::getSubdivision()
+{
+ create();
+ return *subdiv;
+}
+
+std::auto_ptr<MultiLineString> DelaunayTriangulationBuilder::getEdges(
+ GeometryFactory& geomFact)
+{
+ create();
+ return subdiv->getEdges(geomFact);
+}
+
+std::auto_ptr<geom::GeometryCollection> DelaunayTriangulationBuilder::getTriangles(
+ geom::GeometryFactory& geomFact)
+{
+ create();
+ return subdiv->getTriangles(geomFact);
+}
+
+}//namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/IncrementalDelaunayTriangulator.cpp
===================================================================
--- trunk/src/triangulate/IncrementalDelaunayTriangulator.cpp (rev 0)
+++ trunk/src/triangulate/IncrementalDelaunayTriangulator.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,102 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/IncrementalDelaunayTriangulator.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/IncrementalDelaunayTriangulator.h>
+
+#include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+#include <geos/triangulate/quadedge/LocateFailureException.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+
+using namespace quadedge;
+
+IncrementalDelaunayTriangulator::IncrementalDelaunayTriangulator(
+ QuadEdgeSubdivision *subdiv) :
+ subdiv(subdiv), isUsingTolerance(subdiv->getTolerance() > 0.0)
+{
+}
+
+void IncrementalDelaunayTriangulator::insertSites(const VertexList& vertices)
+{
+ for (VertexList::const_iterator x=vertices.begin();
+ x != vertices.end(); ++x) {
+ insertSite(*x);
+ }
+}
+
+QuadEdge& IncrementalDelaunayTriangulator::insertSite(const Vertex &v)
+{
+ /**
+ * This code is based on Guibas and Stolfi (1985), with minor modifications
+ * and a bug fix from Dani Lischinski (Graphic Gems 1993). (The modification
+ * I believe is the test for the inserted site falling exactly on an
+ * existing edge. Without this test zero-width triangles have been observed
+ * to be created)
+ */
+ QuadEdge *e = subdiv->locate(v);
+
+ if(!e) {
+ throw LocateFailureException("");
+ }
+
+ if (subdiv->isVertexOfEdge(*e, v)) {
+ // point is already in subdivision.
+ return *e;
+ }
+ else if (subdiv->isOnEdge(*e, v.getCoordinate())) {
+ // the point lies exactly on an edge, so delete the edge
+ // (it will be replaced by a pair of edges which have the point as a vertex)
+ e = &e->oPrev();
+ subdiv->remove(e->oNext());
+ }
+
+ /**
+ * Connect the new point to the vertices of the containing triangle
+ * (or quadrilateral, if the new point fell on an existing edge.)
+ */
+ QuadEdge* base = &subdiv->makeEdge(e->orig(), v);
+
+ QuadEdge::splice(*base, *e);
+ QuadEdge *startEdge = base;
+ do {
+ base = &subdiv->connect(*e, base->sym());
+ e = &base->oPrev();
+ } while (&e->lNext() != startEdge);
+
+
+ // Examine suspect edges to ensure that the Delaunay condition
+ // is satisfied.
+ do {
+ QuadEdge* t = &e->oPrev();
+ if (t->dest().rightOf(*e) &&
+ v.isInCircle(e->orig(), t->dest(), e->dest())) {
+ QuadEdge::swap(*e);
+ e = &e->oPrev();
+ } else if (&e->oNext() == startEdge) {
+ return *base; // no more suspect edges.
+ } else {
+ e = &e->oNext().lPrev();
+ }
+ } while (true);
+}
+
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/Makefile.am
===================================================================
--- trunk/src/triangulate/Makefile.am (rev 0)
+++ trunk/src/triangulate/Makefile.am 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,16 @@
+#
+# This file is part of project GEOS (http://trac.osgeo.org/geos/)
+#
+SUBDIRS = \
+ quadedge
+
+noinst_LTLIBRARIES = libtriangulate.la
+
+INCLUDES = -I$(top_srcdir)/include
+
+libtriangulate_la_SOURCES = \
+ IncrementalDelaunayTriangulator.cpp \
+ DelaunayTriangulationBuilder.cpp
+
+libtriangulate_la_LIBADD = \
+ quadedge/libquadedge.la
Added: trunk/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp
===================================================================
--- trunk/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/LastFoundQuadEdgeLocator.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,56 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/LastFoundQuadEdgeLocator.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h>
+#include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+LastFoundQuadEdgeLocator::LastFoundQuadEdgeLocator(QuadEdgeSubdivision *subdiv) :
+ subdiv(subdiv), lastEdge(NULL)
+{
+}
+
+void LastFoundQuadEdgeLocator::init()
+{
+ lastEdge = findEdge();
+}
+
+QuadEdge* LastFoundQuadEdgeLocator::findEdge()
+{
+ // assume there is an edge
+ return *(subdiv->getEdges().begin());
+}
+
+QuadEdge* LastFoundQuadEdgeLocator::locate(const Vertex &v)
+{
+ if (!lastEdge || !lastEdge->isLive()) {
+ init();
+ }
+
+ QuadEdge *e = subdiv->locateFromEdge(v, *lastEdge);
+ lastEdge = e;
+ return e;
+}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/quadedge/LocateFailureException.cpp
===================================================================
--- trunk/src/triangulate/quadedge/LocateFailureException.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/LocateFailureException.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,33 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/LocateFailureException.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/LocateFailureException.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+LocateFailureException::LocateFailureException(std::string const&msg)
+{
+ util::GEOSException("LocateFailureException", msg);
+}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/quadedge/Makefile.am
===================================================================
--- trunk/src/triangulate/quadedge/Makefile.am (rev 0)
+++ trunk/src/triangulate/quadedge/Makefile.am 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,20 @@
+#
+# This file is part of project GEOS (http://trac.osgeo.org/geos/)
+#
+SUBDIRS =
+
+noinst_LTLIBRARIES = libquadedge.la
+
+INCLUDES = -I$(top_srcdir)/include
+
+libquadedge_la_SOURCES = \
+ QuadEdge.cpp \
+ Vertex.cpp \
+ TrianglePredicate.cpp \
+ QuadEdgeSubdivision.cpp \
+ QuadEdgeLocator.cpp \
+ LastFoundQuadEdgeLocator.cpp \
+ LocateFailureException.cpp \
+ TriangleVisitor.cpp
+
+libquadedge_la_LIBADD =
Added: trunk/src/triangulate/quadedge/QuadEdge.cpp
===================================================================
--- trunk/src/triangulate/quadedge/QuadEdge.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/QuadEdge.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,166 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/QuadEdge.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/QuadEdge.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+using namespace geos::geom;
+
+std::auto_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::auto_ptr<QuadEdge>(base);
+}
+
+std::auto_ptr<QuadEdge> QuadEdge::connect(QuadEdge &a, QuadEdge &b)
+{
+ std::auto_ptr<QuadEdge> q0 = makeEdge(a.dest(), b.orig());
+ splice(*q0, a.lNext());
+ splice(q0->sym(), b);
+ return q0;
+}
+
+void QuadEdge::splice(QuadEdge &a, QuadEdge &b)
+{
+ QuadEdge &alpha = a.oNext().rot();
+ QuadEdge &beta = b.oNext().rot();
+
+ QuadEdge &t1 = b.oNext();
+ QuadEdge &t2 = a.oNext();
+ QuadEdge &t3 = beta.oNext();
+ QuadEdge &t4 = alpha.oNext();
+
+ a.setNext(&t1);
+ b.setNext(&t2);
+ alpha.setNext(&t3);
+ beta.setNext(&t4);
+}
+
+void QuadEdge::swap(QuadEdge &e)
+{
+ QuadEdge &a = e.oPrev();
+ QuadEdge &b = e.sym().oPrev();
+ splice(e, a);
+ splice(e.sym(), b);
+ splice(e, a.lNext());
+ splice(e.sym(), b.lNext());
+ e.setOrig(a.dest());
+ e.setDest(b.dest());
+}
+
+QuadEdge::QuadEdge() : _rot(NULL), vertex(), next(NULL), data(NULL), isAlive(true)
+{ }
+
+QuadEdge::~QuadEdge()
+{
+}
+
+void QuadEdge::free()
+{
+ if(_rot)
+ {
+ if(_rot->_rot)
+ {
+ if(_rot->_rot->_rot)
+ {
+ delete _rot->_rot->_rot;
+ _rot->_rot->_rot = NULL;
+ }
+ delete _rot->_rot;
+ _rot->_rot = NULL;
+ }
+ delete _rot;
+ _rot = NULL;
+ }
+}
+
+const QuadEdge& QuadEdge::getPrimary() const
+{
+ if (orig().getCoordinate().compareTo(dest().getCoordinate()) <= 0)
+ return *this;
+ else
+ return sym();
+}
+
+void QuadEdge::setData(void* data)
+{
+ this->data = data;
+}
+
+void* QuadEdge::getData()
+{
+ return data;
+}
+
+void QuadEdge::remove()
+{
+ rot().rot().rot().isAlive = false;
+ rot().rot().isAlive = false;
+ rot().isAlive = false;
+ isAlive = false;
+}
+
+bool QuadEdge::equalsNonOriented(const QuadEdge &qe) const
+{
+ if (equalsOriented(qe))
+ return true;
+ if (equalsOriented(qe.sym()))
+ return true;
+ return false;
+}
+
+bool QuadEdge::equalsOriented(const QuadEdge &qe) const
+{
+ if (orig().getCoordinate().equals2D(qe.orig().getCoordinate())
+ && dest().getCoordinate().equals2D(qe.dest().getCoordinate()))
+ return true;
+ return false;
+}
+
+std::auto_ptr<LineSegment> QuadEdge::toLineSegment() const
+{
+ return std::auto_ptr<geom::LineSegment>(
+ new geom::LineSegment(vertex.getCoordinate(), dest().getCoordinate()));
+}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/quadedge/QuadEdgeLocator.cpp
===================================================================
--- trunk/src/triangulate/quadedge/QuadEdgeLocator.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/QuadEdgeLocator.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,30 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/QuadEdgeLocator.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/QuadEdgeLocator.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+QuadEdgeLocator::~QuadEdgeLocator() {}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp
===================================================================
--- trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,454 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/QuadEdgeSubdivision.java rev. r524
+ *
+ **********************************************************************/
+#include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+
+#include <vector>
+
+#include <geos/geom/Polygon.h>
+#include <geos/geom/LineSegment.h>
+#include <geos/geom/LineString.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/geom/CoordinateArraySequenceFactory.h>
+#include <geos/geom/GeometryCollection.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/util/IllegalArgumentException.h>
+#include <geos/util/GEOSException.h>
+#include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeLocator.h>
+#include <geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h>
+#include <geos/triangulate/quadedge/LocateFailureException.h>
+#include <geos/triangulate/quadedge/TriangleVisitor.h>
+
+using namespace geos::geom;
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+void QuadEdgeSubdivision::getTriangleEdges(const QuadEdge &startQE,
+ const QuadEdge* triEdge[3])
+{
+ triEdge[0] = &startQE;
+ triEdge[1] = &triEdge[0]->lNext();
+ triEdge[2] = &triEdge[1]->lNext();
+ if (&triEdge[2]->lNext() != triEdge[0]) {
+ throw new
+ util::IllegalArgumentException("Edges do not form a triangle");
+ }
+}
+
+QuadEdgeSubdivision::QuadEdgeSubdivision(const geom::Envelope &env, double tolerance) :
+ tolerance(tolerance),
+ locator(new LastFoundQuadEdgeLocator(this))
+{
+ edgeCoincidenceTolerance = tolerance / EDGE_COINCIDENCE_TOL_FACTOR;
+ createFrame(env);
+ initSubdiv(startingEdges);
+ quadEdges.push_back(startingEdges[0]);
+ quadEdges.push_back(startingEdges[1]);
+ quadEdges.push_back(startingEdges[2]);
+}
+
+QuadEdgeSubdivision::~QuadEdgeSubdivision()
+{
+ for(QuadEdgeList::iterator iter=quadEdges.begin(); iter!=quadEdges.end(); ++iter)
+ {
+ (*iter)->free();
+ delete *iter;
+ }
+
+ for(QuadEdgeList::iterator iter=removedEdges.begin(); iter!=removedEdges.end(); ++iter)
+ {
+ (*iter)->free();
+ delete *iter;
+ }
+}
+
+void QuadEdgeSubdivision::createFrame(const geom::Envelope &env)
+{
+ double deltaX = env.getWidth();
+ double deltaY = env.getHeight();
+ double offset = 0.0;
+ if (deltaX > deltaY) {
+ offset = deltaX * 10.0;
+ } else {
+ offset = deltaY * 10.0;
+ }
+
+ frameVertex[0] = Vertex((env.getMaxX() + env.getMinX()) / 2.0, env
+ .getMaxY() + offset);
+ frameVertex[1] = Vertex(env.getMinX() - offset, env.getMinY() - offset);
+ frameVertex[2] = Vertex(env.getMaxX() + offset, env.getMinY() - offset);
+
+ frameEnv = Envelope(frameVertex[0].getCoordinate(), frameVertex[1]
+ .getCoordinate());
+ frameEnv.expandToInclude(frameVertex[2].getCoordinate());
+}
+void QuadEdgeSubdivision::initSubdiv(QuadEdge* initEdges[3])
+{
+ std::auto_ptr<QuadEdge> tmp_auto_ptr;
+ // build initial subdivision from frame
+ tmp_auto_ptr = QuadEdge::makeEdge(frameVertex[0], frameVertex[1]);
+ initEdges[0] = tmp_auto_ptr.get();
+ tmp_auto_ptr.release();
+
+
+ tmp_auto_ptr = QuadEdge::makeEdge(frameVertex[1], frameVertex[2]);
+ initEdges[1] = tmp_auto_ptr.get();
+ tmp_auto_ptr.release();
+
+ QuadEdge::splice(initEdges[0]->sym(), *initEdges[1]);
+
+ tmp_auto_ptr = QuadEdge::makeEdge(frameVertex[2], frameVertex[0]);
+ initEdges[2] = tmp_auto_ptr.get();
+ tmp_auto_ptr.release();
+
+ QuadEdge::splice(initEdges[1]->sym(), *initEdges[2]);
+ QuadEdge::splice(initEdges[2]->sym(), *initEdges[0]);
+}
+
+QuadEdge& QuadEdgeSubdivision::makeEdge(const Vertex &o, const Vertex &d)
+{
+ std::auto_ptr<QuadEdge> q0 = QuadEdge::makeEdge(o, d);
+ QuadEdge *q0_ptr = q0.get();
+ q0.release();
+
+ quadEdges.push_back(q0_ptr);
+ return *q0_ptr;
+}
+
+QuadEdge& QuadEdgeSubdivision::connect(QuadEdge &a, QuadEdge &b)
+{
+ std::auto_ptr<QuadEdge> q0 = QuadEdge::connect(a, b);
+ QuadEdge *q0_ptr = q0.get();
+ q0.release();
+
+ quadEdges.push_back(q0_ptr);
+ return *q0_ptr;
+}
+
+void QuadEdgeSubdivision::remove(QuadEdge &e)
+{
+ QuadEdge::splice(e, e.oPrev());
+ QuadEdge::splice(e.sym(), e.sym().oPrev());
+
+ // this is inefficient on an ArrayList, but this method should be called infrequently
+ quadEdges.remove(&e);
+
+ //mark these edges as removed
+ e.remove();
+
+ //keep a list of removed edges so that we can
+ //properly free memory
+ removedEdges.push_back(&e);
+}
+
+QuadEdge* QuadEdgeSubdivision::locateFromEdge(const Vertex &v,
+ const QuadEdge &startEdge) const
+{
+ int iter = 0;
+ int maxIter = quadEdges.size();
+
+ QuadEdge *e = startingEdges[0];
+
+ while (true) {
+ ++iter;
+ /**
+ * So far it has always been the case that failure to locate indicates an
+ * invalid subdivision. So just fail completely. (An alternative would be
+ * to perform an exhaustive search for the containing triangle, but this
+ * would mask errors in the subdivision topology)
+ *
+ * This can also happen if two vertices are located very close together,
+ * since the orientation predicates may experience precision failures.
+ */
+ if (iter > maxIter) {
+ throw LocateFailureException("");
+ }
+
+ if ((v.equals(e->orig())) || (v.equals(e->dest()))) {
+ break;
+ } else if (v.rightOf(*e)) {
+ e = &e->sym();
+ } else if (!v.rightOf(e->oNext())) {
+ e = &e->oNext();
+ } else if (!v.rightOf(e->dPrev())) {
+ e = &e->dPrev();
+ } else {
+ // on edge or in triangle containing edge
+ break;
+ }
+ }
+ return e;
+}
+
+QuadEdge* QuadEdgeSubdivision::locate(const Coordinate &p0, const Coordinate &p1)
+{
+ // find an edge containing one of the points
+ QuadEdge *e = locator->locate(Vertex(p0));
+ if (e == NULL)
+ return NULL;
+
+ // normalize so that p0 is origin of base edge
+ QuadEdge *base = e;
+ if (e->dest().getCoordinate().equals2D(p0))
+ base = &e->sym();
+ // check all edges around origin of base edge
+ QuadEdge *locEdge = base;
+ do {
+ if (locEdge->dest().getCoordinate().equals2D(p1))
+ return locEdge;
+ locEdge = &locEdge->oNext();
+ } while (locEdge != base);
+ return NULL;
+}
+
+QuadEdge& QuadEdgeSubdivision::insertSite(const Vertex &v)
+{
+ QuadEdge *e = locate(v);
+
+ if ((v.equals(e->orig(), tolerance)) || (v.equals(e->dest(), tolerance))) {
+ return *e; // point already in subdivision.
+ }
+
+ // Connect the new point to the vertices of the containing
+ // triangle (or quadrilateral, if the new point fell on an
+ // existing edge.)
+ QuadEdge *base = &makeEdge(e->orig(), v);
+ QuadEdge::splice(*base, *e);
+ QuadEdge *startEdge = base;
+ do {
+ base = &connect(*e, base->sym());
+ e = &base->oPrev();
+ } while (&e->lNext() != startEdge);
+
+ return *startEdge;
+}
+
+bool QuadEdgeSubdivision::isFrameEdge(const QuadEdge &e) const
+{
+ if (isFrameVertex(e.orig()) || isFrameVertex(e.dest()))
+ return true;
+ return false;
+}
+
+bool QuadEdgeSubdivision::isFrameBorderEdge(const QuadEdge &e) const
+{
+ // check other vertex of triangle to left of edge
+ Vertex vLeftTriOther = e.lNext().dest();
+ if (isFrameVertex(vLeftTriOther))
+ return true;
+ // check other vertex of triangle to right of edge
+ Vertex vRightTriOther = e.sym().lNext().dest();
+ if (isFrameVertex(vRightTriOther))
+ return true;
+
+ return false;
+}
+
+bool QuadEdgeSubdivision::isFrameVertex(const Vertex &v) const
+{
+ if (v.equals(frameVertex[0]))
+ return true;
+ if (v.equals(frameVertex[1]))
+ return true;
+ if (v.equals(frameVertex[2]))
+ return true;
+ return false;
+}
+
+bool QuadEdgeSubdivision::isOnEdge(const QuadEdge &e, const Coordinate &p) const
+{
+ geom::LineSegment seg;
+ seg.setCoordinates(e.orig().getCoordinate(), e.dest().getCoordinate());
+ double dist = seg.distance(p);
+ // heuristic (hack?)
+ return dist < edgeCoincidenceTolerance;
+}
+
+bool QuadEdgeSubdivision::isVertexOfEdge(const QuadEdge &e, const Vertex &v) const
+{
+ if ((v.equals(e.orig(), tolerance)) || (v.equals(e.dest(), tolerance))) {
+ return true;
+ }
+ return false;
+}
+
+std::auto_ptr<QuadEdgeSubdivision::QuadEdgeList> QuadEdgeSubdivision::getPrimaryEdges(bool includeFrame)
+{
+ QuadEdgeList *edges = new QuadEdgeList();
+ QuadEdgeStack edgeStack;
+ QuadEdgeSet visitedEdges;
+
+ edgeStack.push(startingEdges[0]);
+
+ while (!edgeStack.empty())
+ {
+ QuadEdge *edge = edgeStack.top();
+ edgeStack.pop();
+ if (visitedEdges.find(edge) == visitedEdges.end())
+ {
+ QuadEdge* priQE = (QuadEdge*)&edge->getPrimary();
+
+ if (includeFrame || ! isFrameEdge(*priQE))
+ edges->push_back(priQE);
+
+ edgeStack.push(&edge->oNext());
+ edgeStack.push(&edge->sym().oNext());
+
+ visitedEdges.insert(edge);
+ visitedEdges.insert(&edge->sym());
+ }
+ }
+ return std::auto_ptr<QuadEdgeList>(edges);
+}
+
+QuadEdge** QuadEdgeSubdivision::fetchTriangleToVisit(QuadEdge *edge,
+ QuadEdgeStack &edgeStack, bool includeFrame, QuadEdgeSet &visitedEdges)
+{
+ QuadEdge *curr = edge;
+ int edgeCount = 0;
+ bool isFrame = false;
+ do
+ {
+ triEdges[edgeCount] = curr;
+
+ if (isFrameEdge(*curr))
+ isFrame = true;
+
+ // push sym edges to visit next
+ QuadEdge *sym = &curr->sym();
+ if (visitedEdges.find(sym) == visitedEdges.end())
+ edgeStack.push(sym);
+
+ // mark this edge as visited
+ visitedEdges.insert(curr);
+
+ edgeCount++;
+ curr = &curr->lNext();
+
+ } while (curr != edge);
+
+ if (isFrame && !includeFrame)
+ return NULL;
+ return triEdges;
+}
+
+class QuadEdgeSubdivision::TriangleCoordinatesVisitor : public TriangleVisitor {
+private:
+ QuadEdgeSubdivision::TriList *triCoords;
+ CoordinateArraySequenceFactory coordSeqFact;
+
+public:
+ TriangleCoordinatesVisitor(QuadEdgeSubdivision::TriList *triCoords): triCoords(triCoords)
+ {
+ }
+
+ void visit(QuadEdge* triEdges[3])
+ {
+ geom::CoordinateSequence *coordSeq = coordSeqFact.create(4,2);
+ for (int i = 0; i < 3; i++) {
+ Vertex v = triEdges[i]->orig();
+ coordSeq->setAt(v.getCoordinate(), i);
+ }
+ coordSeq->setAt(triEdges[0]->orig().getCoordinate(), 3);
+ triCoords->push_back(coordSeq);
+ }
+};
+
+void QuadEdgeSubdivision::getTriangleCoordinates(QuadEdgeSubdivision::TriList* triList, bool includeFrame)
+{
+ TriangleCoordinatesVisitor visitor(triList);
+ visitTriangles((TriangleVisitor*)&visitor, includeFrame);
+}
+
+void QuadEdgeSubdivision::visitTriangles(TriangleVisitor *triVisitor, bool includeFrame)
+{
+
+ QuadEdgeStack edgeStack;
+ edgeStack.push(startingEdges[0]);
+
+ QuadEdgeSet visitedEdges;
+
+ while (!edgeStack.empty()) {
+ QuadEdge *edge = edgeStack.top();
+ edgeStack.pop();
+ if (visitedEdges.find(edge) == visitedEdges.end()) {
+ QuadEdge **triEdges = fetchTriangleToVisit(edge, edgeStack,
+ includeFrame, visitedEdges);
+ if (triEdges != NULL)
+ triVisitor->visit(triEdges);
+ }
+ }
+}
+
+std::auto_ptr<geom::MultiLineString> QuadEdgeSubdivision::getEdges(const geom::GeometryFactory& geomFact)
+{
+ std::auto_ptr<QuadEdgeList> quadEdges(getPrimaryEdges(false));
+ std::vector<Geometry *> edges(quadEdges->size());
+ CoordinateArraySequenceFactory coordSeqFact;
+ int i = 0;
+ for (QuadEdgeSubdivision::QuadEdgeList::iterator it = quadEdges->begin(); it != quadEdges->end(); ++it)
+ {
+ QuadEdge *qe = *it;
+ CoordinateSequence *coordSeq = coordSeqFact.create((std::vector<geom::Coordinate>*)NULL, 2);;
+
+ coordSeq->add(qe->orig().getCoordinate());
+ coordSeq->add(qe->dest().getCoordinate());
+
+ edges[i++] = static_cast<Geometry*>(geomFact.createLineString(*coordSeq));
+
+ delete coordSeq;
+ }
+
+ geom::MultiLineString* result = geomFact.createMultiLineString(edges);
+
+ for(std::vector<Geometry*>::iterator it=edges.begin(); it!=edges.end(); ++it)
+ delete *it;
+
+ return std::auto_ptr<MultiLineString>(result);
+}
+
+std::auto_ptr<GeometryCollection> QuadEdgeSubdivision::getTriangles( const GeometryFactory &geomFact)
+{
+ TriList triPtsList;
+ getTriangleCoordinates(&triPtsList, false);
+ std::vector<Geometry*> tris;
+
+ for(TriList::const_iterator it = triPtsList.begin();
+ it != triPtsList.end(); ++it)
+ {
+ CoordinateSequence *coordSeq = *it;
+ Polygon *tri = geomFact.createPolygon(
+ geomFact.createLinearRing(coordSeq), NULL);
+ tris.push_back(static_cast<Geometry*>(tri));
+ }
+ GeometryCollection* ret = geomFact.createGeometryCollection(tris);
+
+ //release memory
+ for(std::vector<Geometry*>::iterator it=tris.begin(); it!=tris.end(); ++it)
+ delete *it;
+ tris.clear();
+
+ return std::auto_ptr<GeometryCollection>(ret);
+}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
Added: trunk/src/triangulate/quadedge/TrianglePredicate.cpp
===================================================================
--- trunk/src/triangulate/quadedge/TrianglePredicate.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/TrianglePredicate.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,79 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/TrianglePredicate.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/TrianglePredicate.h>
+
+#include <geos/geom/Coordinate.h>
+
+namespace geos {
+namespace geom { // geos.geom
+
+bool TrianglePredicate::isInCircleNonRobust(
+ const Coordinate &a, const Coordinate &b, const Coordinate &c,
+ const Coordinate &p)
+{
+ bool isInCircle =
+ (a.x * a.x + a.y * a.y) * triArea(b, c, p)
+ - (b.x * b.x + b.y * b.y) * triArea(a, c, p)
+ + (c.x * c.x + c.y * c.y) * triArea(a, b, p)
+ - (p.x * p.x + p.y * p.y) * triArea(a, b, c)
+ > 0;
+ return isInCircle;
+}
+
+bool TrianglePredicate::isInCircleNormalized(
+ const Coordinate &a, const Coordinate &b, const Coordinate &c,
+ const Coordinate &p)
+{
+ double adx = a.x - p.x;
+ double ady = a.y - p.y;
+ double bdx = b.x - p.x;
+ double bdy = b.y - p.y;
+ double cdx = c.x - p.x;
+ double cdy = c.y - p.y;
+
+ double abdet = adx * bdy - bdx * ady;
+ double bcdet = bdx * cdy - cdx * bdy;
+ double cadet = cdx * ady - adx * cdy;
+ double alift = adx * adx + ady * ady;
+ double blift = bdx * bdx + bdy * bdy;
+ double clift = cdx * cdx + cdy * cdy;
+
+ double disc = alift * bcdet + blift * cadet + clift * abdet;
+ return disc > 0;
+}
+
+double TrianglePredicate::triArea(const Coordinate &a,
+ const Coordinate &b, const Coordinate &c)
+{
+ return (b.x - a.x) * (c.y - a.y)
+ - (b.y - a.y) * (c.x - a.x);
+}
+
+bool TrianglePredicate::isInCircleRobust(
+ const Coordinate &a, const Coordinate &b, const Coordinate &c,
+ const Coordinate &p)
+{
+ //checkRobustInCircle(a, b, c, p);
+ // return isInCircleNonRobust(a, b, c, p);
+ return isInCircleNormalized(a, b, c, p);
+}
+
+} // namespace geos.geom
+} // namespace geos
+
Added: trunk/src/triangulate/quadedge/TriangleVisitor.cpp
===================================================================
--- trunk/src/triangulate/quadedge/TriangleVisitor.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/TriangleVisitor.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,30 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/quadedge/TriangleVisitor.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/TriangleVisitor.h>
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+TriangleVisitor::~TriangleVisitor() {}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace goes
+
Added: trunk/src/triangulate/quadedge/Vertex.cpp
===================================================================
--- trunk/src/triangulate/quadedge/Vertex.cpp (rev 0)
+++ trunk/src/triangulate/quadedge/Vertex.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,195 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2012 Excensus LLC.
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: triangulate/Vertex.java rev. r524
+ *
+ **********************************************************************/
+
+#include <geos/triangulate/quadedge/Vertex.h>
+
+#include <geos/triangulate/quadedge/TrianglePredicate.h>
+#include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/algorithm/NotRepresentableException.h>
+
+
+namespace geos {
+namespace triangulate { //geos.triangulate
+namespace quadedge { //geos.triangulate.quadedge
+
+using namespace algorithm;
+using namespace geom;
+
+Vertex::Vertex(double _x, double _y) : p(_x, _y)
+{
+}
+
+Vertex::Vertex(double _x, double _y, double _z): p( _x, _y, _z)
+{
+}
+
+Vertex::Vertex(const Coordinate &_p) : p(_p)
+{
+}
+
+Vertex::Vertex() : p() {
+}
+
+int Vertex::classify(const Vertex &p0, const Vertex &p1)
+{
+ Vertex &p2 = *this;
+ std::auto_ptr<Vertex> a = p1.sub(p0);
+ std::auto_ptr<Vertex> b = p2.sub(p0);
+ double sa = a->crossProduct(*b);
+ int ret;
+
+ if (sa > 0.0)
+ ret = LEFT;
+ if (sa < 0.0)
+ ret = RIGHT;
+ if ((a->getX() * b->getX() < 0.0) || (a->getY() * b->getY() < 0.0))
+ ret = BEHIND;
+ if (a->magn() < b->magn())
+ ret = BEYOND;
+ if (p0.equals(p2))
+ ret = ORIGIN;
+ if (p1.equals(p2))
+ ret = DESTINATION;
+ else
+ ret = BETWEEN;
+
+ return ret;
+}
+
+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());
+}
+
+bool Vertex::leftOf(const QuadEdge &e) const {
+ return isCCW(e.orig(), e.dest());
+}
+
+std::auto_ptr<HCoordinate> Vertex::bisector(const Vertex &a, const Vertex &b)
+{
+ // returns the perpendicular bisector of the line segment ab
+ double dx = b.getX() - a.getX();
+ double dy = b.getY() - a.getY();
+ HCoordinate l1 = HCoordinate(a.getX() + dx / 2.0, a.getY() + dy / 2.0, 1.0);
+ HCoordinate l2 = HCoordinate(a.getX() - dy + dx / 2.0, a.getY() + dx + dy / 2.0, 1.0);
+
+ return std::auto_ptr<HCoordinate>(new HCoordinate(l1, l2));
+}
+
+double Vertex::circumRadiusRatio(const Vertex &b, const Vertex &c)
+{
+ std::auto_ptr<Vertex> x(circleCenter(b, c));
+ double radius = distance(*x, b);
+ double edgeLength = distance(*this, b);
+ double el = distance(b, c);
+ if (el < edgeLength)
+ {
+ edgeLength = el;
+ }
+ el = distance(c, *this);
+ if (el < edgeLength)
+ {
+ edgeLength = el;
+ }
+
+ return radius / edgeLength;
+}
+
+std::auto_ptr<Vertex> Vertex::midPoint(const Vertex &a)
+{
+ double xm = (p.x + a.getX()) / 2.0;
+ double ym = (p.y + a.getY()) / 2.0;
+ double zm = (p.z + a.getZ()) / 2.0;
+ return std::auto_ptr<Vertex>(new Vertex(xm, ym, zm));
+}
+
+std::auto_ptr<Vertex> Vertex::circleCenter(const Vertex &b, const Vertex &c) const
+{
+ std::auto_ptr<Vertex> a(new Vertex(getX(), getY()));
+ // compute the perpendicular bisector of cord ab
+ std::auto_ptr<HCoordinate> cab = bisector(*a, b);
+ // compute the perpendicular bisector of cord bc
+ std::auto_ptr<HCoordinate> cbc = bisector(b, c);
+ // compute the intersection of the bisectors (circle radii)
+ std::auto_ptr<HCoordinate> hcc(new HCoordinate(*cab, *cbc));
+ std::auto_ptr<Vertex> cc;
+
+ try
+ {
+ cc.reset(new Vertex(hcc->getX(), hcc->getY()));
+ } catch (NotRepresentableException nre) {
+ }
+
+ return cc;
+}
+
+double Vertex::interpolateZValue(const Vertex &v0, const Vertex &v1,
+ const Vertex &v2) const
+{
+ double x0 = v0.getX();
+ double y0 = v0.getY();
+ double a = v1.getX() - x0;
+ double b = v2.getX() - x0;
+ double c = v1.getY() - y0;
+ double d = v2.getY() - y0;
+ double det = a * d - b * c;
+ double dx = this->getX() - x0;
+ double dy = this->getY() - y0;
+ double t = (d * dx - b * dy) / det;
+ double u = (-c * dx + a * dy) / det;
+ double z = v0.getZ() + t * (v1.getZ() - v0.getZ()) + u * (v2.getZ() - v0.getZ());
+ return z;
+}
+
+double Vertex::interpolateZ(const Coordinate &p, const Coordinate &v0,
+ const Coordinate &v1, const Coordinate &v2)
+{
+ double x0 = v0.x;
+ double y0 = v0.y;
+ double a = v1.x - x0;
+ double b = v2.x - x0;
+ double c = v1.y - y0;
+ double d = v2.y - y0;
+ double det = a * d - b * c;
+ double dx = p.x - x0;
+ double dy = p.y - y0;
+ double t = (d * dx - b * dy) / det;
+ double u = (-c * dx + a * dy) / det;
+ double z = v0.z + t * (v1.z - v0.z) + u * (v2.z - v0.z);
+ return z;
+}
+
+double Vertex::interpolateZ(const Coordinate &p, const Coordinate &p0,
+ const Coordinate &p1)
+{
+ double segLen = p0.distance(p1);
+ double ptLen = p.distance(p0);
+ double dz = p1.z - p0.z;
+ double pz = p0.z + dz * (ptLen / segLen);
+ return pz;
+}
+
+} //namespace geos.triangulate.quadedge
+} //namespace geos.triangulate
+} //namespace geos
Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am 2012-06-25 23:31:38 UTC (rev 3692)
+++ trunk/tests/unit/Makefile.am 2012-06-26 17:11:33 UTC (rev 3693)
@@ -100,6 +100,9 @@
precision/GeometryPrecisionReducerTest.cpp \
simplify/DouglasPeuckerSimplifierTest.cpp \
simplify/TopologyPreservingSimplifierTest.cpp \
+ triangulate/quadedge/QuadEdgeTest.cpp \
+ triangulate/quadedge/QuadEdgeSubdivisionTest.cpp \
+ triangulate/DelaunayTest.cpp \
util/UniqueCoordinateArrayFilterTest.cpp \
capi/GEOSCoordSeqTest.cpp \
capi/GEOSGeomFromWKBTest.cpp \
Added: trunk/tests/unit/triangulate/DelaunayTest.cpp
===================================================================
--- trunk/tests/unit/triangulate/DelaunayTest.cpp (rev 0)
+++ trunk/tests/unit/triangulate/DelaunayTest.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,149 @@
+
+//
+// Test Suite for geos::triangulate::quadedge::QuadEdge
+//
+// tut
+#include <tut.hpp>
+// geos
+#include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+#include <geos/triangulate/IncrementalDelaunayTriangulator.h>
+#include <geos/triangulate/DelaunayTriangulationBuilder.h>
+//#include <geos/io/WKTWriter.h>
+#include <geos/io/WKTReader.h>
+#include <geos/geom/GeometryCollection.h>
+#include <geos/geom/GeometryFactory.h>
+
+#include <stdio.h>
+
+using namespace geos::triangulate;
+using namespace geos::triangulate::quadedge;
+using namespace geos::geom;
+using namespace geos::io;
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // dummy data, not used
+ struct test_incdelaunaytri_data
+ {
+ test_incdelaunaytri_data()
+ {
+ }
+ };
+
+ typedef test_group<test_incdelaunaytri_data> group;
+ typedef group::object object;
+
+ group test_incdelaunaytri_group("geos::triangulate::Delaunay");
+
+ //helper function for funning triangulation
+ void runDelaunay(const char *sitesWkt, bool computeTriangles, const char *expectedWkt)
+ {
+ WKTReader reader;
+ std::auto_ptr<Geometry> results;
+ Geometry *sites = reader.read(sitesWkt);
+ Geometry *expected = reader.read(expectedWkt);
+ DelaunayTriangulationBuilder builder;
+ GeometryFactory geomFact;
+
+ builder.setSites(*sites);
+ if(computeTriangles)
+ results=builder.getTriangles(geomFact);
+ else
+ results=builder.getEdges(geomFact);
+
+ results->normalize();
+ expected->normalize();
+
+ ensure(results->equalsExact(expected, 1e-7));
+
+ delete sites;
+ delete expected;
+ }
+
+ //
+ // Test Cases
+ //
+
+ // 1 - Basic function test
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ //Create a subdivision centered at (0,0)
+ QuadEdgeSubdivision sub(Envelope(-100, 100, -100, 100), .00001);
+ //make a triagulaor to work on sub
+ IncrementalDelaunayTriangulator triangulator(&sub);
+
+ triangulator.insertSite(Vertex(0, 0));
+
+ //extract the triangles from the subdivision
+ GeometryFactory geomFact;
+ std::auto_ptr<GeometryCollection> tris = sub.getTriangles(geomFact);
+ }
+
+ // 2 - Test Triangle
+ template<>
+ template<>
+ void object::test<2>()
+ {
+ const char * wkt = "MULTIPOINT ((10 10 1), (10 20 2), (20 20 3))";
+ const char* expectedEdges = "MULTILINESTRING ((10 20, 20 20), (10 10, 10 20), (10 10, 20 20))";
+ const char * expectedTri = "GEOMETRYCOLLECTION (POLYGON ((10 20, 10 10, 20 20, 10 20)))";
+
+ runDelaunay(wkt, true, expectedTri);
+ runDelaunay(wkt, false, expectedEdges);
+ }
+
+ // 3 - Test Random
+ template<>
+ template<>
+ void object::test<3>()
+ {
+ const char* wkt = "MULTIPOINT ((50 40), (140 70), (80 100), (130 140), (30 150), (70 180), (190 110), (120 20))";
+ const char* expectedEdges = "MULTILINESTRING ((70 180, 190 110), (30 150, 70 180), (30 150, 50 40), (50 40, 120 20), (190 110, 120 20), (120 20, 140 70), (190 110, 140 70), (130 140, 140 70), (130 140, 190 110), (70 180, 130 140), (80 100, 130 140), (70 180, 80 100), (30 150, 80 100), (50 40, 80 100), (80 100, 120 20), (80 100, 140 70))";
+ const char* expectedTri = "GEOMETRYCOLLECTION (POLYGON ((30 150, 50 40, 80 100, 30 150)), POLYGON ((30 150, 80 100, 70 180, 30 150)), POLYGON ((70 180, 80 100, 130 140, 70 180)), POLYGON ((70 180, 130 140, 190 110, 70 180)), POLYGON ((190 110, 130 140, 140 70, 190 110)), POLYGON ((190 110, 140 70, 120 20, 190 110)), POLYGON ((120 20, 140 70, 80 100, 120 20)), POLYGON ((120 20, 80 100, 50 40, 120 20)), POLYGON ((80 100, 140 70, 130 140, 80 100)))";
+
+ runDelaunay(wkt, false, expectedEdges);
+ runDelaunay(wkt, true, expectedTri);
+ }
+
+ // 4 - Test grid
+ template<>
+ template<>
+ void object::test<4>()
+ {
+ const char * wkt = "MULTIPOINT ((10 10), (10 20), (20 20), (20 10), (20 0), (10 0), (0 0), (0 10), (0 20))";
+ const char* expectedEdges = "MULTILINESTRING ((10 20, 20 20), (0 20, 10 20), (0 10, 0 20), (0 0, 0 10), (0 0, 10 0), (10 0, 20 0), (20 0, 20 10), (20 10, 20 20), (10 20, 20 10), (10 10, 20 10), (10 10, 10 20), (10 10, 0 20), (10 10, 0 10), (10 0, 10 10), (0 10, 10 0), (10 10, 20 0))";
+ const char * expectedTri = "GEOMETRYCOLLECTION (POLYGON ((0 20, 0 10, 10 10, 0 20)), POLYGON ((0 20, 10 10, 10 20, 0 20)), POLYGON ((10 20, 10 10, 20 10, 10 20)), POLYGON ((10 20, 20 10, 20 20, 10 20)), POLYGON ((10 0, 20 0, 10 10, 10 0)), POLYGON ((10 0, 10 10, 0 10, 10 0)), POLYGON ((10 0, 0 10, 0 0, 10 0)), POLYGON ((10 10, 20 0, 20 10, 10 10)))";
+
+ runDelaunay(wkt, false, expectedEdges);
+ runDelaunay(wkt, true, expectedTri);
+ }
+
+ // 5 - Test Circle
+ template<>
+ template<>
+ void object::test<5>()
+ {
+ const char * wkt = "POLYGON ((42 30, 41.96 29.61, 41.85 29.23, 41.66 28.89, 41.41 28.59, 41.11 28.34, 40.77 28.15, 40.39 28.04, 40 28, 39.61 28.04, 39.23 28.15, 38.89 28.34, 38.59 28.59, 38.34 28.89, 38.15 29.23, 38.04 29.61, 38 30, 38.04 30.39, 38.15 30.77, 38.34 31.11, 38.59 31.41, 38.89 31.66, 39.23 31.85, 39.61 31.96, 40 32, 40.39 31.96, 40.77 31.85, 41.11 31.66, 41.41 31.41, 41.66 31.11, 41.85 30.77, 41.96 30.39, 42 30))";
+ const char* expectedEdges = "MULTILINESTRING ((41.66 31.11, 41.85 30.77), (41.41 31.41, 41.66 31.11), (41.11 31.66, 41.41 31.41), (40.77 31.85, 41.11 31.66), (40.39 31.96, 40.77 31.85), (40 32, 40.39 31.96), (39.61 31.96, 40 32), (39.23 31.85, 39.61 31.96), (38.89 31.66, 39.23 31.85), (38.59 31.41, 38.89 31.66), (38.34 31.11, 38.59 31.41), (38.15 30.77, 38.34 31.11), (38.04 30.39, 38.15 30.77), (38 30, 38.04 30.39), (38 30, 38.04 29.61), (38.04 29.61, 38.15 29.23), (38.15 29.23, 38.34 28.89), (38.34 28.89, 38.59 28.59), (38.59 28.59, 38.89 28.34), (38.89 28.34, 39.23 28.15), (39.23 28.15, 39.61 28.04), (39.61 28.04, 40 28), (40 28, 40.39 28.04), (40.39 28.04, 40.77 28.15), (40.77 28.15, 41.11 28.34), (41.11 28.34, 41.41 28.59), (41.41 28.59, 41.66 28.89), (41.66 28.89, 41.85 29.23), (41.85 29.23, 41.96 29.61), (41.96 29.61, 42 30), (41.96 30.39, 42 30), (41.85 30.77, 41.96 30.39), (41.66 31.11, 41.96 30.39), (41.41 31.41, 41.96 30.39), (41.41 28.59, 41.96 30.39), (41.41 28
.59, 41.41 31.41), (38.59 28.59, 41.41 28.59), (38.59 28.59, 41.41 31.41), (38.59 28.59, 38.59 31.41), (38.59 31.41, 41.41 31.41), (38.59 31.41, 39.61 31.96), (39.61 31.96, 41.41 31.41), (39.61 31.96, 40.39 31.96), (40.39 31.96, 41.41 31.41), (40.39 31.96, 41.11 31.66), (38.04 30.39, 38.59 28.59), (38.04 30.39, 38.59 31.41), (38.04 30.39, 38.34 31.11), (38.04 29.61, 38.59 28.59), (38.04 29.61, 38.04 30.39), (39.61 28.04, 41.41 28.59), (38.59 28.59, 39.61 28.04), (38.89 28.34, 39.61 28.04), (40.39 28.04, 41.41 28.59), (39.61 28.04, 40.39 28.04), (41.96 29.61, 41.96 30.39), (41.41 28.59, 41.96 29.61), (41.66 28.89, 41.96 29.61), (40.39 28.04, 41.11 28.34), (38.04 29.61, 38.34 28.89), (38.89 31.66, 39.61 31.96))";
+
+ runDelaunay(wkt, false, expectedEdges);
+ }
+
+ // 6 - Test Polygon With Chevron Holes
+ template<>
+ template<>
+ void object::test<6>()
+ {
+ const char * wkt = "POLYGON ((0 0, 0 200, 180 200, 180 0, 0 0), (20 180, 160 180, 160 20, 152.625 146.75, 20 180), (30 160, 150 30, 70 90, 30 160))";
+ const char* expectedEdges = "MULTILINESTRING ((0 200, 180 200), (0 0, 0 200), (0 0, 180 0), (180 200, 180 0), (152.625 146.75, 180 0), (152.625 146.75, 180 200), (152.625 146.75, 160 180), (160 180, 180 200), (0 200, 160 180), (20 180, 160 180), (0 200, 20 180), (20 180, 30 160), (30 160, 0 200), (0 0, 30 160), (30 160, 70 90), (0 0, 70 90), (70 90, 150 30), (150 30, 0 0), (150 30, 160 20), (0 0, 160 20), (160 20, 180 0), (152.625 146.75, 160 20), (150 30, 152.625 146.75), (70 90, 152.625 146.75), (30 160, 152.625 146.75), (30 160, 160 180))";
+
+ runDelaunay(wkt, false, expectedEdges);
+ }
+} // namespace tut
+
Added: trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
===================================================================
--- trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp (rev 0)
+++ trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,72 @@
+
+//
+// Test Suite for geos::triangulate::quadedge::QuadEdge
+//
+// tut
+#include <tut.hpp>
+// geos
+#include <geos/triangulate/quadedge/Vertex.h>
+#include <geos/triangulate/quadedge/QuadEdge.h>
+#include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+#include <geos/geom/GeometryCollection.h>
+#include <geos/geom/GeometryFactory.h>
+//#include <geos/io/WKTWriter.h>
+#include <geos/geom/Envelope.h>
+#include <geos/geom/Coordinate.h>
+// std
+#include <stdio.h>
+
+using namespace geos::triangulate::quadedge;
+using namespace geos::geom;
+using namespace geos::io;
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // dummy data, not used
+ struct test_quadedgesub_data
+ {
+ test_quadedgesub_data()
+ {
+ }
+ };
+
+ typedef test_group<test_quadedgesub_data> group;
+ typedef group::object object;
+
+ group test_quadedgesub_group("geos::triangulate::quadedge::QuadEdgeSubdivision");
+
+
+ //
+ // Test Cases
+ //
+
+ // 1 - Basic function test
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ //create subdivision centered around (0,0)
+ QuadEdgeSubdivision sub(Envelope(-100, 100, -100, 100), .00001);
+ //stick a point in the middle
+ QuadEdge& e = sub.insertSite(Vertex(0, 0));
+ ensure(sub.isFrameEdge(e));
+ ensure(sub.isOnEdge(e, e.orig().getCoordinate()));
+ ensure(sub.isVertexOfEdge(e, e.orig()));
+
+ ensure(!sub.isOnEdge(e, Coordinate(10, 10)));
+ ensure(!sub.isVertexOfEdge(e, Vertex(10, 10)));
+
+ GeometryFactory geomFact;
+ std::auto_ptr<GeometryCollection> tris = sub.getTriangles(geomFact);
+ tris.reset();
+ //WKTWriter wkt;
+ //printf("%s\n", wkt.writeFormatted(tris).c_str());
+ }
+
+} // namespace tut
+
+
Added: trunk/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp
===================================================================
--- trunk/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp (rev 0)
+++ trunk/tests/unit/triangulate/quadedge/QuadEdgeTest.cpp 2012-06-26 17:11:33 UTC (rev 3693)
@@ -0,0 +1,171 @@
+//
+// Test Suite for geos::triangulate::quadedge::QuadEdge
+//
+// tut
+#include <tut.hpp>
+// geos
+#include <geos/triangulate/quadedge/Vertex.h>
+#include <geos/triangulate/quadedge/QuadEdge.h>
+// std
+#include <stdio.h>
+
+using namespace geos::triangulate::quadedge;
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // dummy data, not used
+ struct test_quadedge_data
+ {
+ test_quadedge_data()
+ {
+ }
+ };
+
+ typedef test_group<test_quadedge_data> group;
+ typedef group::object object;
+
+ group test_quadedge_group("geos::triangulate::quadedge::QuadEdge");
+
+
+ //
+ // Test Cases
+ //
+
+ // 1 - QuadEdge::connect()
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ Vertex v1(0, 0);
+ Vertex v2(0, 1);
+
+ Vertex v3(1, 0);
+ Vertex v4(1, 1);
+
+ std::auto_ptr<QuadEdge> q0;
+ std::auto_ptr<QuadEdge> r0;
+ std::auto_ptr<QuadEdge> s0;
+
+ q0 = QuadEdge::makeEdge(v1, v2);
+ r0 = QuadEdge::makeEdge(v3, v4);
+ s0 = QuadEdge::connect(*q0, *r0);
+
+ //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();
+ }
+
+ // 2 - QuadEdge::connect(), causing a loop
+ template<>
+ template<>
+ void object::test<2>()
+ {
+ Vertex v1(0, 0);
+ Vertex v2(0, 1);
+
+ Vertex v3(1, 0);
+ Vertex v4(1, 1);
+
+ std::auto_ptr<QuadEdge> q0;
+ std::auto_ptr<QuadEdge> r0;
+ std::auto_ptr<QuadEdge> s0;
+
+ q0 = QuadEdge::makeEdge(v1, v2);
+ r0 = QuadEdge::makeEdge(v2, v3);
+ s0 = QuadEdge::connect(*q0, *r0);
+
+ //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();
+ }
+
+ // 3 - QuadEdge::swap()
+ template<>
+ template<>
+ void object::test<3>()
+ {
+ Vertex v1(0, 0);
+ Vertex v2(0, 1);
+
+ Vertex v3(1, 0);
+ Vertex v4(1, 1);
+
+ std::auto_ptr<QuadEdge> q0;
+ std::auto_ptr<QuadEdge> r0;
+ std::auto_ptr<QuadEdge> s0;
+ std::auto_ptr<QuadEdge> t0;
+ std::auto_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);
+
+ //printf("\n=====================\n");
+ //printf("r0->orig(): %f %f\n", r0->orig().getX(), r0->orig().getY());
+ //printf("r0->dest(): %f %f\n", r0->dest().getX(), r0->dest().getY());
+ //printf("s0->orig(): %f %f\n", s0->orig().getX(), s0->orig().getY());
+ //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);
+ //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());
+ //printf("r0->orig(): %f %f\n", r0->orig().getX(), r0->orig().getY());
+ //printf("r0->dest(): %f %f\n", r0->dest().getX(), r0->dest().getY());
+ //printf("s0->orig(): %f %f\n", s0->orig().getX(), s0->orig().getY());
+ //printf("s0->dest(): %f %f\n", s0->dest().getX(), s0->dest().getY());
+ //printf("t0->orig(): %f %f\n", t0->orig().getX(), t0->orig().getY());
+ //printf("t0->dest(): %f %f\n", t0->dest().getX(), t0->dest().getY());
+ //printf("u0->orig(): %f %f\n", u0->orig().getX(), u0->orig().getY());
+ //printf("u0->dest(): %f %f\n", u0->dest().getX(), u0->dest().getY());
+ ensure(t0->dest().equals(u0->orig()));
+ ensure(u0->dest().equals(r0->orig()));
+
+ //now swap the interior edge
+ QuadEdge::swap(*u0);
+ //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());
+ //printf("r0->orig(): %f %f\n", r0->orig().getX(), r0->orig().getY());
+ //printf("r0->dest(): %f %f\n", r0->dest().getX(), r0->dest().getY());
+ //printf("s0->orig(): %f %f\n", s0->orig().getX(), s0->orig().getY());
+ //printf("s0->dest(): %f %f\n", s0->dest().getX(), s0->dest().getY());
+ //printf("t0->orig(): %f %f\n", t0->orig().getX(), t0->orig().getY());
+ //printf("t0->dest(): %f %f\n", t0->dest().getX(), t0->dest().getY());
+ //printf("u0->orig(): %f %f\n", u0->orig().getX(), u0->orig().getY());
+ //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
+
+
More information about the geos-commits
mailing list