📄 rectangleintersects.cpp
字号:
/********************************************************************** * $Id: RectangleIntersects.cpp 1820 2006-09-06 16:54:23Z mloskot $ * * GEOS - Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2006 Refractions Research Inc. * * 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/predicate/RectangleIntersects.java rev 1.3 (JTS-1.7) * **********************************************************************/#include <geos/operation/predicate/RectangleIntersects.h>#include <geos/operation/predicate/SegmentIntersectionTester.h>/// for EnvelopeIntersectsVisitor inheritance#include <geos/geom/util/ShortCircuitedGeometryVisitor.h>#include <geos/geom/util/LinearComponentExtracter.h>#include <geos/geom/Envelope.h>#include <geos/geom/CoordinateSequence.h>#include <geos/geom/LineString.h>#include <geos/geom/IntersectionMatrix.h>#include <geos/algorithm/SimplePointInAreaLocator.h>//using namespace geos::geom::util;namespace geos {namespace operation { // geos.operationnamespace predicate { // geos.operation.predicateconst size_t RectangleIntersects::MAXIMUM_SCAN_SEGMENT_COUNT = 200;//----------------------------------------------------------------// EnvelopeIntersectsVisitor//----------------------------------------------------------------class EnvelopeIntersectsVisitor: public geom::util::ShortCircuitedGeometryVisitor{private: const geom::Envelope &rectEnv; bool intersectsVar;protected: /** * Reports whether it can be concluded that an intersection occurs, * or whether further testing is required. * * @return <code>true</code> if an intersection must occur * <code>false</code> if no conclusion can be made */ void visit(const geom::Geometry &element) { const geom::Envelope &elementEnv = *(element.getEnvelopeInternal()); // disjoint if ( ! rectEnv.intersects(elementEnv) ) { return; } // fully contained - must intersect if ( rectEnv.contains(elementEnv) ) { intersectsVar = true; return; } /* * Since the envelopes intersect and the test element is * connected, if the test envelope is completely bisected by * an edge of the rectangle the element and the rectangle * must touch (This is basically an application of the * Jordan Curve Theorem). The alternative situation * is that the test envelope is "on a corner" of the * rectangle envelope, i.e. is not completely bisected. * In this case it is not possible to make a conclusion * about the presence of an intersection. */ if (elementEnv.getMinX() >= rectEnv.getMinX() && elementEnv.getMaxX() <= rectEnv.getMaxX()) { intersectsVar=true; return; } if (elementEnv.getMinY() >= rectEnv.getMinY() && elementEnv.getMaxY() <= rectEnv.getMaxY()) { intersectsVar = true; return; } } bool isDone() { return intersectsVar==true; }public: EnvelopeIntersectsVisitor(const geom::Envelope &env) : rectEnv(env), intersectsVar(false) {} bool intersects() { return intersectsVar; }};//----------------------------------------------------------------// ContainsPointVisitor//----------------------------------------------------------------/** * Tests whether it can be concluded * that a geometry contains a corner point of a rectangle. */class ContainsPointVisitor: public geom::util::ShortCircuitedGeometryVisitor{private: const geom::Envelope &rectEnv; bool containsPointVar; const geom::CoordinateSequence &rectSeq;protected: void visit(const geom::Geometry &geom) { using geos::algorithm::SimplePointInAreaLocator; const geom::Polygon *poly; if ( !(poly=dynamic_cast<const geom::Polygon *>(&geom)) ) { return; } const geom::Envelope &elementEnv = *(geom.getEnvelopeInternal()); if ( !rectEnv.intersects(elementEnv) ) { return; } // test each corner of rectangle for inclusion for (int i=0; i<4; i++) { const geom::Coordinate &rectPt=rectSeq.getAt(i); if ( !elementEnv.contains(rectPt) ) { continue; } // check rect point in poly (rect is known not to // touch polygon at this point) if ( SimplePointInAreaLocator::containsPointInPolygon(rectPt, poly) ) { containsPointVar=true; return; } } } bool isDone() { return containsPointVar; }public: ContainsPointVisitor(const geom::Polygon &rect) : rectEnv(*(rect.getEnvelopeInternal())), containsPointVar(false), rectSeq(*(rect.getExteriorRing()->getCoordinatesRO())) {} bool containsPoint() { return containsPointVar; }};//----------------------------------------------------------------// LineIntersectsVisitor//----------------------------------------------------------------class LineIntersectsVisitor: public geom::util::ShortCircuitedGeometryVisitor{private: const geom::Polygon& rectangle; const geom::Envelope& rectEnv; bool intersectsVar; const geom::CoordinateSequence &rectSeq; void computeSegmentIntersection(const geom::Geometry &geom) { using geos::geom::util::LinearComponentExtracter; // check segment intersection // get all lines from geom (e.g. if it's a multi-ring polygon) geom::LineString::ConstVect lines; LinearComponentExtracter::getLines(geom, lines); SegmentIntersectionTester si; if ( si.hasIntersectionWithLineStrings(rectSeq, lines) ) { intersectsVar = true; return; } }protected: 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) { intersectsVar = rectangle.relate(geom)->isIntersects(); return; } // if small enough, test for segment intersection directly computeSegmentIntersection(geom); } bool isDone() { return intersectsVar; }public: LineIntersectsVisitor(const geom::Polygon &rect) : rectangle(rect), rectEnv(*(rect.getEnvelopeInternal())), intersectsVar(false), rectSeq(*(rect.getExteriorRing()->getCoordinatesRO())) {} /** * Reports whether any segment intersection exists. * * @return <code>true</code> if a segment intersection exists * <code>false</code> if no segment intersection exists */ bool intersects() { return intersectsVar; }};//----------------------------------------------------------------// RectangleIntersects//----------------------------------------------------------------boolRectangleIntersects::intersects(const geom::Geometry& geom){ if (!rectEnv.intersects(geom.getEnvelopeInternal())) return false; // test envelope relationships EnvelopeIntersectsVisitor visitor(rectEnv); visitor.applyTo(geom); if (visitor.intersects()) return true; // test if any rectangle corner is contained in the target ContainsPointVisitor ecpVisitor(rectangle); ecpVisitor.applyTo(geom); if (ecpVisitor.containsPoint()) return true; // test if any lines intersect LineIntersectsVisitor liVisitor(rectangle); liVisitor.applyTo(geom); if (liVisitor.intersects()) return true; return false;}} // namespace geos.operation.predicate} // namespace geos.operation} // namespace geos
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -