[geos-commits] r3321 - in trunk: . include/geos/operation/predicate
src/operation/predicate
svn_geos at osgeo.org
svn_geos at osgeo.org
Thu Apr 28 12:39:02 EDT 2011
Author: strk
Date: 2011-04-28 09:39:02 -0700 (Thu, 28 Apr 2011)
New Revision: 3321
Modified:
trunk/.gitignore
trunk/NEWS
trunk/include/geos/operation/predicate/RectangleIntersects.h
trunk/include/geos/operation/predicate/SegmentIntersectionTester.h
trunk/src/operation/predicate/RectangleIntersects.cpp
trunk/src/operation/predicate/SegmentIntersectionTester.cpp
Log:
Improve performance of RectangleIntersects (of one order of magnitude).
Modified: trunk/.gitignore
===================================================================
--- trunk/.gitignore 2011-04-28 16:38:43 UTC (rev 3320)
+++ trunk/.gitignore 2011-04-28 16:39:02 UTC (rev 3321)
@@ -22,6 +22,7 @@
tests/bigtest/bug234
tests/geostest/geostest
tests/perf/operation/buffer/IteratedBufferStressTest
+tests/perf/operation/predicate/RectangleIntersectsPerfTest
include/geos/platform.h
include/geos/stamp-h2
include/geos/version.h
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2011-04-28 16:38:43 UTC (rev 3320)
+++ trunk/NEWS 2011-04-28 16:39:02 UTC (rev 3321)
@@ -31,7 +31,7 @@
ownership of vector elements
- Empty LinearRings are closed by definition
- Fixed Geometry.distance() and DistanceOp to return 0.0 for empty inputs
-- Bug fixes:
+- Bug fixes / improvements
- Invalid compound geometries reported as valid (#333)
- Return up to 15 digits of precision from GEOSisValidReason_t (#329)
- CAPI: do not leak contexts when using the non-reentrant interface
@@ -42,6 +42,8 @@
(via safeOctant)
- Fixed buffer OffsetCurveSetBuilder to handle "flat" rings correctly
- Added illegal state check in LineSegment::pointAlongOffset()
+ - Improved performance of RectangleIntersects by always using
+ segment-scanning and refining SegmentIntersectionTester
Changes in 3.2.0
2009-12-14
Modified: trunk/include/geos/operation/predicate/RectangleIntersects.h
===================================================================
--- trunk/include/geos/operation/predicate/RectangleIntersects.h 2011-04-28 16:38:43 UTC (rev 3320)
+++ trunk/include/geos/operation/predicate/RectangleIntersects.h 2011-04-28 16:39:02 UTC (rev 3321)
@@ -1,9 +1,9 @@
/**********************************************************************
- * $Id$
*
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2006 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
@@ -13,7 +13,7 @@
*
**********************************************************************
*
- * Last port: operation/predicate/RectangleIntersects.java rev 1.4 (JTS-1.10)
+ * Last port: operation/predicate/RectangleIntersects.java r378 (JTS-1.12)
*
**********************************************************************/
@@ -37,12 +37,16 @@
namespace predicate { // geos::operation::predicate
/** \brief
- * Optimized implementation of spatial predicate "intersects"
- * for cases where the first Geometry is a rectangle.
+ * Optimized implementation of the "intersects" spatial predicate
+ * for cases where one Geometry is a rectangle.
+ *
+ * This class works for all input geometries, including
+ * {@link GeometryCollection}s.
*
* As a further optimization,
- * this class can be used directly to test many geometries against a single
- * rectangle.
+ * this class can be used to test
+ * many geometries against a single
+ * rectangle in a slightly more efficient way.
*
*/
class GEOS_DLL RectangleIntersects {
@@ -60,15 +64,6 @@
public:
/** \brief
- * Crossover size at which brute-force intersection scanning
- * is slower than indexed intersection detection.
- *
- * Must be determined empirically. Should err on the
- * safe side by making value smaller rather than larger.
- */
- static const std::size_t MAXIMUM_SCAN_SEGMENT_COUNT;
-
- /** \brief
* Create a new intersects computer for a rectangle.
*
* @param newRect a rectangular geometry
@@ -81,6 +76,13 @@
bool intersects(const geom::Geometry& geom);
+ /** \brief
+ * Tests whether a rectangle intersects a given geometry.
+ *
+ * @param rectangle a rectangular Polygon
+ * @param b a Geometry of any type
+ * @return true if the geometries intersect
+ */
static bool intersects(const geom::Polygon &rectangle,
const geom::Geometry &b)
{
Modified: trunk/include/geos/operation/predicate/SegmentIntersectionTester.h
===================================================================
--- trunk/include/geos/operation/predicate/SegmentIntersectionTester.h 2011-04-28 16:38:43 UTC (rev 3320)
+++ trunk/include/geos/operation/predicate/SegmentIntersectionTester.h 2011-04-28 16:39:02 UTC (rev 3321)
@@ -1,9 +1,9 @@
/**********************************************************************
- * $Id$
*
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2006 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
@@ -13,7 +13,7 @@
*
**********************************************************************
*
- * Last port: operation/predicate/SegmentIntersectionTester.java rev. 1.3 (JTS-1.10)
+ * Last port: operation/predicate/SegmentIntersectionTester.java r378 (JTS-1.12)
*
**********************************************************************/
@@ -23,6 +23,7 @@
#include <geos/export.h>
#include <geos/algorithm/LineIntersector.h> // for composition
+#include <geos/geom/Coordinate.h> // for composition
// Forward declarations
namespace geos {
@@ -38,9 +39,10 @@
/** \brief
* Tests if any line segments in two sets of CoordinateSequences intersect.
- * Optimized for use when at least one input is of small size.
*
- * Short-circuited to return as soon an intersection is found.
+ * The algorithm is optimized for use when the first input has smaller extent
+ * than the set of test lines.
+ * The code is short-circuited to return as soon an intersection is found.
*
*/
class GEOS_DLL SegmentIntersectionTester {
@@ -55,17 +57,40 @@
bool hasIntersectionVar;
+ geom::Coordinate pt10;
+ geom::Coordinate pt11;
+ geom::Coordinate pt00;
+ geom::Coordinate pt01;
+
+
public:
SegmentIntersectionTester(): hasIntersectionVar(false) {}
- bool hasIntersectionWithLineStrings(const geom::CoordinateSequence &seq,
+ bool hasIntersectionWithLineStrings(const geom::LineString &line,
const std::vector<const geom::LineString *>& lines);
- bool hasIntersection(const geom::CoordinateSequence &seq0,
- const geom::CoordinateSequence &seq1);
+ bool hasIntersection(const geom::LineString &line,
+ const geom::LineString &testLine);
+ /**
+ * Tests the segments of a LineString against the segs in
+ * another LineString for intersection.
+ * Uses the envelope of the query LineString
+ * to filter before testing segments directly.
+ * This is optimized for the case when the query
+ * LineString is a rectangle.
+ *
+ * Testing shows this is somewhat faster than not checking the envelope.
+ *
+ * @param line
+ * @param testLine
+ * @return
+ */
+ bool hasIntersectionWithEnvelopeFilter(const geom::LineString &line,
+ const geom::LineString &testLine);
+
};
} // namespace geos::operation::predicate
Modified: trunk/src/operation/predicate/RectangleIntersects.cpp
===================================================================
--- trunk/src/operation/predicate/RectangleIntersects.cpp 2011-04-28 16:38:43 UTC (rev 3320)
+++ trunk/src/operation/predicate/RectangleIntersects.cpp 2011-04-28 16:39:02 UTC (rev 3321)
@@ -1,9 +1,9 @@
/**********************************************************************
- * $Id$
*
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2006 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
@@ -13,7 +13,7 @@
*
**********************************************************************
*
- * Last port: operation/predicate/RectangleIntersects.java rev 1.4 (JTS-1.10)
+ * Last port: operation/predicate/RectangleIntersects.java r378 (JTS-1.12)
*
**********************************************************************/
@@ -39,9 +39,6 @@
namespace operation { // geos.operation
namespace predicate { // geos.operation.predicate
-const size_t RectangleIntersects::MAXIMUM_SCAN_SEGMENT_COUNT = 200;
-
-
//----------------------------------------------------------------
// EnvelopeIntersectsVisitor
//----------------------------------------------------------------
@@ -70,10 +67,8 @@
{
const geom::Envelope &elementEnv = *(element.getEnvelopeInternal());
- // disjoint
- if ( ! rectEnv.intersects(elementEnv) ) {
- return;
- }
+ // skip if envelopes do not intersect
+ if ( ! rectEnv.intersects(elementEnv) ) return;
// fully contained - must intersect
if ( rectEnv.contains(elementEnv) ) {
@@ -148,6 +143,7 @@
const geom::Polygon *poly;
+ // if test geometry is not polygonal this check is not needed
if ( 0 == (poly=dynamic_cast<const geom::Polygon *>(&geom)) ) {
return;
}
@@ -201,10 +197,11 @@
{
private:
- const geom::Polygon& rectangle;
+ //const geom::Polygon& rectangle;
const geom::Envelope& rectEnv;
+ const geom::LineString& rectLine;
bool intersectsVar;
- const geom::CoordinateSequence &rectSeq;
+ //const geom::CoordinateSequence &rectSeq;
void computeSegmentIntersection(const geom::Geometry &geom)
{
@@ -215,7 +212,7 @@
geom::LineString::ConstVect lines;
LinearComponentExtracter::getLines(geom, lines);
SegmentIntersectionTester si;
- if ( si.hasIntersectionWithLineStrings(rectSeq, lines) )
+ if ( si.hasIntersectionWithLineStrings(rectLine, lines) )
{
intersectsVar = true;
return;
@@ -231,20 +228,10 @@
void visit(const geom::Geometry &geom)
{
const geom::Envelope &elementEnv = *(geom.getEnvelopeInternal());
- if (! rectEnv.intersects(elementEnv) ) {
- return;
- }
- // check if general relate algorithm should be used,
- // since it's faster for large inputs
- if (geom.getNumPoints() > RectangleIntersects::MAXIMUM_SCAN_SEGMENT_COUNT)
- {
- std::auto_ptr<geom::IntersectionMatrix> im ( rectangle.relate(geom) );
- intersectsVar = im->isIntersects();
- return;
- }
+ // check for envelope intersection
+ if (! rectEnv.intersects(elementEnv) ) return;
- // if small enough, test for segment intersection directly
computeSegmentIntersection(geom);
}
@@ -254,10 +241,11 @@
LineIntersectsVisitor(const geom::Polygon &rect)
:
- rectangle(rect),
+ //rectangle(rect),
rectEnv(*(rect.getEnvelopeInternal())),
- intersectsVar(false),
- rectSeq(*(rect.getExteriorRing()->getCoordinatesRO()))
+ rectLine(*(rect.getExteriorRing())),
+ intersectsVar(false)
+ //rectSeq(*(rect.getExteriorRing()->getCoordinatesRO()))
{}
/**
@@ -266,7 +254,7 @@
* @return <code>true</code> if a segment intersection exists
* <code>false</code> if no segment intersection exists
*/
- bool intersects() { return intersectsVar; }
+ bool intersects() const { return intersectsVar; }
};
Modified: trunk/src/operation/predicate/SegmentIntersectionTester.cpp
===================================================================
--- trunk/src/operation/predicate/SegmentIntersectionTester.cpp 2011-04-28 16:38:43 UTC (rev 3320)
+++ trunk/src/operation/predicate/SegmentIntersectionTester.cpp 2011-04-28 16:39:02 UTC (rev 3321)
@@ -1,9 +1,9 @@
/**********************************************************************
- * $Id$
*
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2006 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
@@ -13,7 +13,7 @@
*
**********************************************************************
*
- * Last port: operation/predicate/SegmentIntersectionTester.java rev. 1.3 (JTS-1.10)
+ * Last port: operation/predicate/SegmentIntersectionTester.java r378 (JTS-1.12)
*
**********************************************************************/
@@ -30,13 +30,14 @@
bool
SegmentIntersectionTester::hasIntersectionWithLineStrings(
- const CoordinateSequence &seq,
+ const LineString &line,
const LineString::ConstVect& lines)
{
+ hasIntersectionVar = false;
for (size_t i=0, n=lines.size(); i<n; ++i )
{
- const LineString *line = lines[i];
- hasIntersection(seq, *(line->getCoordinatesRO()));
+ const LineString *testLine = lines[i];
+ hasIntersection(line, *testLine);
if (hasIntersectionVar) break;
}
return hasIntersectionVar;
@@ -44,30 +45,68 @@
bool
SegmentIntersectionTester::hasIntersection(
- const CoordinateSequence &seq0, const CoordinateSequence &seq1)
+ const LineString &line, const LineString &testLine)
{
+ typedef std::size_t size_type;
- for (std::size_t i = 1, ni = seq0.getSize(); i < ni; ++i)
+ const CoordinateSequence &seq0 = *(line.getCoordinatesRO());
+ size_type seq0size = seq0.getSize();
+
+ const CoordinateSequence &seq1 = *(testLine.getCoordinatesRO());
+ size_type seq1size = seq1.getSize();
+
+ for (size_type i = 1; i<seq0size && !hasIntersectionVar; ++i)
{
- const Coordinate& pt00 = seq0.getAt(i - 1);
- const Coordinate& pt01 = seq0.getAt(i);
+ seq0.getAt(i - 1, pt00);
+ seq0.getAt(i, pt01);
+
+ for (size_type j = 1; j < seq1size && !hasIntersectionVar; ++j)
+ {
+ seq1.getAt(j-1, pt10);
+ seq1.getAt(j, pt11);
- for (std::size_t j = 1, nj = seq1.getSize(); j < nj; ++j)
+ li.computeIntersection(pt00, pt01, pt10, pt11);
+ if (li.hasIntersection()) hasIntersectionVar = true;
+ }
+ }
+
+ return hasIntersectionVar;
+}
+
+bool
+SegmentIntersectionTester::hasIntersectionWithEnvelopeFilter(
+ const LineString &line, const LineString &testLine)
+{
+ typedef std::size_t size_type;
+
+ const CoordinateSequence &seq0 = *(line.getCoordinatesRO());
+ size_type seq0size = seq0.getSize();
+
+ const CoordinateSequence &seq1 = *(testLine.getCoordinatesRO());
+ size_type seq1size = seq1.getSize();
+
+ const Envelope* lineEnv = line.getEnvelopeInternal();
+
+ typedef std::size_t size_type;
+
+ for (size_type i = 1; i<seq1size && !hasIntersectionVar; ++i)
+ {
+ seq1.getAt(i-1, pt10);
+ seq1.getAt(i, pt11);
+
+ // skip test if segment does not intersect query envelope
+ if (! lineEnv->intersects(Envelope(pt10, pt11))) continue;
+
+ for (size_type j = 1; j < seq0size && !hasIntersectionVar; ++j)
{
- const Coordinate& pt10 = seq1.getAt(j-1);
- const Coordinate& pt11 = seq1.getAt(j);
-
- li.algorithm::LineIntersector::computeIntersection(pt00, pt01, pt10, pt11);
- if (li.hasIntersection())
- {
- hasIntersectionVar = true;
- goto out_of_loop;
- }
+ seq0.getAt(j - 1, pt00);
+ seq0.getAt(j, pt01);
+
+ li.computeIntersection(pt00, pt01, pt10, pt11);
+ if (li.hasIntersection()) hasIntersectionVar = true;
}
}
- out_of_loop:
-
return hasIntersectionVar;
}
More information about the geos-commits
mailing list