[geos-commits] r3944 - in trunk: include/geos/triangulate/quadedge src/triangulate/quadedge tests/unit/triangulate/quadedge

svn_geos at osgeo.org svn_geos at osgeo.org
Sat Sep 7 13:11:58 PDT 2013


Author: strk
Date: 2013-09-07 13:11:58 -0700 (Sat, 07 Sep 2013)
New Revision: 3944

Modified:
   trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h
   trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp
   trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
Log:
Voronoi APIs added to QuadEdgeSubdivision class, with test added

Contributed by Vishal Tiwari

Modified: trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h
===================================================================
--- trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h	2013-09-04 23:15:33 UTC (rev 3943)
+++ trunk/include/geos/triangulate/quadedge/QuadEdgeSubdivision.h	2013-09-07 20:11:58 UTC (rev 3944)
@@ -23,8 +23,8 @@
 #include <list>
 #include <stack>
 #include <set>
+#include <vector>
 
-#include <geos/geom/Envelope.h>
 #include <geos/geom/MultiLineString.h>
 #include <geos/triangulate/quadedge/QuadEdgeLocator.h>
 #include <geos/triangulate/quadedge/Vertex.h>
@@ -37,6 +37,8 @@
 	class GeometryCollection;
 	class GeometryFactory;
 	class Coordinate;
+	class Geometry;
+	class Envelope;
 }
 
 namespace triangulate { //geos.triangulate
@@ -372,7 +374,8 @@
 	void getTriangleCoordinates(TriList* triList, bool includeFrame);
 
 private:
-	class TriangleCoordinatesVisitor; 
+	class TriangleCoordinatesVisitor;
+	class TriangleCircumcentreVisitor;
 
 public:
 	/**
@@ -392,7 +395,61 @@
 	 * @return a GeometryCollection of triangular Polygons. The caller takes ownership of the returned object.
 	 */
 	std::auto_ptr<geom::GeometryCollection> getTriangles(const geom::GeometryFactory &geomFact);
-
+	
+	/**  
+	 * Gets the cells in the Voronoi diagram for this triangulation.
+	 * The cells are returned as a {@link GeometryCollection} of {@link Polygon}s
+	 * The userData of each polygon is set to be the {@link Coordinate}
+	 * of the cell site.  This allows easily associating external 
+	 * data associated with the sites to the cells.
+	 *
+	 * @param geomFact a geometry factory
+	 * @return a GeometryCollection of Polygons
+	 */
+	std::auto_ptr<geom::GeometryCollection> getVoronoiDiagram(const geom::GeometryFactory& geomFact);
+	
+	/**  
+	 * Gets a List of {@link Polygon}s for the Voronoi cells 
+	 * of this triangulation.
+	 * The userData of each polygon is set to be the {@link Coordinate}
+	 * of the cell site.  This allows easily associating external 
+	 * data associated with the sites to the cells.
+	 *
+	 * @param geomFact a geometry factory
+	 * @return a List of Polygons
+	 */
+	std::auto_ptr< std::vector<geom::Geometry*> > getVoronoiCellPolygons(const geom::GeometryFactory& geomFact);
+	
+	/**
+	 * Gets a collection of {@link QuadEdge}s whose origin
+	 * vertices are a unique set which includes
+	 * all vertices in the subdivision. 
+	 * The frame vertices can be included if required.
+	 * This is useful for algorithms which require traversing the 
+	 * subdivision starting at all vertices.
+	 * Returning a quadedge for each vertex
+	 * is more efficient than 
+	 * the alternative of finding the actual vertices
+	 * using {@link #getVertices} and then locating 
+	 * quadedges attached to them.
+	 *
+	 * @param includeFrame true if the frame vertices should be included
+	 * @return a collection of QuadEdge with the vertices of the subdivision as their origins
+	 */
+	std::auto_ptr<QuadEdgeSubdivision::QuadEdgeList> getVertexUniqueEdges(bool includeFrame);
+	
+	/**
+	 * Gets the Voronoi cell around a site specified
+	 * by the origin of a QuadEdge.
+	 * The userData of the polygon is set to be the {@link Coordinate}
+	 * of the site.  This allows attaching external 
+	 * data associated with the site to this cell polygon.
+	 *
+	 * @param qe a quadedge originating at the cell site
+	 * @param geomFact a factory for building the polygon
+	 * @return a polygon indicating the cell extent
+	 */
+	std::auto_ptr<geom::Geometry> getVoronoiCellPolygon(QuadEdge* qe ,const geom::GeometryFactory& geomFact);
 };
 
 } //namespace geos.triangulate.quadedge

Modified: trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp
===================================================================
--- trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp	2013-09-04 23:15:33 UTC (rev 3943)
+++ trunk/src/triangulate/quadedge/QuadEdgeSubdivision.cpp	2013-09-07 20:11:58 UTC (rev 3944)
@@ -18,6 +18,8 @@
 #include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
 
 #include <vector>
+#include <set>
+#include <iostream>
 
 #include <geos/geom/Polygon.h>
 #include <geos/geom/LineSegment.h>
@@ -26,6 +28,7 @@
 #include <geos/geom/CoordinateArraySequence.h>
 #include <geos/geom/CoordinateSequenceFactory.h>
 #include <geos/geom/CoordinateArraySequenceFactory.h>
+#include <geos/geom/CoordinateList.h>
 #include <geos/geom/GeometryCollection.h>
 #include <geos/geom/GeometryFactory.h>
 #include <geos/util/IllegalArgumentException.h>
@@ -35,9 +38,11 @@
 #include <geos/triangulate/quadedge/LastFoundQuadEdgeLocator.h>
 #include <geos/triangulate/quadedge/LocateFailureException.h>
 #include <geos/triangulate/quadedge/TriangleVisitor.h>
+#include <geos/geom/Triangle.h>
 
+
 using namespace geos::geom;
-
+using namespace std;
 namespace geos {
 namespace triangulate { //geos.triangulate
 namespace quadedge { //geos.triangulate.quadedge
@@ -389,6 +394,27 @@
     }
 }; 
 
+
+class
+QuadEdgeSubdivision::TriangleCircumcentreVisitor : public TriangleVisitor
+{
+public:
+	void visit(QuadEdge* triEdges[3])
+	{
+		Triangle triangle(triEdges[0]->orig().getCoordinate(),
+				triEdges[1]->orig().getCoordinate(), triEdges[2]->orig().getCoordinate());
+		Coordinate cc;
+		triangle.circumcentre(cc);
+
+		Vertex ccVertex(cc);
+
+		for(int i=0 ; i<3 ; i++){
+			triEdges[i]->rot().setOrig(ccVertex);
+		}
+	}
+};
+
+
 void
 QuadEdgeSubdivision::getTriangleCoordinates(QuadEdgeSubdivision::TriList* triList, bool includeFrame)
 {
@@ -470,6 +496,102 @@
     return std::auto_ptr<GeometryCollection>(ret);
 }
 
+
+//Methods for VoronoiDiagram
+std::auto_ptr<geom::GeometryCollection> 
+QuadEdgeSubdivision::getVoronoiDiagram(const geom::GeometryFactory& geomFact)
+{
+	std::auto_ptr< std::vector<geom::Geometry*> > vorCells = getVoronoiCellPolygons(geomFact);
+	return std::auto_ptr<GeometryCollection>(geomFact.createGeometryCollection(vorCells.release()));
+}
+
+std::auto_ptr< std::vector<geom::Geometry*> >
+QuadEdgeSubdivision::getVoronoiCellPolygons(const geom::GeometryFactory& geomFact)
+{
+	std::auto_ptr< std::vector<geom::Geometry*> > cells(new std::vector<geom::Geometry*>);
+	TriangleCircumcentreVisitor* tricircumVisitor = new TriangleCircumcentreVisitor();
+	visitTriangles((TriangleVisitor*)tricircumVisitor, true);
+
+	std::auto_ptr<QuadEdgeSubdivision::QuadEdgeList> edges = getVertexUniqueEdges(false);
+
+	for(QuadEdgeSubdivision::QuadEdgeList::iterator it=edges->begin() ; it!=edges->end() ; ++it)
+	{
+		QuadEdge *qe = *it;
+		std::auto_ptr<geom::Geometry> poly = getVoronoiCellPolygon(qe,geomFact);
+
+		cells->push_back(poly.release());
+	}
+	delete tricircumVisitor;
+	return cells;
+}
+std::auto_ptr<geom::Geometry>
+QuadEdgeSubdivision::getVoronoiCellPolygon(QuadEdge* qe ,const geom::GeometryFactory& geomFact)
+{
+	std::vector<Coordinate> cellPts;
+	QuadEdge *startQE = qe;
+	do{
+		Coordinate cc = qe->rot().orig().getCoordinate();
+		cellPts.push_back(cc);
+		qe = &qe->oPrev();
+
+	}while ( qe != startQE);
+
+
+	//CoordList from a vector of Coordinates.
+	geom::CoordinateList coordList(cellPts);
+	//for checking close ring in CoordList class:
+	coordList.closeRing();
+
+	if(coordList.size() < 4)
+	{
+		cout << coordList << endl;
+		coordList.insert(coordList.end(),*(coordList.end()),true);
+	}
+	
+	std::auto_ptr<Coordinate::Vect> pts = coordList.toCoordinateArray();
+	std::auto_ptr<geom::Geometry> cellPoly( 
+		geomFact.createPolygon(geomFact.createLinearRing(new geom::CoordinateArraySequence(pts.release())),NULL));
+
+	Vertex v = startQE->orig();
+	Coordinate c(0,0);
+	c = v.getCoordinate();
+	cellPoly->setUserData(reinterpret_cast<void*>(&c));
+	return cellPoly;
+}
+
+std::auto_ptr<QuadEdgeSubdivision::QuadEdgeList>
+QuadEdgeSubdivision::getVertexUniqueEdges(bool includeFrame)
+{
+	std::auto_ptr<QuadEdgeSubdivision::QuadEdgeList> edges(new QuadEdgeList());
+	std::set<Vertex> visitedVertices;
+	for(QuadEdgeSubdivision::QuadEdgeList::iterator it=quadEdges.begin() ; it!=quadEdges.end() ; ++it)
+	{
+		QuadEdge *qe = (QuadEdge*)(*it);
+		Vertex v = qe->orig();
+
+
+		if(visitedVertices.find(v) == visitedVertices.end())	//if v not found
+		{
+			visitedVertices.insert(v);
+			if(includeFrame || ! QuadEdgeSubdivision::isFrameVertex(v))
+			{
+				edges->push_back(qe);
+			}
+		}
+		QuadEdge *qd = &(qe->sym());
+		Vertex vd = qd->orig();
+
+
+		if(visitedVertices.find(vd) == visitedVertices.end()){
+			visitedVertices.insert(vd);
+			if(includeFrame || ! QuadEdgeSubdivision::isFrameVertex(vd)){
+				edges->push_back(qd);
+			}
+		}
+	}
+	return edges;
+}
+
 } //namespace geos.triangulate.quadedge
 } //namespace geos.triangulate
 } //namespace goes

Modified: trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
===================================================================
--- trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp	2013-09-04 23:15:33 UTC (rev 3943)
+++ trunk/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp	2013-09-07 20:11:58 UTC (rev 3944)
@@ -8,15 +8,19 @@
 #include <geos/triangulate/quadedge/Vertex.h>
 #include <geos/triangulate/quadedge/QuadEdge.h>
 #include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+#include <geos/triangulate/DelaunayTriangulationBuilder.h>
 #include <geos/geom/GeometryCollection.h>
 #include <geos/geom/GeometryFactory.h>
+#include <geos/geom/CoordinateSequence.h>
 //#include <geos/io/WKTWriter.h>
+#include <geos/io/WKTReader.h>
 #include <geos/geom/Envelope.h>
 #include <geos/geom/Coordinate.h>
 // std
 #include <stdio.h>
-
+#include <iostream>
 using namespace geos::triangulate::quadedge;
+using namespace geos::triangulate;
 using namespace geos::geom;
 using namespace geos::io;
 
@@ -66,7 +70,43 @@
 		//WKTWriter wkt;
 		//printf("%s\n", wkt.writeFormatted(tris).c_str());
 	}
+	template<>
+	template<>
+	void object::test<2>()
+	{
+		WKTReader reader;
+		Geometry* sites;
+		QuadEdgeSubdivision* subdiv;
+		sites = reader.read("MULTIPOINT ((150 200), (180 270), (275 163))");
+		CoordinateSequence* siteCoords = DelaunayTriangulationBuilder::extractUniqueCoordinates(*sites);
+		Envelope Env = DelaunayTriangulationBuilder::envelope(*siteCoords);
 
+		double expandBy = fmax(Env.getWidth() , Env.getHeight());
+		Env.expandBy(expandBy);
+
+		IncrementalDelaunayTriangulator::VertexList* vertices = DelaunayTriangulationBuilder::toVertices(*siteCoords);
+		subdiv = new quadedge::QuadEdgeSubdivision(Env,0);
+		IncrementalDelaunayTriangulator triangulator(subdiv);
+		triangulator.insertSites(*vertices);
+
+		//Test for getVoronoiDiagram::
+		GeometryFactory geomFact;
+		std::auto_ptr<GeometryCollection> polys = subdiv->getVoronoiDiagram(geomFact);
+		const char *expected_str = "GEOMETRYCOLLECTION (POLYGON ((-5849.974929324658 2268.0517257497568, -4529.9920486948895 2247.139449440667, 221.20588235294116 210.91176470588235, -684.4227119984187 -2848.644297291955, -5849.974929324658 2268.0517257497568)), POLYGON ((212.5 -3774.5, -684.4227119984187 -2848.644297291955, 221.20588235294116 210.91176470588235, 2448.7167655626645 2188.608343256571, 6235.0370264064295 2248.0370264064295, 212.5 -3774.5)), POLYGON ((-4529.9920486948895 2247.139449440667, 2448.7167655626645 2188.608343256571, 221.20588235294116 210.91176470588235, -4529.9920486948895 2247.139449440667)))";
+//		std::cout << polys->toString() << std::endl;
+
+		Geometry *expected = reader.read(expected_str);
+		polys->normalize();
+		expected->normalize();
+		ensure(polys->equalsExact(expected, 1e-7));
+		delete siteCoords;
+		delete sites;
+		delete subdiv;
+		delete vertices;
+		delete expected;
+//		ensure(polys->getCoordinateDimension() == expected->getCoordinateDimension());
+	}
+
 } // namespace tut
 
 



More information about the geos-commits mailing list