[geos-commits] r4017 - in trunk: . include/geos/geomgraph include/geos/operation/overlay src/geomgraph src/operation/overlay
svn_geos at osgeo.org
svn_geos at osgeo.org
Tue Sep 23 00:55:54 PDT 2014
Author: strk
Date: 2014-09-23 00:55:54 -0700 (Tue, 23 Sep 2014)
New Revision: 4017
Modified:
trunk/NEWS
trunk/include/geos/geomgraph/GeometryGraph.h
trunk/include/geos/geomgraph/GeometryGraph.inl
trunk/include/geos/operation/overlay/OverlayOp.h
trunk/src/geomgraph/GeometryGraph.cpp
trunk/src/operation/overlay/OverlayOp.cpp
Log:
OverlayOp: restrict intersection computations to the target extent
Speeds up INTERSECTION and DIFFERENCE operations between geometries
with small bounding box overlap.
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2014-09-22 14:13:11 UTC (rev 4016)
+++ trunk/NEWS 2014-09-23 07:55:54 UTC (rev 4017)
@@ -7,6 +7,9 @@
- GEOS_USE_ONLY_R_API macro support (#695)
- PHP: WKBReader->read() & WKBWriter::write() methods (Benjamin Morel)
...
+- Improvements:
+ - Speed-up intersection and difference between geometries
+ with small bounding box overlap.
Changes in 3.4.2
2013-08-25
Modified: trunk/include/geos/geomgraph/GeometryGraph.h
===================================================================
--- trunk/include/geos/geomgraph/GeometryGraph.h 2014-09-22 14:13:11 UTC (rev 4016)
+++ trunk/include/geos/geomgraph/GeometryGraph.h 2014-09-23 07:55:54 UTC (rev 4017)
@@ -48,6 +48,7 @@
class Geometry;
class GeometryCollection;
class Point;
+ class Envelope;
}
namespace algorithm {
class LineIntersector;
@@ -212,16 +213,21 @@
*/
index::SegmentIntersector* computeSelfNodes(
algorithm::LineIntersector *li,
- bool computeRingSelfNodes);
+ bool computeRingSelfNodes,
+ const geom::Envelope *env=0)
+ {
+ return computeSelfNodes(*li, computeRingSelfNodes, env);
+ }
// Quick inline calling the function above, the above should probably
// be deprecated.
index::SegmentIntersector* computeSelfNodes(
algorithm::LineIntersector& li,
- bool computeRingSelfNodes);
+ bool computeRingSelfNodes, const geom::Envelope *env=0);
index::SegmentIntersector* computeEdgeIntersections(GeometryGraph *g,
- algorithm::LineIntersector *li, bool includeProper);
+ algorithm::LineIntersector *li, bool includeProper,
+ const geom::Envelope *env=0);
std::vector<Edge*> *getEdges();
Modified: trunk/include/geos/geomgraph/GeometryGraph.inl
===================================================================
--- trunk/include/geos/geomgraph/GeometryGraph.inl 2014-09-22 14:13:11 UTC (rev 4016)
+++ trunk/include/geos/geomgraph/GeometryGraph.inl 2014-09-23 07:55:54 UTC (rev 4017)
@@ -26,14 +26,6 @@
namespace geos {
namespace geomgraph { // geos::geomgraph
-INLINE index::SegmentIntersector*
-GeometryGraph::computeSelfNodes(
- algorithm::LineIntersector& li,
- bool computeRingSelfNodes)
-{
- return computeSelfNodes(&li, computeRingSelfNodes);
-}
-
INLINE void
GeometryGraph::getBoundaryNodes(std::vector<Node*>&bdyNodes)
{
Modified: trunk/include/geos/operation/overlay/OverlayOp.h
===================================================================
--- trunk/include/geos/operation/overlay/OverlayOp.h 2014-09-22 14:13:11 UTC (rev 4016)
+++ trunk/include/geos/operation/overlay/OverlayOp.h 2014-09-23 07:55:54 UTC (rev 4017)
@@ -38,6 +38,7 @@
namespace geom {
class Geometry;
class Coordinate;
+ class Envelope;
class GeometryFactory;
class Polygon;
class LineString;
@@ -240,7 +241,7 @@
* but in the original arg Geometry it is actually
* in the interior due to the Boundary Determination Rule)
*/
- void copyPoints(int argIndex);
+ void copyPoints(int argIndex, const geom::Envelope *env=0);
/** \brief
* Compute initial labelling for all DirectedEdges at each node.
Modified: trunk/src/geomgraph/GeometryGraph.cpp
===================================================================
--- trunk/src/geomgraph/GeometryGraph.cpp 2014-09-22 14:13:11 UTC (rev 4016)
+++ trunk/src/geomgraph/GeometryGraph.cpp 2014-09-23 07:55:54 UTC (rev 4017)
@@ -37,6 +37,7 @@
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/Location.h>
#include <geos/geom/Point.h>
+#include <geos/geom/Envelope.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/LineString.h>
#include <geos/geom/Polygon.h>
@@ -165,6 +166,9 @@
#endif
e->eiList.addSplitEdges(edgelist);
}
+#if GEOS_DEBUG
+ cerr<<"["<<this<<"] GeometryGraph::computeSplitEdges() completed "<<endl;
+#endif
}
void
@@ -343,24 +347,44 @@
insertPoint(argIndex,pt,Location::INTERIOR);
}
+template <class T, class C>
+void collect_intersecting_edges(const Envelope *env, T start, T end, C &to)
+{
+ for (T i=start; i != end; ++i)
+ {
+ Edge *e = *i;
+ if ( e->getEnvelope()->intersects(env) ) to.push_back(e);
+ }
+}
+
/*public*/
SegmentIntersector*
-GeometryGraph::computeSelfNodes(LineIntersector *li, bool computeRingSelfNodes)
+GeometryGraph::computeSelfNodes(LineIntersector &li,
+ bool computeRingSelfNodes, const Envelope *env)
{
- SegmentIntersector *si=new SegmentIntersector(li,true,false);
+ SegmentIntersector *si=new SegmentIntersector(&li,true,false);
auto_ptr<EdgeSetIntersector> esi(createEdgeSetIntersector());
+ typedef vector<Edge*> EC;
+ EC *se = edges;
+ EC self_edges_copy;
+ if ( env ) { // TODO: ... and env does not cover self geom env
+ collect_intersecting_edges(env, se->begin(), se->end(), self_edges_copy);
+ cerr << "(computeSelfNodes) Self edges reduced from " << se->size() << " to " << self_edges_copy.size() << endl;
+ se = &self_edges_copy;
+ }
+
// optimized test for Polygons and Rings
if (! computeRingSelfNodes
&& ( dynamic_cast<const LinearRing*>(parentGeom)
|| dynamic_cast<const Polygon*>(parentGeom)
|| dynamic_cast<const MultiPolygon*>(parentGeom) ))
{
- esi->computeIntersections(edges, si, false);
+ esi->computeIntersections(se, si, false);
}
else
{
- esi->computeIntersections(edges, si, true);
+ esi->computeIntersections(se, si, true);
}
#if GEOS_DEBUG
@@ -373,7 +397,7 @@
SegmentIntersector*
GeometryGraph::computeEdgeIntersections(GeometryGraph *g,
- LineIntersector *li, bool includeProper)
+ LineIntersector *li, bool includeProper, const Envelope *env)
{
#if GEOS_DEBUG
cerr<<"GeometryGraph::computeEdgeIntersections call"<<endl;
@@ -382,7 +406,25 @@
si->setBoundaryNodes(getBoundaryNodes(), g->getBoundaryNodes());
auto_ptr<EdgeSetIntersector> esi(createEdgeSetIntersector());
- esi->computeIntersections(edges, g->edges, si);
+
+ typedef vector<Edge*> EC;
+
+ EC self_edges_copy;
+ EC other_edges_copy;
+
+ EC *se = edges;
+ EC *oe = g->edges;
+ if ( env ) { // TODO: ... and env does not cover self geom env
+ collect_intersecting_edges(env, se->begin(), se->end(), self_edges_copy);
+ cerr << "Self edges reduced from " << se->size() << " to " << self_edges_copy.size() << endl;
+ se = &self_edges_copy;
+ }
+ if ( env ) { // TODO: ... and env does not cover other geom env
+ collect_intersecting_edges(env, oe->begin(), oe->end(), other_edges_copy);
+ cerr << "Other edges reduced from " << oe->size() << " to " << other_edges_copy.size() << endl;
+ oe = &other_edges_copy;
+ }
+ esi->computeIntersections(se, oe, si);
#if GEOS_DEBUG
cerr<<"GeometryGraph::computeEdgeIntersections returns"<<endl;
#endif
Modified: trunk/src/operation/overlay/OverlayOp.cpp
===================================================================
--- trunk/src/operation/overlay/OverlayOp.cpp 2014-09-22 14:13:11 UTC (rev 4016)
+++ trunk/src/operation/overlay/OverlayOp.cpp 2014-09-23 07:55:54 UTC (rev 4017)
@@ -232,20 +232,40 @@
/*private*/
void
-OverlayOp::copyPoints(int argIndex)
+OverlayOp::copyPoints(int argIndex, const Envelope *env)
{
+#define GEOS_DEBUG_COPY_POINTS 1
+
+#ifdef GEOS_DEBUG_COPY_POINTS
+ int copied = 0;
+#endif
+
+ //env = 0; // WARNING: uncomment to disable env-optimization
+
+ // TODO: set env to null if it covers arg geometry envelope
+
NodeMap::container& nodeMap=arg[argIndex]->getNodeMap()->nodeMap;
for ( NodeMap::const_iterator it=nodeMap.begin(), itEnd=nodeMap.end();
it != itEnd; ++it )
{
Node* graphNode=it->second;
assert(graphNode);
+ const Coordinate &coord = graphNode->getCoordinate();
- Node* newNode=graph.addNode(graphNode->getCoordinate());
+ if ( env && ! env->covers(coord) ) continue;
+
+#ifdef GEOS_DEBUG_COPY_POINTS
+ ++copied;
+#endif
+ Node* newNode=graph.addNode(coord);
assert(newNode);
newNode->setLabel(argIndex, graphNode->getLabel().getLocation(argIndex));
}
+
+#ifdef GEOS_DEBUG_COPY_POINTS
+ cerr << "Copied " << copied << " nodes out of " << nodeMap.size() << " for geom " << argIndex << endl;
+#endif
}
/*private*/
@@ -648,17 +668,41 @@
//throw(TopologyException *)
{
+ // Compute the target envelope
+ const Envelope *env = 0;
+ const Envelope *env0 = getArgGeometry(0)->getEnvelopeInternal();
+ const Envelope *env1 = getArgGeometry(1)->getEnvelopeInternal();
+ Envelope opEnv;
+ if ( resultPrecisionModel->isFloating() )
+ {
+ // Envelope-based optimization only works in floating precision
+ switch (opCode) {
+ case opINTERSECTION:
+ env0->intersection(*env1, opEnv);
+ env = &opEnv;
+ break;
+ case opDIFFERENCE:
+ opEnv = *env0;
+ env = &opEnv;
+ break;
+ default:
+ break;
+ }
+ }
+ //env = 0; // WARNING: uncomment to disable env-optimization
+
// copy points from input Geometries.
// This ensures that any Point geometries
// in the input are considered for inclusion in the result set
- copyPoints(0);
- copyPoints(1);
+ copyPoints(0, env);
+ copyPoints(1, env);
GEOS_CHECK_FOR_INTERRUPTS();
// node the input Geometries
- delete arg[0]->computeSelfNodes(li,false);
- delete arg[1]->computeSelfNodes(li,false);
+ delete arg[0]->computeSelfNodes(li, false, env);
+ GEOS_CHECK_FOR_INTERRUPTS();
+ delete arg[1]->computeSelfNodes(li, false, env);
#if GEOS_DEBUG
cerr<<"OverlayOp::computeOverlay: computed SelfNodes"<<endl;
@@ -667,7 +711,7 @@
GEOS_CHECK_FOR_INTERRUPTS();
// compute intersections between edges of the two input geometries
- delete arg[0]->computeEdgeIntersections(arg[1], &li,true);
+ delete arg[0]->computeEdgeIntersections(arg[1], &li, true, env);
#if GEOS_DEBUG
cerr<<"OverlayOp::computeOverlay: computed EdgeIntersections"<<endl;
@@ -679,6 +723,7 @@
vector<Edge*> baseSplitEdges;
arg[0]->computeSplitEdges(&baseSplitEdges);
+ GEOS_CHECK_FOR_INTERRUPTS();
arg[1]->computeSplitEdges(&baseSplitEdges);
GEOS_CHECK_FOR_INTERRUPTS();
More information about the geos-commits
mailing list