[geos-commits] [SCM] GEOS branch master updated. 63f2794d7798da8db62ec41bf2bd07502b7d0894

git at osgeo.org git at osgeo.org
Tue Apr 9 14:53:02 PDT 2019


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

The branch, master has been updated
       via  63f2794d7798da8db62ec41bf2bd07502b7d0894 (commit)
      from  8124f173f33c7c14a97ae9fa9a2a2767aa2d38d6 (commit)

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

- Log -----------------------------------------------------------------
commit 63f2794d7798da8db62ec41bf2bd07502b7d0894
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Tue Apr 9 14:52:34 2019 -0700

    Improvements to IndexedFacetDistance
    JTS 15cb864a9dbba54cc0f81778e2f455b30a8d53c5
    https://github.com/locationtech/jts/pull/363

diff --git a/include/geos/index/strtree/BoundablePair.h b/include/geos/index/strtree/BoundablePair.h
index 8294a65..cb896cd 100644
--- a/include/geos/index/strtree/BoundablePair.h
+++ b/include/geos/index/strtree/BoundablePair.h
@@ -103,7 +103,8 @@ public:
     static double area(const Boundable* b);
 
     void expandToQueue(BoundablePairQueue&, double minDistance);
-    void expand(const Boundable* bndComposite, const Boundable* bndOther, BoundablePairQueue& priQ, double minDistance);
+    void expand(const Boundable* bndComposite, const Boundable* bndOther, bool isFlipped, BoundablePairQueue& priQ,
+                double minDistance);
 };
 }
 }
diff --git a/include/geos/operation/distance/FacetSequence.h b/include/geos/operation/distance/FacetSequence.h
index b3790fc..7953db3 100644
--- a/include/geos/operation/distance/FacetSequence.h
+++ b/include/geos/operation/distance/FacetSequence.h
@@ -22,6 +22,8 @@
 #include <geos/geom/CoordinateSequence.h>
 #include <geos/geom/Envelope.h>
 #include <geos/geom/Coordinate.h>
+#include <geos/geom/LineSegment.h>
+#include <geos/operation/distance/GeometryLocation.h>
 
 namespace geos {
 namespace operation {
@@ -31,15 +33,30 @@ private:
     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)
-     * */
+    const geom::Geometry* geom;
+    /*
+    * 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)
+    */
     geom::Envelope env;
 
-    double computeLineLineDistance(const FacetSequence& facetSeq) const;
+    double computeDistanceLineLine(const FacetSequence& facetSeq,
+                                   std::vector<GeometryLocation> *locs) const;
+
+    double computeDistancePointLine(const geom::Coordinate& pt,
+                                    const FacetSequence& facetSeq,
+                                    std::vector<GeometryLocation> *locs) const;
+
+    void updateNearestLocationsPointLine(const geom::Coordinate& pt,
+                                         const FacetSequence& facetSeq, int i,
+                                         const geom::Coordinate& q0, const geom::Coordinate &q1,
+                                         std::vector<GeometryLocation> *locs) const;
 
-    double computePointLineDistance(const geom::Coordinate& pt, const FacetSequence& facetSeq) const;
+    void updateNearestLocationsLineLine(int i, const geom::Coordinate& p0, const geom::Coordinate& p1,
+                                        const FacetSequence& facetSeq,
+                                        int j, const geom::Coordinate& q0, const geom::Coordinate &q1,
+                                        std::vector<GeometryLocation> *locs) const;
 
     void computeEnvelope();
 
@@ -55,6 +72,11 @@ public:
     double distance(const FacetSequence& facetSeq) const;
 
     FacetSequence(const geom::CoordinateSequence* pts, size_t start, size_t end);
+
+    FacetSequence(const geom::Geometry* geom, const geom::CoordinateSequence* pts, size_t start, size_t end);
+
+    std::vector<GeometryLocation> nearestLocations(const FacetSequence& facetSeq) const;
+
 };
 
 }
diff --git a/include/geos/operation/distance/FacetSequenceTreeBuilder.h b/include/geos/operation/distance/FacetSequenceTreeBuilder.h
index 4dc003d..fef2ed3 100644
--- a/include/geos/operation/distance/FacetSequenceTreeBuilder.h
+++ b/include/geos/operation/distance/FacetSequenceTreeBuilder.h
@@ -35,7 +35,9 @@ private:
     // Seems to be better to use a minimum node capacity
     static const int STR_TREE_NODE_CAPACITY = 4;
 
-    static void addFacetSequences(const geom::CoordinateSequence* pts, std::vector<FacetSequence*>& sections);
+    static void addFacetSequences(const geom::Geometry* geom,
+                                  const geom::CoordinateSequence* pts,
+                                  std::vector<FacetSequence*>& sections);
     static std::vector<FacetSequence*>* computeFacetSequences(const geom::Geometry* g);
 
 public:
diff --git a/include/geos/operation/distance/GeometryLocation.h b/include/geos/operation/distance/GeometryLocation.h
index a8a3913..deaf3eb 100644
--- a/include/geos/operation/distance/GeometryLocation.h
+++ b/include/geos/operation/distance/GeometryLocation.h
@@ -110,6 +110,8 @@ public:
      * inside an area geometry.
      */
     bool isInsideArea();
+
+    std::string toString();
 };
 
 } // namespace geos::operation::distance
diff --git a/include/geos/operation/distance/IndexedFacetDistance.h b/include/geos/operation/distance/IndexedFacetDistance.h
index 257d802..508c9c5 100644
--- a/include/geos/operation/distance/IndexedFacetDistance.h
+++ b/include/geos/operation/distance/IndexedFacetDistance.h
@@ -32,7 +32,12 @@ public:
 
     static double distance(const geom::Geometry* g1, const geom::Geometry* g2);
 
-    double getDistance(const geom::Geometry* g) const;
+    static std::vector<geom::Coordinate> nearestPoints(const geom::Geometry* g1, const geom::Geometry* g2);
+
+    double distance(const geom::Geometry* g) const;
+
+    std::vector<GeometryLocation> nearestLocations(const geom::Geometry* g) const;
+    std::vector<geom::Coordinate> nearestPoints(const geom::Geometry* g) const;
 
     ~IndexedFacetDistance();
 
diff --git a/src/index/strtree/BoundablePair.cpp b/src/index/strtree/BoundablePair.cpp
index 209249c..d168f95 100644
--- a/src/index/strtree/BoundablePair.cpp
+++ b/src/index/strtree/BoundablePair.cpp
@@ -96,36 +96,59 @@ BoundablePair::expandToQueue(BoundablePairQueue& priQ, double minDistance)
      * choose the one with largest area to expand.
      * Otherwise, simply expand whichever is composite.
      */
-    if(isComp1 && isComp2) {
+    if (isComp1 && isComp2) {
         if(area(boundable1) > area(boundable2)) {
-            expand(boundable1, boundable2, priQ, minDistance);
+            expand(boundable1, boundable2, false, priQ, minDistance);
             return;
         }
         else {
-            expand(boundable2, boundable1, priQ, minDistance);
+            expand(boundable2, boundable1, true, priQ, minDistance);
             return;
         }
     }
-    else if(isComp1) {
-        expand(boundable1, boundable2, priQ, minDistance);
+    else if (isComp1) {
+        expand(boundable1, boundable2, false, priQ, minDistance);
         return;
     }
-    else if(isComp2) {
-        expand(boundable2, boundable1, priQ, minDistance);
+    else if (isComp2) {
+        expand(boundable2, boundable1, true, priQ, minDistance);
         return;
     }
 
     throw geos::util::IllegalArgumentException("neither boundable is composite");
 }
 
+// void
+// BoundablePair::expand(const Boundable* bndComposite, const Boundable* bndOther,
+//                       bool isFlipped, BoundablePairQueue& priQ,
+//                       double minDistance)
+// {
+//     std::vector<Boundable*> children = ((AbstractNode*) bndComposite)->getChildBoundables();
+//     for(std::vector<Boundable*>::iterator it = children.begin(); it != children.end(); ++it) {
+//         Boundable* child = *it;
+//         std::unique_ptr<BoundablePair> bp(new BoundablePair(child, bndOther, itemDistance));
+//         if(minDistance == std::numeric_limits<double>::infinity() || bp->getDistance() < minDistance) {
+//             priQ.push(bp.release());
+//         }
+//     }
+// }
+
 void
-BoundablePair::expand(const Boundable* bndComposite, const Boundable* bndOther, BoundablePairQueue& priQ,
+BoundablePair::expand(const Boundable* bndComposite, const Boundable* bndOther,
+                      bool isFlipped, BoundablePairQueue& priQ,
                       double minDistance)
 {
     std::vector<Boundable*>* children = ((AbstractNode*) bndComposite)->getChildBoundables();
     for(std::vector<Boundable*>::iterator it = children->begin(); it != children->end(); ++it) {
         Boundable* child = *it;
-        std::unique_ptr<BoundablePair> bp(new BoundablePair(child, bndOther, itemDistance));
+        std::unique_ptr<BoundablePair> bp;
+        if (isFlipped) {
+            bp.reset(new BoundablePair(bndOther, child, itemDistance));
+        }
+        else {
+            bp.reset(new BoundablePair(child, bndOther, itemDistance));
+        }
+
         if(minDistance == std::numeric_limits<double>::infinity() || bp->getDistance() < minDistance) {
             priQ.push(bp.release());
         }
diff --git a/src/operation/distance/FacetSequence.cpp b/src/operation/distance/FacetSequence.cpp
index fc15b1c..297de1f 100644
--- a/src/operation/distance/FacetSequence.cpp
+++ b/src/operation/distance/FacetSequence.cpp
@@ -23,7 +23,17 @@ using namespace geos::geom;
 using namespace geos::operation::distance;
 using namespace geos::algorithm;
 
+FacetSequence::FacetSequence(const Geometry *p_geom, const CoordinateSequence* p_pts, size_t p_start, size_t p_end) :
+    geom(p_geom),
+    pts(p_pts),
+    start(p_start),
+    end(p_end)
+{
+    computeEnvelope();
+}
+
 FacetSequence::FacetSequence(const CoordinateSequence* p_pts, size_t p_start, size_t p_end) :
+    geom(nullptr),
     pts(p_pts),
     start(p_start),
     end(p_end)
@@ -48,27 +58,68 @@ FacetSequence::distance(const FacetSequence& facetSeq) const
 {
     bool isPointThis = isPoint();
     bool isPointOther = facetSeq.isPoint();
+    double distance;
 
     if(isPointThis && isPointOther) {
         Coordinate pt = pts->getAt(start);
         Coordinate seqPt = facetSeq.pts->getAt(facetSeq.start);
-        return pt.distance(seqPt);
-
+        distance = pt.distance(seqPt);
     }
     else if(isPointThis) {
         Coordinate pt = pts->getAt(start);
-        return computePointLineDistance(pt, facetSeq);
+        distance = computeDistancePointLine(pt, facetSeq, nullptr);
     }
     else if(isPointOther) {
         Coordinate seqPt = facetSeq.pts->getAt(facetSeq.start);
-        return computePointLineDistance(seqPt, *this);
+        distance = computeDistancePointLine(seqPt, *this, nullptr);
+    }
+    else {
+        distance = computeDistanceLineLine(facetSeq, nullptr);
     }
 
-    return computeLineLineDistance(facetSeq);
+    return distance;
+}
+
+/*
+* Rather than get bent out of shape about returning a pointer
+* just return the whole mess, since it only ends up holding two
+* locations.
+*/
+std::vector<GeometryLocation>
+FacetSequence::nearestLocations(const FacetSequence& facetSeq)  const
+{
+    Coordinate pt, seqPt;
+    bool isPointThis = isPoint();
+    bool isPointOther = facetSeq.isPoint();
+    std::vector<GeometryLocation> locs;
+    if (isPointThis && isPointOther) {
+        pts->getAt(start, pt);
+        facetSeq.pts->getAt(facetSeq.start, seqPt);
+        GeometryLocation gl1(geom, start, pt);
+        GeometryLocation gl2(facetSeq.geom, facetSeq.start, seqPt);
+    }
+    else if (isPointThis) {
+        pts->getAt(start, pt);
+        computeDistancePointLine(pt, facetSeq, &locs);
+    }
+    else if (isPointOther) {
+        facetSeq.pts->getAt(facetSeq.start, seqPt);
+        computeDistancePointLine(seqPt, *this, &locs);
+        // unflip the locations
+        GeometryLocation tmp = locs[0];
+        locs[0] = locs[1];
+        locs[1] = tmp;
+    }
+    else {
+        computeDistanceLineLine(facetSeq, &locs);
+    }
+    return locs;
 }
 
 double
-FacetSequence::computePointLineDistance(const Coordinate& pt, const FacetSequence& facetSeq) const
+FacetSequence::computeDistancePointLine(const Coordinate& pt,
+                                        const FacetSequence& facetSeq,
+                                        std::vector<GeometryLocation> *locs) const
 {
     double minDistance = std::numeric_limits<double>::infinity();
     double dist;
@@ -84,14 +135,37 @@ FacetSequence::computePointLineDistance(const Coordinate& pt, const FacetSequenc
         }
         if(dist < minDistance) {
             minDistance = dist;
+            if (locs != nullptr) {
+                updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs);
+            }
+            if(minDistance <= 0.0) {
+                return minDistance;
+            }
         }
     }
 
     return minDistance;
 }
 
+void
+FacetSequence::updateNearestLocationsPointLine(const Coordinate& pt,
+        const FacetSequence& facetSeq, int i,
+        const Coordinate& q0, const Coordinate &q1,
+        std::vector<GeometryLocation> *locs) const
+{
+    geom::LineSegment seg(q0, q1);
+    Coordinate segClosestPoint;
+    seg.closestPoint(pt, segClosestPoint);
+    GeometryLocation gl0(geom, start, pt);
+    GeometryLocation gl1(facetSeq.geom, i, segClosestPoint);
+    locs->clear();
+    locs->push_back(gl0);
+    locs->push_back(gl1);
+    return;
+}
+
 double
-FacetSequence::computeLineLineDistance(const FacetSequence& facetSeq) const
+FacetSequence::computeDistanceLineLine(const FacetSequence& facetSeq, std::vector<GeometryLocation> *locs) const
 {
     double minDistance = std::numeric_limits<double>::infinity();
     double dist;
@@ -106,11 +180,12 @@ FacetSequence::computeLineLineDistance(const FacetSequence& facetSeq) const
             facetSeq.pts->getAt(j + 1, q1);
 
             dist = Distance::segmentToSegment(p0, p1, q0, q1);
-            if(dist == 0.0) {
-                return dist;
-            }
-            if(dist < minDistance) {
+            if(dist <= minDistance) {
                 minDistance = dist;
+                if(locs != nullptr) {
+                    updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs);
+                }
+                if(minDistance <= 0.0) return minDistance;
             }
         }
     }
@@ -119,6 +194,26 @@ FacetSequence::computeLineLineDistance(const FacetSequence& facetSeq) const
 }
 
 void
+FacetSequence::updateNearestLocationsLineLine(int i, const Coordinate& p0, const Coordinate& p1,
+        const FacetSequence& facetSeq,
+        int j, const Coordinate& q0, const Coordinate &q1,
+        std::vector<GeometryLocation> *locs) const
+{
+    LineSegment seg0(p0, p1);
+    LineSegment seg1(q0, q1);
+    CoordinateSequence* closestPts = seg0.closestPoints(seg1);
+    Coordinate c0, c1;
+    closestPts->getAt(0, c0);
+    closestPts->getAt(1, c1);
+    GeometryLocation gl0(geom, i, c0);
+    GeometryLocation gl1(facetSeq.geom, j, c1);
+    locs->clear();
+    locs->push_back(gl0);
+    locs->push_back(gl1);
+    return;
+}
+
+void
 FacetSequence::computeEnvelope()
 {
     env = Envelope();
diff --git a/src/operation/distance/FacetSequenceTreeBuilder.cpp b/src/operation/distance/FacetSequenceTreeBuilder.cpp
index 5ebf85f..58e632c 100644
--- a/src/operation/distance/FacetSequenceTreeBuilder.cpp
+++ b/src/operation/distance/FacetSequenceTreeBuilder.cpp
@@ -58,11 +58,11 @@ FacetSequenceTreeBuilder::computeFacetSequences(const Geometry* g)
         {
             if(const LineString* ls = dynamic_cast<const LineString*>(geom)) {
                 const CoordinateSequence* seq = ls->getCoordinatesRO();
-                addFacetSequences(seq, *m_sections);
+                addFacetSequences(geom, seq, *m_sections);
             }
             else if(const Point* pt = dynamic_cast<const Point*>(geom)) {
                 const CoordinateSequence* seq = pt->getCoordinatesRO();
-                addFacetSequences(seq, *m_sections);
+                addFacetSequences(geom, seq, *m_sections);
             }
         }
     };
@@ -74,7 +74,8 @@ FacetSequenceTreeBuilder::computeFacetSequences(const Geometry* g)
 }
 
 void
-FacetSequenceTreeBuilder::addFacetSequences(const CoordinateSequence* pts, std::vector<FacetSequence*>& sections)
+FacetSequenceTreeBuilder::addFacetSequences(const Geometry* geom, const CoordinateSequence* pts,
+        std::vector<FacetSequence*>& sections)
 {
     size_t i = 0;
     size_t size = pts->size();
@@ -86,7 +87,7 @@ FacetSequenceTreeBuilder::addFacetSequences(const CoordinateSequence* pts, std::
         if(end >= size - 1) {
             end = size;
         }
-        FacetSequence* sect = new FacetSequence(pts, i, end);
+        FacetSequence* sect = new FacetSequence(geom, pts, i, end);
         sections.push_back(sect);
         i += FACET_SEQUENCE_SIZE;
     }
diff --git a/src/operation/distance/GeometryLocation.cpp b/src/operation/distance/GeometryLocation.cpp
index 185b54e..3c343a0 100644
--- a/src/operation/distance/GeometryLocation.cpp
+++ b/src/operation/distance/GeometryLocation.cpp
@@ -17,6 +17,8 @@
  *
  **********************************************************************/
 
+#include <geos/io/WKTWriter.h>
+#include <geos/geom/Geometry.h>
 #include <geos/operation/distance/GeometryLocation.h>
 
 using namespace geos::geom;
@@ -82,6 +84,17 @@ GeometryLocation::isInsideArea()
     return inside_area;
 }
 
+std::string
+GeometryLocation::toString()
+{
+    geos::io::WKTWriter writer;
+    std::string str(component->getGeometryType());
+    str += "[" + std::to_string(segIndex) + "]";
+    str += "-";
+    str += writer.toPoint(pt);
+    return str;
+}
+
 } // namespace geos.operation.distance
 } // namespace geos.operation
 } // namespace geos
diff --git a/src/operation/distance/IndexedFacetDistance.cpp b/src/operation/distance/IndexedFacetDistance.cpp
index ca3ea38..7c4877c 100644
--- a/src/operation/distance/IndexedFacetDistance.cpp
+++ b/src/operation/distance/IndexedFacetDistance.cpp
@@ -16,9 +16,10 @@
  *
  **********************************************************************/
 
+#include <geos/geom/Coordinate.h>
+#include <geos/index/ItemVisitor.h>
 #include <geos/index/strtree/STRtree.h>
 #include <geos/operation/distance/IndexedFacetDistance.h>
-#include <geos/index/ItemVisitor.h>
 
 using namespace geos::geom;
 using namespace geos::index::strtree;
@@ -34,15 +35,24 @@ struct Deleter : public index::ItemVisitor {
     }
 } deleter;
 
+/*public static*/
 double
 IndexedFacetDistance::distance(const Geometry* g1, const Geometry* g2)
 {
     IndexedFacetDistance ifd(g1);
-    return ifd.getDistance(g2);
+    return ifd.distance(g2);
+}
+
+/*public static*/
+std::vector<geom::Coordinate>
+IndexedFacetDistance::nearestPoints(const geom::Geometry* g1, const geom::Geometry* g2)
+{
+    IndexedFacetDistance dist(g1);
+    return dist.nearestPoints(g2);
 }
 
 double
-IndexedFacetDistance::getDistance(const Geometry* g) const
+IndexedFacetDistance::distance(const Geometry* g) const
 {
     struct : public ItemDistance {
         double
@@ -58,14 +68,49 @@ IndexedFacetDistance::getDistance(const Geometry* g) const
     std::pair<const void*, const void*> obj = cachedTree->nearestNeighbour(tree2.get(),
             dynamic_cast<ItemDistance*>(&itemDistance));
 
-    double p_distance = static_cast<const FacetSequence*>(obj.first)->distance(*static_cast<const FacetSequence*>
-                        (obj.second));
+    const FacetSequence *fs1 = static_cast<const FacetSequence*>(obj.first);
+    const FacetSequence *fs2 = static_cast<const FacetSequence*>(obj.second);
+
+    double p_distance = fs1->distance(*fs2);
 
     tree2->iterate(deleter);
 
     return p_distance;
 }
 
+std::vector<GeometryLocation>
+IndexedFacetDistance::nearestLocations(const geom::Geometry* g) const
+{
+    struct : public ItemDistance {
+        double
+        distance(const ItemBoundable* item1, const ItemBoundable* item2) override
+        {
+            return static_cast<const FacetSequence*>(item1->getItem())->distance(*static_cast<const FacetSequence*>
+                    (item2->getItem()));
+        }
+    } itemDistance;
+    std::unique_ptr<STRtree> tree2(FacetSequenceTreeBuilder::build(g));
+    std::pair<const void*, const void*> obj = cachedTree->nearestNeighbour(tree2.get(),
+            dynamic_cast<ItemDistance*>(&itemDistance));
+    const FacetSequence *fs1 = static_cast<const FacetSequence*>(obj.first);
+    const FacetSequence *fs2 = static_cast<const FacetSequence*>(obj.second);
+    std::vector<GeometryLocation> locs;
+    locs = fs1->nearestLocations(*fs2);
+    tree2->iterate(deleter);
+    return locs;
+}
+
+std::vector<Coordinate>
+IndexedFacetDistance::nearestPoints(const geom::Geometry* g) const
+{
+    std::vector<GeometryLocation> minDistanceLocation = nearestLocations(g);
+    std::vector<Coordinate> nearestPts;
+    nearestPts.push_back(minDistanceLocation[0].getCoordinate());
+    nearestPts.push_back(minDistanceLocation[1].getCoordinate());
+    return nearestPts;
+}
+
+
 IndexedFacetDistance::~IndexedFacetDistance()
 {
     cachedTree->iterate(deleter);
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 3a9ceb6..e965957 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -104,11 +104,12 @@ geos_unit_SOURCES = \
 	operation/buffer/BufferOpTest.cpp \
 	operation/buffer/BufferParametersTest.cpp \
 	operation/distance/DistanceOpTest.cpp \
+	operation/distance/IndexedFacetDistanceTest.cpp \
 	operation/intersection/RectangleIntersectionTest.cpp \
 	operation/IsSimpleOpTest.cpp \
 	operation/linemerge/LineMergerTest.cpp \
 	operation/linemerge/LineSequencerTest.cpp \
-    operation/overlay/OverlayOpUnionTest.cpp \
+	operation/overlay/OverlayOpUnionTest.cpp \
 	operation/overlay/validate/FuzzyPointLocatorTest.cpp \
 	operation/overlay/validate/OffsetPointGeneratorTest.cpp \
 	operation/overlay/validate/OverlayResultValidatorTest.cpp \
diff --git a/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp b/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
new file mode 100644
index 0000000..b239c52
--- /dev/null
+++ b/tests/unit/operation/distance/IndexedFacetDistanceTest.cpp
@@ -0,0 +1,180 @@
+//
+// Test Suite for geos::operation::distance::DistanceOp class.
+
+// tut
+#include <tut/tut.hpp>
+// geos
+#include <geos/algorithm/PointLocator.h>
+#include <geos/io/WKTReader.h>
+#include <geos/io/WKBReader.h>
+#include <geos/constants.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/LineSegment.h>
+#include <geos/geom/LineString.h>
+#include <geos/geom/PrecisionModel.h>
+#include <geos/operation/distance/DistanceOp.h>
+#include <geos/operation/distance/IndexedFacetDistance.h>
+// std
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace tut {
+//
+// Test Group
+//
+
+// Common data used by tests
+struct test_facetdistanceop_data {
+    geos::io::WKTReader wktreader;
+
+    typedef std::unique_ptr<geos::geom::Geometry> GeomPtr;
+    typedef std::unique_ptr<geos::geom::CoordinateSequence> CSPtr;
+
+    test_facetdistanceop_data()
+        : wktreader()
+    {}
+
+    void
+    checkDistanceNearestPoints(std::string wkt1, std::string wkt2, double distance,
+                               geos::geom::Coordinate& p1, geos::geom::Coordinate& p2)
+    {
+        using geos::operation::distance::IndexedFacetDistance;
+        GeomPtr g1(wktreader.read(wkt1));
+        GeomPtr g2(wktreader.read(wkt2));
+        std::vector<geos::geom::Coordinate> pts;
+        pts = IndexedFacetDistance::nearestPoints(g1.get(), g2.get());
+        ensure(fabs(pts[0].distance(pts[1])-distance) < 1e08);
+        ensure(fabs(pts[0].x - p1.x) < 1e08);
+        ensure(fabs(pts[0].y - p1.y) < 1e08);
+        ensure(fabs(pts[1].x - p2.x) < 1e08);
+        ensure(fabs(pts[1].y - p2.y) < 1e08);
+        return;
+    }
+
+};
+
+typedef test_group<test_facetdistanceop_data> group;
+typedef group::object object;
+
+group test_facetdistanceop_group("geos::operation::distance::IndexedFacetDistance");
+
+
+
+//
+// Test Cases
+//
+template<>
+template<>
+void object::test<1>
+()
+{
+    using geos::operation::distance::IndexedFacetDistance;
+    using geos::geom::Coordinate;
+
+    std::string wkt0("POINT(0 0)");
+    std::string wkt1("POINT(10 0)");
+    GeomPtr g0(wktreader.read(wkt0));
+    GeomPtr g1(wktreader.read(wkt1));
+    double d = IndexedFacetDistance::distance(g0.get(), g1.get());
+    ensure_equals(d, 10);
+}
+
+template<>
+template<>
+void object::test<2>
+()
+{
+    using geos::operation::distance::DistanceOp;
+    using geos::geom::Coordinate;
+
+    std::string wkt0("POLYGON ((200 180, 60 140, 60 260, 200 180))");
+    std::string wkt1("POINT (140 280)");
+    double dist = 57.05597791103589;
+    Coordinate p1(111.6923076923077, 230.46153846153845);
+    Coordinate p2(140, 280);
+
+    checkDistanceNearestPoints(wkt0, wkt1, dist, p1, p2);
+}
+
+template<>
+template<>
+void object::test<3>
+()
+{
+    using geos::operation::distance::DistanceOp;
+    using geos::geom::Coordinate;
+
+    std::string wkt0("POLYGON ((200 180, 60 140, 60 260, 200 180))");
+    std::string wkt1("MULTIPOINT ((140 280), (140 320))");
+    double dist = 57.05597791103589;
+    Coordinate p1(111.6923076923077, 230.46153846153845);
+    Coordinate p2(140, 280);
+
+    checkDistanceNearestPoints(wkt0, wkt1, dist, p1, p2);
+}
+
+template<>
+template<>
+void object::test<4>
+()
+{
+    using geos::operation::distance::DistanceOp;
+    using geos::geom::Coordinate;
+
+    std::string wkt0("LINESTRING (100 100, 200 100, 200 200, 100 200, 100 100)");
+    std::string wkt1("POINT (10 10)");
+    double dist = 127.27922061357856;
+    Coordinate p1(100, 100);
+    Coordinate p2(10, 10);
+
+    checkDistanceNearestPoints(wkt0, wkt1, dist, p1, p2);
+}
+
+template<>
+template<>
+void object::test<5>
+()
+{
+    using geos::operation::distance::DistanceOp;
+    using geos::geom::Coordinate;
+
+    std::string wkt0("POLYGON ((76 185, 125 283, 331 276, 324 122, 177 70, 184 155, 69 123, 76 185), (267 237, 148 248, 135 185, 223 189, 251 151, 286 183, 267 237))");
+    std::string wkt1("LINESTRING (153 204, 185 224, 209 207, 238 222, 254 186)");
+    double dist = 13.788860460124573;
+    Coordinate p1(139.4956500724988, 206.78661188980183);
+    Coordinate p2(153, 204);
+
+    checkDistanceNearestPoints(wkt0, wkt1, dist, p1, p2);
+}
+
+template<>
+template<>
+void object::test<6>
+()
+{
+    using geos::operation::distance::DistanceOp;
+    using geos::geom::Coordinate;
+
+    std::string wkt0("POLYGON ((76 185, 125 283, 331 276, 324 122, 177 70, 184 155, 69 123, 76 185), (267 237, 148 248, 135 185, 223 189, 251 151, 286 183, 267 237))");
+    std::string wkt1("LINESTRING (120 215, 185 224, 209 207, 238 222, 254 186)");
+    double dist = 0.0;
+    Coordinate p1(120, 215);
+    Coordinate p2(120, 215);
+
+    checkDistanceNearestPoints(wkt0, wkt1, dist, p1, p2);
+}
+
+// TODO: finish the tests by adding:
+// 	LINESTRING - *all*
+// 	MULTILINESTRING - *all*
+// 	POLYGON - *all*
+// 	MULTIPOLYGON - *all*
+// 	COLLECTION - *all*
+
+} // namespace tut
+

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

Summary of changes:
 include/geos/index/strtree/BoundablePair.h         |   3 +-
 include/geos/operation/distance/FacetSequence.h    |  34 +++-
 .../operation/distance/FacetSequenceTreeBuilder.h  |   4 +-
 include/geos/operation/distance/GeometryLocation.h |   2 +
 .../geos/operation/distance/IndexedFacetDistance.h |   7 +-
 src/index/strtree/BoundablePair.cpp                |  41 +++--
 src/operation/distance/FacetSequence.cpp           | 117 ++++++++++++--
 .../distance/FacetSequenceTreeBuilder.cpp          |   9 +-
 src/operation/distance/GeometryLocation.cpp        |  13 ++
 src/operation/distance/IndexedFacetDistance.cpp    |  55 ++++++-
 tests/unit/Makefile.am                             |   3 +-
 .../distance/IndexedFacetDistanceTest.cpp          | 180 +++++++++++++++++++++
 12 files changed, 429 insertions(+), 39 deletions(-)
 create mode 100644 tests/unit/operation/distance/IndexedFacetDistanceTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list