[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