[geos-commits] r4295 - in trunk: . capi include/geos/index/strtree include/geos/operation/distance src/index/strtree src/operation/distance src/precision tests/unit/capi

Sandro Santilli strk at kbt.io
Fri Oct 28 02:43:22 PDT 2016


Author: strk
Date: 2016-10-28 02:43:22 -0700 (Fri, 28 Oct 2016)
New Revision: 4295

Added:
   trunk/include/geos/operation/distance/IndexedFacetDistance.h
   trunk/src/operation/distance/IndexedFacetDistance.cpp
Modified:
   trunk/NEWS
   trunk/capi/geos_c.cpp
   trunk/capi/geos_c.h.in
   trunk/capi/geos_ts_c.cpp
   trunk/include/geos/index/strtree/BoundablePair.h
   trunk/include/geos/index/strtree/STRtree.h
   trunk/include/geos/operation/distance/FacetSequence.h
   trunk/include/geos/operation/distance/FacetSequenceTreeBuilder.h
   trunk/include/geos/operation/distance/Makefile.am
   trunk/src/index/strtree/BoundablePair.cpp
   trunk/src/index/strtree/STRtree.cpp
   trunk/src/operation/distance/FacetSequence.cpp
   trunk/src/operation/distance/FacetSequenceTreeBuilder.cpp
   trunk/src/operation/distance/Makefile.am
   trunk/src/precision/MinimumClearance.cpp
   trunk/tests/unit/capi/GEOSDistanceTest.cpp
Log:
Port IndexedFacetDistance from JTS

Contributed by Dan Baston
Closes #795

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/NEWS	2016-10-28 09:43:22 UTC (rev 4295)
@@ -1,6 +1,9 @@
 Changes in 3.7.0
 YYYY-MM-DD
 
+- New things:
+  - CAPI: GEOSDistanceIndexed (#795, Dan Baston)
+
 Changes in 3.6.0
 2016-10-25
 

Modified: trunk/capi/geos_c.cpp
===================================================================
--- trunk/capi/geos_c.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/capi/geos_c.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -279,6 +279,12 @@
 }
 
 int
+GEOSDistanceIndexed(const Geometry *g1, const Geometry *g2, double *dist)
+{
+    return GEOSDistanceIndexed_r( handle, g1, g2, dist );
+}
+
+int
 GEOSHausdorffDistance(const Geometry *g1, const Geometry *g2, double *dist)
 {
     return GEOSHausdorffDistance_r( handle, g1, g2, dist );

Modified: trunk/capi/geos_c.h.in
===================================================================
--- trunk/capi/geos_c.h.in	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/capi/geos_c.h.in	2016-10-28 09:43:22 UTC (rev 4295)
@@ -1100,6 +1100,9 @@
 extern int GEOS_DLL GEOSDistance_r(GEOSContextHandle_t handle,
                                    const GEOSGeometry* g1,
                                    const GEOSGeometry* g2, double *dist);
+extern int GEOS_DLL GEOSDistanceIndexed_r(GEOSContextHandle_t handle,
+                                   const GEOSGeometry* g1,
+                                   const GEOSGeometry* g2, double *dist);
 extern int GEOS_DLL GEOSHausdorffDistance_r(GEOSContextHandle_t handle,
                                    const GEOSGeometry *g1,
                                    const GEOSGeometry *g2,
@@ -1963,6 +1966,8 @@
 extern int GEOS_DLL GEOSLength(const GEOSGeometry* g, double *length);
 extern int GEOS_DLL GEOSDistance(const GEOSGeometry* g1, const GEOSGeometry* g2,
     double *dist);
+extern int GEOS_DLL GEOSDistanceIndexed(const GEOSGeometry* g1, const GEOSGeometry* g2,
+    double *dist);
 extern int GEOS_DLL GEOSHausdorffDistance(const GEOSGeometry *g1,
         const GEOSGeometry *g2, double *dist);
 extern int GEOS_DLL GEOSHausdorffDistanceDensify(const GEOSGeometry *g1,

Modified: trunk/capi/geos_ts_c.cpp
===================================================================
--- trunk/capi/geos_ts_c.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/capi/geos_ts_c.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -53,6 +53,7 @@
 #include <geos/operation/buffer/BufferOp.h>
 #include <geos/operation/buffer/BufferParameters.h>
 #include <geos/operation/distance/DistanceOp.h>
+#include <geos/operation/distance/IndexedFacetDistance.h>
 #include <geos/operation/linemerge/LineMerger.h>
 #include <geos/operation/overlay/OverlayOp.h>
 #include <geos/operation/overlay/snap/GeometrySnapper.h>
@@ -134,6 +135,7 @@
 using geos::operation::overlay::OverlayOp;
 using geos::operation::overlay::overlayOp;
 using geos::operation::geounion::CascadedPolygonUnion;
+using geos::operation::distance::IndexedFacetDistance;
 using geos::operation::buffer::BufferParameters;
 using geos::operation::buffer::BufferBuilder;
 using geos::precision::GeometryPrecisionReducer;
@@ -1158,6 +1160,40 @@
 }
 
 int
+GEOSDistanceIndexed_r(GEOSContextHandle_t extHandle, const Geometry *g1, const Geometry *g2, double *dist)
+{
+    assert(0 != dist);
+
+    if ( 0 == extHandle )
+    {
+        return 0;
+    }
+
+    GEOSContextHandleInternal_t *handle = 0;
+    handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+    if ( 0 == handle->initialized )
+    {
+        return 0;
+    }
+
+    try
+    {
+        *dist = IndexedFacetDistance::distance(g1, g2);
+        return 1;
+    }
+    catch (const std::exception &e)
+    {
+        handle->ERROR_MESSAGE("%s", e.what());
+    }
+    catch (...)
+    {
+        handle->ERROR_MESSAGE("Unknown exception thrown");
+    }
+
+    return 0;
+}
+
+int
 GEOSHausdorffDistance_r(GEOSContextHandle_t extHandle, const Geometry *g1, const Geometry *g2, double *dist)
 {
     assert(0 != dist);
@@ -6074,6 +6110,7 @@
                               GEOSDistanceCallback distancefn,
                               void* userdata)
 {
+    using namespace geos::index::strtree;
 
     GEOSContextHandleInternal_t *handle = 0;
 

Modified: trunk/include/geos/index/strtree/BoundablePair.h
===================================================================
--- trunk/include/geos/index/strtree/BoundablePair.h	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/include/geos/index/strtree/BoundablePair.h	2016-10-28 09:43:22 UTC (rev 4295)
@@ -36,13 +36,10 @@
  * @author Martin Davis
  *
  */
-
-using namespace geos::index::strtree;
-
-
 namespace geos {
 namespace index {
 namespace strtree {
+
 class BoundablePair {
 	private:
 		const Boundable* boundable1;

Modified: trunk/include/geos/index/strtree/STRtree.h
===================================================================
--- trunk/include/geos/index/strtree/STRtree.h	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/include/geos/index/strtree/STRtree.h	2016-10-28 09:43:22 UTC (rev 4295)
@@ -143,10 +143,12 @@
 	std::pair<const void*, const void*> nearestNeighbour(BoundablePair* initBndPair);
 	std::pair<const void*, const void*> nearestNeighbour(ItemDistance* itemDist);
 	std::pair<const void*, const void*> nearestNeighbour(BoundablePair* initBndPair, double maxDistance);
+	std::pair<const void*, const void*> nearestNeighbour(STRtree *tree, ItemDistance *itemDist);
 
 	bool remove(const geom::Envelope *itemEnv, void* item) {
 		return AbstractSTRtree::remove(itemEnv, item);
 	}
+
 };
 
 } // namespace geos::index::strtree

Modified: trunk/include/geos/operation/distance/FacetSequence.h
===================================================================
--- trunk/include/geos/operation/distance/FacetSequence.h	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/include/geos/operation/distance/FacetSequence.h	2016-10-28 09:43:22 UTC (rev 4295)
@@ -23,40 +23,38 @@
 #include <geos/geom/Envelope.h>
 #include <geos/geom/Coordinate.h>
 
-using namespace geos::geom;
-
 namespace geos {
     namespace operation {
         namespace distance {
             class FacetSequence {
             private:
-                const CoordinateSequence *pts;
+                const geom::CoordinateSequence *pts;
                 const size_t start;
                 const size_t end;
 
                 /* Unlike JTS, we store the envelope in the FacetSequence so that it has a clear owner.  This is
                  * helpful when making a tree of FacetSequence objects (FacetSequenceTreeBuilder)
                  * */
-                Envelope env;
+                geom::Envelope env;
 
                 double computeLineLineDistance(const FacetSequence & facetSeq) const;
 
-                double computePointLineDistance(const Coordinate & pt, const FacetSequence & facetSeq) const;
+                double computePointLineDistance(const geom::Coordinate & pt, const FacetSequence & facetSeq) const;
 
                 void computeEnvelope();
 
             public:
-                const Envelope * getEnvelope() const;
+                const geom::Envelope * getEnvelope() const;
 
-                const Coordinate * getCoordinate(size_t index) const;
+                const geom::Coordinate * getCoordinate(size_t index) const;
 
                 size_t size() const;
 
                 bool isPoint() const;
 
-                double distance(const FacetSequence & facetSeq);
+                double distance(const FacetSequence & facetSeq) const;
 
-                FacetSequence(const CoordinateSequence *pts, size_t start, size_t end);
+                FacetSequence(const geom::CoordinateSequence *pts, size_t start, size_t end);
             };
 
         }

Modified: trunk/include/geos/operation/distance/FacetSequenceTreeBuilder.h
===================================================================
--- trunk/include/geos/operation/distance/FacetSequenceTreeBuilder.h	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/include/geos/operation/distance/FacetSequenceTreeBuilder.h	2016-10-28 09:43:22 UTC (rev 4295)
@@ -24,10 +24,6 @@
 #include <geos/geom/CoordinateSequence.h>
 #include <geos/operation/distance/FacetSequence.h>
 
-using namespace geos::geom;
-using namespace geos::index::strtree;
-using namespace geos::operation::distance;
-
 namespace geos {
     namespace operation {
         namespace distance {
@@ -39,11 +35,11 @@
                 // Seems to be better to use a minimum node capacity
                 static const int STR_TREE_NODE_CAPACITY = 4;
 
-                static void addFacetSequences(const CoordinateSequence* pts, std::vector<FacetSequence*> & sections);
-                static std::vector<FacetSequence*> * computeFacetSequences(const Geometry* g);
+                static void addFacetSequences(const geom::CoordinateSequence* pts, std::vector<FacetSequence*> & sections);
+                static std::vector<FacetSequence*> * computeFacetSequences(const geom::Geometry* g);
 
             public:
-                static STRtree* build(const Geometry* g);
+                static geos::index::strtree::STRtree* build(const geom::Geometry* g);
             };
         }
     }

Added: trunk/include/geos/operation/distance/IndexedFacetDistance.h
===================================================================
--- trunk/include/geos/operation/distance/IndexedFacetDistance.h	                        (rev 0)
+++ trunk/include/geos/operation/distance/IndexedFacetDistance.h	2016-10-28 09:43:22 UTC (rev 4295)
@@ -0,0 +1,45 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2016 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************
+ *
+ * Last port: operation/distance/IndexedFacetDistance.java (f6187ee2 JTS-1.14)
+ *
+ **********************************************************************/
+
+#ifndef GEOS_INDEXEDFACETDISTANCE_H
+#define GEOS_INDEXEDFACETDISTANCE_H
+
+#include <geos/operation/distance/FacetSequenceTreeBuilder.h>
+
+namespace geos {
+    namespace operation {
+        namespace distance {
+            class GEOS_DLL IndexedFacetDistance {
+            public:
+                IndexedFacetDistance(const geom::Geometry * g) :
+                        cachedTree(FacetSequenceTreeBuilder::build(g))
+                        {}
+
+                static double distance(const geom::Geometry * g1, const geom::Geometry * g2);
+
+                double getDistance(const geom::Geometry * g) const;
+
+            private:
+                std::auto_ptr<geos::index::strtree::STRtree> cachedTree;
+
+            };
+        }
+    }
+}
+
+#endif //GEOS_INDEXEDFACETDISTANCE_H

Modified: trunk/include/geos/operation/distance/Makefile.am
===================================================================
--- trunk/include/geos/operation/distance/Makefile.am	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/include/geos/operation/distance/Makefile.am	2016-10-28 09:43:22 UTC (rev 4295)
@@ -11,6 +11,7 @@
 	ConnectedElementLocationFilter.h \
 	ConnectedElementPointFilter.h \
 	DistanceOp.h \
+	IndexedFacetDistance.h \
 	FacetSequence.h \
 	FacetSequenceTreeBuilder.h \
 	GeometryLocation.h

Modified: trunk/src/index/strtree/BoundablePair.cpp
===================================================================
--- trunk/src/index/strtree/BoundablePair.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/src/index/strtree/BoundablePair.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -21,6 +21,10 @@
 #include <geos/index/strtree/AbstractNode.h>
 #include <geos/util/IllegalArgumentException.h>
 
+namespace geos {
+namespace index {
+namespace strtree {
+
 BoundablePair::BoundablePair(const Boundable* boundable1, const Boundable* boundable2, ItemDistance* itemDistance) :
 	boundable1(boundable1),
 	boundable2(boundable2),
@@ -107,3 +111,7 @@
 	}
 }
 
+}
+}
+}
+

Modified: trunk/src/index/strtree/STRtree.cpp
===================================================================
--- trunk/src/index/strtree/STRtree.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/src/index/strtree/STRtree.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -204,6 +204,11 @@
 	return nearestNeighbour(&bp);
 }
 
+std::pair<const void*, const void*> STRtree::nearestNeighbour(STRtree* tree, ItemDistance* itemDist) {
+	BoundablePair bp(getRoot(), tree->getRoot(), itemDist);
+	return nearestNeighbour(&bp);
+}
+
 std::pair<const void*, const void*> STRtree::nearestNeighbour(BoundablePair* initBndPair, double maxDistance) {
 	double distanceLowerBound = maxDistance;
 	BoundablePair* minPair = NULL;

Modified: trunk/src/operation/distance/FacetSequence.cpp
===================================================================
--- trunk/src/operation/distance/FacetSequence.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/src/operation/distance/FacetSequence.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -19,6 +19,7 @@
 #include <geos/algorithm/CGAlgorithms.h>
 #include <geos/operation/distance/FacetSequence.h>
 
+using namespace geos::geom;
 using namespace geos::operation::distance;
 using namespace geos::algorithm;
 
@@ -37,7 +38,7 @@
     return end - start == 1;
 }
 
-double FacetSequence::distance(const FacetSequence & facetSeq) {
+double FacetSequence::distance(const FacetSequence & facetSeq) const {
     bool isPointThis = isPoint();
     bool isPointOther = facetSeq.isPoint();
 

Modified: trunk/src/operation/distance/FacetSequenceTreeBuilder.cpp
===================================================================
--- trunk/src/operation/distance/FacetSequenceTreeBuilder.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/src/operation/distance/FacetSequenceTreeBuilder.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -20,6 +20,13 @@
 #include <geos/geom/LineString.h>
 #include <geos/geom/Point.h>
 
+using namespace geos::geom;
+using namespace geos::index::strtree;
+
+namespace geos {
+namespace operation {
+namespace distance {
+
 STRtree* FacetSequenceTreeBuilder::build(const Geometry* g) {
     std::auto_ptr<STRtree> tree(new STRtree(STR_TREE_NODE_CAPACITY));
     std::auto_ptr<std::vector<FacetSequence*> > sections(computeFacetSequences(g));
@@ -74,3 +81,8 @@
         i += FACET_SEQUENCE_SIZE;
     }
 }
+
+}
+}
+}
+

Added: trunk/src/operation/distance/IndexedFacetDistance.cpp
===================================================================
--- trunk/src/operation/distance/IndexedFacetDistance.cpp	                        (rev 0)
+++ trunk/src/operation/distance/IndexedFacetDistance.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -0,0 +1,48 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2016 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************
+ *
+ * Last port: operation/distance/IndexedFacetDistance.java (f6187ee2 JTS-1.14)
+ *
+ **********************************************************************/
+
+#include <geos/index/strtree/STRtree.h>
+#include <geos/operation/distance/IndexedFacetDistance.h>
+
+using namespace geos::geom;
+using namespace geos::index::strtree;
+
+namespace geos {
+    namespace operation {
+        namespace distance {
+            double IndexedFacetDistance::distance(const Geometry * g1, const Geometry * g2) {
+                IndexedFacetDistance ifd(g1);
+                return ifd.getDistance(g2);
+            }
+
+            double IndexedFacetDistance::getDistance(const Geometry * g) const {
+                struct : public ItemDistance {
+                    double distance(const ItemBoundable* item1, const ItemBoundable* item2) {
+                        return static_cast<const FacetSequence*>(item1->getItem())->distance(*static_cast<const FacetSequence*>(item2->getItem()));
+                    }
+                } itemDistance;
+
+                std::auto_ptr<STRtree> tree2(FacetSequenceTreeBuilder::build(g));
+
+                std::pair<const void*, const void*> obj = cachedTree->nearestNeighbour(tree2.get(), dynamic_cast<ItemDistance*>(&itemDistance));
+
+                return static_cast<const FacetSequence*>(obj.first)->distance(*static_cast<const FacetSequence*>(obj.second));
+            }
+        }
+    }
+}

Modified: trunk/src/operation/distance/Makefile.am
===================================================================
--- trunk/src/operation/distance/Makefile.am	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/src/operation/distance/Makefile.am	2016-10-28 09:43:22 UTC (rev 4295)
@@ -11,6 +11,7 @@
     ConnectedElementLocationFilter.cpp \
     ConnectedElementPointFilter.cpp \
     DistanceOp.cpp \
+    IndexedFacetDistance.cpp \
     FacetSequence.cpp \
     FacetSequenceTreeBuilder.cpp \
     GeometryLocation.cpp 

Modified: trunk/src/precision/MinimumClearance.cpp
===================================================================
--- trunk/src/precision/MinimumClearance.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/src/precision/MinimumClearance.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -25,6 +25,10 @@
 #include <geos/geom/LineSegment.h>
 #include <geos/index/ItemVisitor.h>
 
+using namespace geos::geom;
+using namespace geos::operation::distance;
+using namespace geos::index::strtree;
+
 namespace geos {
 namespace precision {
 

Modified: trunk/tests/unit/capi/GEOSDistanceTest.cpp
===================================================================
--- trunk/tests/unit/capi/GEOSDistanceTest.cpp	2016-10-27 19:24:22 UTC (rev 4294)
+++ trunk/tests/unit/capi/GEOSDistanceTest.cpp	2016-10-28 09:43:22 UTC (rev 4295)
@@ -9,6 +9,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <memory>
+#include <math.h>
 
 namespace tut
 {
@@ -81,7 +82,54 @@
         ensure_equals(ret, 1);
         ensure_distance(dist, 8.06225774829855, 1e-12);
     }
-    
 
+    GEOSGeometry* random_polygon(double x, double y, double r, size_t num_points)
+    {
+        std::vector<double> angle(num_points);
+        std::vector<double> radius(num_points);
+
+
+        for (size_t i = 0; i < num_points; i++) {
+            angle[i] = 2 * M_PI * std::rand() / RAND_MAX;
+            radius[i] = r*std::rand() / RAND_MAX;
+        }
+
+        std::sort(angle.begin(), angle.end());
+
+        GEOSCoordSequence* seq_1 = GEOSCoordSeq_create(num_points, 2);
+        for (size_t i = 0; i < num_points; i++)
+        {
+            size_t idx = i == (num_points - 1) ? 0 : i;
+
+            GEOSCoordSeq_setX(seq_1, i, x + radius[idx] * cos(angle[idx]));
+            GEOSCoordSeq_setY(seq_1, i, y + radius[idx] * sin(angle[idx]));
+        }
+
+        return GEOSGeom_createPolygon(GEOSGeom_createLinearRing(seq_1), NULL, 0);
+    }
+
+    /* Generate two complex polygons and verify that GEOSDistance and GEOSDistanceIndexed
+     * return identical results.
+     */
+    template<>
+    template<>
+    void object::test<2>()
+    {
+        std::srand(12345);
+
+        GEOSGeometry* g1 = random_polygon(-3, -8, 7, 1000);
+        GEOSGeometry* g2 = random_polygon(14, 22, 6, 500);
+
+        double d_raw, d_indexed;
+        ensure(GEOSDistance(g1, g2, &d_raw));
+        ensure(GEOSDistanceIndexed(g1, g2, &d_indexed));
+
+        ensure_equals(d_indexed, d_raw);
+
+        GEOSGeom_destroy(g1);
+        GEOSGeom_destroy(g2);
+    }
+
+
 } // namespace tut
 



More information about the geos-commits mailing list