[jts] 03/10: Imported Upstream version 1.6
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Tue Aug 4 17:08:45 UTC 2015
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository jts.
commit de1e1dd5049d6a3f06a81855d853df58c4aef059
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Tue Aug 4 19:06:17 2015 +0200
Imported Upstream version 1.6
---
bin/test_robust.bat | 25 +
doc/JTS Developer Guide.pdf | Bin 261007 -> 565884 bytes
doc/JTS Technical Specs.pdf | Bin 318452 -> 804075 bytes
doc/JTS TestBuilder & TestRunner User Guide.pdf | Bin 1837712 -> 598039 bytes
doc/JTS Version History.html | 301 ++
doc/JTS Version History.pdf | Bin 361171 -> 0 bytes
doc/LICENSE.txt | 504 ---
src/MANIFEST.MF | 2 +-
.../vividsolutions/jts/algorithm/CGAlgorithms.java | 68 +-
.../vividsolutions/jts/algorithm/CentroidArea.java | 2 +-
.../vividsolutions/jts/algorithm/CentroidLine.java | 2 +-
.../jts/algorithm/CentroidPoint.java | 2 +-
.../vividsolutions/jts/algorithm/ConvexHull.java | 2 +-
.../vividsolutions/jts/algorithm/HCoordinate.java | 4 +-
.../jts/algorithm/InteriorPointArea.java | 2 +-
.../jts/algorithm/InteriorPointLine.java | 2 +-
.../jts/algorithm/InteriorPointPoint.java | 2 +-
.../jts/algorithm/LineIntersector.java | 4 +-
.../jts/algorithm/MCPointInRing.java | 2 +-
.../jts/algorithm/MinimumDiameter.java | 2 +-
.../jts/algorithm/NonRobustCGAlgorithms.java | 3 +-
.../jts/algorithm/NonRobustLineIntersector.java | 4 +-
.../jts/algorithm/NotRepresentableException.java | 2 +-
.../vividsolutions/jts/algorithm/PointInRing.java | 2 +-
.../vividsolutions/jts/algorithm/PointLocator.java | 2 +-
.../jts/algorithm/RobustCGAlgorithms.java | 7 +-
.../jts/algorithm/RobustDeterminant.java | 4 +-
.../jts/algorithm/RobustLineIntersector.java | 4 +-
.../jts/algorithm/SIRtreePointInRing.java | 2 +-
.../jts/algorithm/SimplePointInAreaLocator.java | 2 +-
.../jts/algorithm/SimplePointInRing.java | 2 +-
src/com/vividsolutions/jts/geom/Coordinate.java | 2 +-
.../vividsolutions/jts/geom/CoordinateArrays.java | 2 +-
.../vividsolutions/jts/geom/CoordinateFilter.java | 2 +-
.../vividsolutions/jts/geom/CoordinateList.java | 2 +-
.../jts/geom/CoordinateSequence.java | 221 +-
.../jts/geom/CoordinateSequenceFactory.java | 105 +-
.../jts/geom/DefaultCoordinateSequence.java | 310 +-
.../jts/geom/DefaultCoordinateSequenceFactory.java | 120 +-
src/com/vividsolutions/jts/geom/Dimension.java | 2 +-
src/com/vividsolutions/jts/geom/Envelope.java | 2 +-
src/com/vividsolutions/jts/geom/Geometry.java | 116 +-
.../jts/geom/GeometryCollection.java | 10 +-
.../jts/geom/GeometryCollectionIterator.java | 6 +-
.../jts/geom/GeometryComponentFilter.java | 2 +-
.../vividsolutions/jts/geom/GeometryFactory.java | 12 +-
.../vividsolutions/jts/geom/GeometryFilter.java | 2 +-
.../jts/geom/IntersectionMatrix.java | 2 +-
src/com/vividsolutions/jts/geom/LineSegment.java | 2 +-
src/com/vividsolutions/jts/geom/LineString.java | 41 +-
src/com/vividsolutions/jts/geom/LinearRing.java | 16 +-
src/com/vividsolutions/jts/geom/Location.java | 2 +-
.../vividsolutions/jts/geom/MultiLineString.java | 16 +-
src/com/vividsolutions/jts/geom/MultiPoint.java | 16 +-
src/com/vividsolutions/jts/geom/MultiPolygon.java | 12 +-
src/com/vividsolutions/jts/geom/Point.java | 25 +-
src/com/vividsolutions/jts/geom/Polygon.java | 53 +-
.../vividsolutions/jts/geom/PrecisionModel.java | 13 +-
.../vividsolutions/jts/geom/TopologyException.java | 2 +-
src/com/vividsolutions/jts/geom/Triangle.java | 2 +-
.../jts/geom/impl/CoordinateArraySequence.java | 223 ++
.../geom/impl/CoordinateArraySequenceFactory.java | 92 +
.../jts/geom/impl/PackedCoordinateSequence.java | 435 +++
.../geom/impl/PackedCoordinateSequenceFactory.java | 137 +
.../jts/geom/util/GeometryEditor.java | 4 +-
.../jts/geom/util/GeometryTransformer.java | 4 +-
.../jts/geom/util/LinearComponentExtracter.java | 2 +-
.../jts/geom/util/PointExtracter.java | 2 +-
.../jts/geom/util/PolygonExtracter.java | 2 +-
.../geom/util/ShortCircuitedGeometryVisitor.java | 36 +
src/com/vividsolutions/jts/geomgraph/Depth.java | 2 +-
.../vividsolutions/jts/geomgraph/DirectedEdge.java | 18 +-
.../jts/geomgraph/DirectedEdgeStar.java | 2 +-
src/com/vividsolutions/jts/geomgraph/Edge.java | 2 +-
src/com/vividsolutions/jts/geomgraph/EdgeEnd.java | 2 +-
.../vividsolutions/jts/geomgraph/EdgeEndStar.java | 2 +-
.../jts/geomgraph/EdgeIntersection.java | 2 +-
.../jts/geomgraph/EdgeIntersectionList.java | 2 +-
src/com/vividsolutions/jts/geomgraph/EdgeList.java | 2 +-
.../jts/geomgraph/EdgeNodingValidator.java | 2 +-
src/com/vividsolutions/jts/geomgraph/EdgeRing.java | 2 +-
.../jts/geomgraph/GeometryGraph.java | 2 +-
.../jts/geomgraph/GraphComponent.java | 2 +-
src/com/vividsolutions/jts/geomgraph/Label.java | 2 +-
src/com/vividsolutions/jts/geomgraph/Node.java | 2 +-
.../vividsolutions/jts/geomgraph/NodeFactory.java | 2 +-
src/com/vividsolutions/jts/geomgraph/NodeMap.java | 2 +-
.../vividsolutions/jts/geomgraph/PlanarGraph.java | 4 +-
src/com/vividsolutions/jts/geomgraph/Position.java | 2 +-
src/com/vividsolutions/jts/geomgraph/Quadrant.java | 4 +-
.../jts/geomgraph/TopologyLocation.java | 2 +-
.../jts/geomgraph/index/EdgeSetIntersector.java | 4 +-
.../jts/geomgraph/index/MonotoneChain.java | 2 +-
.../jts/geomgraph/index/MonotoneChainEdge.java | 2 +-
.../jts/geomgraph/index/MonotoneChainIndexer.java | 2 +-
.../jts/geomgraph/index/SegmentIntersector.java | 2 +-
.../geomgraph/index/SimpleEdgeSetIntersector.java | 2 +-
.../index/SimpleMCSweepLineIntersector.java | 4 +-
.../index/SimpleSweepLineIntersector.java | 4 +-
.../jts/geomgraph/index/SweepLineEvent.java | 2 +-
.../jts/geomgraph/index/SweepLineSegment.java | 2 +-
.../vividsolutions/jts/index/ArrayListVisitor.java | 2 +-
src/com/vividsolutions/jts/index/IndexVisitor.java | 2 +-
src/com/vividsolutions/jts/index/ItemVisitor.java | 2 +-
src/com/vividsolutions/jts/index/SpatialIndex.java | 2 +-
.../vividsolutions/jts/index/bintree/Bintree.java | 2 +-
.../vividsolutions/jts/index/bintree/Interval.java | 2 +-
src/com/vividsolutions/jts/index/bintree/Key.java | 2 +-
src/com/vividsolutions/jts/index/bintree/Node.java | 2 +-
.../vividsolutions/jts/index/bintree/NodeBase.java | 2 +-
src/com/vividsolutions/jts/index/bintree/Root.java | 2 +-
.../jts/index/chain/MonotoneChain.java | 2 +-
.../jts/index/chain/MonotoneChainBuilder.java | 2 +-
.../index/chain/MonotoneChainOverlapAction.java | 2 +-
.../jts/index/chain/MonotoneChainSelectAction.java | 2 +-
.../jts/index/quadtree/DoubleBits.java | 2 +-
.../jts/index/quadtree/IntervalSize.java | 2 +-
src/com/vividsolutions/jts/index/quadtree/Key.java | 3 +-
.../vividsolutions/jts/index/quadtree/Node.java | 2 +-
.../jts/index/quadtree/NodeBase.java | 2 +-
.../jts/index/quadtree/Quadtree.java | 2 +-
.../vividsolutions/jts/index/quadtree/Root.java | 2 +-
.../jts/index/strtree/AbstractNode.java | 2 +-
.../jts/index/strtree/AbstractSTRtree.java | 2 +-
.../jts/index/strtree/Boundable.java | 2 +-
.../vividsolutions/jts/index/strtree/Interval.java | 2 +-
.../jts/index/strtree/ItemBoundable.java | 2 +-
.../vividsolutions/jts/index/strtree/SIRtree.java | 2 +-
.../vividsolutions/jts/index/strtree/STRtree.java | 2 +-
.../jts/index/sweepline/SweepLineEvent.java | 2 +-
.../jts/index/sweepline/SweepLineIndex.java | 2 +-
.../jts/index/sweepline/SweepLineInterval.java | 2 +-
.../index/sweepline/SweepLineOverlapAction.java | 2 +-
src/com/vividsolutions/jts/io/ParseException.java | 2 +-
src/com/vividsolutions/jts/io/WKTReader.java | 2 +-
src/com/vividsolutions/jts/io/WKTWriter.java | 2 +-
.../vividsolutions/jts/noding/IteratedNoder.java | 2 +-
.../vividsolutions/jts/noding/MCQuadtreeNoder.java | 2 +-
src/com/vividsolutions/jts/noding/Noder.java | 2 +-
.../vividsolutions/jts/noding/NodingValidator.java | 2 +-
.../jts/noding/SegmentIntersector.java | 2 +-
src/com/vividsolutions/jts/noding/SegmentNode.java | 4 +-
.../vividsolutions/jts/noding/SegmentNodeList.java | 2 +-
.../vividsolutions/jts/noding/SegmentString.java | 2 +-
src/com/vividsolutions/jts/noding/SimpleNoder.java | 2 +-
.../jts/noding/snapround/SegmentSnapper.java | 2 +-
.../snapround/SimpleSegmentStringsSnapper.java | 2 +-
.../jts/noding/snapround/SnapRounder.java | 2 +-
.../jts/operation/GeometryGraphOperation.java | 2 +-
.../vividsolutions/jts/operation/IsSimpleOp.java | 2 +-
.../jts/operation/buffer/BufferBuilder.java | 4 +-
.../jts/operation/buffer/BufferOp.java | 4 +-
.../jts/operation/buffer/BufferSubgraph.java | 4 +-
.../jts/operation/buffer/OffsetCurveBuilder.java | 2 +-
.../operation/buffer/OffsetCurveSetBuilder.java | 4 +-
.../jts/operation/buffer/RightmostEdgeFinder.java | 4 +-
.../jts/operation/buffer/SubgraphDepthLocater.java | 2 +-
.../distance/ConnectedElementLocationFilter.java | 2 +-
.../distance/ConnectedElementPointFilter.java | 2 +-
.../jts/operation/distance/DistanceOp.java | 2 +-
.../jts/operation/distance/GeometryLocation.java | 2 +-
.../jts/operation/linemerge/EdgeString.java | 2 +-
.../operation/linemerge/LineMergeDirectedEdge.java | 2 +-
.../jts/operation/linemerge/LineMergeEdge.java | 2 +-
.../jts/operation/linemerge/LineMergeGraph.java | 2 +-
.../jts/operation/linemerge/LineMerger.java | 2 +-
.../jts/operation/overlay/EdgeSetNoder.java | 2 +-
.../jts/operation/overlay/LineBuilder.java | 59 +-
.../jts/operation/overlay/MaximalEdgeRing.java | 2 +-
.../jts/operation/overlay/MinimalEdgeRing.java | 2 +-
.../jts/operation/overlay/OverlayNodeFactory.java | 4 +-
.../jts/operation/overlay/OverlayOp.java | 2 +-
.../jts/operation/overlay/PointBuilder.java | 2 +-
.../jts/operation/overlay/PolygonBuilder.java | 6 +-
.../jts/operation/polygonize/EdgeRing.java | 2 +-
.../polygonize/PolygonizeDirectedEdge.java | 2 +-
.../jts/operation/polygonize/PolygonizeEdge.java | 2 +-
.../jts/operation/polygonize/PolygonizeGraph.java | 2 +-
.../jts/operation/polygonize/Polygonizer.java | 2 +-
.../jts/operation/predicate/RectangleContains.java | 122 +
.../operation/predicate/RectangleIntersects.java | 211 ++
.../predicate/SegmentIntersectionTester.java | 54 +
.../jts/operation/relate/EdgeEndBuilder.java | 4 +-
.../jts/operation/relate/EdgeEndBundle.java | 4 +-
.../jts/operation/relate/EdgeEndBundleStar.java | 2 +-
.../jts/operation/relate/RelateComputer.java | 4 +-
.../jts/operation/relate/RelateNode.java | 4 +-
.../jts/operation/relate/RelateNodeFactory.java | 2 +-
.../jts/operation/relate/RelateNodeGraph.java | 4 +-
.../jts/operation/relate/RelateOp.java | 4 +-
.../operation/valid/ConnectedInteriorTester.java | 2 +-
.../jts/operation/valid/ConsistentAreaTester.java | 2 +-
.../jts/operation/valid/IsValidOp.java | 2 +-
.../operation/valid/QuadtreeNestedRingTester.java | 2 +-
.../jts/operation/valid/RepeatedPointTester.java | 2 +-
.../operation/valid/SimpleNestedRingTester.java | 2 +-
.../operation/valid/SweeplineNestedRingTester.java | 2 +-
.../operation/valid/TopologyValidationError.java | 2 +-
.../jts/planargraph/DirectedEdge.java | 2 +-
.../jts/planargraph/DirectedEdgeStar.java | 2 +-
src/com/vividsolutions/jts/planargraph/Edge.java | 2 +-
.../jts/planargraph/GraphComponent.java | 2 +-
src/com/vividsolutions/jts/planargraph/Node.java | 2 +-
.../vividsolutions/jts/planargraph/NodeMap.java | 2 +-
.../jts/planargraph/PlanarGraph.java | 2 +-
.../vividsolutions/jts/precision/CommonBits.java | 2 +-
.../vividsolutions/jts/precision/CommonBitsOp.java | 2 +-
.../jts/precision/CommonBitsRemover.java | 2 +-
.../jts/precision/EnhancedPrecisionOp.java | 2 +-
.../precision/SimpleGeometryPrecisionReducer.java | 4 +-
.../jts/simplify/DouglasPeuckerLineSimplifier.java | 11 +-
.../jts/simplify/DouglasPeuckerSimplifier.java | 12 +-
.../jts/simplify/TaggedLineString.java | 2 +-
.../jts/simplify/TaggedLineStringSimplifier.java | 35 +-
.../jts/simplify/TaggedLinesSimplifier.java | 6 +-
.../jts/simplify/TopologyPreservingSimplifier.java | 7 +
src/com/vividsolutions/jts/util/Assert.java | 2 +-
.../jts/util/AssertionFailedException.java | 2 +-
.../jts/util/CoordinateArrayFilter.java | 2 +-
.../jts/util/CoordinateCountFilter.java | 2 +-
src/com/vividsolutions/jts/util/Debug.java | 28 +-
.../jts/util/GeometricShapeFactory.java | 2 +-
src/com/vividsolutions/jts/util/Stopwatch.java | 2 +-
.../jts/util/UniqueCoordinateArrayFilter.java | 2 +-
.../jtsexample/geom/BasicExample.java | 2 +-
.../jtsexample/geom/ConstructionExample.java | 2 +-
.../jtsexample/geom/ExtendedCoordinate.java | 7 +-
.../jtsexample/geom/ExtendedCoordinateExample.java | 2 +-
.../geom/ExtendedCoordinateSequence.java | 108 +-
.../geom/ExtendedCoordinateSequenceFactory.java | 19 +-
.../jtsexample/geom/PrecisionModelExample.java | 2 +-
.../jtsexample/geom/SimpleMethodsExample.java | 2 +-
.../geom/TwoArrayCoordinateSequenceExample.java | 89 -
.../geom/TwoArrayCoordinateSequenceFactory.java | 118 -
.../operation/distance/ClosestPointExample.java | 2 +-
.../operation/linemerge/LineMergeExample.java | 2 +-
.../operation/polygonize/PolygonizeExample.java | 2 +-
.../precision/EnhancedPrecisionOpExample.java | 2 +-
.../technique/LineStringSelfIntersections.java | 2 +-
.../jtsexample/technique/UnionUsingBuffer.java | 2 +-
test/robust/TestRobustOverlayFixed.xml | 18 +
test/robust/TestRobustOverlayFloat.xml | 94 +
test/robust/TestRobustRelate.xml | 19 +
test/validate/TestRelateLL.xml | 3890 ++++++++++----------
test/validate/TestRelatePA.xml | 1238 +++----
test/validate/TestRelatePL.xml | 2560 ++++++-------
test/validate/TestRelatePP.xml | 340 +-
test/vivid/TestBoundary.xml | 3 +-
test/vivid/TestCentroid.xml | 4 +-
test/vivid/TestFunctionAA.xml | 38 +-
test/vivid/TestFunctionAAPrec.xml | 3 +-
test/vivid/TestFunctionLAPrec.xml | 3 +-
test/vivid/TestFunctionLLPrec.xml | 12 +-
test/vivid/TestRectanglePredicate.xml | 101 +
test/vivid/TestValid.xml | 11 +-
255 files changed, 7122 insertions(+), 5482 deletions(-)
diff --git a/bin/test_robust.bat b/bin/test_robust.bat
new file mode 100644
index 0000000..daa95a0
--- /dev/null
+++ b/bin/test_robust.bat
@@ -0,0 +1,25 @@
+ at echo off
+rem A batch file to run the XML test files written by Geographic Data BC.
+
+set CLASSPATH=
+for %%i in (..\lib\*.*) do (
+ set jarfile=%%i
+
+ rem If we append to a variable inside the for, only the last entry will
+ rem be kept. So append to the variable outside the for.
+ rem See http://www.experts-exchange.com/Operating_Systems/MSDOS/Q_20561701.html.
+ rem [Jon Aquino]
+
+ call :setclass
+)
+
+java com.vividsolutions.jtstest.testrunner.TopologyTestApp -Files ..\test\robust
+pause
+
+goto :eof
+
+:setclass
+set CLASSPATH=%jarfile%;%CLASSPATH%
+set jarfile=
+
+:eof
\ No newline at end of file
diff --git a/doc/JTS Developer Guide.pdf b/doc/JTS Developer Guide.pdf
index 362d333..314ea4f 100644
Binary files a/doc/JTS Developer Guide.pdf and b/doc/JTS Developer Guide.pdf differ
diff --git a/doc/JTS Technical Specs.pdf b/doc/JTS Technical Specs.pdf
index 8b71d0c..57d17c2 100644
Binary files a/doc/JTS Technical Specs.pdf and b/doc/JTS Technical Specs.pdf differ
diff --git a/doc/JTS TestBuilder & TestRunner User Guide.pdf b/doc/JTS TestBuilder & TestRunner User Guide.pdf
index d2e863d..719bbf6 100644
Binary files a/doc/JTS TestBuilder & TestRunner User Guide.pdf and b/doc/JTS TestBuilder & TestRunner User Guide.pdf differ
diff --git a/doc/JTS Version History.html b/doc/JTS Version History.html
new file mode 100644
index 0000000..92eb99e
--- /dev/null
+++ b/doc/JTS Version History.html
@@ -0,0 +1,301 @@
+<html>
+
+<head>
+<title>JTS Version History</title>
+</head>
+
+<body bgcolor='lightblue'>
+<h1 style='text-align:center;'>
+JTS TOPOLOGY SUITE
+<br>
+Version History
+</h1>
+
+
+This document lists the change history of release versions of the JTS Topology Suite
+
+<hr>
+<h2>Version 1.6</h2>
+
+Release Date: February 3, 2005
+
+<h3>API Changes</h3>
+<ul>
+<li>Changed to using <code>CoordinateArraySequence</code> instead of <code>DefaultCoordinateSequence</code>
+(to provide a more descriptive name).
+</ul>
+
+<h3>Semantics Changes</h3>
+<ul>
+<li>PrecisionModel#makePrecise changed to use Symmetric Arithmetic Rounding rather than Banker's Rounding
+</ul>
+
+<h3>Functionality Improvements</h3>
+<ul>
+<li>Added ability to enable <code>Debug</code> methods by setting a system property
+<li>Added <code>getNumGeometries</code> and <code>getGeometryN</code> methods to Geometry class, to make API more uniform
+<li>Improved API for <code>CoordinateSequence</code> allows more options for improving memory usage and handling custom coordinate storage methods
+<li>Added <code>PackedCoordinateSequence</code> to provide reduced memory footprint for geometry objects if desired
+<li>Added optimized spatial predicates for rectangles
+<li>Added Debug#isDebugging method
+</ul>
+
+<h3>Bug Fixes</h3>
+<ul>
+<li>Fixed bug in <code>Geometry#within()</code> short circuiting
+<li>Fixed bug causing <code>Geometry#isValid</code> to throw IllegalArgumentException for certain kinds of holes with invalid rings
+<li>Fixed bug causing redundant linestrings to be returned in the result of overlaying polygons containing holes touching their shell.
+<li><code>Polygon#getBoundary</code> now returns a <code>LinearRing</code> if the polygon does not have holes
+</ul>
+
+<h3>Architecture Changes</h3>
+<ul>
+<li>Removed a proliferation of references to the default <code>CoordinateSequenceFactory</code>
+</ul>
+
+<h2>Contributors</h2>
+<ul>
+<li>Andrea Aime
+</ul>
+
+<h2>Version 1.5</h2>
+Release Date: September 22, 2004
+<p>
+This version is upwards compatible with Version 1.4
+
+<h3>API Changes</h3>
+<ul>
+<li>None
+</ul>
+
+<h3>Semantics Changes</h3>
+<ul>
+<li>None
+</ul>
+
+<h3>Functionality Improvements</h3>
+<ul>
+<li>CGAlgorithms#isCCW now handles coordinate lists with repeated points. Also throws an IllegalArgumentException if the input ring does not have 3 distinct points
+<li>isValid now checks for invalid coordinates (e.g. ones with Nan or infinite numbers)
+<li>added copyDeep() method to CoordinateArrays
+<li>added geometry simplification operations DouglasPeuckerSimplifier and TopologyPreservingSimplifier
+<li>added methods to Quadtree and STRtree to remove items and query using the Visitor pattern
+</ul>
+
+<h3>Performance Improvements</h3>
+<ul>
+<li>Added short-circuit tests in geometry named predicates based on envelope tests
+</ul>
+<h3>Bug Fixes</h3>
+<ul>
+<li>Fixed bugs in Geometry serialization
+<li>Fixed bug in ValidOp which reported some MultiPolygons with shells nested inside a hole as invalid
+<li>Fixed bug in buffer which caused buffers of some polygons with small & large holes to not contain any holes
+<li>Fixed bug in Polygonizer which caused exception if no lines were supplied
+</ul>
+<h3>Architecture Changes</h3>
+<ul>
+<li>Basic CG algorithm methods made static in the in CGAlgorithms class
+<li>Various utility methods made public in CoordinateArrays class
+</ul>
+<h3>Documentation</h3>
+<ul>
+<li>More examples provided in com.vividsolutions.jtsexamples package
+</ul>
+
+<h2>Version 1.4</h2>
+
+Release Date: November 4, 2003
+<h3>Semantics Changes</h3>
+<ul>
+<li>none
+</ul>
+<h3>Functionality Improvements</h3>
+<ul>
+<li>Added "LINEARRING" tag to WKT syntax
+<li>Added GeometryEditor class to allow easy copy/modify of Geometrys
+<li>Added GeometricShapeFactory class to easily create standard geometric shapes
+<li>Geometries can now carry arbitrary user-defined data objects (via Geometry#get/setUserData(Object) method)
+<li>Added CoordinateSequence and CoordinateSequenceFactory interfaces, and default implementations (BasicCoordinateSequence, BasicCoordinateSequenceFactory)
+<li>Added Geometry#getFactory
+<li>Added new PrecisionModel type of FLOATING_SINGLE, for rounding to single precision floating point
+<li>Added DistanceOp#getClosestPoints method, which returns the closest points between two Geometries
+<li>Added com.vividsolutions.jts.noding package containing classes to perform fast indexed noding of linestrings
+<li>Added com.vividsolutions.jts.operation.polygonize package containing classes to perform polygonization
+<li>Added com.vividsolutions.jts.operation.linemerge package containing classes to perform line merging
+<li>Added SimpleGeometryPrecisionReducer to allow reducing precision of coordinates of a Geometry
+<li>Added LineSegment#closestPoints method to compute the closest points between two line segments
+<li>Added MinimumDiameter class to compute minimum diameters of Geometries
+<li>Added geom.Triangle class to contain algorithms for Triangles
+<li>BufferOp now allows end cap styles to be specified. Three types are supported: round, butt and square.
+</ul>
+<h3>Performance Improvements</h3>
+<ul>
+<li>EdgeList now provides a findEqualEdge method which is substantially faster than findEdgeIndex, for large lists
+<li>Buffering is now faster and much more robust
+<li>Overlap operations are now more robust
+</ul>
+<h3>Bug Fixes</h3>
+<ul>
+<li>Envelope#init(Envelope) now handles null Envelopes correctly
+<li>CoordinateList#add() now correctly ignores the z-value of Coordinates in determining equality
+<li>Geometry#isValid now correctly handles checking validity of LinearRings
+<li>Fixed infinite loop bug causing Out Of Memory errors during polygon intersection
+<li>Geometry#clone now correctly clones the Geometry's Envelope
+<li>LineIntersector#computeEdgeDistance now correctly computes a non-zero edge distance in certain situations when a fixed precision model was being used and the line segment was a single unit in length
+<li>Fixed incorrect calculation of depths in DirectedEdgeStar#computeDepths
+<li>Fixed BufferSubgraph#addReachable to use explicit stack to avoid stack overflow problems
+<li>Fixed various bugs causing some kinds of buffers to be computed incorrectly
+</ul>
+<h3>API Changes</h3>
+<ul>
+<li>WKTReader/Writer: changed protected members to private
+<li>PrecisionModel type is now an object rather than an int
+<li>ConvexHull API changed to remove requirement to pass in CGAlgorithms object
+</ul>
+<h3>Code Architecture Changes</h3>
+<ul>
+<li>geom.util package added for utility classes which parse and modify geometries
+</ul>
+<h3>Documentation</h3>
+<ul>
+<li>More examples provided in com.vividsolutions.jtsexamples package
+<li>Added JTS Developers Guide
+</ul>
+
+<h2>Version 1.3</h2>
+Release Date: April 4, 2003
+<h3>Semantics Changes</h3>
+<ul>
+<li>all Geometry methods are now reentrant (thread-safe)
+<li>Fixed-precision coordinates are now stored in a rounded but non-scaled form. This makes them compatible with non-precise (Floating) coordinates, and simplifies working with precise coordinates directly. Mixed precision models are now supported in Geometry methods; method results are in the more precise of the input precision models.
+<li>Offsets are no longer supported in the Fixed precision model. This is necessary to allow storing fixed precision coordinates in a non-scaled form. This does not reduce the total precision available, since coordinates are stored in a floating-point format.
+<li>SRID and Precision Model are no longer checked for equality during Geometry operations. This removes a limitation which provided little semantic benefit.
+</ul>
+
+<h3>Functionality Improvements</h3>
+<ul>
+<li>added Geometry.isWithinDistance(Geometry g, double distance) method, to provide optimized proximity queries
+<li>added Geometry.buffer(double distance, int quadrantSegments) method, allowing control over accuracy of buffer approximation
+<li>added Geometry.getCentroid() method
+<li>added Geometry.getInteriorPoint() method, which uses heuristic methods to return a point in the interior of a Geometry
+<li>GeometryFactory.toGeometryArray now returns null if the argument is null
+</ul>
+<h3>Performance Improvements</h3>
+<ul>
+<li>Removed unnecessary string construction in EdgeEndStar.propagateSideLabels()
+<li>Eliminated unnecessary computation of self-intersections in rings during relate and spatial functions. This provides a large increase in speed when working with large rings and polygons. (Note that IsValid still checks for these self-intersections, which are illegal in LinearRings)
+<li>Add short-circuit code to RobustLineIntersector to detect non-intersections more efficiently
+</ul>
+<h3>Bug Fixes</h3>
+<ul>
+<li>Fixed ClassCastException occurring in GeometryCollection.getLength()
+<li>Fixed bug in Edge Intersection insertion (replaced Coordinate#equals with equals2D to ensure that intersection creation is not sensitive to Z-value).
+<li>Fixed handling LineStrings with too few points in GeometryGraph.addLineString
+<li>Fixed: was not checking that MultiPolygons don't contain components with too few points.
+<li>Fixed Envelope.distance() to return correct distance for all envelopes.
+<li>Fixed a few Geometry methods to make them re-entrant.
+<li>Fixed CoordinateList.closeRing() to ensure endpoints are not duplicated
+<li>Fixed CGAlgorithms.signedArea() to use a simpler algorithm which is more robust and faster.
+<li>Fixed bug preventing validating Rings containing an initial repeated point.
+</ul>
+<h3>API Changes</h3>
+<ul>
+<li>Added default constructor to WKTReader. It uses the default GeometryFactory
+<li>Add two static intersects() methods to Envelope, to allow computing intersections with envelopes defined by points only.
+<li>Dropped BinaryPower; its functionality is provided by DoubleBits in a more robust fashion.
+<li>Removed a couple of redundant private static methods from Geometry; they have been replaced by methods in CoordinateArrays
+<li>The Geometry class is now marked as Serializable
+</ul>
+
+<h2>Version 1.2</h2>
+Release Date: 7 October 2002
+<h3>Semantics Changes</h3>
+<ul>
+<li>JTS now allows Geometrys to have repeated points. All operations will continue to perform as before. This removes a significant incompatibility with the OGC spatial data model.
+<li>TopologyExceptions may now be thrown by spatial overlay methods. This helps to distinguish between code bugs and known robustness problems. It also provides a machine-readable coordinate for the error location.
+</ul>
+<h3>Functionality Improvements</h3>
+<ul>
+<li>RobustLineIntersector now uses "normalized" coordinates to maximize the accuracy of intersection computation.
+<li>Upgraded Quadtree with more robust implementation
+<li>Replaced IntervalTree with a more robust implementation of BinTree
+<li>Added STRTree 2-D spatial index, which exhibits better performance than QuadTrees in many situations.
+<li>Added EnhancePrecisionOp, which uses precisioning enhancing techniques to reduce the number of failure cases due to robustness problems.
+</ul>
+<h3>Bug Fixes</h3>
+<ul>
+<li>fixed ConvexHull to use TreeSet instead of HashSet for coordinates
+<li>Fixed isValid for GeometryCollections containing Polygons, which were sometimes erroneously returning a validity failure for correct Geometrys.
+<li>Fixed bug in LineSegment.distancePointLine() which would return the incorrect distance for a LineSegment with two identical points
+<li>Improved error handling in CGAlgorithms.isCCW()
+<li>IsValid now checks for too few points in a geometry component (e.g. due to repeated points in a ring)
+</ul>
+<h3>API Changes</h3>
+<ul>
+<li>added Stopwatch class
+<li>added Geometry.getArea() and Geometry.getLength() methods
+<li>added CGAlgorithms.signedArea() method
+<li>added methods to LineSegment - closestPoint(), getLength()
+<li>added CoordinateArrrays and CoordinateLists utility classes
+<li>Added TopologyValidationError.getErrorType() method
+<li>Added Envelope#intersects; deprecated Envelope#overlaps.
+<li>Added Geometry#geometryChanged() method to allow signaling when Geometry coordinates have been mutated by a client class
+<li>Added STRTree class implementing a Sort-Tile-Recursive spatial index (a variant of a packed R-tree)
+<li>Deleted IntervalTree 1-D spatial index (replaced by BinTree)
+<li>Add BinTree 1-D spatial index
+</ul>
+
+<h2>Version 1.1.1</h2>
+Release Date: 9 April 2002
+<h3>Bug Fixes</h3>
+<ul>
+<li>fixed decimal-point symbol localization bug in WKTWriter
+<li>fixed bug in Envelope.int(Envelope env)
+<li>fixed filename case of SFSMultiLineString.java and IntervalTree.java
+</ul>
+<h3>API Changes</h3>
+<ul>
+<li>deleted TopologyException class
+<li>renamed CGAlgorithms.isPointInPolygon to isPointInRing (a more accurate description of what the method computes)
+</ul>
+<h3>API Additions</h3>
+<ul>
+<li>added Geometry.getCoordinate() method
+<li>added Geometry.distance() method
+<li>added GeometryComponentFilter interface and Geometry.apply(GeometryComponentFilter) method
+</ul>
+
+<h2>Version 1.1</h2>
+Release Date: 28 March 2002
+<h3>New Features</h3>
+<ul>
+<li>added Geometry.isSimple() and Geometry.isValid() methods
+<li>improved design of topological data structures
+<li>added Geometry.setSRID() method
+<li>improved functionality of the Envelope class
+<li>added ability to write to an arbitrary java.io.Writer object to WKTWriter
+<li>added Validate and Mark Location functionality to TestBuilder
+</ul>
+
+<h2>Version 1.0</h2>
+Release Date: 1 February 2002
+<ul>
+<li>Removed some non-compatibilities with Java 1.1
+<li>Fixed bug in constructing buffer outline around inside of angles
+<li>In TestBuilder vertices are now displayed with fixed size in view units
+<li>Improved code for WKTWriter.writeFormatted()
+<li>Fixed bug in constructor for LinearRing
+<li>Improved implementation of sweepline intersection algorithm to avoid use of dynamic set.
+<li>Fixed bug in ConvexHull.cleanRing()
+<li>Refactored RobustLineIntersector and NonRobustLineIntersector
+</ul>
+
+<h2>Version 0.0</h2>
+Release Date: 30 May 2001
+
+<p>
+<i>Baseline version</i>
+
+</body>
+</html>
diff --git a/doc/JTS Version History.pdf b/doc/JTS Version History.pdf
deleted file mode 100644
index 2a456b7..0000000
Binary files a/doc/JTS Version History.pdf and /dev/null differ
diff --git a/doc/LICENSE.txt b/doc/LICENSE.txt
deleted file mode 100644
index b1e3f5a..0000000
--- a/doc/LICENSE.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/src/MANIFEST.MF b/src/MANIFEST.MF
index 29aef23..78e8373 100644
--- a/src/MANIFEST.MF
+++ b/src/MANIFEST.MF
@@ -1,4 +1,4 @@
Manifest-version: 1.0
Implementation-Title: Java Topology Suite
-Implementation-Version: 1.5
+Implementation-Version: 1.6
Implementation-Vendor: Vivid Solutions
diff --git a/src/com/vividsolutions/jts/algorithm/CGAlgorithms.java b/src/com/vividsolutions/jts/algorithm/CGAlgorithms.java
index f5143b9..ebb6479 100644
--- a/src/com/vividsolutions/jts/algorithm/CGAlgorithms.java
+++ b/src/com/vividsolutions/jts/algorithm/CGAlgorithms.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.CoordinateSequence;
* Specifies and implements various fundamental Computational Geometric algorithms.
* The algorithms supplied in this class are robust for double-precision floating point.
*
- * @version 1.5
+ * @version 1.6
*/
public class CGAlgorithms
{
@@ -100,39 +100,30 @@ public class CGAlgorithms
* @return <code>true</code> if p is inside ring
*/
public static boolean isPointInRing(Coordinate p, Coordinate[] ring) {
- int i;
- int i1; // point index; i1 = i-1
- double xInt; // x intersection of segment with ray
- int crossings = 0; // number of segment/ray crossings
- double x1; // translated coordinates
- double y1;
- double x2;
- double y2;
- int nPts = ring.length;
-
/*
* For each segment l = (i-1, i), see if it crosses ray from test point in positive x direction.
*/
- for (i = 1; i < nPts; i++) {
- i1 = i - 1;
+ int crossings = 0; // number of segment/ray crossings
+ for (int i = 1; i < ring.length; i++) {
+ int i1 = i - 1;
Coordinate p1 = ring[i];
Coordinate p2 = ring[i1];
- x1 = p1.x - p.x;
- y1 = p1.y - p.y;
- x2 = p2.x - p.x;
- y2 = p2.y - p.y;
- if (((y1 > 0) && (y2 <= 0)) ||
- ((y2 > 0) && (y1 <= 0))) {
+ if (((p1.y > p.y) && (p2.y <= p.y)) ||
+ ((p2.y > p.y) && (p1.y <= p.y))) {
+ double x1 = p1.x - p.x;
+ double y1 = p1.y - p.y;
+ double x2 = p2.x - p.x;
+ double y2 = p2.y - p.y;
/*
- * segment straddles x axis, so compute intersection.
+ * segment straddles x axis, so compute intersection with x-axis.
*/
- xInt = RobustDeterminant.signOfDet2x2(x1, y1, x2, y2) / (y2 - y1);
+ double xInt = RobustDeterminant.signOfDet2x2(x1, y1, x2, y2) / (y2 - y1);
//xsave = xInt;
/*
- * crosses ray if strictly positive intersection.
+ * crosses ray if strictly positive intersection.
*/
- if (0.0 < xInt) {
+ if (xInt > 0.0) {
crossings++;
}
}
@@ -170,23 +161,16 @@ public class CGAlgorithms
}
/**
- * Tests whether a ring (simple polygon) is oriented counter-clockwise.
- * The list of points is assumed to have the first and last points equal.
- * If the point list does not form a valid ring the result is undefined.
- * This method is not guaranteed to work on coordinate lists which contain repeated points.
- *
- * @param ring an array of coordinates forming a ring
- * @return <code>true</code> if the ring is oriented counter-clockwise
- */
- /**
* Computes whether a ring defined by an array of {@link Coordinate} is
* oriented counter-clockwise.
- * <p>
- * This will handle coordinate lists which contain repeated points.
+ * <ul>
+ * <li>The list of points is assumed to have the first and last points equal.
+ * <li>This will handle coordinate lists which contain repeated points.
+ * <li>If the ring is invalid, the answer returned may not be correct.
+ * </ul>
*
* @param ring an array of coordinates forming a ring
* @return <code>true</code> if the ring is oriented counter-clockwise.
- * @throws IllegalArgumentException if the ring is degenerate (does not contain 3 distinct points)
*/
public static boolean isCCW(Coordinate[] ring) {
// # of points without closing endpoint
@@ -219,10 +203,16 @@ public class CGAlgorithms
Coordinate prev = ring[iPrev];
Coordinate next = ring[iNext];
- // this will catch all cases where there are not 3 distinct points,
- // including the case where the input array has fewer than 4 elements
+ /**
+ * This check catches cases where the ring contains an A-B-A configuration of points.
+ * This can happen if the ring does not contain 3 distinct points
+ * (including the case where the input array has fewer than 4 elements),
+ * or it contains coincident line segments.
+ */
if (prev.equals(hip) || next.equals(hip) || prev.equals(next))
- throw new IllegalArgumentException("degenerate ring (does not contain 3 distinct points)");
+ return false;
+ // MD - don't bother throwing exception, since this isn't a complete check for ring validity
+// throw new IllegalArgumentException("Invalid ring (contains repeated line segments)");
int disc = computeOrientation(prev, hip, next);
@@ -232,7 +222,7 @@ public class CGAlgorithms
* (2) the lines lie on top of one another
*
* (1) is handled by checking if next is left of prev ==> CCW
- * (2) should never happen, so we're going to ignore it!
+ * (2) will never happen if the ring is valid, so don't check for it
* (Might want to assert this)
*/
boolean isCCW = false;
diff --git a/src/com/vividsolutions/jts/algorithm/CentroidArea.java b/src/com/vividsolutions/jts/algorithm/CentroidArea.java
index 1c32752..061e87c 100644
--- a/src/com/vividsolutions/jts/algorithm/CentroidArea.java
+++ b/src/com/vividsolutions/jts/algorithm/CentroidArea.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.geom.*;
* See <code>http://www.faqs.org/faqs/graphics/algorithms-faq/</code>
* for further details of the basic approach.
*
- * @version 1.5
+ * @version 1.6
*/
public class CentroidArea
{
diff --git a/src/com/vividsolutions/jts/algorithm/CentroidLine.java b/src/com/vividsolutions/jts/algorithm/CentroidLine.java
index a1caf88..0cc2c56 100644
--- a/src/com/vividsolutions/jts/algorithm/CentroidLine.java
+++ b/src/com/vividsolutions/jts/algorithm/CentroidLine.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geom.*;
* Compute the average of the midpoints
* of all line segments weighted by the segment length.
*
- * @version 1.5
+ * @version 1.6
*/
public class CentroidLine
{
diff --git a/src/com/vividsolutions/jts/algorithm/CentroidPoint.java b/src/com/vividsolutions/jts/algorithm/CentroidPoint.java
index 5359ebd..1b9a172 100644
--- a/src/com/vividsolutions/jts/algorithm/CentroidPoint.java
+++ b/src/com/vividsolutions/jts/algorithm/CentroidPoint.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.*;
* <h2>Algorithm</h2>
* Compute the average of all points.
*
- * @version 1.5
+ * @version 1.6
*/
public class CentroidPoint
{
diff --git a/src/com/vividsolutions/jts/algorithm/ConvexHull.java b/src/com/vividsolutions/jts/algorithm/ConvexHull.java
index d769f73..00cf3de 100644
--- a/src/com/vividsolutions/jts/algorithm/ConvexHull.java
+++ b/src/com/vividsolutions/jts/algorithm/ConvexHull.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.UniqueCoordinateArrayFilter;
* points in the input Geometry.
* Uses the Graham Scan algorithm.
*
- *@version 1.5
+ *@version 1.6
*/
public class ConvexHull
{
diff --git a/src/com/vividsolutions/jts/algorithm/HCoordinate.java b/src/com/vividsolutions/jts/algorithm/HCoordinate.java
index e1f44a0..5a515b4 100644
--- a/src/com/vividsolutions/jts/algorithm/HCoordinate.java
+++ b/src/com/vividsolutions/jts/algorithm/HCoordinate.java
@@ -36,14 +36,14 @@
package com.vividsolutions.jts.algorithm;
/**
- * @version 1.5
+ * @version 1.6
*/
import com.vividsolutions.jts.geom.*;
/**
* Represents a homogeneous coordinate for 2-D coordinates.
*
- * @version 1.5
+ * @version 1.6
*/
public class HCoordinate
{
diff --git a/src/com/vividsolutions/jts/algorithm/InteriorPointArea.java b/src/com/vividsolutions/jts/algorithm/InteriorPointArea.java
index d8d2c91..5021d93 100644
--- a/src/com/vividsolutions/jts/algorithm/InteriorPointArea.java
+++ b/src/com/vividsolutions/jts/algorithm/InteriorPointArea.java
@@ -52,7 +52,7 @@ import com.vividsolutions.jts.geom.*;
* which does not lie in the interior.
* </b>
*
- * @version 1.5
+ * @version 1.6
*/
public class InteriorPointArea {
diff --git a/src/com/vividsolutions/jts/algorithm/InteriorPointLine.java b/src/com/vividsolutions/jts/algorithm/InteriorPointLine.java
index 23a6900..c6aec93 100644
--- a/src/com/vividsolutions/jts/algorithm/InteriorPointLine.java
+++ b/src/com/vividsolutions/jts/algorithm/InteriorPointLine.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.geom.*;
* closest to the centroid.
* </ul>
*
- * @version 1.5
+ * @version 1.6
*/
public class InteriorPointLine {
diff --git a/src/com/vividsolutions/jts/algorithm/InteriorPointPoint.java b/src/com/vividsolutions/jts/algorithm/InteriorPointPoint.java
index 9ec4cc4..49abc6a 100644
--- a/src/com/vividsolutions/jts/algorithm/InteriorPointPoint.java
+++ b/src/com/vividsolutions/jts/algorithm/InteriorPointPoint.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.*;
* <h2>Algorithm</h2>
* Find a point which is closest to the centroid of the geometry.
*
- * @version 1.5
+ * @version 1.6
*/
public class InteriorPointPoint {
diff --git a/src/com/vividsolutions/jts/algorithm/LineIntersector.java b/src/com/vividsolutions/jts/algorithm/LineIntersector.java
index fad4f3d..15c0394 100644
--- a/src/com/vividsolutions/jts/algorithm/LineIntersector.java
+++ b/src/com/vividsolutions/jts/algorithm/LineIntersector.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.algorithm;
/**
- * @version 1.5
+ * @version 1.6
*/
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.util.*;
@@ -50,7 +50,7 @@ import com.vividsolutions.jts.util.*;
* that the input coordinates have been made precise by scaling them to
* an integer grid.)
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class LineIntersector {
diff --git a/src/com/vividsolutions/jts/algorithm/MCPointInRing.java b/src/com/vividsolutions/jts/algorithm/MCPointInRing.java
index d2f7604..00fa608 100644
--- a/src/com/vividsolutions/jts/algorithm/MCPointInRing.java
+++ b/src/com/vividsolutions/jts/algorithm/MCPointInRing.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.index.bintree.Interval;
* using {@link MonotoneChain}s and a {@link BinTree} index to
* increase performance.
*
- * @version 1.5
+ * @version 1.6
*/
public class MCPointInRing implements PointInRing {
diff --git a/src/com/vividsolutions/jts/algorithm/MinimumDiameter.java b/src/com/vividsolutions/jts/algorithm/MinimumDiameter.java
index acf3df6..c3e8a60 100644
--- a/src/com/vividsolutions/jts/algorithm/MinimumDiameter.java
+++ b/src/com/vividsolutions/jts/algorithm/MinimumDiameter.java
@@ -51,7 +51,7 @@ import com.vividsolutions.jts.geom.*;
*
* @see ConvexHull
*
- * @version 1.5
+ * @version 1.6
*/
public class MinimumDiameter
{
diff --git a/src/com/vividsolutions/jts/algorithm/NonRobustCGAlgorithms.java b/src/com/vividsolutions/jts/algorithm/NonRobustCGAlgorithms.java
index 5b5c75e..196d1bc 100644
--- a/src/com/vividsolutions/jts/algorithm/NonRobustCGAlgorithms.java
+++ b/src/com/vividsolutions/jts/algorithm/NonRobustCGAlgorithms.java
@@ -32,7 +32,6 @@
*/
package com.vividsolutions.jts.algorithm;
-import com.vividsolutions.jts.geom.DefaultCoordinateSequenceFactory;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;
@@ -41,7 +40,7 @@ import com.vividsolutions.jts.geom.CoordinateSequence;
* <b>FOR TESTING PURPOSES ONLY!</b>.
* The non-robustness is due to rounding error in floating point computation.
*
- * @version 1.5
+ * @version 1.6
*/
public class NonRobustCGAlgorithms
extends CGAlgorithms
diff --git a/src/com/vividsolutions/jts/algorithm/NonRobustLineIntersector.java b/src/com/vividsolutions/jts/algorithm/NonRobustLineIntersector.java
index 32ad4af..7b00766 100644
--- a/src/com/vividsolutions/jts/algorithm/NonRobustLineIntersector.java
+++ b/src/com/vividsolutions/jts/algorithm/NonRobustLineIntersector.java
@@ -36,7 +36,7 @@ package com.vividsolutions.jts.algorithm;
import com.vividsolutions.jts.algorithm.LineIntersector;
/**
- *@version 1.5
+ *@version 1.6
*/
import com.vividsolutions.jts.geom.*;
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.Debug;
/**
* A non-robust version of {@LineIntersector}.
*
- * @version 1.5
+ * @version 1.6
*/
public class NonRobustLineIntersector
extends LineIntersector
diff --git a/src/com/vividsolutions/jts/algorithm/NotRepresentableException.java b/src/com/vividsolutions/jts/algorithm/NotRepresentableException.java
index 3eb7902..af6efa5 100644
--- a/src/com/vividsolutions/jts/algorithm/NotRepresentableException.java
+++ b/src/com/vividsolutions/jts/algorithm/NotRepresentableException.java
@@ -39,7 +39,7 @@ package com.vividsolutions.jts.algorithm;
* Indicates that a {@link HCoordinate} has been computed which is
* not representable on the Cartesian plane.
*
- * @version 1.5
+ * @version 1.6
* @see HCoordinate
*/
public class NotRepresentableException extends Exception {
diff --git a/src/com/vividsolutions/jts/algorithm/PointInRing.java b/src/com/vividsolutions/jts/algorithm/PointInRing.java
index e8e5562..b9fdfff 100644
--- a/src/com/vividsolutions/jts/algorithm/PointInRing.java
+++ b/src/com/vividsolutions/jts/algorithm/PointInRing.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* An interface for classes which test whether a {@link Coordinate} lies inside
* a ring.
*
- * @version 1.5
+ * @version 1.6
*/
public interface PointInRing {
diff --git a/src/com/vividsolutions/jts/algorithm/PointLocator.java b/src/com/vividsolutions/jts/algorithm/PointLocator.java
index 32c9aac..ca86dff 100644
--- a/src/com/vividsolutions/jts/algorithm/PointLocator.java
+++ b/src/com/vividsolutions/jts/algorithm/PointLocator.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.geomgraph.GeometryGraph;
* The algorithm obeys the SFS boundaryDetermination rule to correctly determine
* whether the point lies on the boundary or not.
* Note that instances of this class are not reentrant.
- * @version 1.5
+ * @version 1.6
*/
public class PointLocator {
diff --git a/src/com/vividsolutions/jts/algorithm/RobustCGAlgorithms.java b/src/com/vividsolutions/jts/algorithm/RobustCGAlgorithms.java
index 337a609..c7aba52 100644
--- a/src/com/vividsolutions/jts/algorithm/RobustCGAlgorithms.java
+++ b/src/com/vividsolutions/jts/algorithm/RobustCGAlgorithms.java
@@ -34,16 +34,13 @@
*/
package com.vividsolutions.jts.algorithm;
-import com.vividsolutions.jts.geom.DefaultCoordinateSequenceFactory;
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.CoordinateSequence;
-import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.geom.*;
/**
* Stub version of RobustCGAlgorithms for backwards compatibility.
* Will be deprecated in next release - use CGAlgorithms instead.
*
- * @version 1.5
+ * @version 1.6
*
*/
public class RobustCGAlgorithms extends CGAlgorithms {
diff --git a/src/com/vividsolutions/jts/algorithm/RobustDeterminant.java b/src/com/vividsolutions/jts/algorithm/RobustDeterminant.java
index ec81210..634b216 100644
--- a/src/com/vividsolutions/jts/algorithm/RobustDeterminant.java
+++ b/src/com/vividsolutions/jts/algorithm/RobustDeterminant.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.algorithm;
/**
- * @version 1.5
+ * @version 1.6
*/
/**
@@ -59,7 +59,7 @@ package com.vividsolutions.jts.algorithm;
**************************************************************************
* </pre>
*
- * @version 1.5
+ * @version 1.6
*/
public class RobustDeterminant {
diff --git a/src/com/vividsolutions/jts/algorithm/RobustLineIntersector.java b/src/com/vividsolutions/jts/algorithm/RobustLineIntersector.java
index de07869..9bdb4f2 100644
--- a/src/com/vividsolutions/jts/algorithm/RobustLineIntersector.java
+++ b/src/com/vividsolutions/jts/algorithm/RobustLineIntersector.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.algorithm;
/**
- *@version 1.5
+ *@version 1.6
*/
import com.vividsolutions.jts.geom.*;
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.util.Assert;
/**
* A robust version of {@LineIntersector}.
*
- * @version 1.5
+ * @version 1.6
* @see RobustDeterminant
*/
public class RobustLineIntersector
diff --git a/src/com/vividsolutions/jts/algorithm/SIRtreePointInRing.java b/src/com/vividsolutions/jts/algorithm/SIRtreePointInRing.java
index 008abbb..9ca4b79 100644
--- a/src/com/vividsolutions/jts/algorithm/SIRtreePointInRing.java
+++ b/src/com/vividsolutions/jts/algorithm/SIRtreePointInRing.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.index.strtree.*;
* using a {@link SIRtree} index to
* increase performance.
*
- * @version 1.5
+ * @version 1.6
*/
public class SIRtreePointInRing implements PointInRing {
diff --git a/src/com/vividsolutions/jts/algorithm/SimplePointInAreaLocator.java b/src/com/vividsolutions/jts/algorithm/SimplePointInAreaLocator.java
index 709ccaf..8322de4 100644
--- a/src/com/vividsolutions/jts/algorithm/SimplePointInAreaLocator.java
+++ b/src/com/vividsolutions/jts/algorithm/SimplePointInAreaLocator.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geom.*;
* The algorithm used is only guaranteed to return correct results
* for points which are <b>not</b> on the boundary of the Geometry.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimplePointInAreaLocator
{
diff --git a/src/com/vividsolutions/jts/algorithm/SimplePointInRing.java b/src/com/vividsolutions/jts/algorithm/SimplePointInRing.java
index b130fce..b9a8d1c 100644
--- a/src/com/vividsolutions/jts/algorithm/SimplePointInRing.java
+++ b/src/com/vividsolutions/jts/algorithm/SimplePointInRing.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.*;
* Tests whether a {@link Coordinate} lies inside
* a ring, using a linear-time algorithm.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimplePointInRing
implements PointInRing
diff --git a/src/com/vividsolutions/jts/geom/Coordinate.java b/src/com/vividsolutions/jts/geom/Coordinate.java
index a1685d9..1f56b46 100644
--- a/src/com/vividsolutions/jts/geom/Coordinate.java
+++ b/src/com/vividsolutions/jts/geom/Coordinate.java
@@ -52,7 +52,7 @@ import com.vividsolutions.jts.util.Assert;
* z-ordinate of <code>NaN</code>. The standard comparison functions will ignore
* the z-ordinate.
*
- *@version 1.5
+ *@version 1.6
*/
public class Coordinate implements Comparable, Cloneable, Serializable {
private static final long serialVersionUID = 6683108902428366910L;
diff --git a/src/com/vividsolutions/jts/geom/CoordinateArrays.java b/src/com/vividsolutions/jts/geom/CoordinateArrays.java
index 096865a..28fb2ba 100644
--- a/src/com/vividsolutions/jts/geom/CoordinateArrays.java
+++ b/src/com/vividsolutions/jts/geom/CoordinateArrays.java
@@ -39,7 +39,7 @@ import java.util.List;
/**
* Useful utility functions for handling Coordinate arrays
*
- * @version 1.5
+ * @version 1.6
*/
public class CoordinateArrays {
diff --git a/src/com/vividsolutions/jts/geom/CoordinateFilter.java b/src/com/vividsolutions/jts/geom/CoordinateFilter.java
index a530b5f..9a9a8c1 100644
--- a/src/com/vividsolutions/jts/geom/CoordinateFilter.java
+++ b/src/com/vividsolutions/jts/geom/CoordinateFilter.java
@@ -45,7 +45,7 @@ package com.vividsolutions.jts.geom;
* used to implement such things as coordinate transformations, centroid and
* envelope computation, and many other functions.
*
- *@version 1.5
+ *@version 1.6
*/
public interface CoordinateFilter {
diff --git a/src/com/vividsolutions/jts/geom/CoordinateList.java b/src/com/vividsolutions/jts/geom/CoordinateList.java
index 0e0c1c0..24c4776 100644
--- a/src/com/vividsolutions/jts/geom/CoordinateList.java
+++ b/src/com/vividsolutions/jts/geom/CoordinateList.java
@@ -43,7 +43,7 @@ import java.util.Iterator;
* be set to prevent repeated coordinates from occuring in the list.
*
*
- * @version 1.5
+ * @version 1.6
*/
public class CoordinateList
extends ArrayList
diff --git a/src/com/vividsolutions/jts/geom/CoordinateSequence.java b/src/com/vividsolutions/jts/geom/CoordinateSequence.java
index 4cf9b44..167288c 100644
--- a/src/com/vividsolutions/jts/geom/CoordinateSequence.java
+++ b/src/com/vividsolutions/jts/geom/CoordinateSequence.java
@@ -1,35 +1,34 @@
-
/*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
+* The JTS Topology Suite is a collection of Java classes that
+* implement the fundamental operations required to validate a given
+* geo-spatial data set to a known topological specification.
+*
+* Copyright (C) 2001 Vivid Solutions
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For more information, contact:
+*
+* Vivid Solutions
+* Suite #1A
+* 2328 Government Street
+* Victoria BC V8T 5G5
+* Canada
+*
+* (250)385-6040
+* www.vividsolutions.com
*/
package com.vividsolutions.jts.geom;
@@ -38,8 +37,8 @@ package com.vividsolutions.jts.geom;
* <p>
* There are some cases in which you might want Geometries to store their
* points using something other than the JTS Coordinate class. For example, you
- * may want to experiment with another implementation, such as an array of x�s
- * and an array of y�s. or you might want to use your own coordinate class, one
+ * may want to experiment with another implementation, such as an array of x's
+ * and an array of y's. Or you might want to use your own coordinate class, one
* that supports extra attributes like M-values.
* <p>
* You can do this by implementing the CoordinateSequence and
@@ -50,50 +49,126 @@ package com.vividsolutions.jts.geom;
* <p>
* For an example, see the code for
* {@link com.vividsolutions.jtsexample.geom.TwoArrayCoordinateSequenceExample}.
- * <p>
- * A note on performance. If your CoordinateSequence is not based on an array
- * of Coordinates, it may incur a performance penalty when its #toArray method
- * is called because the array needs to be built from scratch.
- *
+ *
* @see DefaultCoordinateSequenceFactory
* @see TwoArrayCoordinateSequenceFactory
*
- * @version 1.5
+ * @version 1.6
*/
-public interface CoordinateSequence extends Cloneable {
+public interface CoordinateSequence
+ extends Cloneable
+{
+ /**
+ * Standard ordinate index values
+ */
+ public static final int X = 0;
+ public static final int Y = 1;
+ public static final int Z = 2;
+ public static final int M = 3;
+
+ /**
+ * Returns (possibly a copy of) the i'th coordinate in this sequence.
+ * Whether or not the Coordinate returned is the actual underlying
+ * Coordinate or merely a copy depends on the implementation.
+ * <p>
+ * Note that in the future the semantics of this method may change
+ * to guarantee that the Coordinate returned is always a copy.
+ * Callers should not to assume that they can modify a CoordinateSequence by
+ * modifying the object returned by this method.
+ *
+ * @param i the index of the coordinate to retrieve
+ * @return the i'th coordinate in the sequence
+ */
+ public Coordinate getCoordinate(int i);
+
+ /**
+ * Returns a copy of the i'th coordinate in this sequence.
+ * This method optimizes the situation where the caller is
+ * going to make a copy anyway - if the implementation
+ * has already created a new Coordinate object, no further copy is needed.
+ *
+ * @param i the index of the coordinate to retrieve
+ * @return a copy of the i'th coordinate in the sequence
+ */
+ public Coordinate getCoordinateCopy(int i);
+
+ /**
+ * Copies the i'th coordinate in the sequence to the supplied
+ * {@link Coordinate}. Only the first two dimensions are copied.
+ *
+ * @param index the index of the coordinate to copy
+ * @param coord a {@link Coordinate} to receive the value
+ */
+ public void getCoordinate(int index, Coordinate coord);
+
+ /**
+ * Returns ordinate X (0) of the specified coordinate.
+ *
+ * @param index
+ * @return the value of the X ordinate in the index'th coordinate
+ */
+ public double getX(int index);
+
+ /**
+ * Returns ordinate Y (1) of the specified coordinate.
+ *
+ * @param index
+ * @return the value of the Y ordinate in the index'th coordinate
+ */
+ public double getY(int index);
+
+ /**
+ * Returns the ordinate of a coordinate in this sequence.
+ * Ordinate indices 0 and 1 are assumed to be X and Y.
+ * Ordinates indices greater than 1 have user-defined semantics
+ * (for instance, they may contain other dimensions or measure values).
+ *
+ * @param index the coordinate index in the sequence
+ * @param ordinateIndex the ordinate index in the coordinate (in range [0, dimension-1])
+ */
+ public double getOrdinate(int index, int ordinateIndex);
+
+ /**
+ * Returns the number of coordinates in this sequence.
+ * @return the size of the sequence
+ */
+ public int size();
+
+ /**
+ * Sets the value for a given ordinate of a coordinate in this sequence.
+ *
+ * @param index the coordinate index in the sequence
+ * @param ordinateIndex the ordinate index in the coordinate (in range [0, dimension-1])
+ * @param value the new ordinate value
+ */
+ public void setOrdinate(int index, int ordinateIndex, double value);
+
+ /**
+ * Returns (possibly copies of) the Coordinates in this collection.
+ * Whether or not the Coordinates returned are the actual underlying
+ * Coordinates or merely copies depends on the implementation. Note that
+ * if this implementation does not store its data as an array of Coordinates,
+ * this method will incur a performance penalty because the array needs to
+ * be built from scratch.
+ *
+ * @return a array of coordinates containing the point values in this sequence
+ */
+ public Coordinate[] toCoordinateArray();
- /**
- * Returns (possibly a copy of) the ith Coordinate in this collection.
- * Whether or not the Coordinate returned is the actual underlying
- * Coordinate or merely a copy depends on the implementation.
- * <p>
- * Note that in the future the semantics of this method may change
- * to guarantee that the Coordinate returned is always a copy. Callers are
- * advised not to assume that they can modify a CoordinateSequence by
- * modifying the Coordinate returned by this method.
- */
- public Coordinate getCoordinate(int i);
+ /**
+ * Expands the given {@link Envelope} to include the coordinates in the sequence.
+ * Allows implementing classes to optimize access to coordinate values.
+ *
+ * @param env the envelope to expand
+ * @return a ref to the expanded envelope
+ */
+ public Envelope expandEnvelope(Envelope env);
- /**
- * Returns the number of Coordinates (actual or
- * otherwise, as this implementation may not store its data in Coordinate
- * objects).
- */
- public int size();
-
- /**
- * Returns (possibly copies of) the Coordinates in this collection.
- * Whether or not the Coordinates returned are the actual underlying
- * Coordinates or merely copies depends on the implementation. Note that
- * if this implementation does not store its data as an array of Coordinates,
- * this method will incur a performance penalty because the array needs to
- * be built from scratch.
- */
- public Coordinate[] toCoordinateArray();
-
- /**
- * Returns a deep copy of this collection. Called by Geometry#clone.
- */
- public Object clone();
-
+ /**
+ * Returns a deep copy of this collection.
+ * Called by Geometry#clone.
+ *
+ * @return a copy of the coordinate sequence containing copies of all points
+ */
+ public Object clone();
}
diff --git a/src/com/vividsolutions/jts/geom/CoordinateSequenceFactory.java b/src/com/vividsolutions/jts/geom/CoordinateSequenceFactory.java
index ca382dd..3bda335 100644
--- a/src/com/vividsolutions/jts/geom/CoordinateSequenceFactory.java
+++ b/src/com/vividsolutions/jts/geom/CoordinateSequenceFactory.java
@@ -1,52 +1,73 @@
-
/*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
+* The JTS Topology Suite is a collection of Java classes that
+* implement the fundamental operations required to validate a given
+* geo-spatial data set to a known topological specification.
+*
+* Copyright (C) 2001 Vivid Solutions
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For more information, contact:
+*
+* Vivid Solutions
+* Suite #1A
+* 2328 Government Street
+* Victoria BC V8T 5G5
+* Canada
+*
+* (250)385-6040
+* www.vividsolutions.com
*/
package com.vividsolutions.jts.geom;
/**
- * An object that knows how to build a particular implementation of
- * CoordinateSequence from an array of Coordinates.
+ * A factory to create concrete instances of {@link CoordinateSequence}s.
*
- * @version 1.5
+ * @version 1.6
*/
-public interface CoordinateSequenceFactory {
-
+public interface CoordinateSequenceFactory
+{
+
+ /**
+ * Returns a {@link CoordinateSequence} based on the given array.
+ * Whether the array is copied or simply referenced
+ * is implementation-dependent.
+ * This method must handle null arguments by creating an empty sequence.
+ *
+ * @param coordinates the coordinates
+ */
+ public CoordinateSequence create(Coordinate[] coordinates);
+
/**
- * Returns a CoordinateSequence based on the given array; whether or not the
- * array is copied is implementation-dependent.
- * @param coordinates
- * the coordinates, which may not be null nor contain null
- * elements
+ * Creates a {@link CoordinateSequence} which is a copy
+ * of the given {@link CoordinateSequence}.
+ * This method must handle null arguments by creating an empty sequence.
+ *
+ * @param coordSeq the coordinate sequence to copy
*/
- public CoordinateSequence create(Coordinate[] coordinates);
+ public CoordinateSequence create(CoordinateSequence coordSeq);
+
+ /**
+ * Creates a {@link CoordinateSequence} of the specified size and dimension.
+ * For this to be useful, the {@link CoordinateSequence} implementation must
+ * be mutable.
+ *
+ * @param size the number of coordinates in the sequence
+ * @param dimension the dimension of the coordinates in the sequence (if user-specifiable,
+ * otherwise ignored)
+ */
+ public CoordinateSequence create(int size, int dimension);
+
}
diff --git a/src/com/vividsolutions/jts/geom/DefaultCoordinateSequence.java b/src/com/vividsolutions/jts/geom/DefaultCoordinateSequence.java
index 038f72c..901cc38 100644
--- a/src/com/vividsolutions/jts/geom/DefaultCoordinateSequence.java
+++ b/src/com/vividsolutions/jts/geom/DefaultCoordinateSequence.java
@@ -1,118 +1,214 @@
/*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
+* The JTS Topology Suite is a collection of Java classes that
+* implement the fundamental operations required to validate a given
+* geo-spatial data set to a known topological specification.
+*
+* Copyright (C) 2001 Vivid Solutions
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For more information, contact:
+*
+* Vivid Solutions
+* Suite #1A
+* 2328 Government Street
+* Victoria BC V8T 5G5
+* Canada
+*
+* (250)385-6040
+* www.vividsolutions.com
*/
package com.vividsolutions.jts.geom;
import java.io.Serializable;
+
/**
* The CoordinateSequence implementation that Geometries use by default. In
* this implementation, Coordinates returned by #toArray and #get are live --
* parties that change them are actually changing the
* DefaultCoordinateSequence's underlying data.
- *
- * @version 1.5
+ *
+ * @version 1.6
+ *
+ * @deprecated no longer used
*/
-class DefaultCoordinateSequence implements CoordinateSequence, Serializable {
- //With contributions from Markus Schaber [schabios at logi-track.com] 2004-03-26
- private static final long serialVersionUID = -915438501601840650L;
- private Coordinate[] coordinates;
- /**
- * Constructs a DefaultCoordinateSequence based on the given array (the
- * array is not copied).
- *
- * @param coordinates
- * The coordinate array that will be assimilated.
- */
- public DefaultCoordinateSequence(Coordinate[] coordinates) {
- if (Geometry.hasNullElements(coordinates)) {
- throw new IllegalArgumentException("Null coordinate");
- }
- this.coordinates = coordinates;
- }
- /**
- * Get the Coordinate with index i.
- *
- * @param i
- * the index of the coordinate
- * @return the requested Coordinate instance
- */
- public Coordinate getCoordinate(int i) {
- return coordinates[i];
- }
- /**
- * Creates a deep copy of the Object
- *
- * @return The deep copy
- */
- public Object clone() {
- Coordinate[] cloneCoordinates = new Coordinate[size()];
- for (int i = 0; i < coordinates.length; i++) {
- cloneCoordinates[i] = (Coordinate) coordinates[i].clone();
- }
- return new DefaultCoordinateSequence(cloneCoordinates);
- }
- /**
- * Returns the size of the coordinate sequence
- *
- * @return the number of coordinates
- */
- public int size() {
- return coordinates.length;
- }
- /**
- * This method exposes the internal Array of Coordinate Objects
- *
- * @return the Coordinate[] array.
- */
- public Coordinate[] toCoordinateArray() {
- return coordinates;
- }
- /**
- * Returns the string Representation of the coordinate array
- *
- * @return The string
- */
- public String toString() {
- if (coordinates.length > 0) {
- StringBuffer strBuf = new StringBuffer(17 * coordinates.length);
- strBuf.append('(');
- strBuf.append(coordinates[0]);
- for (int i = 1; i < coordinates.length; i++) {
- strBuf.append(", ");
- strBuf.append(coordinates[i]);
- }
- strBuf.append(')');
- return strBuf.toString();
- } else {
- return "()";
- }
- }
+class DefaultCoordinateSequence
+ implements CoordinateSequence, Serializable
+{
+ //With contributions from Markus Schaber [schabios at logi-track.com] 2004-03-26
+ private static final long serialVersionUID = -915438501601840650L;
+ private Coordinate[] coordinates;
+
+ /**
+ * Constructs a DefaultCoordinateSequence based on the given array (the
+ * array is not copied).
+ *
+ * @param coordinates the coordinate array that will be referenced.
+ */
+ public DefaultCoordinateSequence(Coordinate[] coordinates) {
+ if (Geometry.hasNullElements(coordinates)) {
+ throw new IllegalArgumentException("Null coordinate");
+ }
+ this.coordinates = coordinates;
+ }
+
+ /**
+ * Constructs a DefaultCoordinateSequence based on the given array (the
+ * array is not copied).
+ *
+ * @param coordinates the coordinate array that will be referenced.
+ */
+ public DefaultCoordinateSequence(CoordinateSequence coordSeq) {
+ coordinates = new Coordinate[coordSeq.size()];
+ for (int i = 0; i < coordinates.length; i++) {
+ coordinates[i] = coordSeq.getCoordinateCopy(i);
+ }
+ }
+
+ /**
+ * Constructs a sequence of a given size, populated
+ * with new {@link Coordinate}s.
+ *
+ * @param size the size of the sequence to create
+ */
+ public DefaultCoordinateSequence(int size) {
+ coordinates = new Coordinate[size];
+ for (int i = 0; i < size; i++) {
+ coordinates[i] = new Coordinate();
+ }
+ }
+
+ /**
+ * Get the Coordinate with index i.
+ *
+ * @param i
+ * the index of the coordinate
+ * @return the requested Coordinate instance
+ */
+ public Coordinate getCoordinate(int i) {
+ return coordinates[i];
+ }
+ /**
+ * Get a copy of the Coordinate with index i.
+ *
+ * @param i the index of the coordinate
+ * @return a copy of the requested Coordinate
+ */
+ public Coordinate getCoordinateCopy(int i) {
+ return new Coordinate(coordinates[i]);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public void getCoordinate(int index, Coordinate coord) {
+ coord.x = coordinates[index].x;
+ coord.y = coordinates[index].y;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public double getX(int index) {
+ return coordinates[index].x;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int)
+ */
+ public double getY(int index) {
+ return coordinates[index].y;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int)
+ */
+ public double getOrdinate(int index, int ordinateIndex)
+ {
+ switch (ordinateIndex) {
+ case CoordinateSequence.X: return coordinates[index].x;
+ case CoordinateSequence.Y: return coordinates[index].y;
+ case CoordinateSequence.Z: return coordinates[index].z;
+ }
+ return Double.NaN;
+ }
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#setOrdinate(int, int, double)
+ */
+ public void setOrdinate(int index, int ordinateIndex, double value)
+ {
+ switch (ordinateIndex) {
+ case CoordinateSequence.X: coordinates[index].x = value;
+ case CoordinateSequence.Y: coordinates[index].y = value;
+ case CoordinateSequence.Z: coordinates[index].z = value;
+ }
+ }
+ /**
+ * Creates a deep copy of the Object
+ *
+ * @return The deep copy
+ */
+ public Object clone() {
+ Coordinate[] cloneCoordinates = new Coordinate[size()];
+ for (int i = 0; i < coordinates.length; i++) {
+ cloneCoordinates[i] = (Coordinate) coordinates[i].clone();
+ }
+ return new DefaultCoordinateSequence(cloneCoordinates);
+ }
+ /**
+ * Returns the size of the coordinate sequence
+ *
+ * @return the number of coordinates
+ */
+ public int size() {
+ return coordinates.length;
+ }
+ /**
+ * This method exposes the internal Array of Coordinate Objects
+ *
+ * @return the Coordinate[] array.
+ */
+ public Coordinate[] toCoordinateArray() {
+ return coordinates;
+ }
+
+ public Envelope expandEnvelope(Envelope env)
+ {
+ for (int i = 0; i < coordinates.length; i++ ) {
+ env.expandToInclude(coordinates[i]);
+ }
+ return env;
+ }
+
+ /**
+ * Returns the string Representation of the coordinate array
+ *
+ * @return The string
+ */
+ public String toString() {
+ if (coordinates.length > 0) {
+ StringBuffer strBuf = new StringBuffer(17 * coordinates.length);
+ strBuf.append('(');
+ strBuf.append(coordinates[0]);
+ for (int i = 1; i < coordinates.length; i++) {
+ strBuf.append(", ");
+ strBuf.append(coordinates[i]);
+ }
+ strBuf.append(')');
+ return strBuf.toString();
+ } else {
+ return "()";
+ }
+ }
}
diff --git a/src/com/vividsolutions/jts/geom/DefaultCoordinateSequenceFactory.java b/src/com/vividsolutions/jts/geom/DefaultCoordinateSequenceFactory.java
index bcf0a19..80f2c2c 100644
--- a/src/com/vividsolutions/jts/geom/DefaultCoordinateSequenceFactory.java
+++ b/src/com/vividsolutions/jts/geom/DefaultCoordinateSequenceFactory.java
@@ -1,68 +1,69 @@
/*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
+* The JTS Topology Suite is a collection of Java classes that
+* implement the fundamental operations required to validate a given
+* geo-spatial data set to a known topological specification.
+*
+* Copyright (C) 2001 Vivid Solutions
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For more information, contact:
+*
+* Vivid Solutions
+* Suite #1A
+* 2328 Government Street
+* Victoria BC V8T 5G5
+* Canada
+*
+* (250)385-6040
+* www.vividsolutions.com
*/
package com.vividsolutions.jts.geom;
import java.io.Serializable;
/**
- * Creates CoordinateSequences internally represented as an array of x's and
- * an array of y's.
+ * Creates CoordinateSequences represented as an array of {@link Coordinate}s.
*
- * @version 1.5
+ * @version 1.6
+ *
+ * @deprecated no longer used
*/
public class DefaultCoordinateSequenceFactory
implements CoordinateSequenceFactory, Serializable
{
- private static final long serialVersionUID = -4099577099607551657L;
- private static DefaultCoordinateSequenceFactory instance = new DefaultCoordinateSequenceFactory();
+ private static final long serialVersionUID = -4099577099607551657L;
+ private static final DefaultCoordinateSequenceFactory instance = new DefaultCoordinateSequenceFactory();
+
+ public DefaultCoordinateSequenceFactory() {
+ }
- private DefaultCoordinateSequenceFactory() {
- }
-
- /**
- * @see http://www.javaworld.com/javaworld/javatips/jw-javatip122.html
- */
- private Object readResolve() {
- return DefaultCoordinateSequenceFactory.instance();
- }
+ /**
+ * @see http://www.javaworld.com/javaworld/javatips/jw-javatip122.html
+ */
+ private Object readResolve() {
+ return DefaultCoordinateSequenceFactory.instance();
+ }
- /**
- * Returns the singleton instance of DefaultCoordinateSequenceFactory
- */
- public static DefaultCoordinateSequenceFactory instance() {
- return instance;
- }
+ /**
+ * Returns the singleton instance of DefaultCoordinateSequenceFactory
+ */
+ public static DefaultCoordinateSequenceFactory instance() {
+ return instance;
+ }
@@ -74,8 +75,21 @@ public class DefaultCoordinateSequenceFactory
* the coordinates, which may not be null nor contain null
* elements
*/
+ public CoordinateSequence create(Coordinate[] coordinates) {
+ return new DefaultCoordinateSequence(coordinates);
+ }
- public CoordinateSequence create(Coordinate[] coordinates) {
- return new DefaultCoordinateSequence(coordinates);
- }
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.CoordinateSequence)
+ */
+ public CoordinateSequence create(CoordinateSequence coordSeq) {
+ return new DefaultCoordinateSequence(coordSeq);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int, int)
+ */
+ public CoordinateSequence create(int size, int dimension) {
+ return new DefaultCoordinateSequence(size);
+ }
}
diff --git a/src/com/vividsolutions/jts/geom/Dimension.java b/src/com/vividsolutions/jts/geom/Dimension.java
index a777f89..0feda20 100644
--- a/src/com/vividsolutions/jts/geom/Dimension.java
+++ b/src/com/vividsolutions/jts/geom/Dimension.java
@@ -39,7 +39,7 @@ package com.vividsolutions.jts.geom;
* Also, constants representing the dimensions of the empty geometry and
* non-empty geometries, and a wildcard dimension meaning "any dimension".
*
- * @version 1.5
+ * @version 1.6
*/
public class Dimension {
diff --git a/src/com/vividsolutions/jts/geom/Envelope.java b/src/com/vividsolutions/jts/geom/Envelope.java
index bcf6751..47bcc11 100644
--- a/src/com/vividsolutions/jts/geom/Envelope.java
+++ b/src/com/vividsolutions/jts/geom/Envelope.java
@@ -47,7 +47,7 @@ import java.io.Serializable;
* When Envelope objects are created or initialized,
* the supplies extent values are automatically sorted into the correct order.
*
- *@version 1.5
+ *@version 1.6
*/
public class Envelope
implements Serializable
diff --git a/src/com/vividsolutions/jts/geom/Geometry.java b/src/com/vividsolutions/jts/geom/Geometry.java
index b2df75a..f938524 100644
--- a/src/com/vividsolutions/jts/geom/Geometry.java
+++ b/src/com/vividsolutions/jts/geom/Geometry.java
@@ -43,6 +43,8 @@ import com.vividsolutions.jts.io.WKTWriter;
import com.vividsolutions.jts.operation.buffer.BufferOp;
import com.vividsolutions.jts.operation.distance.DistanceOp;
import com.vividsolutions.jts.operation.overlay.OverlayOp;
+import com.vividsolutions.jts.operation.predicate.RectangleIntersects;
+import com.vividsolutions.jts.operation.predicate.RectangleContains;
import com.vividsolutions.jts.operation.relate.RelateOp;
import com.vividsolutions.jts.operation.valid.IsValidOp;
import com.vividsolutions.jts.util.Assert;
@@ -124,7 +126,7 @@ import com.vividsolutions.jts.util.Assert;
* topologically equal Geometries are added to HashMaps and HashSets, they
* remain distinct. This behaviour is desired in many cases.
*
- *@version 1.5
+ *@version 1.6
*/
public abstract class Geometry
implements Cloneable, Comparable, Serializable
@@ -160,7 +162,8 @@ public abstract class Geometry
private GeometryFactory factory;
- private static final GeometryFactory INTERNAL_GEOMETRY_FACTORY = new GeometryFactory();
+ // MD - no longer used. Remove in next version
+ //private static final GeometryFactory INTERNAL_GEOMETRY_FACTORY = new GeometryFactory();
/**
* The ID of the Spatial Reference System used by this <code>Geometry</code>
@@ -261,6 +264,28 @@ public abstract class Geometry
}
/**
+ * Returns the number of {@link Geometry}s in a {@link GeometryCollection}
+ * (or 1, if the geometry is not a collection).
+ *
+ * @return the number of geometries contained in this geometry
+ */
+ public int getNumGeometries() {
+ return 1;
+ }
+
+ /**
+ * Returns an element {@link Geometry} from a {@link GeometryCollection}
+ * (or <code>this</code>, if the geometry is not a collection).
+ *
+ * @param n the index of the geometry element
+ * @return the n'th geometry contained in this geometry
+ */
+ public Geometry getGeometryN(int n) {
+ return this;
+ }
+
+
+ /**
* A simple scheme for applications to add their own custom data to a Geometry.
* An example use might be to add an object representing a Coordinate Reference System.
* <p>
@@ -339,7 +364,7 @@ public abstract class Geometry
*/
public boolean isValid()
{
- IsValidOp isValidOp = new IsValidOp(toInternalGeometry(this));
+ IsValidOp isValidOp = new IsValidOp(this);
return isValidOp.isValid();
}
@@ -360,7 +385,7 @@ public abstract class Geometry
*/
public double distance(Geometry g)
{
- return DistanceOp.distance(toInternalGeometry(this), toInternalGeometry(g));
+ return DistanceOp.distance(this, g);
}
/**
@@ -382,6 +407,13 @@ public abstract class Geometry
return false;
return true;
}
+
+ public boolean isRectangle()
+ {
+ // Polygon overrides to check for actual rectangle
+ return false;
+ }
+
/**
* Returns the area of this <code>Geometry</code>.
* Areal Geometries have a non-zero area.
@@ -425,17 +457,17 @@ public abstract class Geometry
int dim = getDimension();
if (dim == 0) {
CentroidPoint cent = new CentroidPoint();
- cent.add(toInternalGeometry(this));
+ cent.add(this);
centPt = cent.getCentroid();
}
else if (dim == 1) {
CentroidLine cent = new CentroidLine();
- cent.add(toInternalGeometry(this));
+ cent.add(this);
centPt = cent.getCentroid();
}
else {
CentroidArea cent = new CentroidArea();
- cent.add(toInternalGeometry(this));
+ cent.add(this);
centPt = cent.getCentroid();
}
return createPointFromInternalCoord(centPt, this);
@@ -455,15 +487,15 @@ public abstract class Geometry
Coordinate interiorPt = null;
int dim = getDimension();
if (dim == 0) {
- InteriorPointPoint intPt = new InteriorPointPoint(toInternalGeometry(this));
+ InteriorPointPoint intPt = new InteriorPointPoint(this);
interiorPt = intPt.getInteriorPoint();
}
else if (dim == 1) {
- InteriorPointLine intPt = new InteriorPointLine(toInternalGeometry(this));
+ InteriorPointLine intPt = new InteriorPointLine(this);
interiorPt = intPt.getInteriorPoint();
}
else {
- InteriorPointArea intPt = new InteriorPointArea(toInternalGeometry(this));
+ InteriorPointArea intPt = new InteriorPointArea(this);
interiorPt = intPt.getInteriorPoint();
}
return createPointFromInternalCoord(interiorPt, this);
@@ -552,10 +584,7 @@ public abstract class Geometry
* disjoint
*/
public boolean disjoint(Geometry g) {
- // short-circuit test
- if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
- return true;
- return relate(g).isDisjoint();
+ return ! intersects(g);
}
/**
@@ -580,9 +609,17 @@ public abstract class Geometry
*@return <code>true</code> if the two <code>Geometry</code>s intersect
*/
public boolean intersects(Geometry g) {
- // short-circuit test
+ // short-circuit envelope test
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
return false;
+ // optimizations for rectangle arguments
+ if (isRectangle()) {
+ return RectangleIntersects.intersects((Polygon) this, g);
+ }
+ if (g.isRectangle()) {
+ return RectangleIntersects.intersects((Polygon) g, this);
+ }
+ // general case
return relate(g).isIntersects();
}
@@ -618,10 +655,7 @@ public abstract class Geometry
* <code>other</code>
*/
public boolean within(Geometry g) {
- // short-circuit test
- if (! getEnvelopeInternal().contains(g.getEnvelopeInternal()))
- return false;
- return relate(g).isWithin();
+ return g.contains(this);
}
/**
@@ -636,6 +670,11 @@ public abstract class Geometry
// short-circuit test
if (! getEnvelopeInternal().contains(g.getEnvelopeInternal()))
return false;
+ // optimizations for rectangle arguments
+ if (isRectangle()) {
+ return RectangleContains.contains((Polygon) this, g);
+ }
+ // general case
return relate(g).isContains();
}
@@ -696,7 +735,7 @@ public abstract class Geometry
public IntersectionMatrix relate(Geometry g) {
checkNotGeometryCollection(this);
checkNotGeometryCollection(g);
- return RelateOp.relate(toInternalGeometry(this), toInternalGeometry(g));
+ return RelateOp.relate(this, g);
}
/**
@@ -745,32 +784,11 @@ public abstract class Geometry
* are less than or equal to <code>distance</code>
*/
public Geometry buffer(double distance) {
- return fromInternalGeometry(BufferOp.bufferOp(toInternalGeometry(this), distance));
- }
-
- /**
- * The JTS algorithms assume that Geometry#getCoordinate and #getCoordinates
- * are fast, which may not be the case if the CoordinateSequence is not a
- * BasicCoordinateSequence (e.g. if it were implemented using separate arrays
- * for the x- and y-values), in which case frequent construction of Coordinates
- * takes up much space and time. To solve this performance problem,
- * #toInternalGeometry converts the Geometry to a BasicCoordinateSequence
- * implementation before sending it to the JTS algorithms.
- */
- protected Geometry toInternalGeometry(Geometry g) {
- if (DefaultCoordinateSequenceFactory.instance().equals(
- factory.getCoordinateSequenceFactory())) { return g; }
- return INTERNAL_GEOMETRY_FACTORY.createGeometry(g);
- }
-
- protected Geometry fromInternalGeometry(Geometry g) {
- if (DefaultCoordinateSequenceFactory.instance().equals(
- factory.getCoordinateSequenceFactory())) { return g; }
- return getFactory().createGeometry(g);
+ return BufferOp.bufferOp(this, distance);
}
/**
- * Returns a buffer region around this <code>Geometry</code> having the given
+ * Returns a buffer region around this {@link Geometry} having the given
* width and with a specified number of segments used to approximate curves.
* The buffer of a Geometry is the Minkowski sum of the Geometry with
* a disc of radius <code>distance</code>. Curves in the buffer polygon are
@@ -784,7 +802,7 @@ public abstract class Geometry
* are less than or equal to <code>distance</code>
*/
public Geometry buffer(double distance, int quadrantSegments) {
- return fromInternalGeometry(BufferOp.bufferOp(toInternalGeometry(this), distance, quadrantSegments));
+ return BufferOp.bufferOp(this, distance, quadrantSegments);
}
/**
@@ -818,7 +836,7 @@ public abstract class Geometry
* s points
*/
public Geometry convexHull() {
- return fromInternalGeometry((new ConvexHull(toInternalGeometry(this))).getConvexHull());
+ return (new ConvexHull(this)).getConvexHull();
}
/**
@@ -832,7 +850,7 @@ public abstract class Geometry
public Geometry intersection(Geometry other) {
checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
- return fromInternalGeometry(OverlayOp.overlayOp(toInternalGeometry(this), toInternalGeometry(other), OverlayOp.INTERSECTION));
+ return OverlayOp.overlayOp(this, other, OverlayOp.INTERSECTION);
}
/**
@@ -846,7 +864,7 @@ public abstract class Geometry
public Geometry union(Geometry other) {
checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
- return fromInternalGeometry(OverlayOp.overlayOp(toInternalGeometry(this), toInternalGeometry(other), OverlayOp.UNION));
+ return OverlayOp.overlayOp(this, other, OverlayOp.UNION);
}
/**
@@ -862,7 +880,7 @@ public abstract class Geometry
public Geometry difference(Geometry other) {
checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
- return fromInternalGeometry(OverlayOp.overlayOp(toInternalGeometry(this), toInternalGeometry(other), OverlayOp.DIFFERENCE));
+ return OverlayOp.overlayOp(this, other, OverlayOp.DIFFERENCE);
}
/**
@@ -879,7 +897,7 @@ public abstract class Geometry
public Geometry symDifference(Geometry other) {
checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
- return fromInternalGeometry(OverlayOp.overlayOp(toInternalGeometry(this), toInternalGeometry(other), OverlayOp.SYMDIFFERENCE));
+ return OverlayOp.overlayOp(this, other, OverlayOp.SYMDIFFERENCE);
}
/**
diff --git a/src/com/vividsolutions/jts/geom/GeometryCollection.java b/src/com/vividsolutions/jts/geom/GeometryCollection.java
index 23589c7..b730461 100644
--- a/src/com/vividsolutions/jts/geom/GeometryCollection.java
+++ b/src/com/vividsolutions/jts/geom/GeometryCollection.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.util.Assert;
/**
* Basic implementation of <code>GeometryCollection</code>.
*
- *@version 1.5
+ *@version 1.6
*/
public class GeometryCollection extends Geometry {
// With contributions from Markus Schaber [schabios at logi-track.com] 2004-03-26
@@ -54,7 +54,7 @@ public class GeometryCollection extends Geometry {
/** @deprecated Use GeometryFactory instead */
public GeometryCollection(Geometry[] geometries, PrecisionModel precisionModel, int SRID) {
- this(geometries, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ this(geometries, new GeometryFactory(precisionModel, SRID));
}
@@ -83,11 +83,11 @@ public class GeometryCollection extends Geometry {
/**
* Collects all coordinates of all subgeometries into an Array.
- *
+ *
* Note that while changes to the coordinate objects themselves
- * may modify the Geometries in place, the returned Array as such
+ * may modify the Geometries in place, the returned Array as such
* is only a temporary container which is not synchronized back.
- *
+ *
* @return the collected coordinates
* */
public Coordinate[] getCoordinates() {
diff --git a/src/com/vividsolutions/jts/geom/GeometryCollectionIterator.java b/src/com/vividsolutions/jts/geom/GeometryCollectionIterator.java
index 0be438f..8fd21e3 100644
--- a/src/com/vividsolutions/jts/geom/GeometryCollectionIterator.java
+++ b/src/com/vividsolutions/jts/geom/GeometryCollectionIterator.java
@@ -45,14 +45,14 @@ import java.util.NoSuchElementException;
* simple to ignore the <code>GeometryCollection</code> objects if they are not
* needed.
*
- *@version 1.5
+ *@version 1.6
*/
public class GeometryCollectionIterator implements Iterator {
/**
* The <code>GeometryCollection</code> being iterated over.
*/
- private GeometryCollection parent;
+ private Geometry parent;
/**
* Indicates whether or not the first element (the <code>GeometryCollection</code>
* ) has been returned.
@@ -81,7 +81,7 @@ public class GeometryCollectionIterator implements Iterator {
*@param parent the collection over which to iterate; also, the first
* element returned by the iterator.
*/
- public GeometryCollectionIterator(GeometryCollection parent) {
+ public GeometryCollectionIterator(Geometry parent) {
this.parent = parent;
atStart = true;
index = 0;
diff --git a/src/com/vividsolutions/jts/geom/GeometryComponentFilter.java b/src/com/vividsolutions/jts/geom/GeometryComponentFilter.java
index 7c5947e..6eb8058 100644
--- a/src/com/vividsolutions/jts/geom/GeometryComponentFilter.java
+++ b/src/com/vividsolutions/jts/geom/GeometryComponentFilter.java
@@ -49,7 +49,7 @@ package com.vividsolutions.jts.geom;
* <code>GeometryComponentFilter</code>
* is an example of the Gang-of-Four Visitor pattern.
*
- *@version 1.5
+ *@version 1.6
*/
public interface GeometryComponentFilter {
diff --git a/src/com/vividsolutions/jts/geom/GeometryFactory.java b/src/com/vividsolutions/jts/geom/GeometryFactory.java
index 00e2a53..967d56b 100644
--- a/src/com/vividsolutions/jts/geom/GeometryFactory.java
+++ b/src/com/vividsolutions/jts/geom/GeometryFactory.java
@@ -36,6 +36,7 @@ package com.vividsolutions.jts.geom;
import java.util.*;
import java.io.Serializable;
+import com.vividsolutions.jts.geom.impl.*;
import com.vividsolutions.jts.geom.util.*;
import com.vividsolutions.jts.util.Assert;
@@ -43,7 +44,7 @@ import com.vividsolutions.jts.util.Assert;
* Supplies a set of utility methods for building Geometry objects from lists
* of Coordinates.
*
- * @version 1.5
+ * @version 1.6
*/
public class GeometryFactory
implements Serializable
@@ -88,7 +89,7 @@ public class GeometryFactory
* @param precisionModel the PrecisionModel to use
*/
public GeometryFactory(PrecisionModel precisionModel) {
- this(precisionModel, 0, DefaultCoordinateSequenceFactory.instance());
+ this(precisionModel, 0, getDefaultCoordinateSequenceFactory());
}
/**
@@ -100,7 +101,7 @@ public class GeometryFactory
* @param SRID the SRID to use
*/
public GeometryFactory(PrecisionModel precisionModel, int SRID) {
- this(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance());
+ this(precisionModel, SRID, getDefaultCoordinateSequenceFactory());
}
/**
@@ -111,6 +112,11 @@ public class GeometryFactory
this(new PrecisionModel(), 0);
}
+ private static CoordinateSequenceFactory getDefaultCoordinateSequenceFactory()
+ {
+ return CoordinateArraySequenceFactory.instance();
+ }
+
/**
* Converts the <code>List</code> to an array.
*
diff --git a/src/com/vividsolutions/jts/geom/GeometryFilter.java b/src/com/vividsolutions/jts/geom/GeometryFilter.java
index 52f9aa8..8eaec5e 100644
--- a/src/com/vividsolutions/jts/geom/GeometryFilter.java
+++ b/src/com/vividsolutions/jts/geom/GeometryFilter.java
@@ -44,7 +44,7 @@ package com.vividsolutions.jts.geom;
* <code>GeometryFilter</code>
* is an example of the Gang-of-Four Visitor pattern.
*
- *@version 1.5
+ *@version 1.6
*/
public interface GeometryFilter {
diff --git a/src/com/vividsolutions/jts/geom/IntersectionMatrix.java b/src/com/vividsolutions/jts/geom/IntersectionMatrix.java
index 50c45c1..7033a73 100644
--- a/src/com/vividsolutions/jts/geom/IntersectionMatrix.java
+++ b/src/com/vividsolutions/jts/geom/IntersectionMatrix.java
@@ -52,7 +52,7 @@ package com.vividsolutions.jts.geom;
* HREF="http://www.opengis.org/techno/specs.htm">OpenGIS Simple Features
* Specification for SQL</A> .
*
- *@version 1.5
+ *@version 1.6
*/
public class IntersectionMatrix implements Cloneable {
/**
diff --git a/src/com/vividsolutions/jts/geom/LineSegment.java b/src/com/vividsolutions/jts/geom/LineSegment.java
index 305948b..49c40bf 100644
--- a/src/com/vividsolutions/jts/geom/LineSegment.java
+++ b/src/com/vividsolutions/jts/geom/LineSegment.java
@@ -49,7 +49,7 @@ import com.vividsolutions.jts.algorithm.*;
* object as a way of computing segment properties on the
* segments defined by arrays or lists of {@link Coordinate}s.
*
- *@version 1.5
+ *@version 1.6
*/
public class LineSegment
implements Comparable, Serializable
diff --git a/src/com/vividsolutions/jts/geom/LineString.java b/src/com/vividsolutions/jts/geom/LineString.java
index c9d4407..3e998ab 100644
--- a/src/com/vividsolutions/jts/geom/LineString.java
+++ b/src/com/vividsolutions/jts/geom/LineString.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.operation.IsSimpleOp;
/**
* Basic implementation of <code>LineString</code>.
*
- *@version 1.5
+ *@version 1.6
*/
public class LineString extends Geometry {
private static final long serialVersionUID = 3110669828065365560L;
@@ -60,32 +60,36 @@ public class LineString extends Geometry {
*@param SRID the ID of the Spatial Reference System used by this
* <code>LineString</code>
*/
- /** @deprecated Use GeometryFactory instead */
- public LineString(Coordinate points[], PrecisionModel precisionModel, int SRID) {
- this(DefaultCoordinateSequenceFactory.instance()
- .create(points == null ? new Coordinate[]{} : points),
- new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ /** @deprecated Use GeometryFactory instead */
+ public LineString(Coordinate points[], PrecisionModel precisionModel, int SRID)
+ {
+ super(new GeometryFactory(precisionModel, SRID));
+ init(getFactory().getCoordinateSequenceFactory().create(points));
}
-
+
/**
*@param points the points of the linestring, or <code>null</code>
* to create the empty geometry. Consecutive points may not be equal.
- */
+ */
public LineString(CoordinateSequence points, GeometryFactory factory) {
super(factory);
+ init(points);
+ }
+
+ private void init(CoordinateSequence points)
+ {
if (points == null) {
- points = factory.getCoordinateSequenceFactory().create(new Coordinate[]{});
- }
+ points = getFactory().getCoordinateSequenceFactory().create(new Coordinate[]{});
+ }
if (points.size() == 1) {
throw new IllegalArgumentException("point array must contain 0 or >1 elements");
}
this.points = points;
}
-
public Coordinate[] getCoordinates() {
return points.toCoordinateArray();
- }
-
+ }
+
public CoordinateSequence getCoordinateSequence() {
return points;
}
@@ -158,13 +162,13 @@ public class LineString extends Geometry {
*@return the area of the polygon
*/
public double getLength()
- {
+ {
return CGAlgorithms.length(points);
}
public boolean isSimple()
{
- return (new IsSimpleOp()).isSimple((LineString)toInternalGeometry(this));
+ return (new IsSimpleOp()).isSimple(this);
}
public Geometry getBoundary() {
@@ -201,6 +205,8 @@ public class LineString extends Geometry {
if (isEmpty()) {
return new Envelope();
}
+ return points.expandEnvelope(new Envelope());
+ /*
//Convert to array, then access array directly, to avoid the function-call overhead
//of calling #get millions of times. #toArray may be inefficient for
//non-BasicCoordinateSequence CoordinateSequences. [Jon Aquino]
@@ -210,7 +216,7 @@ public class LineString extends Geometry {
double maxx = coordinates[0].x;
double maxy = coordinates[0].y;
//OptimizeIt shows that Math#min and Math#max here are a bottleneck.
- //Replace with direct comparisons. [Jon Aquino]
+ //Replace with direct comparisons. [Jon Aquino]
for (int i = 1; i < coordinates.length; i++) {
minx = minx < coordinates[i].x ? minx : coordinates[i].x;
maxx = maxx > coordinates[i].x ? maxx : coordinates[i].x;
@@ -218,8 +224,9 @@ public class LineString extends Geometry {
maxy = maxy > coordinates[i].y ? maxy : coordinates[i].y;
}
return new Envelope(minx, maxx, miny, maxy);
+ */
}
-
+
public boolean equalsExact(Geometry other, double tolerance) {
if (!isEquivalentClass(other)) {
return false;
diff --git a/src/com/vividsolutions/jts/geom/LinearRing.java b/src/com/vividsolutions/jts/geom/LinearRing.java
index 894ac28..990df10 100644
--- a/src/com/vividsolutions/jts/geom/LinearRing.java
+++ b/src/com/vividsolutions/jts/geom/LinearRing.java
@@ -40,7 +40,7 @@ package com.vividsolutions.jts.geom;
* Either orientation of the ring is allowed.
* A valid ring must not self-intersect.
*
- *@version 1.5
+ *@version 1.6
*/
public class LinearRing extends LineString
{
@@ -60,9 +60,17 @@ public class LinearRing extends LineString
*/
public LinearRing(Coordinate points[], PrecisionModel precisionModel,
int SRID) {
- this(DefaultCoordinateSequenceFactory.instance()
- .create(points == null ? new Coordinate[]{} : points),
- new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ this(points, new GeometryFactory(precisionModel, SRID));
+ validateConstruction();
+ }
+
+ /**
+ * This method is ONLY used to avoid deprecation warnings.
+ * @param points
+ * @param factory
+ */
+ private LinearRing(Coordinate points[], GeometryFactory factory) {
+ this(factory.getCoordinateSequenceFactory().create(points), factory);
}
diff --git a/src/com/vividsolutions/jts/geom/Location.java b/src/com/vividsolutions/jts/geom/Location.java
index f3c644f..59ad532 100644
--- a/src/com/vividsolutions/jts/geom/Location.java
+++ b/src/com/vividsolutions/jts/geom/Location.java
@@ -41,7 +41,7 @@ package com.vividsolutions.jts.geom;
* HREF="http://www.opengis.org/techno/specs.htm">OpenGIS Simple Features
* Specification for SQL</A> .
*
- *@version 1.5
+ *@version 1.6
*/
public class Location {
/**
diff --git a/src/com/vividsolutions/jts/geom/MultiLineString.java b/src/com/vividsolutions/jts/geom/MultiLineString.java
index 280f55f..7ee1daa 100644
--- a/src/com/vividsolutions/jts/geom/MultiLineString.java
+++ b/src/com/vividsolutions/jts/geom/MultiLineString.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.operation.IsSimpleOp;
/**
* Basic implementation of <code>MultiLineString</code>.
*
- *@version 1.5
+ *@version 1.6
*/
public class MultiLineString extends GeometryCollection {
private static final long serialVersionUID = 8166665132445433741L;
@@ -59,11 +59,11 @@ public class MultiLineString extends GeometryCollection {
* @deprecated Use GeometryFactory instead
*/
public MultiLineString(LineString[] lineStrings, PrecisionModel precisionModel, int SRID) {
- super(lineStrings, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ super(lineStrings, new GeometryFactory(precisionModel, SRID));
}
-
-
-
+
+
+
/**
* @param lineStrings
* the <code>LineString</code>s for this <code>MultiLineString</code>,
@@ -73,7 +73,7 @@ public class MultiLineString extends GeometryCollection {
*/
public MultiLineString(LineString[] lineStrings, GeometryFactory factory) {
super(lineStrings, factory);
- }
+ }
public int getDimension() {
return 1;
@@ -104,14 +104,14 @@ public class MultiLineString extends GeometryCollection {
public boolean isSimple()
{
- return (new IsSimpleOp()).isSimple((MultiLineString)toInternalGeometry(this));
+ return (new IsSimpleOp()).isSimple(this);
}
public Geometry getBoundary() {
if (isEmpty()) {
return getFactory().createGeometryCollection(null);
}
- GeometryGraph g = new GeometryGraph(0, toInternalGeometry(this));
+ GeometryGraph g = new GeometryGraph(0, this);
Coordinate[] pts = g.getBoundaryPoints();
return getFactory().createMultiPoint(pts);
}
diff --git a/src/com/vividsolutions/jts/geom/MultiPoint.java b/src/com/vividsolutions/jts/geom/MultiPoint.java
index c49e755..2fe0e4d 100644
--- a/src/com/vividsolutions/jts/geom/MultiPoint.java
+++ b/src/com/vividsolutions/jts/geom/MultiPoint.java
@@ -39,13 +39,13 @@ import com.vividsolutions.jts.operation.IsSimpleOp;
/**
* Models a collection of <code>Point</code>s.
*
- *@version 1.5
+ *@version 1.6
*/
public class MultiPoint
extends GeometryCollection
{
-
- private static final long serialVersionUID = -8048474874175355449L;
+
+ private static final long serialVersionUID = -8048474874175355449L;
/**
* Constructs a <code>MultiPoint</code>.
@@ -60,9 +60,9 @@ public class MultiPoint
* @deprecated Use GeometryFactory instead
*/
public MultiPoint(Point[] points, PrecisionModel precisionModel, int SRID) {
- super(points, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ super(points, new GeometryFactory(precisionModel, SRID));
}
-
+
/**
*@param points the <code>Point</code>s for this <code>MultiPoint</code>
* , or <code>null</code> or an empty array to create the empty geometry.
@@ -70,7 +70,7 @@ public class MultiPoint
*/
public MultiPoint(Point[] points, GeometryFactory factory) {
super(points, factory);
- }
+ }
public int getDimension() {
return 0;
@@ -84,12 +84,12 @@ public class MultiPoint
return "MultiPoint";
}
- public Geometry getBoundary() {
+ public Geometry getBoundary() {
return getFactory().createGeometryCollection(null);
}
public boolean isSimple() {
- return (new IsSimpleOp()).isSimple((MultiPoint)toInternalGeometry(this));
+ return (new IsSimpleOp()).isSimple(this);
}
public boolean isValid() {
diff --git a/src/com/vividsolutions/jts/geom/MultiPolygon.java b/src/com/vividsolutions/jts/geom/MultiPolygon.java
index 94debea..bbc1c71 100644
--- a/src/com/vividsolutions/jts/geom/MultiPolygon.java
+++ b/src/com/vividsolutions/jts/geom/MultiPolygon.java
@@ -39,7 +39,7 @@ import java.util.ArrayList;
/**
* Basic implementation of <code>MultiPolygon</code>.
*
- *@version 1.5
+ *@version 1.6
*/
public class MultiPolygon extends GeometryCollection {
private static final long serialVersionUID = -551033529766975875L;
@@ -59,10 +59,10 @@ public class MultiPolygon extends GeometryCollection {
* @deprecated Use GeometryFactory instead
*/
public MultiPolygon(Polygon[] polygons, PrecisionModel precisionModel, int SRID) {
- this(polygons, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ this(polygons, new GeometryFactory(precisionModel, SRID));
}
-
-
+
+
/**
* @param polygons
* the <code>Polygon</code>s for this <code>MultiPolygon</code>,
@@ -75,7 +75,7 @@ public class MultiPolygon extends GeometryCollection {
*/
public MultiPolygon(Polygon[] polygons, GeometryFactory factory) {
super(polygons, factory);
- }
+ }
public int getDimension() {
return 2;
@@ -100,7 +100,7 @@ public class MultiPolygon extends GeometryCollection {
ArrayList allRings = new ArrayList();
for (int i = 0; i < geometries.length; i++) {
Polygon polygon = (Polygon) geometries[i];
- GeometryCollection rings = (GeometryCollection) polygon.getBoundary();
+ Geometry rings = polygon.getBoundary();
for (int j = 0; j < rings.getNumGeometries(); j++) {
allRings.add(rings.getGeometryN(j));
}
diff --git a/src/com/vividsolutions/jts/geom/Point.java b/src/com/vividsolutions/jts/geom/Point.java
index c37c5d2..f2a64e3 100644
--- a/src/com/vividsolutions/jts/geom/Point.java
+++ b/src/com/vividsolutions/jts/geom/Point.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.util.Assert;
/**
* Basic implementation of <code>Point</code>.
*
- *@version 1.5
+ *@version 1.6
*/
public class Point extends Geometry {
private static final long serialVersionUID = 4902022702746614570L;
@@ -60,20 +60,25 @@ public class Point extends Geometry {
* @deprecated Use GeometryFactory instead
*/
public Point(Coordinate coordinate, PrecisionModel precisionModel, int SRID) {
- this(DefaultCoordinateSequenceFactory.instance().create(
- coordinate != null ? new Coordinate[]{coordinate} : new Coordinate[]{}),
- new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ super(new GeometryFactory(precisionModel, SRID));
+ init(getFactory().getCoordinateSequenceFactory().create(
+ coordinate != null ? new Coordinate[]{coordinate} : new Coordinate[]{}));
}
/**
*@param coordinates contains the single coordinate on which to base this <code>Point</code>
* , or <code>null</code> to create the empty geometry.
- */
+ */
public Point(CoordinateSequence coordinates, GeometryFactory factory) {
- super(factory);
+ super(factory);
+ init(coordinates);
+ }
+
+ private void init(CoordinateSequence coordinates)
+ {
if (coordinates == null) {
- coordinates = factory.getCoordinateSequenceFactory().create(new Coordinate[]{});
- }
+ coordinates = getFactory().getCoordinateSequenceFactory().create(new Coordinate[]{});
+ }
Assert.isTrue(coordinates.size() <= 1);
this.coordinates = coordinates;
}
@@ -138,7 +143,9 @@ public class Point extends Geometry {
if (isEmpty()) {
return new Envelope();
}
- return new Envelope(getCoordinate().x, getCoordinate().x, getCoordinate().y, getCoordinate().y);
+ Envelope env = new Envelope();
+ env.expandToInclude(coordinates.getX(0), coordinates.getY(0));
+ return env;
}
public boolean equalsExact(Geometry other, double tolerance) {
diff --git a/src/com/vividsolutions/jts/geom/Polygon.java b/src/com/vividsolutions/jts/geom/Polygon.java
index af27d95..7742106 100644
--- a/src/com/vividsolutions/jts/geom/Polygon.java
+++ b/src/com/vividsolutions/jts/geom/Polygon.java
@@ -49,18 +49,22 @@ import com.vividsolutions.jts.algorithm.*;
* HREF="http://www.opengis.org/techno/specs.htm">OpenGIS Simple Features
* Specification for SQL</A> .
*
- *@version 1.5
+ *@version 1.6
*/
public class Polygon extends Geometry {
- private static final long serialVersionUID = -3494792200821764533L;
+ private static final long serialVersionUID = -3494792200821764533L;
+
/**
- * The exterior boundary, or <code>null</code> if this <code>Polygon</code>
- * is the empty geometry.
+ * The exterior boundary,
+ * or <code>null</code> if this <code>Polygon</code>
+ * is empty.
*/
protected LinearRing shell = null;
/**
- * The interior boundaries, if any.
+ * The interior boundaries, if any.
+ * This instance var is never null.
+ * If there are no holes, the array is of zero length.
*/
protected LinearRing[] holes;
@@ -77,7 +81,7 @@ public class Polygon extends Geometry {
* @deprecated Use GeometryFactory instead
*/
public Polygon(LinearRing shell, PrecisionModel precisionModel, int SRID) {
- this(shell, new LinearRing[]{}, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ this(shell, new LinearRing[]{}, new GeometryFactory(precisionModel, SRID));
}
/**
@@ -97,7 +101,7 @@ public class Polygon extends Geometry {
* @deprecated Use GeometryFactory instead
*/
public Polygon(LinearRing shell, LinearRing[] holes, PrecisionModel precisionModel, int SRID) {
- this(shell, holes, new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.instance()));
+ this(shell, holes, new GeometryFactory(precisionModel, SRID));
}
/**
@@ -178,6 +182,39 @@ public class Polygon extends Geometry {
return true;
}
+ public boolean isRectangle()
+ {
+ if (getNumInteriorRing() != 0) return false;
+ if (shell == null) return false;
+ if (shell.getNumPoints() != 5) return false;
+
+ CoordinateSequence seq = shell.getCoordinateSequence();
+
+ // check vertices have correct values
+ Envelope env = getEnvelopeInternal();
+ for (int i = 0; i < 5; i++) {
+ double x = seq.getX(i);
+ if (! (x == env.getMinX() || x == env.getMaxX())) return false;
+ double y = seq.getX(i);
+ if (! (y == env.getMinY() || y == env.getMaxY())) return false;
+ }
+
+ // check vertices are in right order
+ double prevX = seq.getX(0);
+ double prevY = seq.getX(0);
+ for (int i = 1; i <= 4; i++) {
+ double x = seq.getX(i);
+ double y = seq.getY(i);
+ boolean xChanged = x != prevX;
+ boolean yChanged = y != prevY;
+ if (xChanged == yChanged)
+ return false;
+ prevX = x;
+ prevY = y;
+ }
+ return true;
+ }
+
public LineString getExteriorRing() {
return shell;
}
@@ -233,6 +270,8 @@ public class Polygon extends Geometry {
for (int i = 0; i < holes.length; i++) {
rings[i + 1] = holes[i];
}
+ if (rings.length <= 1)
+ return getFactory().createLinearRing(rings[0].getCoordinateSequence());
return getFactory().createMultiLineString(rings);
}
diff --git a/src/com/vividsolutions/jts/geom/PrecisionModel.java b/src/com/vividsolutions/jts/geom/PrecisionModel.java
index 388fdd5..8a4aa32 100644
--- a/src/com/vividsolutions/jts/geom/PrecisionModel.java
+++ b/src/com/vividsolutions/jts/geom/PrecisionModel.java
@@ -79,7 +79,7 @@ import java.util.Map;
*<p>
* JTS methods currently do not handle inputs with different precision models.
*
- *@version 1.5
+ *@version 1.6
*/
public class PrecisionModel implements Serializable, Comparable
{
@@ -357,10 +357,14 @@ public class PrecisionModel implements Serializable, Comparable
external.y = internal.y;
}
-
-
/**
* Rounds a numeric value to the PrecisionModel grid.
+ * Symmetric Arithmetic Rounding is used, to provide
+ * uniform rounding behaviour no matter where the number is
+ * on the number line.
+ * <p>
+ * <b>Note:</b> Java's <code>Math#rint</code> uses the "banker's rounding" algorithm,
+ * which is not suitable for precision operations elsewhere in JTS.
*/
public double makePrecise(double val) {
if (modelType == FLOATING_SINGLE) {
@@ -368,7 +372,8 @@ public class PrecisionModel implements Serializable, Comparable
return (double) floatSingleVal;
}
if (modelType == FIXED) {
- return Math.rint(val * scale) / scale;
+ return Math.round(val * scale) / scale;
+// return Math.rint(val * scale) / scale;
}
// modelType == FLOATING - no rounding necessary
return val;
diff --git a/src/com/vividsolutions/jts/geom/TopologyException.java b/src/com/vividsolutions/jts/geom/TopologyException.java
index a8d70dc..a6d282d 100644
--- a/src/com/vividsolutions/jts/geom/TopologyException.java
+++ b/src/com/vividsolutions/jts/geom/TopologyException.java
@@ -38,7 +38,7 @@ package com.vividsolutions.jts.geom;
/**
* Indicates an invalid or inconsistent topological situation encountered during processing
*
- * @version 1.5
+ * @version 1.6
*/
public class TopologyException
extends RuntimeException
diff --git a/src/com/vividsolutions/jts/geom/Triangle.java b/src/com/vividsolutions/jts/geom/Triangle.java
index 875da24..489068c 100644
--- a/src/com/vividsolutions/jts/geom/Triangle.java
+++ b/src/com/vividsolutions/jts/geom/Triangle.java
@@ -37,7 +37,7 @@ package com.vividsolutions.jts.geom;
* Represents a planar triangle, and provides methods for calculating various
* properties of triangles.
*
- * @version 1.5
+ * @version 1.6
*/
public class Triangle
{
diff --git a/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequence.java b/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequence.java
new file mode 100644
index 0000000..e8880da
--- /dev/null
+++ b/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequence.java
@@ -0,0 +1,223 @@
+/*
+* The JTS Topology Suite is a collection of Java classes that
+* implement the fundamental operations required to validate a given
+* geo-spatial data set to a known topological specification.
+*
+* Copyright (C) 2001 Vivid Solutions
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For more information, contact:
+*
+* Vivid Solutions
+* Suite #1A
+* 2328 Government Street
+* Victoria BC V8T 5G5
+* Canada
+*
+* (250)385-6040
+* www.vividsolutions.com
+ */
+package com.vividsolutions.jts.geom.impl;
+
+import java.io.Serializable;
+import com.vividsolutions.jts.geom.*;
+
+/**
+ * The {@link CoordinateSequence} implementation that {@link Geometry}s use by default.
+ * In this implementation, Coordinates returned by #toArray and #getCoordinate are live --
+ * modifications to them are actually changing the
+ * CoordinateSequence's underlying data.
+ *
+ * @version 1.6
+ */
+public class CoordinateArraySequence
+ implements CoordinateSequence, Serializable
+{
+ //With contributions from Markus Schaber [schabios at logi-track.com] 2004-03-26
+ private static final long serialVersionUID = -915438501601840650L;
+
+ private Coordinate[] coordinates;
+
+ /**
+ * Constructs a sequence based on the given array (the
+ * array is not copied).
+ *
+ * @param coordinates the coordinate array that will be referenced.
+ */
+ public CoordinateArraySequence(Coordinate[] coordinates) {
+ this.coordinates = coordinates;
+ if (coordinates == null)
+ this.coordinates = new Coordinate[0];
+ }
+
+ /**
+ * Constructs a sequence of a given size, populated
+ * with new {@link Coordinate}s.
+ *
+ * @param size the size of the sequence to create
+ */
+ public CoordinateArraySequence(int size) {
+ coordinates = new Coordinate[size];
+ for (int i = 0; i < size; i++) {
+ coordinates[i] = new Coordinate();
+ }
+ }
+
+ /**
+ * Constructs a sequence based on the given array (the
+ * array is not copied).
+ *
+ * @param coordinates the coordinate array that will be referenced.
+ */
+ public CoordinateArraySequence(CoordinateSequence coordSeq)
+ {
+ if (coordSeq != null)
+ coordinates = new Coordinate[coordSeq.size()];
+ else
+ coordinates = new Coordinate[0];
+
+ for (int i = 0; i < coordinates.length; i++) {
+ coordinates[i] = coordSeq.getCoordinateCopy(i);
+ }
+ }
+
+ /**
+ * Get the Coordinate with index i.
+ *
+ * @param i
+ * the index of the coordinate
+ * @return the requested Coordinate instance
+ */
+ public Coordinate getCoordinate(int i) {
+ return coordinates[i];
+ }
+
+ /**
+ * Get a copy of the Coordinate with index i.
+ *
+ * @param i the index of the coordinate
+ * @return a copy of the requested Coordinate
+ */
+ public Coordinate getCoordinateCopy(int i) {
+ return new Coordinate(coordinates[i]);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public void getCoordinate(int index, Coordinate coord) {
+ coord.x = coordinates[index].x;
+ coord.y = coordinates[index].y;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public double getX(int index) {
+ return coordinates[index].x;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int)
+ */
+ public double getY(int index) {
+ return coordinates[index].y;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int)
+ */
+ public double getOrdinate(int index, int ordinateIndex)
+ {
+ switch (ordinateIndex) {
+ case CoordinateSequence.X: return coordinates[index].x;
+ case CoordinateSequence.Y: return coordinates[index].y;
+ case CoordinateSequence.Z: return coordinates[index].z;
+ }
+ return Double.NaN;
+ }
+
+ /**
+ * Creates a deep copy of the Object
+ *
+ * @return The deep copy
+ */
+ public Object clone() {
+ Coordinate[] cloneCoordinates = new Coordinate[size()];
+ for (int i = 0; i < coordinates.length; i++) {
+ cloneCoordinates[i] = (Coordinate) coordinates[i].clone();
+ }
+ return new CoordinateArraySequence(cloneCoordinates);
+ }
+ /**
+ * Returns the size of the coordinate sequence
+ *
+ * @return the number of coordinates
+ */
+ public int size() {
+ return coordinates.length;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#setOrdinate(int, int, double)
+ */
+ public void setOrdinate(int index, int ordinateIndex, double value)
+ {
+ switch (ordinateIndex) {
+ case CoordinateSequence.X: coordinates[index].x = value;
+ case CoordinateSequence.Y: coordinates[index].y = value;
+ case CoordinateSequence.Z: coordinates[index].z = value;
+ }
+ }
+
+ /**
+ * This method exposes the internal Array of Coordinate Objects
+ *
+ * @return the Coordinate[] array.
+ */
+ public Coordinate[] toCoordinateArray() {
+ return coordinates;
+ }
+
+ public Envelope expandEnvelope(Envelope env)
+ {
+ for (int i = 0; i < coordinates.length; i++ ) {
+ env.expandToInclude(coordinates[i]);
+ }
+ return env;
+ }
+
+ /**
+ * Returns the string Representation of the coordinate array
+ *
+ * @return The string
+ */
+ public String toString() {
+ if (coordinates.length > 0) {
+ StringBuffer strBuf = new StringBuffer(17 * coordinates.length);
+ strBuf.append('(');
+ strBuf.append(coordinates[0]);
+ for (int i = 1; i < coordinates.length; i++) {
+ strBuf.append(", ");
+ strBuf.append(coordinates[i]);
+ }
+ strBuf.append(')');
+ return strBuf.toString();
+ } else {
+ return "()";
+ }
+ }
+}
diff --git a/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequenceFactory.java b/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequenceFactory.java
new file mode 100644
index 0000000..86813f8
--- /dev/null
+++ b/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequenceFactory.java
@@ -0,0 +1,92 @@
+
+/*
+* The JTS Topology Suite is a collection of Java classes that
+* implement the fundamental operations required to validate a given
+* geo-spatial data set to a known topological specification.
+*
+* Copyright (C) 2001 Vivid Solutions
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For more information, contact:
+*
+* Vivid Solutions
+* Suite #1A
+* 2328 Government Street
+* Victoria BC V8T 5G5
+* Canada
+*
+* (250)385-6040
+* www.vividsolutions.com
+ */
+package com.vividsolutions.jts.geom.impl;
+
+import java.io.Serializable;
+import com.vividsolutions.jts.geom.*;
+
+/**
+ * Creates CoordinateSequences represented as an array of {@link Coordinate}s.
+ *
+ * @version 1.6
+ */
+public final class CoordinateArraySequenceFactory
+ implements CoordinateSequenceFactory, Serializable
+{
+ private static final long serialVersionUID = -4099577099607551657L;
+ private static CoordinateArraySequenceFactory instance = new CoordinateArraySequenceFactory();
+
+ private CoordinateArraySequenceFactory() {
+ }
+
+ /**
+ * @see http://www.javaworld.com/javaworld/javatips/jw-javatip122.html
+ */
+ private Object readResolve() {
+ return CoordinateArraySequenceFactory.instance();
+ }
+
+ /**
+ * Returns the singleton instance of {@link CoordinateArraySequenceFactory}
+ */
+ public static CoordinateArraySequenceFactory instance() {
+ return instance;
+ }
+
+ /**
+ * Returns a {@link CoordinateArraySequence} based on the given array (the array is
+ * not copied).
+ *
+ * @param coordinates
+ * the coordinates, which may not be null nor contain null
+ * elements
+ */
+ public CoordinateSequence create(Coordinate[] coordinates) {
+ return new CoordinateArraySequence(coordinates);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.CoordinateSequence)
+ */
+ public CoordinateSequence create(CoordinateSequence coordSeq) {
+ return new CoordinateArraySequence(coordSeq);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int, int)
+ */
+ public CoordinateSequence create(int size, int dimension) {
+ return new CoordinateArraySequence(size);
+ }
+}
diff --git a/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequence.java b/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequence.java
new file mode 100644
index 0000000..ecab30e
--- /dev/null
+++ b/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequence.java
@@ -0,0 +1,435 @@
+package com.vividsolutions.jts.geom.impl;
+
+import com.vividsolutions.jts.geom.*;
+
+import java.lang.ref.SoftReference;
+
+/**
+ * A {@link CoordinateSequence} implementation based on a packed arrays.
+ * In this implementation, {@link Coordinate}s returned by #toArray and #get are copies
+ * of the internal values.
+ * To change the actual values, use the provided setters.
+ * <p>
+ * For efficiency, created Coordinate arrays
+ * are cached using a soft reference.
+ * The cache is cleared each time the coordinate sequence contents are
+ * modified through a setter method.
+ *
+ * @version 1.6
+ */
+public abstract class PackedCoordinateSequence
+ implements CoordinateSequence
+{
+ /**
+ * The dimensions of the coordinates hold in the packed array
+ */
+ protected int dimension;
+
+ /**
+ * A soft reference to the Coordinate[] representation of this sequence.
+ * Makes repeated coordinate array accesses more efficient.
+ */
+ protected SoftReference coordRef;
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getDimension()
+ */
+ public int getDimension() {
+ return this.dimension;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int)
+ */
+ public Coordinate getCoordinate(int i) {
+ Coordinate[] coords = getCachedCoords();
+ if(coords != null)
+ return coords[i];
+ else
+ return getCoordinateInternal(i);
+ }
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int)
+ */
+ public Coordinate getCoordinateCopy(int i) {
+ return getCoordinateInternal(i);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int)
+ */
+ public void getCoordinate(int i, Coordinate coord) {
+ coord.x = getOrdinate(i, 0);
+ coord.y = getOrdinate(i, 1);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#toCoordinateArray()
+ */
+ public Coordinate[] toCoordinateArray() {
+ Coordinate[] coords = getCachedCoords();
+// testing - never cache
+ if (coords != null)
+ return coords;
+
+ coords = new Coordinate[size()];
+ for (int i = 0; i < coords.length; i++) {
+ coords[i] = getCoordinateInternal(i);
+ }
+ coordRef = new SoftReference(coords);
+
+ return coords;
+ }
+
+ /**
+ * @return
+ */
+ private Coordinate[] getCachedCoords() {
+ if (coordRef != null) {
+ Coordinate[] coords = (Coordinate[]) coordRef.get();
+ if (coords != null) {
+ return coords;
+ } else {
+ // System.out.print("-");
+ coordRef = null;
+ return null;
+ }
+ } else {
+ // System.out.print("-");
+ return null;
+ }
+
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public double getX(int index) {
+ return getOrdinate(index, 0);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int)
+ */
+ public double getY(int index) {
+ return getOrdinate(index, 1);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int)
+ */
+ public abstract double getOrdinate(int index, int ordinateIndex);
+
+ /**
+ * Sets the first ordinate of a coordinate in this sequence.
+ *
+ * @param index the coordinate index
+ * @param value the new ordinate value
+ */
+ public void setX(int index, double value) {
+ coordRef = null;
+ setOrdinate(index, 0, value);
+ }
+
+ /**
+ * Sets the second ordinate of a coordinate in this sequence.
+ *
+ * @param index the coordinate index
+ * @param value the new ordinate value
+ */
+ public void setY(int index, double value) {
+ coordRef = null;
+ setOrdinate(index, 1, value);
+ }
+
+ /**
+ * Returns a Coordinate representation of the specified coordinate, by always
+ * building a new Coordinate object
+ *
+ * @param index
+ * @return
+ */
+ protected abstract Coordinate getCoordinateInternal(int index);
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ public abstract Object clone();
+
+ /**
+ * Sets the ordinate of a coordinate in this sequence.
+ * <br>
+ * Warning: for performance reasons the ordinate index is not checked
+ * - if it is over dimensions you may not get an exception but a meaningless value.
+ *
+ * @param index
+ * the coordinate index
+ * @param ordinate
+ * the ordinate index in the coordinate, 0 based, smaller than the
+ * number of dimensions
+ * @param value
+ * the new ordinate value
+ */
+ public abstract void setOrdinate(int index, int ordinate, double value);
+
+ /**
+ * Packed coordinate sequence implementation based on doubles
+ */
+ public static class Double extends PackedCoordinateSequence {
+
+ /**
+ * The packed coordinate array
+ */
+ double[] coords;
+
+ /**
+ * Builds a new packed coordinate sequence
+ *
+ * @param coords
+ * @param dimensions
+ */
+ public Double(double[] coords, int dimensions) {
+ if (dimensions < 2) {
+ throw new IllegalArgumentException("Must have at least 2 dimensions");
+ }
+ if (coords.length % dimensions != 0) {
+ throw new IllegalArgumentException("Packed array does not contain "
+ + "an integral number of coordinates");
+ }
+ this.dimension = dimensions;
+ this.coords = coords;
+ }
+
+ /**
+ * Builds a new packed coordinate sequence out of a float coordinate array
+ *
+ * @param coordinates
+ */
+ public Double(float[] coordinates, int dimensions) {
+ this.coords = new double[coordinates.length];
+ this.dimension = dimensions;
+ for (int i = 0; i < coordinates.length; i++) {
+ this.coords[i] = coordinates[i];
+ }
+ }
+
+ /**
+ * Builds a new packed coordinate sequence out of a coordinate array
+ *
+ * @param coordinates
+ */
+ public Double(Coordinate[] coordinates, int dimension) {
+ if (coordinates == null)
+ coordinates = new Coordinate[0];
+ this.dimension = dimension;
+
+ coords = new double[coordinates.length * this.dimension];
+ for (int i = 0; i < coordinates.length; i++) {
+ coords[i * this.dimension] = coordinates[i].x;
+ if (this.dimension >= 2)
+ coords[i * this.dimension + 1] = coordinates[i].y;
+ if (this.dimension >= 3)
+ coords[i * this.dimension + 2] = coordinates[i].z;
+ }
+ }
+ /**
+ * Builds a new packed coordinate sequence out of a coordinate array
+ *
+ * @param coordinates
+ */
+ public Double(Coordinate[] coordinates) {
+ this(coordinates, 3);
+ }
+
+ /**
+ * Builds a new empty packed coordinate sequence of a given size and dimension
+ *
+ * @param coordinates
+ */
+ public Double(int size, int dimension) {
+ this.dimension = dimension;
+ coords = new double[size * this.dimension];
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int)
+ */
+ public Coordinate getCoordinateInternal(int i) {
+ double x = coords[i * dimension];
+ double y = coords[i * dimension + 1];
+ double z = dimension == 2 ? 0.0 : coords[i * dimension + 2];
+ return new Coordinate(x, y, z);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#size()
+ */
+ public int size() {
+ return coords.length / dimension;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ public Object clone() {
+ double[] clone = new double[coords.length];
+ System.arraycopy(coords, 0, clone, 0, coords.length);
+ return new Double(clone, dimension);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int)
+ * Beware, for performace reasons the ordinate index is not checked, if
+ * it's over dimensions you may not get an exception but a meaningless
+ * value.
+ */
+ public double getOrdinate(int index, int ordinate) {
+ return coords[index * dimension + ordinate];
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.PackedCoordinateSequence#setOrdinate(int,
+ * int, double)
+ */
+ public void setOrdinate(int index, int ordinate, double value) {
+ coordRef = null;
+ coords[index * dimension + ordinate] = value;
+ }
+
+ public Envelope expandEnvelope(Envelope env)
+ {
+ for (int i = 0; i < coords.length; i += dimension ) {
+ env.expandToInclude(coords[i], coords[i + 1]);
+ }
+ return env;
+ }
+ }
+
+ /**
+ * Packed coordinate sequence implementation based on floats
+ */
+ public static class Float extends PackedCoordinateSequence {
+
+ /**
+ * The packed coordinate array
+ */
+ float[] coords;
+
+ /**
+ * Constructs a packed coordinate sequence from an array of <code>float<code>s
+ *
+ * @param coords
+ * @param dimensions
+ */
+ public Float(float[] coords, int dimensions) {
+ if (dimensions < 2) {
+ throw new IllegalArgumentException("Must have at least 2 dimensions");
+ }
+ if (coords.length % dimensions != 0) {
+ throw new IllegalArgumentException("Packed array does not contain "
+ + "an integral number of coordinates");
+ }
+ this.dimension = dimensions;
+ this.coords = coords;
+ }
+
+ /**
+ * Constructs a packed coordinate sequence from an array of <code>double<code>s
+ *
+ * @param coordinates
+ * @param dimension
+ */
+ public Float(double[] coordinates, int dimensions) {
+ this.coords = new float[coordinates.length];
+ this.dimension = dimensions;
+ for (int i = 0; i < coordinates.length; i++) {
+ this.coords[i] = (float) coordinates[i];
+ }
+ }
+
+ /**
+ * Constructs a packed coordinate sequence out of a coordinate array
+ *
+ * @param coordinates
+ */
+ public Float(Coordinate[] coordinates, int dimension) {
+ if (coordinates == null)
+ coordinates = new Coordinate[0];
+ this.dimension = dimension;
+
+ coords = new float[coordinates.length * this.dimension];
+ for (int i = 0; i < coordinates.length; i++) {
+ coords[i * this.dimension] = (float) coordinates[i].x;
+ if (this.dimension >= 2)
+ coords[i * this.dimension + 1] = (float) coordinates[i].y;
+ if (this.dimension >= 3)
+ coords[i * this.dimension + 2] = (float) coordinates[i].z;
+ }
+ }
+
+ /**
+ * Constructs an empty packed coordinate sequence of a given size and dimension
+ *
+ * @param coordinates
+ */
+ public Float(int size, int dimension) {
+ this.dimension = dimension;
+ coords = new float[size * this.dimension];
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int)
+ */
+ public Coordinate getCoordinateInternal(int i) {
+ double x = coords[i * dimension];
+ double y = coords[i * dimension + 1];
+ double z = dimension == 2 ? 0.0 : coords[i * dimension + 2];
+ return new Coordinate(x, y, z);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#size()
+ */
+ public int size() {
+ return coords.length / dimension;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ public Object clone() {
+ float[] clone = new float[coords.length];
+ System.arraycopy(coords, 0, clone, 0, coords.length);
+ return new Float(clone, dimension);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int)
+ * Beware, for performace reasons the ordinate index is not checked, if
+ * it's over dimensions you may not get an exception but a meaningless
+ * value.
+ */
+ public double getOrdinate(int index, int ordinate) {
+ return coords[index * dimension + ordinate];
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.PackedCoordinateSequence#setOrdinate(int,
+ * int, double)
+ */
+ public void setOrdinate(int index, int ordinate, double value) {
+ coordRef = null;
+ coords[index * dimension + ordinate] = (float) value;
+ }
+
+ public Envelope expandEnvelope(Envelope env)
+ {
+ for (int i = 0; i < coords.length; i += dimension ) {
+ env.expandToInclude(coords[i], coords[i + 1]);
+ }
+ return env;
+ }
+
+ }
+
+}
diff --git a/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequenceFactory.java b/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequenceFactory.java
new file mode 100644
index 0000000..bab987d
--- /dev/null
+++ b/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequenceFactory.java
@@ -0,0 +1,137 @@
+package com.vividsolutions.jts.geom.impl;
+
+import com.vividsolutions.jts.geom.*;
+
+/**
+ * Builds packed array coordinate sequences. The array data type can be either
+ * double or float, and defaults to float.
+ */
+public class PackedCoordinateSequenceFactory implements
+ CoordinateSequenceFactory
+{
+ public static final int DOUBLE = 0;
+ public static final int FLOAT = 1;
+
+ public static final PackedCoordinateSequenceFactory DOUBLE_FACTORY =
+ new PackedCoordinateSequenceFactory(DOUBLE);
+ public static final PackedCoordinateSequenceFactory FLOAT_FACTORY =
+ new PackedCoordinateSequenceFactory(FLOAT);
+
+ private int type = DOUBLE;
+ private int dimension = 3;
+
+ /**
+ * Creates a new PackedCoordinateSequenceFactory
+ * of type DOUBLE.
+ */
+ public PackedCoordinateSequenceFactory()
+ {
+ this(DOUBLE);
+ }
+
+ /**
+ * Creates a new PackedCoordinateSequenceFactory
+ * of the given type.
+ * Acceptable type values are
+ * {@linkplain PackedCoordinateSequenceFactory#Float}or
+ * {@linkplain PackedCoordinateSequenceFactory#Double}
+ */
+ public PackedCoordinateSequenceFactory(int type)
+ {
+ this(type, 3);
+ }
+ /**
+ * Creates a new PackedCoordinateSequenceFactory
+ * of the given type.
+ * Acceptable type values are
+ * {@linkplain PackedCoordinateSequenceFactory#FLOAT}or
+ * {@linkplain PackedCoordinateSequenceFactory#DOUBLE}
+ */
+ public PackedCoordinateSequenceFactory(int type, int dimension)
+ {
+ setType(type);
+ setDimension(dimension);
+ }
+
+ /**
+ * Returns the type of packed coordinate sequences this factory builds, either
+ * {@linkplain PackedCoordinateSequenceFactory#Float} or
+ * {@linkplain PackedCoordinateSequenceFactory#Double}
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Sets the type of packed coordinate sequences this factory builds,
+ * acceptable values are {@linkplain PackedCoordinateSequenceFactory#Float}or
+ * {@linkplain PackedCoordinateSequenceFactory#Double}
+ */
+ public void setType(int type) {
+ if (type != DOUBLE && type != FLOAT)
+ throw new IllegalArgumentException("Unknown type " + type);
+ this.type = type;
+ }
+
+
+ public int getDimension() { return dimension; }
+
+ public void setDimension(int dimension) { this.dimension = dimension; }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.Coordinate[])
+ */
+ public CoordinateSequence create(Coordinate[] coordinates) {
+ if (type == DOUBLE) {
+ return new PackedCoordinateSequence.Double(coordinates, dimension);
+ } else {
+ return new PackedCoordinateSequence.Float(coordinates, dimension);
+ }
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.CoordinateSequence)
+ */
+ public CoordinateSequence create(CoordinateSequence coordSeq) {
+ if (type == DOUBLE) {
+ return new PackedCoordinateSequence.Double(coordSeq.toCoordinateArray(), dimension);
+ } else {
+ return new PackedCoordinateSequence.Float(coordSeq.toCoordinateArray(), dimension);
+ }
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(double[],
+ * int)
+ */
+ public CoordinateSequence create(double[] packedCoordinates, int dimension) {
+ if (type == DOUBLE) {
+ return new PackedCoordinateSequence.Double(packedCoordinates, dimension);
+ } else {
+ return new PackedCoordinateSequence.Float(packedCoordinates, dimension);
+ }
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(float[],
+ * int)
+ */
+ public CoordinateSequence create(float[] packedCoordinates, int dimension) {
+ if (type == DOUBLE) {
+ return new PackedCoordinateSequence.Double(packedCoordinates, dimension);
+ } else {
+ return new PackedCoordinateSequence.Float(packedCoordinates, dimension);
+ }
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int, int)
+ */
+ public CoordinateSequence create(int size, int dimension) {
+ if (type == DOUBLE) {
+ return new PackedCoordinateSequence.Double(size, dimension);
+ } else {
+ return new PackedCoordinateSequence.Float(size, dimension);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/vividsolutions/jts/geom/util/GeometryEditor.java b/src/com/vividsolutions/jts/geom/util/GeometryEditor.java
index 068a3f8..312b1ca 100644
--- a/src/com/vividsolutions/jts/geom/util/GeometryEditor.java
+++ b/src/com/vividsolutions/jts/geom/util/GeometryEditor.java
@@ -67,7 +67,7 @@ import java.util.ArrayList;
*
* @see Geometry#isValid
*
- * @version 1.5
+ * @version 1.6
*/
public class GeometryEditor
{
@@ -205,7 +205,7 @@ public class GeometryEditor
/**
* A interface which specifies an edit operation for Geometries.
*
- * @version 1.5
+ * @version 1.6
*/
public interface GeometryEditorOperation
{
diff --git a/src/com/vividsolutions/jts/geom/util/GeometryTransformer.java b/src/com/vividsolutions/jts/geom/util/GeometryTransformer.java
index cff39af..fe73375 100644
--- a/src/com/vividsolutions/jts/geom/util/GeometryTransformer.java
+++ b/src/com/vividsolutions/jts/geom/util/GeometryTransformer.java
@@ -31,7 +31,7 @@ import com.vividsolutions.jts.geom.*;
* The @link transform} method itself will always
* return a geometry object.
*
- * @version 1.5
+ * @version 1.6
*
* @see GeometryEditor
*/
@@ -84,7 +84,7 @@ public class GeometryTransformer {
if (inputGeom instanceof MultiPoint)
return transformMultiPoint((MultiPoint) inputGeom, null);
if (inputGeom instanceof LinearRing)
- return transformLineString((LinearRing) inputGeom, null);
+ return transformLinearRing((LinearRing) inputGeom, null);
if (inputGeom instanceof LineString)
return transformLineString((LineString) inputGeom, null);
if (inputGeom instanceof MultiLineString)
diff --git a/src/com/vividsolutions/jts/geom/util/LinearComponentExtracter.java b/src/com/vividsolutions/jts/geom/util/LinearComponentExtracter.java
index e4c4dab..5acd25c 100644
--- a/src/com/vividsolutions/jts/geom/util/LinearComponentExtracter.java
+++ b/src/com/vividsolutions/jts/geom/util/LinearComponentExtracter.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.*;
/**
* Extracts all the 1-dimensional ({@link LineString}) components from a {@link Geometry}.
*
- * @version 1.5
+ * @version 1.6
*/
public class LinearComponentExtracter
implements GeometryComponentFilter
diff --git a/src/com/vividsolutions/jts/geom/util/PointExtracter.java b/src/com/vividsolutions/jts/geom/util/PointExtracter.java
index 27428c6..fd734a0 100644
--- a/src/com/vividsolutions/jts/geom/util/PointExtracter.java
+++ b/src/com/vividsolutions/jts/geom/util/PointExtracter.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.*;
/**
* Extracts all the 0-dimensional ({@link Point}) components from a {@link Geometry}.
*
- * @version 1.5
+ * @version 1.6
*/
public class PointExtracter
implements GeometryFilter
diff --git a/src/com/vividsolutions/jts/geom/util/PolygonExtracter.java b/src/com/vividsolutions/jts/geom/util/PolygonExtracter.java
index 3240789..e01bff9 100644
--- a/src/com/vividsolutions/jts/geom/util/PolygonExtracter.java
+++ b/src/com/vividsolutions/jts/geom/util/PolygonExtracter.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.*;
/**
* Extracts all the 2-dimensional ({@link Polygon}) components from a {@link Geometry}.
*
- * @version 1.5
+ * @version 1.6
*/
public class PolygonExtracter
implements GeometryFilter
diff --git a/src/com/vividsolutions/jts/geom/util/ShortCircuitedGeometryVisitor.java b/src/com/vividsolutions/jts/geom/util/ShortCircuitedGeometryVisitor.java
new file mode 100644
index 0000000..2b5f845
--- /dev/null
+++ b/src/com/vividsolutions/jts/geom/util/ShortCircuitedGeometryVisitor.java
@@ -0,0 +1,36 @@
+package com.vividsolutions.jts.geom.util;
+
+import com.vividsolutions.jts.geom.*;
+
+/**
+ * A visitor to {@link Geometry} elements which can
+ * be short-circuited by a given condition
+ *
+ * @version 1.6
+ */
+public abstract class ShortCircuitedGeometryVisitor
+{
+ private boolean isDone = false;
+
+ public ShortCircuitedGeometryVisitor() {
+ }
+
+ public void applyTo(Geometry geom) {
+ for (int i = 0; i < geom.getNumGeometries() && ! isDone; i++) {
+ Geometry element = geom.getGeometryN(i);
+ if (! (element instanceof GeometryCollection)) {
+ visit(element);
+ if (isDone()) {
+ isDone = true;
+ return;
+ }
+ }
+ else
+ applyTo(element);
+ }
+ }
+
+ protected abstract void visit(Geometry element);
+
+ protected abstract boolean isDone();
+}
diff --git a/src/com/vividsolutions/jts/geomgraph/Depth.java b/src/com/vividsolutions/jts/geomgraph/Depth.java
index 00421c1..9db637a 100644
--- a/src/com/vividsolutions/jts/geomgraph/Depth.java
+++ b/src/com/vividsolutions/jts/geomgraph/Depth.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.Location;
/**
* A Depth object records the topological depth of the sides
* of an Edge for up to two Geometries.
- * @version 1.5
+ * @version 1.6
*/
public class Depth {
diff --git a/src/com/vividsolutions/jts/geomgraph/DirectedEdge.java b/src/com/vividsolutions/jts/geomgraph/DirectedEdge.java
index 1d921f5..69ad216 100644
--- a/src/com/vividsolutions/jts/geomgraph/DirectedEdge.java
+++ b/src/com/vividsolutions/jts/geomgraph/DirectedEdge.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geom.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class DirectedEdge
extends EdgeEnd
@@ -216,22 +216,6 @@ public class DirectedEdge
setDepth(position, depth);
setDepth(oppositePos, oppositeDepth);
}
- /**
- * Set both edge depths. One depth for a given side is provided. The other is
- * computed depending on the Location transition and the depthDelta of the edge.
- */
- public void OLDsetEdgeDepths(int position, int depth)
- {
- int depthDelta = getEdge().getDepthDelta();
- int loc = label.getLocation(0, position);
- int oppositePos = Position.opposite(position);
- int oppositeLoc = label.getLocation(0, oppositePos);
- int delta = Math.abs(depthDelta) * DirectedEdge.depthFactor(loc, oppositeLoc);
- //TESTINGint delta = depthDelta * DirectedEdge.depthFactor(loc, oppositeLoc);
- int oppositeDepth = depth + delta;
- setDepth(position, depth);
- setDepth(oppositePos, oppositeDepth);
- }
public void print(PrintStream out)
{
diff --git a/src/com/vividsolutions/jts/geomgraph/DirectedEdgeStar.java b/src/com/vividsolutions/jts/geomgraph/DirectedEdgeStar.java
index 73f5fa5..c4e9b65 100644
--- a/src/com/vividsolutions/jts/geomgraph/DirectedEdgeStar.java
+++ b/src/com/vividsolutions/jts/geomgraph/DirectedEdgeStar.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.*;
* It supports labelling the edges as well as linking the edges to form both
* MaximalEdgeRings and MinimalEdgeRings.
*
- * @version 1.5
+ * @version 1.6
*/
public class DirectedEdgeStar
extends EdgeEndStar
diff --git a/src/com/vividsolutions/jts/geomgraph/Edge.java b/src/com/vividsolutions/jts/geomgraph/Edge.java
index 98f03ab..1283137 100644
--- a/src/com/vividsolutions/jts/geomgraph/Edge.java
+++ b/src/com/vividsolutions/jts/geomgraph/Edge.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.geomgraph.index.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class Edge
extends GraphComponent
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeEnd.java b/src/com/vividsolutions/jts/geomgraph/EdgeEnd.java
index 83b060b..37c444e 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeEnd.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeEnd.java
@@ -50,7 +50,7 @@ import com.vividsolutions.jts.geomgraph.Edge;
* EdgeEnds are comparable under the ordering
* "a has a greater angle with the x-axis than b".
* This ordering is used to sort EdgeEnds around a node.
- * @version 1.5
+ * @version 1.6
*/
public class EdgeEnd
implements Comparable
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeEndStar.java b/src/com/vividsolutions/jts/geomgraph/EdgeEndStar.java
index d62189e..0be6378 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeEndStar.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeEndStar.java
@@ -46,7 +46,7 @@ import com.vividsolutions.jts.util.*;
* They are maintained in CCW order (starting with the positive x-axis) around the node
* for efficient lookup and topology building.
*
- * @version 1.5
+ * @version 1.6
*/
abstract public class EdgeEndStar
{
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeIntersection.java b/src/com/vividsolutions/jts/geomgraph/EdgeIntersection.java
index afecd8f..0d50883 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeIntersection.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeIntersection.java
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* the edge from this point forwards, until the next
* intersection or the end of the edge.
* The intersection point must be precise.
- * @version 1.5
+ * @version 1.6
*/
public class EdgeIntersection
implements Comparable
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeIntersectionList.java b/src/com/vividsolutions/jts/geomgraph/EdgeIntersectionList.java
index d7887bb..1791abc 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeIntersectionList.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeIntersectionList.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.util.Debug;
/**
* A list of edge intersections along an Edge
- * @version 1.5
+ * @version 1.6
*/
public class EdgeIntersectionList
{
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeList.java b/src/com/vividsolutions/jts/geomgraph/EdgeList.java
index 9196686..dbdb3b9 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeList.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeList.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.index.quadtree.Quadtree;
/**
* A EdgeList is a list of Edges. It supports locating edges
* that are pointwise equals to a target edge.
- * @version 1.5
+ * @version 1.6
*/
public class EdgeList
{
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeNodingValidator.java b/src/com/vividsolutions/jts/geomgraph/EdgeNodingValidator.java
index 66e4270..a7ae4f5 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeNodingValidator.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeNodingValidator.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.noding.*;
* Validates that a collection of SegmentStrings is correctly noded.
* Throws an appropriate exception if an noding error is found.
*
- * @version 1.5
+ * @version 1.6
*/
public class EdgeNodingValidator {
diff --git a/src/com/vividsolutions/jts/geomgraph/EdgeRing.java b/src/com/vividsolutions/jts/geomgraph/EdgeRing.java
index 59ddd83..f20d6e9 100644
--- a/src/com/vividsolutions/jts/geomgraph/EdgeRing.java
+++ b/src/com/vividsolutions/jts/geomgraph/EdgeRing.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.Assert;
/**
- * @version 1.5
+ * @version 1.6
*/
public abstract class EdgeRing {
diff --git a/src/com/vividsolutions/jts/geomgraph/GeometryGraph.java b/src/com/vividsolutions/jts/geomgraph/GeometryGraph.java
index ed630a3..285e8d5 100644
--- a/src/com/vividsolutions/jts/geomgraph/GeometryGraph.java
+++ b/src/com/vividsolutions/jts/geomgraph/GeometryGraph.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.util.*;
/**
* A GeometryGraph is a graph that models a given Geometry
- * @version 1.5
+ * @version 1.6
*/
public class GeometryGraph
extends PlanarGraph
diff --git a/src/com/vividsolutions/jts/geomgraph/GraphComponent.java b/src/com/vividsolutions/jts/geomgraph/GraphComponent.java
index 16e500e..bd0a026 100644
--- a/src/com/vividsolutions/jts/geomgraph/GraphComponent.java
+++ b/src/com/vividsolutions/jts/geomgraph/GraphComponent.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.Assert;
* A GraphComponent is the parent class for the objects'
* that form a graph. Each GraphComponent can carry a
* Label.
- * @version 1.5
+ * @version 1.6
*/
abstract public class GraphComponent {
diff --git a/src/com/vividsolutions/jts/geomgraph/Label.java b/src/com/vividsolutions/jts/geomgraph/Label.java
index 2a90a96..7b59f23 100644
--- a/src/com/vividsolutions/jts/geomgraph/Label.java
+++ b/src/com/vividsolutions/jts/geomgraph/Label.java
@@ -58,7 +58,7 @@ import com.vividsolutions.jts.geom.Location;
* <P>
* It is up to the client code to associate the 0 and 1 <code>TopologyLocation</code>s
* with specific geometries.
- * @version 1.5
+ * @version 1.6
*
*/
public class Label {
diff --git a/src/com/vividsolutions/jts/geomgraph/Node.java b/src/com/vividsolutions/jts/geomgraph/Node.java
index ca5a1a5..2e7f296 100644
--- a/src/com/vividsolutions/jts/geomgraph/Node.java
+++ b/src/com/vividsolutions/jts/geomgraph/Node.java
@@ -46,7 +46,7 @@ import com.vividsolutions.jts.util.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class Node
extends GraphComponent
diff --git a/src/com/vividsolutions/jts/geomgraph/NodeFactory.java b/src/com/vividsolutions/jts/geomgraph/NodeFactory.java
index 125df54..b717b2a 100644
--- a/src/com/vividsolutions/jts/geomgraph/NodeFactory.java
+++ b/src/com/vividsolutions/jts/geomgraph/NodeFactory.java
@@ -37,7 +37,7 @@ import com.vividsolutions.jts.geom.Coordinate;
/**
- * @version 1.5
+ * @version 1.6
*/
public class NodeFactory {
/**
diff --git a/src/com/vividsolutions/jts/geomgraph/NodeMap.java b/src/com/vividsolutions/jts/geomgraph/NodeMap.java
index ad9b923..c1f87a4 100644
--- a/src/com/vividsolutions/jts/geomgraph/NodeMap.java
+++ b/src/com/vividsolutions/jts/geomgraph/NodeMap.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geomgraph.Node;
/**
* A map of nodes, indexed by the coordinate of the node
- * @version 1.5
+ * @version 1.6
*/
public class NodeMap
diff --git a/src/com/vividsolutions/jts/geomgraph/PlanarGraph.java b/src/com/vividsolutions/jts/geomgraph/PlanarGraph.java
index ef5dc13..b65d5c3 100644
--- a/src/com/vividsolutions/jts/geomgraph/PlanarGraph.java
+++ b/src/com/vividsolutions/jts/geomgraph/PlanarGraph.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.io.PrintStream;
import java.util.*;
@@ -61,7 +61,7 @@ import com.vividsolutions.jts.geom.*;
* <LI>Computing the intersections between the edges and nodes of two different graphs
* </UL>
*
- * @version 1.5
+ * @version 1.6
*/
public class PlanarGraph {
diff --git a/src/com/vividsolutions/jts/geomgraph/Position.java b/src/com/vividsolutions/jts/geomgraph/Position.java
index 02cf232..655566b 100644
--- a/src/com/vividsolutions/jts/geomgraph/Position.java
+++ b/src/com/vividsolutions/jts/geomgraph/Position.java
@@ -38,7 +38,7 @@ package com.vividsolutions.jts.geomgraph;
/**
* A Position indicates the position of a Location relative to a graph component
* (Node, Edge, or Area).
- * @version 1.5
+ * @version 1.6
*/
public class Position {
diff --git a/src/com/vividsolutions/jts/geomgraph/Quadrant.java b/src/com/vividsolutions/jts/geomgraph/Quadrant.java
index a3d77c3..8593c4c 100644
--- a/src/com/vividsolutions/jts/geomgraph/Quadrant.java
+++ b/src/com/vividsolutions/jts/geomgraph/Quadrant.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph;
/**
- * @version 1.5
+ * @version 1.6
*/
import com.vividsolutions.jts.geom.Coordinate;
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* 2 | 3
* <pre>
*
- * @version 1.5
+ * @version 1.6
*/
public class Quadrant {
/**
diff --git a/src/com/vividsolutions/jts/geomgraph/TopologyLocation.java b/src/com/vividsolutions/jts/geomgraph/TopologyLocation.java
index 8d60265..89ff3d3 100644
--- a/src/com/vividsolutions/jts/geomgraph/TopologyLocation.java
+++ b/src/com/vividsolutions/jts/geomgraph/TopologyLocation.java
@@ -59,7 +59,7 @@ import com.vividsolutions.jts.geom.Location;
* <p>
* The labelling is stored in an array location[j] where
* where j has the values ON, LEFT, RIGHT
- * @version 1.5
+ * @version 1.6
*/
public class TopologyLocation {
diff --git a/src/com/vividsolutions/jts/geomgraph/index/EdgeSetIntersector.java b/src/com/vividsolutions/jts/geomgraph/index/EdgeSetIntersector.java
index 172c49f..ffcbe32 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/EdgeSetIntersector.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/EdgeSetIntersector.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph.index;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geomgraph.*;
@@ -52,7 +52,7 @@ import com.vividsolutions.jts.geomgraph.*;
* It uses a {@link SegmentIntersector} to compute the intersections between
* segments and to record statistics about what kinds of intersections were found.
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class EdgeSetIntersector {
diff --git a/src/com/vividsolutions/jts/geomgraph/index/MonotoneChain.java b/src/com/vividsolutions/jts/geomgraph/index/MonotoneChain.java
index 7510226..b7ca2e5 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/MonotoneChain.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/MonotoneChain.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph.index;
/**
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChain {
diff --git a/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainEdge.java b/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainEdge.java
index 5778eb7..121a20c 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainEdge.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainEdge.java
@@ -57,7 +57,7 @@ import com.vividsolutions.jts.util.Debug;
* binary search to be used to find the intersection points of two monotone chains.
* For many types of real-world data, these properties eliminate a large number of
* segment comparisons, producing substantial speed gains.
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChainEdge {
diff --git a/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainIndexer.java b/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainIndexer.java
index 1825255..0153549 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainIndexer.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/MonotoneChainIndexer.java
@@ -55,7 +55,7 @@ import com.vividsolutions.jts.geomgraph.Quadrant;
* For many types of real-world data, these properties eliminate a large number of
* segment comparisons, producing substantial speed gains.
*
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChainIndexer {
diff --git a/src/com/vividsolutions/jts/geomgraph/index/SegmentIntersector.java b/src/com/vividsolutions/jts/geomgraph/index/SegmentIntersector.java
index edeb5c1..3247202 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/SegmentIntersector.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/SegmentIntersector.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.util.Debug;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SegmentIntersector {
diff --git a/src/com/vividsolutions/jts/geomgraph/index/SimpleEdgeSetIntersector.java b/src/com/vividsolutions/jts/geomgraph/index/SimpleEdgeSetIntersector.java
index 21bef44..ff452dd 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/SimpleEdgeSetIntersector.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/SimpleEdgeSetIntersector.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geomgraph.*;
* using the straightforward method of
* comparing all segments.
* This algorithm is too slow for production use, but is useful for testing purposes.
- * @version 1.5
+ * @version 1.6
*/
public class SimpleEdgeSetIntersector
extends EdgeSetIntersector
diff --git a/src/com/vividsolutions/jts/geomgraph/index/SimpleMCSweepLineIntersector.java b/src/com/vividsolutions/jts/geomgraph/index/SimpleMCSweepLineIntersector.java
index 8be527f..bd110ec 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/SimpleMCSweepLineIntersector.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/SimpleMCSweepLineIntersector.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph.index;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geomgraph.*;
@@ -49,7 +49,7 @@ import com.vividsolutions.jts.geomgraph.*;
* The use of MonotoneChains as the items in the index
* seems to offer an improvement in performance over a sweep-line alone.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimpleMCSweepLineIntersector
extends EdgeSetIntersector
diff --git a/src/com/vividsolutions/jts/geomgraph/index/SimpleSweepLineIntersector.java b/src/com/vividsolutions/jts/geomgraph/index/SimpleSweepLineIntersector.java
index ccd36cf..b41f5c8 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/SimpleSweepLineIntersector.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/SimpleSweepLineIntersector.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph.index;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geom.Coordinate;
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.geomgraph.*;
* While still O(n^2) in the worst case, this algorithm
* drastically improves the average-case time.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimpleSweepLineIntersector
extends EdgeSetIntersector
diff --git a/src/com/vividsolutions/jts/geomgraph/index/SweepLineEvent.java b/src/com/vividsolutions/jts/geomgraph/index/SweepLineEvent.java
index 3e47514..1072a3e 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/SweepLineEvent.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/SweepLineEvent.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.geomgraph.index;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SweepLineEvent
implements Comparable
diff --git a/src/com/vividsolutions/jts/geomgraph/index/SweepLineSegment.java b/src/com/vividsolutions/jts/geomgraph/index/SweepLineSegment.java
index 9c9ddc5..9bd2a88 100644
--- a/src/com/vividsolutions/jts/geomgraph/index/SweepLineSegment.java
+++ b/src/com/vividsolutions/jts/geomgraph/index/SweepLineSegment.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geomgraph.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SweepLineSegment {
diff --git a/src/com/vividsolutions/jts/index/ArrayListVisitor.java b/src/com/vividsolutions/jts/index/ArrayListVisitor.java
index c9f2c43..39065bc 100644
--- a/src/com/vividsolutions/jts/index/ArrayListVisitor.java
+++ b/src/com/vividsolutions/jts/index/ArrayListVisitor.java
@@ -4,7 +4,7 @@ import java.util.*;
import com.vividsolutions.jts.index.ItemVisitor;
/**
- * @version 1.5
+ * @version 1.6
*/
public class ArrayListVisitor
implements ItemVisitor
diff --git a/src/com/vividsolutions/jts/index/IndexVisitor.java b/src/com/vividsolutions/jts/index/IndexVisitor.java
index af0b628..d7f7042 100644
--- a/src/com/vividsolutions/jts/index/IndexVisitor.java
+++ b/src/com/vividsolutions/jts/index/IndexVisitor.java
@@ -3,7 +3,7 @@ package com.vividsolutions.jts.index;
/**
* A visitor for nodes and items in an index.
*
- * @version 1.5
+ * @version 1.6
*/
public interface IndexVisitor {
diff --git a/src/com/vividsolutions/jts/index/ItemVisitor.java b/src/com/vividsolutions/jts/index/ItemVisitor.java
index e4c095c..60a7b04 100644
--- a/src/com/vividsolutions/jts/index/ItemVisitor.java
+++ b/src/com/vividsolutions/jts/index/ItemVisitor.java
@@ -3,7 +3,7 @@ package com.vividsolutions.jts.index;
/**
* A visitor for items in an index.
*
- * @version 1.5
+ * @version 1.6
*/
public interface ItemVisitor
diff --git a/src/com/vividsolutions/jts/index/SpatialIndex.java b/src/com/vividsolutions/jts/index/SpatialIndex.java
index 7baec29..a464a44 100644
--- a/src/com/vividsolutions/jts/index/SpatialIndex.java
+++ b/src/com/vividsolutions/jts/index/SpatialIndex.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.geom.Envelope;
* secondary filter may consist of other tests besides intersection, such as
* testing other kinds of spatial relationships.
*
- * @version 1.5
+ * @version 1.6
*/
public interface SpatialIndex
{
diff --git a/src/com/vividsolutions/jts/index/bintree/Bintree.java b/src/com/vividsolutions/jts/index/bintree/Bintree.java
index d5e070a..10e007e 100644
--- a/src/com/vividsolutions/jts/index/bintree/Bintree.java
+++ b/src/com/vividsolutions/jts/index/bintree/Bintree.java
@@ -52,7 +52,7 @@ import java.util.List;
* This index is different to the Interval Tree of Edelsbrunner
* or the Segment Tree of Bentley.
*
- * @version 1.5
+ * @version 1.6
*/
public class Bintree
{
diff --git a/src/com/vividsolutions/jts/index/bintree/Interval.java b/src/com/vividsolutions/jts/index/bintree/Interval.java
index 80adcdc..41fe202 100644
--- a/src/com/vividsolutions/jts/index/bintree/Interval.java
+++ b/src/com/vividsolutions/jts/index/bintree/Interval.java
@@ -36,7 +36,7 @@ package com.vividsolutions.jts.index.bintree;
/**
* Represents an (1-dimensional) closed interval on the Real number line.
*
- * @version 1.5
+ * @version 1.6
*/
public class Interval {
diff --git a/src/com/vividsolutions/jts/index/bintree/Key.java b/src/com/vividsolutions/jts/index/bintree/Key.java
index 4c17dc5..84299ad 100644
--- a/src/com/vividsolutions/jts/index/bintree/Key.java
+++ b/src/com/vividsolutions/jts/index/bintree/Key.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.index.quadtree.DoubleBits;
* It contains a lower-left point and a level number. The level number
* is the power of two for the size of the node envelope
*
- * @version 1.5
+ * @version 1.6
*/
public class Key {
diff --git a/src/com/vividsolutions/jts/index/bintree/Node.java b/src/com/vividsolutions/jts/index/bintree/Node.java
index 96da3a7..1489b29 100644
--- a/src/com/vividsolutions/jts/index/bintree/Node.java
+++ b/src/com/vividsolutions/jts/index/bintree/Node.java
@@ -38,7 +38,7 @@ import com.vividsolutions.jts.util.Assert;
/**
* A node of a {@link Bintree}.
*
- * @version 1.5
+ * @version 1.6
*/
public class Node
extends NodeBase
diff --git a/src/com/vividsolutions/jts/index/bintree/NodeBase.java b/src/com/vividsolutions/jts/index/bintree/NodeBase.java
index 458c0d4..d70f26a 100644
--- a/src/com/vividsolutions/jts/index/bintree/NodeBase.java
+++ b/src/com/vividsolutions/jts/index/bintree/NodeBase.java
@@ -41,7 +41,7 @@ import java.util.List;
/**
* The base class for nodes in a {@link Bintree}.
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class NodeBase {
diff --git a/src/com/vividsolutions/jts/index/bintree/Root.java b/src/com/vividsolutions/jts/index/bintree/Root.java
index 4e31d99..d9942be 100644
--- a/src/com/vividsolutions/jts/index/bintree/Root.java
+++ b/src/com/vividsolutions/jts/index/bintree/Root.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.util.Assert;
* It is centred at the origin,
* and does not have a defined extent.
*
- * @version 1.5
+ * @version 1.6
*/
public class Root
extends NodeBase
diff --git a/src/com/vividsolutions/jts/index/chain/MonotoneChain.java b/src/com/vividsolutions/jts/index/chain/MonotoneChain.java
index 410453a..5fe6566 100644
--- a/src/com/vividsolutions/jts/index/chain/MonotoneChain.java
+++ b/src/com/vividsolutions/jts/index/chain/MonotoneChain.java
@@ -75,7 +75,7 @@ import com.vividsolutions.jts.geom.*;
* returned by the query.
* However, it does mean that the queries are not thread-safe.
*
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChain {
diff --git a/src/com/vividsolutions/jts/index/chain/MonotoneChainBuilder.java b/src/com/vividsolutions/jts/index/chain/MonotoneChainBuilder.java
index 4951ff6..c003b4a 100644
--- a/src/com/vividsolutions/jts/index/chain/MonotoneChainBuilder.java
+++ b/src/com/vividsolutions/jts/index/chain/MonotoneChainBuilder.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.geomgraph.Quadrant;
* A MonotoneChainBuilder implements functions to determine the monotone chains
* in a sequence of points.
*
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChainBuilder {
diff --git a/src/com/vividsolutions/jts/index/chain/MonotoneChainOverlapAction.java b/src/com/vividsolutions/jts/index/chain/MonotoneChainOverlapAction.java
index ca105c3..9650317 100644
--- a/src/com/vividsolutions/jts/index/chain/MonotoneChainOverlapAction.java
+++ b/src/com/vividsolutions/jts/index/chain/MonotoneChainOverlapAction.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.*;
* The action for the internal iterator for performing
* overlap queries on a MonotoneChain
*
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChainOverlapAction
{
diff --git a/src/com/vividsolutions/jts/index/chain/MonotoneChainSelectAction.java b/src/com/vividsolutions/jts/index/chain/MonotoneChainSelectAction.java
index 2b90d88..2e8a80d 100644
--- a/src/com/vividsolutions/jts/index/chain/MonotoneChainSelectAction.java
+++ b/src/com/vividsolutions/jts/index/chain/MonotoneChainSelectAction.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.*;
* The action for the internal iterator for performing
* envelope select queries on a MonotoneChain
*
- * @version 1.5
+ * @version 1.6
*/
public class MonotoneChainSelectAction
{
diff --git a/src/com/vividsolutions/jts/index/quadtree/DoubleBits.java b/src/com/vividsolutions/jts/index/quadtree/DoubleBits.java
index e36a7f3..6319141 100644
--- a/src/com/vividsolutions/jts/index/quadtree/DoubleBits.java
+++ b/src/com/vividsolutions/jts/index/quadtree/DoubleBits.java
@@ -43,7 +43,7 @@ package com.vividsolutions.jts.index.quadtree;
* The algorithms and constants in this class
* apply only to IEEE-754 double-precision floating point format.
*
- * @version 1.5
+ * @version 1.6
*/
public class DoubleBits {
diff --git a/src/com/vividsolutions/jts/index/quadtree/IntervalSize.java b/src/com/vividsolutions/jts/index/quadtree/IntervalSize.java
index 9ad7ef0..6299a21 100644
--- a/src/com/vividsolutions/jts/index/quadtree/IntervalSize.java
+++ b/src/com/vividsolutions/jts/index/quadtree/IntervalSize.java
@@ -42,7 +42,7 @@ package com.vividsolutions.jts.index.quadtree;
* computing a midpoint value which does not lie strictly between the
* endpoints.
*
- * @version 1.5
+ * @version 1.6
*/
public class IntervalSize {
diff --git a/src/com/vividsolutions/jts/index/quadtree/Key.java b/src/com/vividsolutions/jts/index/quadtree/Key.java
index 5a77c1c..a2ab714 100644
--- a/src/com/vividsolutions/jts/index/quadtree/Key.java
+++ b/src/com/vividsolutions/jts/index/quadtree/Key.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geom.Envelope;
* It contains a lower-left point and a level number. The level number
* is the power of two for the size of the node envelope
*
- * @version 1.5
+ * @version 1.6
*/
public class Key {
@@ -95,7 +95,6 @@ public class Key {
private void computeKey(int level, Envelope itemEnv)
{
double quadSize = DoubleBits.powerOf2(level);
- //double quadSize = pow2.power(level);
pt.x = Math.floor(itemEnv.getMinX() / quadSize) * quadSize;
pt.y = Math.floor(itemEnv.getMinY() / quadSize) * quadSize;
env.init(pt.x, pt.x + quadSize, pt.y, pt.y + quadSize);
diff --git a/src/com/vividsolutions/jts/index/quadtree/Node.java b/src/com/vividsolutions/jts/index/quadtree/Node.java
index 88ed0d1..ea9ac8c 100644
--- a/src/com/vividsolutions/jts/index/quadtree/Node.java
+++ b/src/com/vividsolutions/jts/index/quadtree/Node.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.util.Assert;
* items which have a spatial extent corresponding to the node's position
* in the quadtree.
*
- * @version 1.5
+ * @version 1.6
*/
public class Node
extends NodeBase
diff --git a/src/com/vividsolutions/jts/index/quadtree/NodeBase.java b/src/com/vividsolutions/jts/index/quadtree/NodeBase.java
index c7817ec..e2501e7 100644
--- a/src/com/vividsolutions/jts/index/quadtree/NodeBase.java
+++ b/src/com/vividsolutions/jts/index/quadtree/NodeBase.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.index.*;
/**
* The base class for nodes in a {@link Quadtree}.
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class NodeBase {
diff --git a/src/com/vividsolutions/jts/index/quadtree/Quadtree.java b/src/com/vividsolutions/jts/index/quadtree/Quadtree.java
index b557291..0e5c7a2 100644
--- a/src/com/vividsolutions/jts/index/quadtree/Quadtree.java
+++ b/src/com/vividsolutions/jts/index/quadtree/Quadtree.java
@@ -59,7 +59,7 @@ import com.vividsolutions.jts.index.*;
* This data structure is also known as an <i>MX-CIF quadtree</i>
* following the usage of Samet and others.
*
- * @version 1.5
+ * @version 1.6
*/
public class Quadtree
implements SpatialIndex
diff --git a/src/com/vividsolutions/jts/index/quadtree/Root.java b/src/com/vividsolutions/jts/index/quadtree/Root.java
index 5dcea4f..1e37a3a 100644
--- a/src/com/vividsolutions/jts/index/quadtree/Root.java
+++ b/src/com/vividsolutions/jts/index/quadtree/Root.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.util.Assert;
* QuadRoot is the root of a single Quadtree. It is centred at the origin,
* and does not have a defined extent.
*
- * @version 1.5
+ * @version 1.6
*/
public class Root
extends NodeBase
diff --git a/src/com/vividsolutions/jts/index/strtree/AbstractNode.java b/src/com/vividsolutions/jts/index/strtree/AbstractNode.java
index a7170dd..6b71e49 100644
--- a/src/com/vividsolutions/jts/index/strtree/AbstractNode.java
+++ b/src/com/vividsolutions/jts/index/strtree/AbstractNode.java
@@ -41,7 +41,7 @@ import java.util.*;
* (AbstractNodes) or real data (ItemBoundables). If this node contains real data
* (rather than nodes), then we say that this node is a "leaf node".
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class AbstractNode implements Boundable {
private ArrayList childBoundables = new ArrayList();
diff --git a/src/com/vividsolutions/jts/index/strtree/AbstractSTRtree.java b/src/com/vividsolutions/jts/index/strtree/AbstractSTRtree.java
index e375bba..c0adc99 100644
--- a/src/com/vividsolutions/jts/index/strtree/AbstractSTRtree.java
+++ b/src/com/vividsolutions/jts/index/strtree/AbstractSTRtree.java
@@ -48,7 +48,7 @@ import java.util.List;
* @see STRtree
* @see SIRtree
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class AbstractSTRtree {
diff --git a/src/com/vividsolutions/jts/index/strtree/Boundable.java b/src/com/vividsolutions/jts/index/strtree/Boundable.java
index 383a261..200cded 100644
--- a/src/com/vividsolutions/jts/index/strtree/Boundable.java
+++ b/src/com/vividsolutions/jts/index/strtree/Boundable.java
@@ -36,7 +36,7 @@ package com.vividsolutions.jts.index.strtree;
/**
* A spatial object in an AbstractSTRtree.
*
- * @version 1.5
+ * @version 1.6
*/
public interface Boundable {
/**
diff --git a/src/com/vividsolutions/jts/index/strtree/Interval.java b/src/com/vividsolutions/jts/index/strtree/Interval.java
index 1913be4..165cf26 100644
--- a/src/com/vividsolutions/jts/index/strtree/Interval.java
+++ b/src/com/vividsolutions/jts/index/strtree/Interval.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.util.*;
* A contiguous portion of 1D-space. Used internally by SIRtree.
* @see SIRtree
*
- * @version 1.5
+ * @version 1.6
*/
public class Interval {
diff --git a/src/com/vividsolutions/jts/index/strtree/ItemBoundable.java b/src/com/vividsolutions/jts/index/strtree/ItemBoundable.java
index cf4af05..fd9a75a 100644
--- a/src/com/vividsolutions/jts/index/strtree/ItemBoundable.java
+++ b/src/com/vividsolutions/jts/index/strtree/ItemBoundable.java
@@ -37,7 +37,7 @@ package com.vividsolutions.jts.index.strtree;
* Boundable wrapper for a non-Boundable spatial object. Used internally by
* AbstractSTRtree.
*
- * @version 1.5
+ * @version 1.6
*/
public class ItemBoundable implements Boundable {
private Object bounds;
diff --git a/src/com/vividsolutions/jts/index/strtree/SIRtree.java b/src/com/vividsolutions/jts/index/strtree/SIRtree.java
index 225dbd9..adb6a66 100644
--- a/src/com/vividsolutions/jts/index/strtree/SIRtree.java
+++ b/src/com/vividsolutions/jts/index/strtree/SIRtree.java
@@ -44,7 +44,7 @@ import java.util.List;
* Application To GIS. Morgan Kaufmann, San Francisco, 2002.
* @see STRtree
*
- * @version 1.5
+ * @version 1.6
*/
public class SIRtree extends AbstractSTRtree {
diff --git a/src/com/vividsolutions/jts/index/strtree/STRtree.java b/src/com/vividsolutions/jts/index/strtree/STRtree.java
index bec887e..58c0be4 100644
--- a/src/com/vividsolutions/jts/index/strtree/STRtree.java
+++ b/src/com/vividsolutions/jts/index/strtree/STRtree.java
@@ -52,7 +52,7 @@ import com.vividsolutions.jts.index.*;
* Described in: P. Rigaux, Michel Scholl and Agnes Voisard. Spatial Databases With
* Application To GIS. Morgan Kaufmann, San Francisco, 2002.
*
- * @version 1.5
+ * @version 1.6
*/
public class STRtree extends AbstractSTRtree implements SpatialIndex {
diff --git a/src/com/vividsolutions/jts/index/sweepline/SweepLineEvent.java b/src/com/vividsolutions/jts/index/sweepline/SweepLineEvent.java
index 996f716..2c9e6b9 100644
--- a/src/com/vividsolutions/jts/index/sweepline/SweepLineEvent.java
+++ b/src/com/vividsolutions/jts/index/sweepline/SweepLineEvent.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.index.sweepline;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SweepLineEvent
implements Comparable
diff --git a/src/com/vividsolutions/jts/index/sweepline/SweepLineIndex.java b/src/com/vividsolutions/jts/index/sweepline/SweepLineIndex.java
index c18fdea..06ff4f1 100644
--- a/src/com/vividsolutions/jts/index/sweepline/SweepLineIndex.java
+++ b/src/com/vividsolutions/jts/index/sweepline/SweepLineIndex.java
@@ -40,7 +40,7 @@ import java.util.*;
* A sweepline implements a sorted index on a set of intervals.
* It is used to compute all overlaps between the interval in the index.
*
- * @version 1.5
+ * @version 1.6
*/
public class SweepLineIndex {
diff --git a/src/com/vividsolutions/jts/index/sweepline/SweepLineInterval.java b/src/com/vividsolutions/jts/index/sweepline/SweepLineInterval.java
index 3e3542d..65014ae 100644
--- a/src/com/vividsolutions/jts/index/sweepline/SweepLineInterval.java
+++ b/src/com/vividsolutions/jts/index/sweepline/SweepLineInterval.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.index.sweepline;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SweepLineInterval {
diff --git a/src/com/vividsolutions/jts/index/sweepline/SweepLineOverlapAction.java b/src/com/vividsolutions/jts/index/sweepline/SweepLineOverlapAction.java
index 4009a49..dfd938b 100644
--- a/src/com/vividsolutions/jts/index/sweepline/SweepLineOverlapAction.java
+++ b/src/com/vividsolutions/jts/index/sweepline/SweepLineOverlapAction.java
@@ -37,7 +37,7 @@ package com.vividsolutions.jts.index.sweepline;
/**
- * @version 1.5
+ * @version 1.6
*/
public interface SweepLineOverlapAction {
diff --git a/src/com/vividsolutions/jts/io/ParseException.java b/src/com/vividsolutions/jts/io/ParseException.java
index de0e106..609f8da 100644
--- a/src/com/vividsolutions/jts/io/ParseException.java
+++ b/src/com/vividsolutions/jts/io/ParseException.java
@@ -37,7 +37,7 @@ package com.vividsolutions.jts.io;
/**
* Thrown by a <code>WKTReader</code> when a parsing problem occurs.
*
- *@version 1.5
+ *@version 1.6
*/
public class ParseException extends Exception {
diff --git a/src/com/vividsolutions/jts/io/WKTReader.java b/src/com/vividsolutions/jts/io/WKTReader.java
index 61898a8..2a7f153 100644
--- a/src/com/vividsolutions/jts/io/WKTReader.java
+++ b/src/com/vividsolutions/jts/io/WKTReader.java
@@ -73,7 +73,7 @@ import java.util.ArrayList;
*
* Reads non-standard "LINEARRING" tags.
*
- *@version 1.5
+ *@version 1.6
*/
public class WKTReader {
private GeometryFactory geometryFactory;
diff --git a/src/com/vividsolutions/jts/io/WKTWriter.java b/src/com/vividsolutions/jts/io/WKTWriter.java
index 29a9709..192b93d 100644
--- a/src/com/vividsolutions/jts/io/WKTWriter.java
+++ b/src/com/vividsolutions/jts/io/WKTWriter.java
@@ -56,7 +56,7 @@ import java.text.DecimalFormatSymbols;
* not define a special tag for LinearRings. The standard tag to use is
* "LINESTRING".
*
- * @version 1.5
+ * @version 1.6
*/
public class WKTWriter {
diff --git a/src/com/vividsolutions/jts/noding/IteratedNoder.java b/src/com/vividsolutions/jts/noding/IteratedNoder.java
index 271d9fb..b19e8b6 100644
--- a/src/com/vividsolutions/jts/noding/IteratedNoder.java
+++ b/src/com/vividsolutions/jts/noding/IteratedNoder.java
@@ -47,7 +47,7 @@ import com.vividsolutions.jts.geom.*;
* due to roundoff error. This problem is detected and an exception is thrown.
* Clients can choose to rerun the noding using a lower precision model.
*
- * @version 1.5
+ * @version 1.6
*/
public class IteratedNoder
{
diff --git a/src/com/vividsolutions/jts/noding/MCQuadtreeNoder.java b/src/com/vividsolutions/jts/noding/MCQuadtreeNoder.java
index f8008b6..cbd2218 100644
--- a/src/com/vividsolutions/jts/noding/MCQuadtreeNoder.java
+++ b/src/com/vividsolutions/jts/noding/MCQuadtreeNoder.java
@@ -47,7 +47,7 @@ import com.vividsolutions.jts.index.quadtree.Quadtree;
* envelope (range) queries efficiently (such as a {@link Quadtree}
* or {@link STRtree}.
*
- * @version 1.5
+ * @version 1.6
*/
public class MCQuadtreeNoder
extends Noder
diff --git a/src/com/vividsolutions/jts/noding/Noder.java b/src/com/vividsolutions/jts/noding/Noder.java
index df3eb7e..27d8439 100644
--- a/src/com/vividsolutions/jts/noding/Noder.java
+++ b/src/com/vividsolutions/jts/noding/Noder.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.geomgraph.index.*;
* Intersections found are represented as {@link SegmentNode}s and add to the
* {@link SegmentString}s in which they occur.
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class Noder
{
diff --git a/src/com/vividsolutions/jts/noding/NodingValidator.java b/src/com/vividsolutions/jts/noding/NodingValidator.java
index 4d66cac..5fa4ddc 100644
--- a/src/com/vividsolutions/jts/noding/NodingValidator.java
+++ b/src/com/vividsolutions/jts/noding/NodingValidator.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geom.*;
* Validates that a collection of {@link SegmentString}s is correctly noded.
* Throws an appropriate exception if an noding error is found.
*
- * @version 1.5
+ * @version 1.6
*/
public class NodingValidator {
diff --git a/src/com/vividsolutions/jts/noding/SegmentIntersector.java b/src/com/vividsolutions/jts/noding/SegmentIntersector.java
index 8ff67a0..f762b15 100644
--- a/src/com/vividsolutions/jts/noding/SegmentIntersector.java
+++ b/src/com/vividsolutions/jts/noding/SegmentIntersector.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.Debug;
* detects that two SegmentStrings <i>might</i> intersect.
* This class is an example of the <i>Strategy</i> pattern.
*
- * @version 1.5
+ * @version 1.6
*/
public class SegmentIntersector
{
diff --git a/src/com/vividsolutions/jts/noding/SegmentNode.java b/src/com/vividsolutions/jts/noding/SegmentNode.java
index f624607..c8ca36e 100644
--- a/src/com/vividsolutions/jts/noding/SegmentNode.java
+++ b/src/com/vividsolutions/jts/noding/SegmentNode.java
@@ -45,7 +45,7 @@ package com.vividsolutions.jts.noding;
* the edge from this point forwards, until the next
* intersection or the end of the edge.
* The intersection point must be precise.
- * @version 1.5
+ * @version 1.6
*/
import java.io.PrintStream;
import com.vividsolutions.jts.geom.Coordinate;
@@ -53,7 +53,7 @@ import com.vividsolutions.jts.geom.Coordinate;
/**
* Represents an intersection point between two {@link SegmentString}s.
*
- * @version 1.5
+ * @version 1.6
*/
public class SegmentNode
implements Comparable
diff --git a/src/com/vividsolutions/jts/noding/SegmentNodeList.java b/src/com/vividsolutions/jts/noding/SegmentNodeList.java
index 8e741ea..af46a14 100644
--- a/src/com/vividsolutions/jts/noding/SegmentNodeList.java
+++ b/src/com/vividsolutions/jts/noding/SegmentNodeList.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.util.Debug;
/**
* A list of the {@link SegmentNode}s present along a noded {@link SegmentString}.
*
- * @version 1.5
+ * @version 1.6
*/
public class SegmentNodeList
{
diff --git a/src/com/vividsolutions/jts/noding/SegmentString.java b/src/com/vividsolutions/jts/noding/SegmentString.java
index 5dfa686..1291b3a 100644
--- a/src/com/vividsolutions/jts/noding/SegmentString.java
+++ b/src/com/vividsolutions/jts/noding/SegmentString.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* The line segments are represented by an array of {@link Coordinate}s.
*
*
- * @version 1.5
+ * @version 1.6
*/
public class SegmentString {
diff --git a/src/com/vividsolutions/jts/noding/SimpleNoder.java b/src/com/vividsolutions/jts/noding/SimpleNoder.java
index 56521b1..dc4a50b 100644
--- a/src/com/vividsolutions/jts/noding/SimpleNoder.java
+++ b/src/com/vividsolutions/jts/noding/SimpleNoder.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.geom.*;
* This has n^2 performance, so is too slow for use on large numbers
* of segments.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimpleNoder
extends Noder
diff --git a/src/com/vividsolutions/jts/noding/snapround/SegmentSnapper.java b/src/com/vividsolutions/jts/noding/snapround/SegmentSnapper.java
index 4affadf..cf3e330 100644
--- a/src/com/vividsolutions/jts/noding/snapround/SegmentSnapper.java
+++ b/src/com/vividsolutions/jts/noding/snapround/SegmentSnapper.java
@@ -38,7 +38,7 @@ import com.vividsolutions.jts.noding.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SegmentSnapper {
diff --git a/src/com/vividsolutions/jts/noding/snapround/SimpleSegmentStringsSnapper.java b/src/com/vividsolutions/jts/noding/snapround/SimpleSegmentStringsSnapper.java
index 861360c..8c8f1e0 100644
--- a/src/com/vividsolutions/jts/noding/snapround/SimpleSegmentStringsSnapper.java
+++ b/src/com/vividsolutions/jts/noding/snapround/SimpleSegmentStringsSnapper.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.noding.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class SimpleSegmentStringsSnapper {
diff --git a/src/com/vividsolutions/jts/noding/snapround/SnapRounder.java b/src/com/vividsolutions/jts/noding/snapround/SnapRounder.java
index ba4662c..6c1c8a7 100644
--- a/src/com/vividsolutions/jts/noding/snapround/SnapRounder.java
+++ b/src/com/vividsolutions/jts/noding/snapround/SnapRounder.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.noding.*;
* Uses snap rounding to compute a rounded, noded arrangement from a
* set of linestrings.
*
- * @version 1.5
+ * @version 1.6
*/
public class SnapRounder
//extends Noder // cut this free for now
diff --git a/src/com/vividsolutions/jts/operation/GeometryGraphOperation.java b/src/com/vividsolutions/jts/operation/GeometryGraphOperation.java
index 31ce828..b4fb950 100644
--- a/src/com/vividsolutions/jts/operation/GeometryGraphOperation.java
+++ b/src/com/vividsolutions/jts/operation/GeometryGraphOperation.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geomgraph.GeometryGraph;
/**
* The base class for operations that require {@link GeometryGraph)s.
*
- * @version 1.5
+ * @version 1.6
*/
public class GeometryGraphOperation
{
diff --git a/src/com/vividsolutions/jts/operation/IsSimpleOp.java b/src/com/vividsolutions/jts/operation/IsSimpleOp.java
index 2255142..a54b5ca 100644
--- a/src/com/vividsolutions/jts/operation/IsSimpleOp.java
+++ b/src/com/vividsolutions/jts/operation/IsSimpleOp.java
@@ -47,7 +47,7 @@ import com.vividsolutions.jts.geomgraph.index.SegmentIntersector;
* by definition, so no test is provided. To test whether a given Polygon is valid,
* use <code>Geometry#isValid</code>)
*
- * @version 1.5
+ * @version 1.6
*/
public class IsSimpleOp {
diff --git a/src/com/vividsolutions/jts/operation/buffer/BufferBuilder.java b/src/com/vividsolutions/jts/operation/buffer/BufferBuilder.java
index 86c527a..0b07be5 100644
--- a/src/com/vividsolutions/jts/operation/buffer/BufferBuilder.java
+++ b/src/com/vividsolutions/jts/operation/buffer/BufferBuilder.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.operation.buffer;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
@@ -58,7 +58,7 @@ import com.vividsolutions.jts.noding.*;
* Retrying the computation in a fixed precision
* can produce more robust results.
*
- * @version 1.5
+ * @version 1.6
*/
public class BufferBuilder
{
diff --git a/src/com/vividsolutions/jts/operation/buffer/BufferOp.java b/src/com/vividsolutions/jts/operation/buffer/BufferOp.java
index 9cdd4e0..53763f8 100644
--- a/src/com/vividsolutions/jts/operation/buffer/BufferOp.java
+++ b/src/com/vividsolutions/jts/operation/buffer/BufferOp.java
@@ -33,7 +33,7 @@
package com.vividsolutions.jts.operation.buffer;
/**
- * @version 1.5
+ * @version 1.6
*/
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer;
@@ -65,7 +65,7 @@ import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer;
* to provide a high degree of robustness.
*
- * @version 1.5
+ * @version 1.6
*/
public class BufferOp
{
diff --git a/src/com/vividsolutions/jts/operation/buffer/BufferSubgraph.java b/src/com/vividsolutions/jts/operation/buffer/BufferSubgraph.java
index fc0c57e..908f649 100644
--- a/src/com/vividsolutions/jts/operation/buffer/BufferSubgraph.java
+++ b/src/com/vividsolutions/jts/operation/buffer/BufferSubgraph.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.operation.buffer;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
@@ -55,7 +55,7 @@ import com.vividsolutions.jts.util.*;
* </ul>
*
*
- * @version 1.5
+ * @version 1.6
*/
public class BufferSubgraph
implements Comparable
diff --git a/src/com/vividsolutions/jts/operation/buffer/OffsetCurveBuilder.java b/src/com/vividsolutions/jts/operation/buffer/OffsetCurveBuilder.java
index d2db76c..9ad0642 100644
--- a/src/com/vividsolutions/jts/operation/buffer/OffsetCurveBuilder.java
+++ b/src/com/vividsolutions/jts/operation/buffer/OffsetCurveBuilder.java
@@ -46,7 +46,7 @@ import com.vividsolutions.jts.geomgraph.*;
* of all the noded raw curves and tracing outside contours.
* The points in the raw curve are rounded to the required precision model.
*
- * @version 1.5
+ * @version 1.6
*/
public class OffsetCurveBuilder {
diff --git a/src/com/vividsolutions/jts/operation/buffer/OffsetCurveSetBuilder.java b/src/com/vividsolutions/jts/operation/buffer/OffsetCurveSetBuilder.java
index cd62467..0e33da4 100644
--- a/src/com/vividsolutions/jts/operation/buffer/OffsetCurveSetBuilder.java
+++ b/src/com/vividsolutions/jts/operation/buffer/OffsetCurveSetBuilder.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.operation.buffer;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geom.*;
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.noding.SegmentString;
* Creates all the raw offset curves for a buffer of a {@link Geometry}.
* Raw curves need to be noded together and polygonized to form the final buffer area.
*
- * @version 1.5
+ * @version 1.6
*/
public class OffsetCurveSetBuilder {
diff --git a/src/com/vividsolutions/jts/operation/buffer/RightmostEdgeFinder.java b/src/com/vividsolutions/jts/operation/buffer/RightmostEdgeFinder.java
index 0d51188..af90e49 100644
--- a/src/com/vividsolutions/jts/operation/buffer/RightmostEdgeFinder.java
+++ b/src/com/vividsolutions/jts/operation/buffer/RightmostEdgeFinder.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.operation.buffer;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geom.*;
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.util.*;
* A RightmostEdgeFinder find the DirectedEdge in a list which has the highest coordinate,
* and which is oriented L to R at that point. (I.e. the right side is on the RHS of the edge.)
*
- * @version 1.5
+ * @version 1.6
*/
public class RightmostEdgeFinder {
diff --git a/src/com/vividsolutions/jts/operation/buffer/SubgraphDepthLocater.java b/src/com/vividsolutions/jts/operation/buffer/SubgraphDepthLocater.java
index b96d0a8..1f227a5 100644
--- a/src/com/vividsolutions/jts/operation/buffer/SubgraphDepthLocater.java
+++ b/src/com/vividsolutions/jts/operation/buffer/SubgraphDepthLocater.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.algorithm.*;
* The input subgraphs are assumed to have had depths
* already calculated for their edges.
*
- * @version 1.5
+ * @version 1.6
*/
public class SubgraphDepthLocater
{
diff --git a/src/com/vividsolutions/jts/operation/distance/ConnectedElementLocationFilter.java b/src/com/vividsolutions/jts/operation/distance/ConnectedElementLocationFilter.java
index 79c990d..1dcc7b2 100644
--- a/src/com/vividsolutions/jts/operation/distance/ConnectedElementLocationFilter.java
+++ b/src/com/vividsolutions/jts/operation/distance/ConnectedElementLocationFilter.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.geom.*;
* and returns them in a list. The elements of the list are
* {@link com.vividsolutions.jts.operation.distance.GeometryLocation}s.
*
- * @version 1.5
+ * @version 1.6
*/
public class ConnectedElementLocationFilter
implements GeometryFilter
diff --git a/src/com/vividsolutions/jts/operation/distance/ConnectedElementPointFilter.java b/src/com/vividsolutions/jts/operation/distance/ConnectedElementPointFilter.java
index b4e0832..8477c28 100644
--- a/src/com/vividsolutions/jts/operation/distance/ConnectedElementPointFilter.java
+++ b/src/com/vividsolutions/jts/operation/distance/ConnectedElementPointFilter.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.geom.*;
* (e.g. a polygon, linestring or point)
* and returns them in a list
*
- * @version 1.5
+ * @version 1.6
*/
public class ConnectedElementPointFilter
implements GeometryFilter
diff --git a/src/com/vividsolutions/jts/operation/distance/DistanceOp.java b/src/com/vividsolutions/jts/operation/distance/DistanceOp.java
index 76329c9..c47e673 100644
--- a/src/com/vividsolutions/jts/operation/distance/DistanceOp.java
+++ b/src/com/vividsolutions/jts/operation/distance/DistanceOp.java
@@ -51,7 +51,7 @@ import com.vividsolutions.jts.algorithm.*;
* comparisons. This worst-case performance could be improved on
* by using Voronoi techniques.
*
- * @version 1.5
+ * @version 1.6
*/
public class DistanceOp {
diff --git a/src/com/vividsolutions/jts/operation/distance/GeometryLocation.java b/src/com/vividsolutions/jts/operation/distance/GeometryLocation.java
index c77b295..1397461 100644
--- a/src/com/vividsolutions/jts/operation/distance/GeometryLocation.java
+++ b/src/com/vividsolutions/jts/operation/distance/GeometryLocation.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.geom.*;
* Locations inside area Geometrys will not have an associated segment index,
* so in this case the segment index will have the sentinel value of INSIDE_AREA.
*
- * @version 1.5
+ * @version 1.6
*/
public class GeometryLocation
{
diff --git a/src/com/vividsolutions/jts/operation/linemerge/EdgeString.java b/src/com/vividsolutions/jts/operation/linemerge/EdgeString.java
index f1f84eb..129fba3 100644
--- a/src/com/vividsolutions/jts/operation/linemerge/EdgeString.java
+++ b/src/com/vividsolutions/jts/operation/linemerge/EdgeString.java
@@ -47,7 +47,7 @@ import java.util.List;
* A sequence of {@link LineMergeDirectedEdge}s forming one of the lines that will
* be output by the line-merging process.
*
- * @version 1.5
+ * @version 1.6
*/
public class EdgeString {
private GeometryFactory factory;
diff --git a/src/com/vividsolutions/jts/operation/linemerge/LineMergeDirectedEdge.java b/src/com/vividsolutions/jts/operation/linemerge/LineMergeDirectedEdge.java
index e66cf8a..67a2f44 100644
--- a/src/com/vividsolutions/jts/operation/linemerge/LineMergeDirectedEdge.java
+++ b/src/com/vividsolutions/jts/operation/linemerge/LineMergeDirectedEdge.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.util.Assert;
* A {@link com.vividsolutions.jts.planargraph.DirectedEdge} of a
* {@link LineMergeGraph}.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineMergeDirectedEdge extends DirectedEdge {
/**
diff --git a/src/com/vividsolutions/jts/operation/linemerge/LineMergeEdge.java b/src/com/vividsolutions/jts/operation/linemerge/LineMergeEdge.java
index 7a282ff..7db2192 100644
--- a/src/com/vividsolutions/jts/operation/linemerge/LineMergeEdge.java
+++ b/src/com/vividsolutions/jts/operation/linemerge/LineMergeEdge.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.planargraph.Edge;
* An edge of a {@link LineMergeGraph}. The <code>marked</code> field indicates
* whether this Edge has been logically deleted from the graph.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineMergeEdge extends Edge {
private LineString line;
diff --git a/src/com/vividsolutions/jts/operation/linemerge/LineMergeGraph.java b/src/com/vividsolutions/jts/operation/linemerge/LineMergeGraph.java
index 3274478..6d4beee 100644
--- a/src/com/vividsolutions/jts/operation/linemerge/LineMergeGraph.java
+++ b/src/com/vividsolutions/jts/operation/linemerge/LineMergeGraph.java
@@ -47,7 +47,7 @@ import com.vividsolutions.jts.planargraph.PlanarGraph;
* and @{link com.vividsolutions.planargraph.Node}s indicates whether they have been
* logically deleted from the graph.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineMergeGraph extends PlanarGraph {
/**
diff --git a/src/com/vividsolutions/jts/operation/linemerge/LineMerger.java b/src/com/vividsolutions/jts/operation/linemerge/LineMerger.java
index 8ad4749..d4b3f9b 100644
--- a/src/com/vividsolutions/jts/operation/linemerge/LineMerger.java
+++ b/src/com/vividsolutions/jts/operation/linemerge/LineMerger.java
@@ -56,7 +56,7 @@ import com.vividsolutions.jts.util.Assert;
* at their endpoints. The LineMerger will still run on incorrectly noded input
* but will not form polygons from incorrected noded edges.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineMerger {
/**
diff --git a/src/com/vividsolutions/jts/operation/overlay/EdgeSetNoder.java b/src/com/vividsolutions/jts/operation/overlay/EdgeSetNoder.java
index 3e3da7a..672ec26 100644
--- a/src/com/vividsolutions/jts/operation/overlay/EdgeSetNoder.java
+++ b/src/com/vividsolutions/jts/operation/overlay/EdgeSetNoder.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.*;
* Takes one or more sets of edges and constructs a
* new set of edges consisting of all the split edges created by
* noding the input edges together
- * @version 1.5
+ * @version 1.6
*/
public class EdgeSetNoder {
diff --git a/src/com/vividsolutions/jts/operation/overlay/LineBuilder.java b/src/com/vividsolutions/jts/operation/overlay/LineBuilder.java
index e2e7782..765e420 100644
--- a/src/com/vividsolutions/jts/operation/overlay/LineBuilder.java
+++ b/src/com/vividsolutions/jts/operation/overlay/LineBuilder.java
@@ -1,6 +1,3 @@
-
-
-
/*
* The JTS Topology Suite is a collection of Java classes that
* implement the fundamental operations required to validate a given
@@ -39,12 +36,13 @@ import java.util.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geomgraph.*;
import com.vividsolutions.jts.algorithm.*;
+import com.vividsolutions.jts.util.*;
/**
* Forms JTS LineStrings out of a the graph of {@link DirectedEdge}s
* created by an {@link OverlayOp}.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineBuilder {
private OverlayOp op;
@@ -108,21 +106,33 @@ public class LineBuilder {
collectBoundaryTouchEdge(de, opCode, lineEdgesList);
}
}
- public void collectLineEdge(DirectedEdge de, int opCode, List edges)
+
+ /**
+ * Collect line edges which are in the result.
+ * Line edges are in the result if they are not part of
+ * an area boundary, if they are in the result of the overlay operation,
+ * and if they are not covered by a result area.
+ *
+ * @param de the directed edge to test
+ * @param opCode the overlap operation
+ * @param edges the list of included line edges
+ */
+ private void collectLineEdge(DirectedEdge de, int opCode, List edges)
{
- Label label = de.getLabel();
- Edge e = de.getEdge();
- // include L edges which are in the result
- if (de.isLineEdge()) {
- if (! de.isVisited() && OverlayOp.isResultOfOp(label, opCode) && ! e.isCovered()) {
+ Label label = de.getLabel();
+ Edge e = de.getEdge();
+ // include L edges which are in the result
+ if (de.isLineEdge()) {
+ if (! de.isVisited() && OverlayOp.isResultOfOp(label, opCode) && ! e.isCovered()) {
//Debug.println("de: " + de.getLabel());
//Debug.println("edge: " + e.getLabel());
- edges.add(e);
- de.setVisitedEdge(true);
- }
+ edges.add(e);
+ de.setVisitedEdge(true);
}
+ }
}
+
/**
* Collect edges from Area inputs which should be in the result but
* which have not been included in a result area.
@@ -133,15 +143,19 @@ public class LineBuilder {
* <li> OR as a result of a dimensional collapse.
* </ul>
*/
- public void collectBoundaryTouchEdge(DirectedEdge de, int opCode, List edges)
+ private void collectBoundaryTouchEdge(DirectedEdge de, int opCode, List edges)
{
Label label = de.getLabel();
- // this smells like a bit of a hack, but it seems to work...
- if (! de.isLineEdge()
- && ! de.isInteriorAreaEdge() // added to handle dimensional collapses
- && ! de.getEdge().isInResult()
- && ! de.isVisited()
- && OverlayOp.isResultOfOp(label, opCode)
+ if (de.isLineEdge()) return; // only interested in area edges
+ if (de.isVisited()) return; // already processed
+ if (de.isInteriorAreaEdge()) return; // added to handle dimensional collapses
+ if (de.getEdge().isInResult()) return; // if the edge linework is already included, don't include it again
+
+ // sanity check for labelling of result edgerings
+ Assert.isTrue(! (de.isInResult() || de.getSym().isInResult()) || ! de.getEdge().isInResult());
+
+ // include the linework if it's in the result of the operation
+ if (OverlayOp.isResultOfOp(label, opCode)
&& opCode == OverlayOp.INTERSECTION)
{
edges.add(de.getEdge());
@@ -151,17 +165,12 @@ public class LineBuilder {
private void buildLines(int opCode)
{
- // need to simplify lines?
for (Iterator it = lineEdgesList.iterator(); it.hasNext(); ) {
Edge e = (Edge) it.next();
Label label = e.getLabel();
-//e.print(System.out);
- ////System.out.println(label);
- //if (OverlayGraph.isResultOfOp(label, opCode)) {
LineString line = geometryFactory.createLineString(e.getCoordinates());
resultLineList.add(line);
e.setInResult(true);
- //}
}
}
diff --git a/src/com/vividsolutions/jts/operation/overlay/MaximalEdgeRing.java b/src/com/vividsolutions/jts/operation/overlay/MaximalEdgeRing.java
index dad5204..1fb5d39 100644
--- a/src/com/vividsolutions/jts/operation/overlay/MaximalEdgeRing.java
+++ b/src/com/vividsolutions/jts/operation/overlay/MaximalEdgeRing.java
@@ -54,7 +54,7 @@ import com.vividsolutions.jts.geomgraph.*;
* A MaximalEdgeRing can be converted to a list of MinimalEdgeRings using the
* {@link #buildMinimalRings() } method.
*
- * @version 1.5
+ * @version 1.6
* @see com.vividsolutions.jts.operation.overlay.MinimalEdgeRing
*/
public class MaximalEdgeRing
diff --git a/src/com/vividsolutions/jts/operation/overlay/MinimalEdgeRing.java b/src/com/vividsolutions/jts/operation/overlay/MinimalEdgeRing.java
index 1f1be94..21166f4 100644
--- a/src/com/vividsolutions/jts/operation/overlay/MinimalEdgeRing.java
+++ b/src/com/vividsolutions/jts/operation/overlay/MinimalEdgeRing.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.geomgraph.*;
* has degree greater than 2. These are the form of rings required
* to represent polygons under the OGC SFS spatial data model.
*
- * @version 1.5
+ * @version 1.6
* @see com.vividsolutions.jts.operation.overlay.MaximalEdgeRing
*/
public class MinimalEdgeRing
diff --git a/src/com/vividsolutions/jts/operation/overlay/OverlayNodeFactory.java b/src/com/vividsolutions/jts/operation/overlay/OverlayNodeFactory.java
index 3ae712f..b7e0971 100644
--- a/src/com/vividsolutions/jts/operation/overlay/OverlayNodeFactory.java
+++ b/src/com/vividsolutions/jts/operation/overlay/OverlayNodeFactory.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.operation.overlay;
/**
- * @version 1.5
+ * @version 1.6
*/
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geomgraph.*;
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geomgraph.*;
* Creates nodes for use in the {@link PlanarGraph}s constructed during
* overlay operations.
*
- * @version 1.5
+ * @version 1.6
*/
public class OverlayNodeFactory
extends NodeFactory
diff --git a/src/com/vividsolutions/jts/operation/overlay/OverlayOp.java b/src/com/vividsolutions/jts/operation/overlay/OverlayOp.java
index 493ac4f..1665ca6 100644
--- a/src/com/vividsolutions/jts/operation/overlay/OverlayOp.java
+++ b/src/com/vividsolutions/jts/operation/overlay/OverlayOp.java
@@ -46,7 +46,7 @@ import com.vividsolutions.jts.operation.GeometryGraphOperation;
* Computes the overlay of two {@link Geometry}s. The overlay
* can be used to determine any boolean combination of the geometries.
*
- * @version 1.5
+ * @version 1.6
*/
public class OverlayOp
extends GeometryGraphOperation
diff --git a/src/com/vividsolutions/jts/operation/overlay/PointBuilder.java b/src/com/vividsolutions/jts/operation/overlay/PointBuilder.java
index cf5b74c..883bada 100644
--- a/src/com/vividsolutions/jts/operation/overlay/PointBuilder.java
+++ b/src/com/vividsolutions/jts/operation/overlay/PointBuilder.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geomgraph.*;
/**
* Constructs {@link Point}s from the nodes of an overlay graph.
- * @version 1.5
+ * @version 1.6
*/
public class PointBuilder {
private OverlayOp op;
diff --git a/src/com/vividsolutions/jts/operation/overlay/PolygonBuilder.java b/src/com/vividsolutions/jts/operation/overlay/PolygonBuilder.java
index 463af35..5d180f1 100644
--- a/src/com/vividsolutions/jts/operation/overlay/PolygonBuilder.java
+++ b/src/com/vividsolutions/jts/operation/overlay/PolygonBuilder.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.util.*;
* The edges to use are marked as being in the result Area.
* <p>
*
- * @version 1.5
+ * @version 1.6
*/
public class PolygonBuilder {
@@ -105,6 +105,7 @@ public class PolygonBuilder {
if (de.getEdgeRing() == null) {
MaximalEdgeRing er = new MaximalEdgeRing(de, geometryFactory, cga);
maxEdgeRings.add(er);
+ er.setInResult();
//System.out.println("max node degree = " + er.getMaxDegree());
}
}
@@ -121,7 +122,6 @@ public class PolygonBuilder {
er.linkDirectedEdgesForMinimalEdgeRings();
List minEdgeRings = er.buildMinimalRings();
// at this point we can go ahead and attempt to place holes, if this EdgeRing is a polygon
- //computePoints(minEdgeRings);
EdgeRing shell = findShell(minEdgeRings);
if (shell != null) {
placePolygonHoles(shell, minEdgeRings);
@@ -193,7 +193,7 @@ public class PolygonBuilder {
{
for (Iterator it = edgeRings.iterator(); it.hasNext(); ) {
EdgeRing er = (EdgeRing) it.next();
- er.setInResult();
+// er.setInResult();
if (er.isHole() ) {
freeHoleList.add(er);
}
diff --git a/src/com/vividsolutions/jts/operation/polygonize/EdgeRing.java b/src/com/vividsolutions/jts/operation/polygonize/EdgeRing.java
index e506d5c..72d8eb9 100644
--- a/src/com/vividsolutions/jts/operation/polygonize/EdgeRing.java
+++ b/src/com/vividsolutions/jts/operation/polygonize/EdgeRing.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.planargraph.*;
* Represents a ring of {@link PolygonizeDirectedEdge}s which form
* a ring of a polygon. The ring may be either an outer shell or a hole.
*
- * @version 1.5
+ * @version 1.6
*/
public class EdgeRing {
diff --git a/src/com/vividsolutions/jts/operation/polygonize/PolygonizeDirectedEdge.java b/src/com/vividsolutions/jts/operation/polygonize/PolygonizeDirectedEdge.java
index 4b984be..fb027da 100644
--- a/src/com/vividsolutions/jts/operation/polygonize/PolygonizeDirectedEdge.java
+++ b/src/com/vividsolutions/jts/operation/polygonize/PolygonizeDirectedEdge.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.planargraph.Node;
* an edge of a polygon formed by the graph.
* May be logically deleted from the graph by setting the <code>marked</code> flag.
*
- * @version 1.5
+ * @version 1.6
*/
public class PolygonizeDirectedEdge
extends DirectedEdge
diff --git a/src/com/vividsolutions/jts/operation/polygonize/PolygonizeEdge.java b/src/com/vividsolutions/jts/operation/polygonize/PolygonizeEdge.java
index e747d83..630952e 100644
--- a/src/com/vividsolutions/jts/operation/polygonize/PolygonizeEdge.java
+++ b/src/com/vividsolutions/jts/operation/polygonize/PolygonizeEdge.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.planargraph.*;
/**
* An edge of a polygonization graph.
*
- * @version 1.5
+ * @version 1.6
*/
class PolygonizeEdge
extends Edge
diff --git a/src/com/vividsolutions/jts/operation/polygonize/PolygonizeGraph.java b/src/com/vividsolutions/jts/operation/polygonize/PolygonizeGraph.java
index d799073..a0f6a8d 100644
--- a/src/com/vividsolutions/jts/operation/polygonize/PolygonizeGraph.java
+++ b/src/com/vividsolutions/jts/operation/polygonize/PolygonizeGraph.java
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.planargraph.*;
* The marked flag on {@link DirectedEdge}s is used to indicate that a directed edge
* has be logically deleted from the graph.
*
- * @version 1.5
+ * @version 1.6
*/
class PolygonizeGraph
extends PlanarGraph
diff --git a/src/com/vividsolutions/jts/operation/polygonize/Polygonizer.java b/src/com/vividsolutions/jts/operation/polygonize/Polygonizer.java
index dfbc06a..37e6047 100644
--- a/src/com/vividsolutions/jts/operation/polygonize/Polygonizer.java
+++ b/src/com/vividsolutions/jts/operation/polygonize/Polygonizer.java
@@ -53,7 +53,7 @@ import com.vividsolutions.jts.geom.*;
* (e.g. the component lines contain a self-intersection)
* </ul>
*
- * @version 1.5
+ * @version 1.6
*/
public class Polygonizer
{
diff --git a/src/com/vividsolutions/jts/operation/predicate/RectangleContains.java b/src/com/vividsolutions/jts/operation/predicate/RectangleContains.java
new file mode 100644
index 0000000..2f5838a
--- /dev/null
+++ b/src/com/vividsolutions/jts/operation/predicate/RectangleContains.java
@@ -0,0 +1,122 @@
+package com.vividsolutions.jts.operation.predicate;
+
+import com.vividsolutions.jts.geom.*;
+
+/**
+ * Optimized implementation of spatial predicate "contains"
+ * for cases where the first {@link Geometry} is a rectangle.
+ * <p>
+ * As a further optimization,
+ * this class can be used directly to test many geometries against a single
+ * rectangle.
+ *
+ * @version 1.6
+ */
+public class RectangleContains {
+
+ public static boolean contains(Polygon rectangle, Geometry b)
+ {
+ RectangleContains rc = new RectangleContains(rectangle);
+ return rc.contains(b);
+ }
+
+ private Polygon rectangle;
+ private Envelope rectEnv;
+
+ /**
+ * Create a new contains computer for two geometries.
+ *
+ * @param rectangle a rectangular geometry
+ */
+ public RectangleContains(Polygon rectangle) {
+ this.rectangle = rectangle;
+ rectEnv = rectangle.getEnvelopeInternal();
+ }
+
+ public boolean contains(Geometry geom)
+ {
+ if (! rectEnv.contains(geom.getEnvelopeInternal()))
+ return false;
+ // check that geom is not contained entirely in the rectangle boundary
+ if (isContainedInBoundary(geom))
+ return false;
+ return true;
+ }
+
+ private boolean isContainedInBoundary(Geometry geom)
+ {
+ // polygons can never be wholely contained in the boundary
+ if (geom instanceof Polygon) return false;
+ if (geom instanceof Point) return isPointContainedInBoundary((Point) geom);
+ if (geom instanceof LineString) return isLineStringContainedInBoundary((LineString) geom);
+
+ for (int i = 0; i < geom.getNumGeometries(); i++) {
+ Geometry comp = geom.getGeometryN(i);
+ if (! isContainedInBoundary(comp))
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isPointContainedInBoundary(Point point)
+ {
+ return isPointContainedInBoundary(point.getCoordinate());
+ }
+
+ private boolean isPointContainedInBoundary(Coordinate pt)
+ {
+ // we already know that the point is contained in the rectangle envelope
+
+ if (! (pt.x == rectEnv.getMinX() ||
+ pt.x == rectEnv.getMaxX()) )
+ return false;
+ if (! (pt.y == rectEnv.getMinY() ||
+ pt.y == rectEnv.getMaxY()) )
+ return false;
+
+ return true;
+ }
+
+ private boolean isLineStringContainedInBoundary(LineString line)
+ {
+ CoordinateSequence seq = line.getCoordinateSequence();
+ Coordinate p0 = new Coordinate();
+ Coordinate p1 = new Coordinate();
+ for (int i = 0; i < seq.size() - 1; i++) {
+ seq.getCoordinate(i, p0);
+ seq.getCoordinate(i + 1, p1);
+
+ if (! isLineSegmentContainedInBoundary(p0, p1))
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isLineSegmentContainedInBoundary(Coordinate p0, Coordinate p1)
+ {
+ if (p0.equals(p1))
+ return isPointContainedInBoundary(p0);
+
+ // we already know that the segment is contained in the rectangle envelope
+ if (p0.x == p1.x) {
+ if (p0.x == rectEnv.getMinX() ||
+ p0.x == rectEnv.getMaxX() )
+ return true;
+ }
+ else if (p0.y == p1.y) {
+ if (p0.y == rectEnv.getMinY() ||
+ p0.y == rectEnv.getMaxY() )
+ return true;
+ }
+ /**
+ * Either
+ * both x and y values are different
+ * or
+ * one of x and y are the same, but the other ordinate is not the same as a boundary ordinate
+ *
+ * In either case, the segment is not wholely in the boundary
+ */
+ return false;
+ }
+
+}
diff --git a/src/com/vividsolutions/jts/operation/predicate/RectangleIntersects.java b/src/com/vividsolutions/jts/operation/predicate/RectangleIntersects.java
new file mode 100644
index 0000000..278a770
--- /dev/null
+++ b/src/com/vividsolutions/jts/operation/predicate/RectangleIntersects.java
@@ -0,0 +1,211 @@
+package com.vividsolutions.jts.operation.predicate;
+
+import java.util.*;
+import com.vividsolutions.jts.geom.*;
+import com.vividsolutions.jts.algorithm.*;
+import com.vividsolutions.jts.geom.util.*;
+
+/**
+ * Optimized implementation of spatial predicate "intersects"
+ * for cases where the first {@link Geometry} is a rectangle.
+ * <p>
+ * As a further optimization,
+ * this class can be used directly to test many geometries against a single
+ * rectangle.
+ *
+ * @version 1.6
+ */
+public class RectangleIntersects {
+
+ /**
+ * 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.
+ */
+ public static final int MAXIMUM_SCAN_SEGMENT_COUNT = 200;
+
+ public static boolean intersects(Polygon rectangle, Geometry b)
+ {
+ RectangleIntersects rp = new RectangleIntersects(rectangle);
+ return rp.intersects(b);
+ }
+
+ private Polygon rectangle;
+ private Envelope rectEnv;
+
+ /**
+ * Create a new intersects computer for a rectangle.
+ *
+ * @param rectangle a rectangular geometry
+ */
+ public RectangleIntersects(Polygon rectangle) {
+ this.rectangle = rectangle;
+ rectEnv = rectangle.getEnvelopeInternal();
+ }
+
+ public boolean intersects(Geometry geom)
+ {
+ if (! rectEnv.intersects(geom.getEnvelopeInternal()))
+ return false;
+ // test envelope relationships
+ EnvelopeIntersectsVisitor visitor = new EnvelopeIntersectsVisitor(rectEnv);
+ visitor.applyTo(geom);
+ if (visitor.intersects())
+ return true;
+
+ // test if any rectangle corner is contained in the target
+ ContainsPointVisitor ecpVisitor = new ContainsPointVisitor(rectangle);
+ ecpVisitor.applyTo(geom);
+ if (ecpVisitor.containsPoint())
+ return true;
+
+ // test if any lines intersect
+ LineIntersectsVisitor liVisitor = new LineIntersectsVisitor(rectangle);
+ liVisitor.applyTo(geom);
+ if (liVisitor.intersects())
+ return true;
+
+ return false;
+ }
+}
+
+class EnvelopeIntersectsVisitor
+ extends ShortCircuitedGeometryVisitor
+{
+ private Envelope rectEnv;
+ private boolean intersects = false;
+
+ public EnvelopeIntersectsVisitor(Envelope rectEnv)
+ {
+ this.rectEnv = rectEnv;
+ }
+
+ public boolean intersects() { return intersects; }
+
+ protected void visit(Geometry element)
+ {
+ Envelope elementEnv = element.getEnvelopeInternal();
+ // disjoint
+ if (! rectEnv.intersects(elementEnv)) {
+ return;
+ }
+ // fully contained - must intersect
+ if (rectEnv.contains(elementEnv)) {
+ intersects = true;
+ return;
+ }
+ /**
+ * Since the envelopes intersect and the test element is connected,
+ * if its envelope is completely bisected by an edge of the rectangle
+ * the element and the rectangle must touch.
+ * (Note it is NOT possible to make this conclusion
+ * if the test envelope is "on a corner" of the rectangle
+ * envelope)
+ */
+ if (elementEnv.getMinX() >= rectEnv.getMinX()
+ && elementEnv.getMaxX() <= rectEnv.getMaxX()) {
+ intersects = true;
+ return;
+ }
+ if (elementEnv.getMinY() >= rectEnv.getMinY()
+ && elementEnv.getMaxY() <= rectEnv.getMaxY()) {
+ intersects = true;
+ return;
+ }
+ }
+
+ protected boolean isDone() {
+ return intersects == true;
+ }
+}
+
+class ContainsPointVisitor
+ extends ShortCircuitedGeometryVisitor
+{
+ private CoordinateSequence rectSeq;
+ private Envelope rectEnv;
+ private boolean containsPoint = false;
+
+ public ContainsPointVisitor(Polygon rectangle)
+ {
+ this.rectSeq = rectangle.getExteriorRing().getCoordinateSequence();
+ rectEnv = rectangle.getEnvelopeInternal();
+ }
+
+ public boolean containsPoint() { return containsPoint; }
+
+ protected void visit(Geometry geom)
+ {
+ if (! (geom instanceof Polygon))
+ return;
+ Envelope elementEnv = geom.getEnvelopeInternal();
+ if (! rectEnv.intersects(elementEnv))
+ return;
+ // test each corner of rectangle for inclusion
+ Coordinate rectPt = new Coordinate();
+ for (int i = 0; i < 4; i++) {
+ rectSeq.getCoordinate(i, rectPt);
+ if (! elementEnv.contains(rectPt))
+ continue;
+ // check rect point in poly (rect is known not to touch polygon at this point)
+ if (SimplePointInAreaLocator.containsPointInPolygon(rectPt, (Polygon) geom)) {
+ containsPoint = true;
+ return;
+ }
+ }
+ }
+
+ protected boolean isDone() {
+ return containsPoint == true;
+ }
+}
+
+class LineIntersectsVisitor
+ extends ShortCircuitedGeometryVisitor
+{
+ private Polygon rectangle;
+ private CoordinateSequence rectSeq;
+ private Envelope rectEnv;
+ private boolean intersects = false;
+
+ public LineIntersectsVisitor(Polygon rectangle)
+ {
+ this.rectangle = rectangle;
+ this.rectSeq = rectangle.getExteriorRing().getCoordinateSequence();
+ rectEnv = rectangle.getEnvelopeInternal();
+ }
+
+ public boolean intersects() { return intersects; }
+
+ protected void visit(Geometry 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) {
+ intersects = rectangle.relate(geom).isIntersects();
+ return;
+ }
+ computeSegmentIntersection(geom);
+ }
+
+ private void computeSegmentIntersection(Geometry geom)
+ {
+ // check segment intersection
+ // get all lines from geom (e.g. if it's a multi-ring polygon)
+ List lines = LinearComponentExtracter.getLines(geom);
+ SegmentIntersectionTester si = new SegmentIntersectionTester();
+ boolean hasIntersection = si.hasIntersectionWithLineStrings(rectSeq, lines);
+ if (hasIntersection) {
+ intersects = true;
+ return;
+ }
+ }
+
+ protected boolean isDone() {
+ return intersects == true;
+ }
+}
+
diff --git a/src/com/vividsolutions/jts/operation/predicate/SegmentIntersectionTester.java b/src/com/vividsolutions/jts/operation/predicate/SegmentIntersectionTester.java
new file mode 100644
index 0000000..c799243
--- /dev/null
+++ b/src/com/vividsolutions/jts/operation/predicate/SegmentIntersectionTester.java
@@ -0,0 +1,54 @@
+package com.vividsolutions.jts.operation.predicate;
+
+import java.util.*;
+import com.vividsolutions.jts.algorithm.*;
+import com.vividsolutions.jts.geom.*;
+
+/**
+ * Tests if any line segments in two sets of CoordinateSequences intersect.
+ * Optimized for small geometry size.
+ * Short-circuited to return as soon an intersection is found.
+ *
+ * @version 1.6
+ */
+public class SegmentIntersectionTester {
+
+ // for purposes of intersection testing, don't need to set precision model
+ private LineIntersector li = new RobustLineIntersector();
+
+ private boolean hasIntersection = false;
+ private Coordinate pt00 = new Coordinate();
+ private Coordinate pt01 = new Coordinate();
+ private Coordinate pt10 = new Coordinate();
+ private Coordinate pt11 = new Coordinate();
+
+ public SegmentIntersectionTester() {
+ }
+
+ public boolean hasIntersectionWithLineStrings(CoordinateSequence seq, List lines)
+ {
+ for (Iterator i = lines.iterator(); i.hasNext(); ) {
+ LineString line = (LineString) i.next();
+ hasIntersection(seq, line.getCoordinateSequence());
+ if (hasIntersection)
+ break;
+ }
+ return hasIntersection;
+ }
+
+ public boolean hasIntersection(CoordinateSequence seq0, CoordinateSequence seq1) {
+ for (int i = 1; i < seq0.size() && ! hasIntersection; i++) {
+ seq0.getCoordinate(i - 1, pt00);
+ seq0.getCoordinate(i, pt01);
+ for (int j = 1; j < seq1.size() && ! hasIntersection; j++) {
+ seq1.getCoordinate(j - 1, pt10);
+ seq1.getCoordinate(j, pt11);
+
+ li.computeIntersection(pt00, pt01, pt10, pt11);
+ if (li.hasIntersection())
+ hasIntersection = true;
+ }
+ }
+ return hasIntersection;
+ }
+}
diff --git a/src/com/vividsolutions/jts/operation/relate/EdgeEndBuilder.java b/src/com/vividsolutions/jts/operation/relate/EdgeEndBuilder.java
index 2709a7b..d32a4a7 100644
--- a/src/com/vividsolutions/jts/operation/relate/EdgeEndBuilder.java
+++ b/src/com/vividsolutions/jts/operation/relate/EdgeEndBuilder.java
@@ -40,7 +40,7 @@ package com.vividsolutions.jts.operation.relate;
* created by the
* intersections determined for an Edge.
*
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geom.*;
@@ -50,7 +50,7 @@ import com.vividsolutions.jts.util.*;
/**
* Computes the {@link EdgeEnd}s which arise from a noded {@link Edge}.
*
- * @version 1.5
+ * @version 1.6
*/
public class EdgeEndBuilder {
diff --git a/src/com/vividsolutions/jts/operation/relate/EdgeEndBundle.java b/src/com/vividsolutions/jts/operation/relate/EdgeEndBundle.java
index c4720bd..e1f63a0 100644
--- a/src/com/vividsolutions/jts/operation/relate/EdgeEndBundle.java
+++ b/src/com/vividsolutions/jts/operation/relate/EdgeEndBundle.java
@@ -38,7 +38,7 @@ package com.vividsolutions.jts.operation.relate;
/**
* A collection of EdgeStubs which obey the following invariant:
* They originate at the same node and have the same direction.
- * @version 1.5
+ * @version 1.6
*/
import java.io.PrintStream;
import java.util.*;
@@ -50,7 +50,7 @@ import com.vividsolutions.jts.util.Assert;
/**
* Contains all {@link EdgeEnd}s which start at the same point and are parallel.
*
- * @version 1.5
+ * @version 1.6
*/
public class EdgeEndBundle
extends EdgeEnd
diff --git a/src/com/vividsolutions/jts/operation/relate/EdgeEndBundleStar.java b/src/com/vividsolutions/jts/operation/relate/EdgeEndBundleStar.java
index 8ea7003..f6e2a44 100644
--- a/src/com/vividsolutions/jts/operation/relate/EdgeEndBundleStar.java
+++ b/src/com/vividsolutions/jts/operation/relate/EdgeEndBundleStar.java
@@ -46,7 +46,7 @@ import com.vividsolutions.jts.util.Assert;
* An ordered list of {@link EdgeEndBundle}s around a {@link RelateNode}.
* They are maintained in CCW order (starting with the positive x-axis) around the node
* for efficient lookup and topology building.
- * @version 1.5
+ * @version 1.6
*/
public class EdgeEndBundleStar
extends EdgeEndStar
diff --git a/src/com/vividsolutions/jts/operation/relate/RelateComputer.java b/src/com/vividsolutions/jts/operation/relate/RelateComputer.java
index 02784d1..6beb57a 100644
--- a/src/com/vividsolutions/jts/operation/relate/RelateComputer.java
+++ b/src/com/vividsolutions/jts/operation/relate/RelateComputer.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.operation.relate;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geom.*;
@@ -58,7 +58,7 @@ import com.vividsolutions.jts.geomgraph.index.SegmentIntersector;
* would first need to be noded and merged (if not explicitly, at least
* implicitly).
*
- * @version 1.5
+ * @version 1.6
*/
public class RelateComputer
{
diff --git a/src/com/vividsolutions/jts/operation/relate/RelateNode.java b/src/com/vividsolutions/jts/operation/relate/RelateNode.java
index 9fd4cda..ac1109d 100644
--- a/src/com/vividsolutions/jts/operation/relate/RelateNode.java
+++ b/src/com/vividsolutions/jts/operation/relate/RelateNode.java
@@ -39,7 +39,7 @@ package com.vividsolutions.jts.operation.relate;
* A RelateNode is a Node that maintains a list of EdgeStubs
* for the edges that are incident on it.
*
- * @version 1.5
+ * @version 1.6
*/
import java.io.PrintStream;
@@ -51,7 +51,7 @@ import com.vividsolutions.jts.geomgraph.*;
/**
* Represents a node in the topological graph used to compute spatial relationships.
*
- * @version 1.5
+ * @version 1.6
*/
public class RelateNode
extends Node
diff --git a/src/com/vividsolutions/jts/operation/relate/RelateNodeFactory.java b/src/com/vividsolutions/jts/operation/relate/RelateNodeFactory.java
index ed1d2ca..520a28d 100644
--- a/src/com/vividsolutions/jts/operation/relate/RelateNodeFactory.java
+++ b/src/com/vividsolutions/jts/operation/relate/RelateNodeFactory.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geomgraph.*;
/**
* Used by the {@link NodeMap} in a {@link RelateNodeGraph} to create {@link RelateNode}s.
*
- * @version 1.5
+ * @version 1.6
*/
public class RelateNodeFactory
extends NodeFactory
diff --git a/src/com/vividsolutions/jts/operation/relate/RelateNodeGraph.java b/src/com/vividsolutions/jts/operation/relate/RelateNodeGraph.java
index 98f8775..30f9cb3 100644
--- a/src/com/vividsolutions/jts/operation/relate/RelateNodeGraph.java
+++ b/src/com/vividsolutions/jts/operation/relate/RelateNodeGraph.java
@@ -34,7 +34,7 @@
package com.vividsolutions.jts.operation.relate;
/**
- * @version 1.5
+ * @version 1.6
*/
import java.util.*;
import com.vividsolutions.jts.geom.*;
@@ -59,7 +59,7 @@ import com.vividsolutions.jts.geomgraph.*;
* have their topology determined implicitly, without creating a Node object
* to represent them.
*
- * @version 1.5
+ * @version 1.6
*/
public class RelateNodeGraph {
diff --git a/src/com/vividsolutions/jts/operation/relate/RelateOp.java b/src/com/vividsolutions/jts/operation/relate/RelateOp.java
index 3fc7874..6ede8b0 100644
--- a/src/com/vividsolutions/jts/operation/relate/RelateOp.java
+++ b/src/com/vividsolutions/jts/operation/relate/RelateOp.java
@@ -36,7 +36,7 @@
package com.vividsolutions.jts.operation.relate;
/**
- * @version 1.5
+ * @version 1.6
*/
import com.vividsolutions.jts.geomgraph.*;
@@ -47,7 +47,7 @@ import java.util.*;
/**
* Implements the relate() operation on {@link Geometry}s.
*
- * @version 1.5
+ * @version 1.6
*/
public class RelateOp
extends GeometryGraphOperation
diff --git a/src/com/vividsolutions/jts/operation/valid/ConnectedInteriorTester.java b/src/com/vividsolutions/jts/operation/valid/ConnectedInteriorTester.java
index 81ddffc..d3fe9b1 100644
--- a/src/com/vividsolutions/jts/operation/valid/ConnectedInteriorTester.java
+++ b/src/com/vividsolutions/jts/operation/valid/ConnectedInteriorTester.java
@@ -53,7 +53,7 @@ import com.vividsolutions.jts.util.*;
* If an inconsistency if found the location of the problem
* is recorded.
*
- * @version 1.5
+ * @version 1.6
*/
public class ConnectedInteriorTester {
diff --git a/src/com/vividsolutions/jts/operation/valid/ConsistentAreaTester.java b/src/com/vividsolutions/jts/operation/valid/ConsistentAreaTester.java
index 47443bf..a2fda05 100644
--- a/src/com/vividsolutions/jts/operation/valid/ConsistentAreaTester.java
+++ b/src/com/vividsolutions/jts/operation/valid/ConsistentAreaTester.java
@@ -55,7 +55,7 @@ import com.vividsolutions.jts.util.*;
* If an inconsistency if found the location of the problem
* is recorded.
*
- * @version 1.5
+ * @version 1.6
*/
public class ConsistentAreaTester {
diff --git a/src/com/vividsolutions/jts/operation/valid/IsValidOp.java b/src/com/vividsolutions/jts/operation/valid/IsValidOp.java
index 83005f3..d17e4bc 100644
--- a/src/com/vividsolutions/jts/operation/valid/IsValidOp.java
+++ b/src/com/vividsolutions/jts/operation/valid/IsValidOp.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.*;
* Implements the algorithsm required to compute the <code>isValid()</code> method
* for {@link Geometry}s.
*
- * @version 1.5
+ * @version 1.6
*/
public class IsValidOp
{
diff --git a/src/com/vividsolutions/jts/operation/valid/QuadtreeNestedRingTester.java b/src/com/vividsolutions/jts/operation/valid/QuadtreeNestedRingTester.java
index 0eacc4c..0e2ff23 100644
--- a/src/com/vividsolutions/jts/operation/valid/QuadtreeNestedRingTester.java
+++ b/src/com/vividsolutions/jts/operation/valid/QuadtreeNestedRingTester.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.*;
* nested inside another ring in the set, using a {@link Quadtree}
* index to speed up the comparisons.
*
- * @version 1.5
+ * @version 1.6
*/
public class QuadtreeNestedRingTester
{
diff --git a/src/com/vividsolutions/jts/operation/valid/RepeatedPointTester.java b/src/com/vividsolutions/jts/operation/valid/RepeatedPointTester.java
index c5f1fbb..f3eec34 100644
--- a/src/com/vividsolutions/jts/operation/valid/RepeatedPointTester.java
+++ b/src/com/vividsolutions/jts/operation/valid/RepeatedPointTester.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.geom.*;
* (consecutive identical coordinates) as defined in the
* JTS spec.
*
- * @version 1.5
+ * @version 1.6
*/
public class RepeatedPointTester {
diff --git a/src/com/vividsolutions/jts/operation/valid/SimpleNestedRingTester.java b/src/com/vividsolutions/jts/operation/valid/SimpleNestedRingTester.java
index f697539..821fc95 100644
--- a/src/com/vividsolutions/jts/operation/valid/SimpleNestedRingTester.java
+++ b/src/com/vividsolutions/jts/operation/valid/SimpleNestedRingTester.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.util.*;
* nested inside another ring in the set, using a simple O(n^2)
* comparison.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimpleNestedRingTester
{
diff --git a/src/com/vividsolutions/jts/operation/valid/SweeplineNestedRingTester.java b/src/com/vividsolutions/jts/operation/valid/SweeplineNestedRingTester.java
index e729bad..c924e89 100644
--- a/src/com/vividsolutions/jts/operation/valid/SweeplineNestedRingTester.java
+++ b/src/com/vividsolutions/jts/operation/valid/SweeplineNestedRingTester.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.util.*;
* nested inside another ring in the set, using a {@link SweepLineIndex}
* index to speed up the comparisons.
*
- * @version 1.5
+ * @version 1.6
*/
public class SweeplineNestedRingTester
{
diff --git a/src/com/vividsolutions/jts/operation/valid/TopologyValidationError.java b/src/com/vividsolutions/jts/operation/valid/TopologyValidationError.java
index f066425..a25565c 100644
--- a/src/com/vividsolutions/jts/operation/valid/TopologyValidationError.java
+++ b/src/com/vividsolutions/jts/operation/valid/TopologyValidationError.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* Contains information about the nature and location of a {@link Geometry}
* validation error
*
- * @version 1.5
+ * @version 1.6
*/
public class TopologyValidationError {
diff --git a/src/com/vividsolutions/jts/planargraph/DirectedEdge.java b/src/com/vividsolutions/jts/planargraph/DirectedEdge.java
index f48d9ac..f36a5c2 100644
--- a/src/com/vividsolutions/jts/planargraph/DirectedEdge.java
+++ b/src/com/vividsolutions/jts/planargraph/DirectedEdge.java
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.geomgraph.Quadrant;
* a client using a <code>PlanarGraph</code> will subclass <code>DirectedEdge</code>
* to add its own application-specific data and methods.
*
- * @version 1.5
+ * @version 1.6
*/
public class DirectedEdge
extends GraphComponent
diff --git a/src/com/vividsolutions/jts/planargraph/DirectedEdgeStar.java b/src/com/vividsolutions/jts/planargraph/DirectedEdgeStar.java
index 62e5a26..924a0e1 100644
--- a/src/com/vividsolutions/jts/planargraph/DirectedEdgeStar.java
+++ b/src/com/vividsolutions/jts/planargraph/DirectedEdgeStar.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* A sorted collection of {@link DirectedEdge}s which leave a {@link Node}
* in a {@link PlanarGraph}.
*
- * @version 1.5
+ * @version 1.6
*/
public class DirectedEdgeStar
{
diff --git a/src/com/vividsolutions/jts/planargraph/Edge.java b/src/com/vividsolutions/jts/planargraph/Edge.java
index 3cbe2d7..eac8adc 100644
--- a/src/com/vividsolutions/jts/planargraph/Edge.java
+++ b/src/com/vividsolutions/jts/planargraph/Edge.java
@@ -41,7 +41,7 @@ package com.vividsolutions.jts.planargraph;
* Usually a client using a <code>PlanarGraph</code> will subclass <code>Edge</code>
* to add its own application-specific data and methods.
*
- * @version 1.5
+ * @version 1.6
*/
public class Edge
extends GraphComponent
diff --git a/src/com/vividsolutions/jts/planargraph/GraphComponent.java b/src/com/vividsolutions/jts/planargraph/GraphComponent.java
index 3c5124b..28a9209 100644
--- a/src/com/vividsolutions/jts/planargraph/GraphComponent.java
+++ b/src/com/vividsolutions/jts/planargraph/GraphComponent.java
@@ -46,7 +46,7 @@ package com.vividsolutions.jts.planargraph;
* graph might use this to indicate that a node has already been traversed.
* The visited flag may be set and cleared many times during the lifetime of a graph.
*
- * @version 1.5
+ * @version 1.6
*/
public class GraphComponent {
diff --git a/src/com/vividsolutions/jts/planargraph/Node.java b/src/com/vividsolutions/jts/planargraph/Node.java
index d16f3a6..2f5a5f0 100644
--- a/src/com/vividsolutions/jts/planargraph/Node.java
+++ b/src/com/vividsolutions/jts/planargraph/Node.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* subclass <code>Node</code> to add their own application-specific
* data and methods.
*
- * @version 1.5
+ * @version 1.6
*/
public class Node
extends GraphComponent
diff --git a/src/com/vividsolutions/jts/planargraph/NodeMap.java b/src/com/vividsolutions/jts/planargraph/NodeMap.java
index 4e08c2a..ed904e4 100644
--- a/src/com/vividsolutions/jts/planargraph/NodeMap.java
+++ b/src/com/vividsolutions/jts/planargraph/NodeMap.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geom.Coordinate;
/**
* A map of {@link Node}s, indexed by the coordinate of the node.
*
- * @version 1.5
+ * @version 1.6
*/
public class NodeMap
diff --git a/src/com/vividsolutions/jts/planargraph/PlanarGraph.java b/src/com/vividsolutions/jts/planargraph/PlanarGraph.java
index 7b072df..cb7a8f8 100644
--- a/src/com/vividsolutions/jts/planargraph/PlanarGraph.java
+++ b/src/com/vividsolutions/jts/planargraph/PlanarGraph.java
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* subclasses for one or more graph components, which hold application-specific
* data and graph algorithms.
*
- * @version 1.5
+ * @version 1.6
*/
public abstract class PlanarGraph
{
diff --git a/src/com/vividsolutions/jts/precision/CommonBits.java b/src/com/vividsolutions/jts/precision/CommonBits.java
index 7771238..d429799 100644
--- a/src/com/vividsolutions/jts/precision/CommonBits.java
+++ b/src/com/vividsolutions/jts/precision/CommonBits.java
@@ -40,7 +40,7 @@ package com.vividsolutions.jts.precision;
* is represented by the common bits.
* If there are no common bits, the number computed is 0.0.
*
- * @version 1.5
+ * @version 1.6
*/
public class CommonBits {
diff --git a/src/com/vividsolutions/jts/precision/CommonBitsOp.java b/src/com/vividsolutions/jts/precision/CommonBitsOp.java
index 610bdf4..e5562ad 100644
--- a/src/com/vividsolutions/jts/precision/CommonBitsOp.java
+++ b/src/com/vividsolutions/jts/precision/CommonBitsOp.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geom.*;
* that the returned Geometry is invalid.
* Client classes should check the validity of the returned result themselves.
*
- * @version 1.5
+ * @version 1.6
*/
public class CommonBitsOp {
diff --git a/src/com/vividsolutions/jts/precision/CommonBitsRemover.java b/src/com/vividsolutions/jts/precision/CommonBitsRemover.java
index 11674a2..3268c69 100644
--- a/src/com/vividsolutions/jts/precision/CommonBitsRemover.java
+++ b/src/com/vividsolutions/jts/precision/CommonBitsRemover.java
@@ -38,7 +38,7 @@ import com.vividsolutions.jts.geom.*;
/**
* Allow computing and removing common mantissa bits from one or more Geometries.
*
- * @version 1.5
+ * @version 1.6
*/
public class CommonBitsRemover
{
diff --git a/src/com/vividsolutions/jts/precision/EnhancedPrecisionOp.java b/src/com/vividsolutions/jts/precision/EnhancedPrecisionOp.java
index c72ce36..d7abe5e 100644
--- a/src/com/vividsolutions/jts/precision/EnhancedPrecisionOp.java
+++ b/src/com/vividsolutions/jts/precision/EnhancedPrecisionOp.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.operation.overlay.OverlayOp;
* Provides versions of Geometry spatial functions which use
* enhanced precision techniques to reduce the likelihood of robustness problems.
*
- * @version 1.5
+ * @version 1.6
*/
public class EnhancedPrecisionOp
{
diff --git a/src/com/vividsolutions/jts/precision/SimpleGeometryPrecisionReducer.java b/src/com/vividsolutions/jts/precision/SimpleGeometryPrecisionReducer.java
index 795706d..aa6f416 100644
--- a/src/com/vividsolutions/jts/precision/SimpleGeometryPrecisionReducer.java
+++ b/src/com/vividsolutions/jts/precision/SimpleGeometryPrecisionReducer.java
@@ -48,7 +48,7 @@ import com.vividsolutions.jts.geom.util.*;
* is simplifying the input to the buffer algorithm.
* The buffer algorithm does not depend on the validity of the input geometry.
*
- * @version 1.5
+ * @version 1.6
*/
public class SimpleGeometryPrecisionReducer
{
@@ -90,7 +90,7 @@ public class SimpleGeometryPrecisionReducer
{
GeometryEditor geomEdit;
if (changePrecisionModel) {
- GeometryFactory newFactory = new GeometryFactory(newPrecisionModel, geom.getSRID());
+ GeometryFactory newFactory = new GeometryFactory(newPrecisionModel, geom.getFactory().getSRID());
geomEdit = new GeometryEditor(newFactory);
}
else
diff --git a/src/com/vividsolutions/jts/simplify/DouglasPeuckerLineSimplifier.java b/src/com/vividsolutions/jts/simplify/DouglasPeuckerLineSimplifier.java
index 535f460..d845fcd 100644
--- a/src/com/vividsolutions/jts/simplify/DouglasPeuckerLineSimplifier.java
+++ b/src/com/vividsolutions/jts/simplify/DouglasPeuckerLineSimplifier.java
@@ -4,10 +4,10 @@ import java.util.*;
import com.vividsolutions.jts.geom.*;
/**
- * Simplifies a line (sequence of points) using
+ * Simplifies a linestring (sequence of points) using
* the standard Douglas-Peucker algorithm.
*
- * @version 1.5
+ * @version 1.6
*/
public class DouglasPeuckerLineSimplifier
{
@@ -26,6 +26,13 @@ public class DouglasPeuckerLineSimplifier
{
this.pts = pts;
}
+ /**
+ * Sets the distance tolerance for the simplification.
+ * All vertices in the simplified linestring will be within this
+ * distance of the original linestring.
+ *
+ * @param distanceTolerance the approximation tolerance to use
+ */
public void setDistanceTolerance(double distanceTolerance) {
this.distanceTolerance = distanceTolerance;
}
diff --git a/src/com/vividsolutions/jts/simplify/DouglasPeuckerSimplifier.java b/src/com/vividsolutions/jts/simplify/DouglasPeuckerSimplifier.java
index 0fc35f5..5672247 100644
--- a/src/com/vividsolutions/jts/simplify/DouglasPeuckerSimplifier.java
+++ b/src/com/vividsolutions/jts/simplify/DouglasPeuckerSimplifier.java
@@ -13,14 +13,13 @@ import com.vividsolutions.jts.geom.util.*;
* e.g. polygons can be split, collapse to lines or disappear
* holes can be created or disappear,
* and lines can cross.
- * To simplify geometry while preserving topology use {@link TopologySafeSimplifier}.
+ * To simplify geometry while preserving topology use {@link TopologyPreservingSimplifier}.
* (However, using D-P is significantly faster).
*
- * @version 1.5
+ * @version 1.6
*/
public class DouglasPeuckerSimplifier
{
- // TODO: prevent polygons and lines from disappearing if they are too flat or small
public static Geometry simplify(Geometry geom, double distanceTolerance)
{
@@ -37,6 +36,13 @@ public class DouglasPeuckerSimplifier
this.inputGeom = inputGeom;
}
+ /**
+ * Sets the distance tolerance for the simplification.
+ * All vertices in the simplified geometry will be within this
+ * distance of the original geometry.
+ *
+ * @param distanceTolerance the approximation tolerance to use
+ */
public void setDistanceTolerance(double distanceTolerance) {
this.distanceTolerance = distanceTolerance;
}
diff --git a/src/com/vividsolutions/jts/simplify/TaggedLineString.java b/src/com/vividsolutions/jts/simplify/TaggedLineString.java
index 91abf85..e4caf59 100644
--- a/src/com/vividsolutions/jts/simplify/TaggedLineString.java
+++ b/src/com/vividsolutions/jts/simplify/TaggedLineString.java
@@ -4,7 +4,7 @@ import java.util.*;
import com.vividsolutions.jts.geom.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class TaggedLineString {
diff --git a/src/com/vividsolutions/jts/simplify/TaggedLineStringSimplifier.java b/src/com/vividsolutions/jts/simplify/TaggedLineStringSimplifier.java
index 523bbbf..b1dbde5 100644
--- a/src/com/vividsolutions/jts/simplify/TaggedLineStringSimplifier.java
+++ b/src/com/vividsolutions/jts/simplify/TaggedLineStringSimplifier.java
@@ -8,9 +8,9 @@ import com.vividsolutions.jts.util.Debug;
/**
* Simplifies a TaggedLineString, preserving topology
* (in the sense that no new intersections are introduced).
- * Uses the recursive D-P algorithm.
+ * Uses the recursive Douglas-Peucker algorithm.
*
- * @version 1.5
+ * @version 1.6
*/
public class TaggedLineStringSimplifier
{
@@ -29,6 +29,13 @@ public class TaggedLineStringSimplifier
this.outputIndex = outputIndex;
}
+ /**
+ * Sets the distance tolerance for the simplification.
+ * All vertices in the simplified geometry will be within this
+ * distance of the original geometry.
+ *
+ * @param distanceTolerance the approximation tolerance to use
+ */
public void setDistanceTolerance(double distanceTolerance) {
this.distanceTolerance = distanceTolerance;
}
@@ -51,23 +58,33 @@ public class TaggedLineStringSimplifier
return;
}
+ boolean isValidToSimplify = true;
+
+ /**
+ * Following logic ensures that there is enough points in the output line.
+ * If there is already more points than the minimum, there's nothing to check.
+ * Otherwise, if in the worst case there wouldn't be enough points,
+ * don't flatten this segment (which avoids the worst case scenario)
+ */
+ if (line.getResultSize() < line.getMinimumSize()) {
+ int worstCaseSize = depth + 1;
+ if (worstCaseSize < line.getMinimumSize())
+ isValidToSimplify = false;
+ }
+
double[] distance = new double[1];
int furthestPtIndex = findFurthestPoint(linePts, i, j, distance);
- boolean isValidToFlatten = true;
-
- // must have enough points in the output line
- if (line.getResultSize() < line.getMinimumSize() && depth < 2) isValidToFlatten = false;
// flattening must be less than distanceTolerance
- if (distance[0] > distanceTolerance) isValidToFlatten = false;
+ if (distance[0] > distanceTolerance) isValidToSimplify = false;
// test if flattened section would cause intersection
LineSegment candidateSeg = new LineSegment();
candidateSeg.p0 = linePts[i];
candidateSeg.p1 = linePts[j];
sectionIndex[0] = i;
sectionIndex[1] = j;
- if (hasBadIntersection(line, sectionIndex, candidateSeg)) isValidToFlatten = false;
+ if (hasBadIntersection(line, sectionIndex, candidateSeg)) isValidToSimplify = false;
- if (isValidToFlatten) {
+ if (isValidToSimplify) {
LineSegment newSeg = flatten(i, j);
line.addToResult(newSeg);
return;
diff --git a/src/com/vividsolutions/jts/simplify/TaggedLinesSimplifier.java b/src/com/vividsolutions/jts/simplify/TaggedLinesSimplifier.java
index 92f8c78..7fbc9d0 100644
--- a/src/com/vividsolutions/jts/simplify/TaggedLinesSimplifier.java
+++ b/src/com/vividsolutions/jts/simplify/TaggedLinesSimplifier.java
@@ -20,10 +20,10 @@ public class TaggedLinesSimplifier
/**
* Sets the distance tolerance for the simplification.
- * Points closer than this tolerance to a simplified segment may
- * be removed.
+ * All vertices in the simplified geometry will be within this
+ * distance of the original geometry.
*
- * @param distanceTolerance the distance tolerance
+ * @param distanceTolerance the approximation tolerance to use
*/
public void setDistanceTolerance(double distanceTolerance) {
this.distanceTolerance = distanceTolerance;
diff --git a/src/com/vividsolutions/jts/simplify/TopologyPreservingSimplifier.java b/src/com/vividsolutions/jts/simplify/TopologyPreservingSimplifier.java
index 2be4104..3a01f35 100644
--- a/src/com/vividsolutions/jts/simplify/TopologyPreservingSimplifier.java
+++ b/src/com/vividsolutions/jts/simplify/TopologyPreservingSimplifier.java
@@ -42,6 +42,13 @@ public class TopologyPreservingSimplifier
//inputIndex = new LineSegmentIndex(new STRtree());
}
+ /**
+ * Sets the distance tolerance for the simplification.
+ * All vertices in the simplified geometry will be within this
+ * distance of the original geometry.
+ *
+ * @param distanceTolerance the approximation tolerance to use
+ */
public void setDistanceTolerance(double distanceTolerance) {
lineSimplifier.setDistanceTolerance(distanceTolerance);
}
diff --git a/src/com/vividsolutions/jts/util/Assert.java b/src/com/vividsolutions/jts/util/Assert.java
index 57426ad..88034ac 100644
--- a/src/com/vividsolutions/jts/util/Assert.java
+++ b/src/com/vividsolutions/jts/util/Assert.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.util.AssertionFailedException;
/**
* A utility for making programming assertions.
*
- *@version 1.5
+ *@version 1.6
*/
public class Assert {
diff --git a/src/com/vividsolutions/jts/util/AssertionFailedException.java b/src/com/vividsolutions/jts/util/AssertionFailedException.java
index 8f48d84..a4f5e96 100644
--- a/src/com/vividsolutions/jts/util/AssertionFailedException.java
+++ b/src/com/vividsolutions/jts/util/AssertionFailedException.java
@@ -38,7 +38,7 @@ package com.vividsolutions.jts.util;
* Thrown when the application is in an inconsistent state. Indicates a problem
* with the code.
*
- *@version 1.5
+ *@version 1.6
*/
public class AssertionFailedException extends RuntimeException {
diff --git a/src/com/vividsolutions/jts/util/CoordinateArrayFilter.java b/src/com/vividsolutions/jts/util/CoordinateArrayFilter.java
index fcee0e3..c0e4a50 100644
--- a/src/com/vividsolutions/jts/util/CoordinateArrayFilter.java
+++ b/src/com/vividsolutions/jts/util/CoordinateArrayFilter.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.*;
* A {@link CoordinateFilter} that creates an array containing every
* coordinate in a {@link Geometry}.
*
- *@version 1.5
+ *@version 1.6
*/
public class CoordinateArrayFilter implements CoordinateFilter {
Coordinate[] pts = null;
diff --git a/src/com/vividsolutions/jts/util/CoordinateCountFilter.java b/src/com/vividsolutions/jts/util/CoordinateCountFilter.java
index 1057cab..30e9c59 100644
--- a/src/com/vividsolutions/jts/util/CoordinateCountFilter.java
+++ b/src/com/vividsolutions/jts/util/CoordinateCountFilter.java
@@ -40,7 +40,7 @@ import com.vividsolutions.jts.geom.*;
* A {@link CoordinateFilter} that counts the total number of coordinates
* in a <code>Geometry</code>.
*
- *@version 1.5
+ *@version 1.6
*/
public class CoordinateCountFilter implements CoordinateFilter {
private int n = 0;
diff --git a/src/com/vividsolutions/jts/util/Debug.java b/src/com/vividsolutions/jts/util/Debug.java
index c8e6780..657cdc9 100644
--- a/src/com/vividsolutions/jts/util/Debug.java
+++ b/src/com/vividsolutions/jts/util/Debug.java
@@ -35,7 +35,7 @@
package com.vividsolutions.jts.util;
/**
- *@version 1.5
+ *@version 1.6
*/
import java.io.*;
import java.util.*;
@@ -44,11 +44,31 @@ import java.lang.reflect.*;
/**
* Provides routines to simplify and localize debugging output.
*
- * @version 1.5
+ * @version 1.6
*/
public class Debug {
- private static boolean debugOn = true;
+ private static String DEBUG_PROPERTY_NAME = "debug";
+ private static String DEBUG_PROPERTY_VALUE_ON = "on";
+ private static String DEBUG_PROPERTY_VALUE_TRUE = "true";
+
+ private static boolean debugOn = false;
+
+ static {
+ String debugValue = System.getProperty(DEBUG_PROPERTY_NAME);
+ if (debugValue != null) {
+ if (debugValue.equalsIgnoreCase(DEBUG_PROPERTY_VALUE_ON)
+ || debugValue.equalsIgnoreCase(DEBUG_PROPERTY_VALUE_TRUE) )
+ debugOn = true;
+ }
+ }
+
+
+ public static void main(String[] args)
+ {
+ Debug.println("Debugging is ON");
+ }
+
private static Debug debug = new Debug();
private static final String DEBUG_LINE_TAG = "D! ";
@@ -58,6 +78,8 @@ public class Debug {
private Object watchObj = null;
private Object[] args = new Object[1];
+ public static boolean isDebugging() { return debugOn; }
+
public static void print(String str) {
if (!debugOn) {
return;
diff --git a/src/com/vividsolutions/jts/util/GeometricShapeFactory.java b/src/com/vividsolutions/jts/util/GeometricShapeFactory.java
index db99c1e..6c98a59 100644
--- a/src/com/vividsolutions/jts/util/GeometricShapeFactory.java
+++ b/src/com/vividsolutions/jts/util/GeometricShapeFactory.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.geom.*;
* Allows various ways of specifying the location and extent of the shapes,
* as well as number of line segments used to form them.
*
- * @version 1.5
+ * @version 1.6
*/
public class GeometricShapeFactory
{
diff --git a/src/com/vividsolutions/jts/util/Stopwatch.java b/src/com/vividsolutions/jts/util/Stopwatch.java
index 05428a4..43edefc 100644
--- a/src/com/vividsolutions/jts/util/Stopwatch.java
+++ b/src/com/vividsolutions/jts/util/Stopwatch.java
@@ -37,7 +37,7 @@ package com.vividsolutions.jts.util;
* Implements a timer function which can compute
* elapsed time as well as split times.
*
- * @version 1.5
+ * @version 1.6
*/
public class Stopwatch {
diff --git a/src/com/vividsolutions/jts/util/UniqueCoordinateArrayFilter.java b/src/com/vividsolutions/jts/util/UniqueCoordinateArrayFilter.java
index 92ae723..526c8a2 100644
--- a/src/com/vividsolutions/jts/util/UniqueCoordinateArrayFilter.java
+++ b/src/com/vividsolutions/jts/util/UniqueCoordinateArrayFilter.java
@@ -44,7 +44,7 @@ import com.vividsolutions.jts.geom.CoordinateFilter;
* A {@link CoordinateFilter} that builds a set of <code>Coordinate</code>s.
* The set of coordinates contains no duplicate points.
*
- *@version 1.5
+ *@version 1.6
*/
public class UniqueCoordinateArrayFilter implements CoordinateFilter {
TreeSet treeSet = new TreeSet();
diff --git a/src/com/vividsolutions/jtsexample/geom/BasicExample.java b/src/com/vividsolutions/jtsexample/geom/BasicExample.java
index cad705b..403511e 100644
--- a/src/com/vividsolutions/jtsexample/geom/BasicExample.java
+++ b/src/com/vividsolutions/jtsexample/geom/BasicExample.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.io.WKTReader;
/**
* Shows basic ways of creating and operating on geometries
*
- * @version 1.5
+ * @version 1.6
*/
public class BasicExample
{
diff --git a/src/com/vividsolutions/jtsexample/geom/ConstructionExample.java b/src/com/vividsolutions/jtsexample/geom/ConstructionExample.java
index 4739f5e..931a396 100644
--- a/src/com/vividsolutions/jtsexample/geom/ConstructionExample.java
+++ b/src/com/vividsolutions/jtsexample/geom/ConstructionExample.java
@@ -16,7 +16,7 @@ import com.vividsolutions.jts.geom.*;
* <li>Insulates your code from changes in the signature of JTS constructors
* </ol>
*
- * @version 1.5
+ * @version 1.6
*/
public class ConstructionExample
{
diff --git a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinate.java b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinate.java
index 8f5a180..bf7d747 100644
--- a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinate.java
+++ b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinate.java
@@ -37,7 +37,7 @@ import com.vividsolutions.jts.geom.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class ExtendedCoordinate
extends Coordinate
@@ -63,7 +63,10 @@ public class ExtendedCoordinate
public ExtendedCoordinate(Coordinate coord)
{
super(coord);
- m = 0.0;
+ if (coord instanceof ExtendedCoordinate)
+ m = ((ExtendedCoordinate) coord).m;
+ else
+ m = Double.NaN;
}
public ExtendedCoordinate(ExtendedCoordinate coord)
diff --git a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateExample.java b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateExample.java
index 3f28b21..5772b55 100644
--- a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateExample.java
+++ b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateExample.java
@@ -37,7 +37,7 @@ import com.vividsolutions.jts.geom.*;
/**
- * @version 1.5
+ * @version 1.6
*/
public class ExtendedCoordinateExample
{
diff --git a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequence.java b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequence.java
index e3cb6b1..ca2ae11 100644
--- a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequence.java
+++ b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequence.java
@@ -33,19 +33,19 @@
*/
package com.vividsolutions.jtsexample.geom;
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.CoordinateSequence;
+import com.vividsolutions.jts.geom.*;
/**
* Demonstrates how to implement a CoordinateSequence for a new kind of
* coordinate (an {@link ExtendedCoordinate} in this example). In this
* implementation, Coordinates returned by #toArray and #get are live -- parties
- * that change them are actually changing the ExtendedCoordinateSequence's
+ * that change them are actually changing the ExtendedCoordinateSequence's
* underlying data.
*
- * @version 1.5
+ * @version 1.6
*/
-public class ExtendedCoordinateSequence implements CoordinateSequence
+public class ExtendedCoordinateSequence
+ implements CoordinateSequence
{
public static ExtendedCoordinate[] copy(Coordinate[] coordinates)
{
@@ -56,8 +56,17 @@ public class ExtendedCoordinateSequence implements CoordinateSequence
return copy;
}
+ public static ExtendedCoordinate[] copy(CoordinateSequence coordSeq)
+ {
+ ExtendedCoordinate[] copy = new ExtendedCoordinate[coordSeq.size()];
+ for (int i = 0; i < coordSeq.size(); i++) {
+ copy[i] = new ExtendedCoordinate(coordSeq.getCoordinate(i));
+ }
+ return copy;
+ }
+
private ExtendedCoordinate[] coordinates;
-
+
/**
* Copy constructor -- simply aliases the input array, for better performance.
*/
@@ -66,7 +75,7 @@ public class ExtendedCoordinateSequence implements CoordinateSequence
}
/**
- * Constructor that makes a copy of an existing array of Coordinates.
+ * Constructor that makes a copy of an array of Coordinates.
* Always makes a copy of the input array, since the actual class
* of the Coordinates in the input array may be different from ExtendedCoordinate.
*/
@@ -74,10 +83,87 @@ public class ExtendedCoordinateSequence implements CoordinateSequence
coordinates = copy(copyCoords);
}
+ /**
+ * Constructor that makes a copy of a CoordinateSequence.
+ */
+ public ExtendedCoordinateSequence(CoordinateSequence coordSeq) {
+ coordinates = copy(coordSeq);
+ }
+
+ /**
+ * Constructs a sequence of a given size, populated
+ * with new {@link ExtendedCoordinate}s.
+ *
+ * @param size the size of the sequence to create
+ */
+ public ExtendedCoordinateSequence(int size) {
+ coordinates = new ExtendedCoordinate[size];
+ for (int i = 0; i < size; i++) {
+ coordinates[i] = new ExtendedCoordinate();
+ }
+ }
+
+
public Coordinate getCoordinate(int i) {
return coordinates[i];
}
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public Coordinate getCoordinateCopy(int index) {
+ return new Coordinate(coordinates[index]);
+ }
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public void getCoordinate(int index, Coordinate coord) {
+ coord.x = coordinates[index].x;
+ coord.y = coordinates[index].y;
+ }
+
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
+ */
+ public double getX(int index) {
+ return coordinates[index].x;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int)
+ */
+ public double getY(int index) {
+ return coordinates[index].y;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int)
+ */
+ public double getOrdinate(int index, int ordinateIndex)
+ {
+ switch (ordinateIndex) {
+ case CoordinateSequence.X: return coordinates[index].x;
+ case CoordinateSequence.Y: return coordinates[index].y;
+ case CoordinateSequence.Z: return coordinates[index].z;
+ case 4: return coordinates[index].getM();
+ }
+ return Double.NaN;
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequence#setOrdinate(int, int, double)
+ */
+ public void setOrdinate(int index, int ordinateIndex, double value)
+ {
+ switch (ordinateIndex) {
+ case CoordinateSequence.X: coordinates[index].x = value;
+ case CoordinateSequence.Y: coordinates[index].y = value;
+ case CoordinateSequence.Z: coordinates[index].z = value;
+ case 4: coordinates[index].setM(value);
+ }
+ }
+
public Object clone() {
ExtendedCoordinate[] cloneCoordinates = new ExtendedCoordinate[size()];
for (int i = 0; i < coordinates.length; i++) {
@@ -95,6 +181,14 @@ public class ExtendedCoordinateSequence implements CoordinateSequence
return coordinates;
}
+ public Envelope expandEnvelope(Envelope env)
+ {
+ for (int i = 0; i < coordinates.length; i++ ) {
+ env.expandToInclude(coordinates[i]);
+ }
+ return env;
+ }
+
public String toString()
{
StringBuffer strBuf = new StringBuffer();
diff --git a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequenceFactory.java b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequenceFactory.java
index 7277038..e7e9012 100644
--- a/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequenceFactory.java
+++ b/src/com/vividsolutions/jtsexample/geom/ExtendedCoordinateSequenceFactory.java
@@ -39,7 +39,7 @@ import com.vividsolutions.jts.geom.*;
* Creates ExtendedCoordinateSequenceFactory internally represented
* as an array of {@link ExtendedCoordinate}s.
*
- * @version 1.5
+ * @version 1.6
*/
public class ExtendedCoordinateSequenceFactory
implements CoordinateSequenceFactory
@@ -54,8 +54,8 @@ public class ExtendedCoordinateSequenceFactory
*/
public static ExtendedCoordinateSequenceFactory instance() {
return instance;
- }
-
+ }
+
/**
* Returns an ExtendedCoordinateSequence based on the given array -- the array is used
* directly if it is an instance of ExtendedCoordinate[]; otherwise it is
@@ -67,4 +67,17 @@ public class ExtendedCoordinateSequenceFactory
: new ExtendedCoordinateSequence(coordinates);
}
+ public CoordinateSequence create(CoordinateSequence coordSeq) {
+ return coordSeq instanceof ExtendedCoordinateSequence
+ ? new ExtendedCoordinateSequence((ExtendedCoordinateSequence) coordSeq)
+ : new ExtendedCoordinateSequence(coordSeq);
+ }
+
+ /**
+ * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int, int)
+ */
+ public CoordinateSequence create(int size, int dimension) {
+ return new ExtendedCoordinateSequence(size);
+ }
+
}
diff --git a/src/com/vividsolutions/jtsexample/geom/PrecisionModelExample.java b/src/com/vividsolutions/jtsexample/geom/PrecisionModelExample.java
index db9d0bc..6418ec8 100644
--- a/src/com/vividsolutions/jtsexample/geom/PrecisionModelExample.java
+++ b/src/com/vividsolutions/jtsexample/geom/PrecisionModelExample.java
@@ -45,7 +45,7 @@ import com.vividsolutions.jts.io.*;
* The output shows the effects of rounding in the single-precision and fixed-precision
* models.
*
- * @version 1.5
+ * @version 1.6
*/
public class PrecisionModelExample
{
diff --git a/src/com/vividsolutions/jtsexample/geom/SimpleMethodsExample.java b/src/com/vividsolutions/jtsexample/geom/SimpleMethodsExample.java
index 9de18b2..bd5c71c 100644
--- a/src/com/vividsolutions/jtsexample/geom/SimpleMethodsExample.java
+++ b/src/com/vividsolutions/jtsexample/geom/SimpleMethodsExample.java
@@ -54,7 +54,7 @@ import com.vividsolutions.jts.io.*;
* ----------------------------------------------------------
* </pre>
*
- * @version 1.5
+ * @version 1.6
*/
public class SimpleMethodsExample
{
diff --git a/src/com/vividsolutions/jtsexample/geom/TwoArrayCoordinateSequenceExample.java b/src/com/vividsolutions/jtsexample/geom/TwoArrayCoordinateSequenceExample.java
deleted file mode 100644
index 2cd5248..0000000
--- a/src/com/vividsolutions/jtsexample/geom/TwoArrayCoordinateSequenceExample.java
+++ /dev/null
@@ -1,89 +0,0 @@
-
-/*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
- */
-package com.vividsolutions.jtsexample.geom;
-
-import com.vividsolutions.jts.geom.*;
-
-
-/**
- * @version 1.5
- */
-public class TwoArrayCoordinateSequenceExample
-{
-
- public static void main(String args[])
- {
- TwoArrayCoordinateSequenceFactory seqFact = TwoArrayCoordinateSequenceFactory.instance();
-
- Coordinate[] array1 = new Coordinate[] {
- new Coordinate(0, 0, 0),
- new Coordinate(10, 0, 0),
- new Coordinate(10, 10, 0),
- new Coordinate(0, 10, 0),
- new Coordinate(0, 0, 0),
- };
- CoordinateSequence seq1 = seqFact.create(array1);
-
- CoordinateSequence seq2 = seqFact.create(
- new Coordinate[] {
- new Coordinate(5, 5, 0),
- new Coordinate(15, 5, 0),
- new Coordinate(15, 15, 0),
- new Coordinate(5, 15, 0),
- new Coordinate(5, 5, 0),
- });
-
- GeometryFactory fact = new GeometryFactory(
- TwoArrayCoordinateSequenceFactory.instance());
-
- Geometry g1 = fact.createPolygon(fact.createLinearRing(seq1), null);
- Geometry g2 = fact.createPolygon(fact.createLinearRing(seq2), null);
-
- System.out.println("WKT for g1: " + g1);
- System.out.println("Internal rep for g1: " + ((Polygon) g1).getExteriorRing().getCoordinateSequence());
-
- System.out.println("WKT for g2: " + g2);
- System.out.println("Internal rep for g2: " + ((Polygon) g2).getExteriorRing().getCoordinateSequence());
-
- Geometry gInt = g1.intersection(g2);
-
- System.out.println("WKT for gInt: " + gInt);
- System.out.println("Internal rep for gInt: " + ((Polygon) gInt).getExteriorRing().getCoordinateSequence());
- }
-
- public TwoArrayCoordinateSequenceExample() {
- }
-
-
-}
diff --git a/src/com/vividsolutions/jtsexample/geom/TwoArrayCoordinateSequenceFactory.java b/src/com/vividsolutions/jtsexample/geom/TwoArrayCoordinateSequenceFactory.java
deleted file mode 100644
index 8cae371..0000000
--- a/src/com/vividsolutions/jtsexample/geom/TwoArrayCoordinateSequenceFactory.java
+++ /dev/null
@@ -1,118 +0,0 @@
-
-/*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
- */
-package com.vividsolutions.jtsexample.geom;
-
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.CoordinateSequence;
-import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
-
-/**
- * Creates CoordinateSequences internally represented as an array of x's and
- * an array of y's.
- *
- * @version 1.5
- */
-public class TwoArrayCoordinateSequenceFactory implements CoordinateSequenceFactory {
- private static TwoArrayCoordinateSequenceFactory instance = new TwoArrayCoordinateSequenceFactory();
- private TwoArrayCoordinateSequenceFactory() {
- }
-
- /**
- * Returns the singleton instance of TwoArrayCoordinateSequenceFactory
- */
- public static TwoArrayCoordinateSequenceFactory instance() {
- return instance;
- }
-
- public CoordinateSequence create(Coordinate[] coordinates) {
- return new TwoArrayCoordinateSequence(coordinates);
- }
-
- private static class TwoArrayCoordinateSequence implements CoordinateSequence {
- private double[] xs;
- private double[] ys;
-
- public TwoArrayCoordinateSequence(Coordinate[] coordinates) {
- xs = new double[coordinates.length];
- ys = new double[coordinates.length];
- for (int i = 0; i < coordinates.length; i++) {
- xs[i] = coordinates[i].x;
- ys[i] = coordinates[i].y;
- }
- }
-
- public Coordinate getCoordinate(int i) {
- return new Coordinate(xs[i], ys[i]);
- }
-
- public Object clone() {
- double[] xsClone = new double[xs.length];
- double[] ysClone = new double[ys.length];
- System.arraycopy(xs, 0, xsClone, 0, xs.length);
- System.arraycopy(ys, 0, ysClone, 0, ys.length);
- return new TwoArrayCoordinateSequence(xsClone, ysClone);
- }
-
- public int size() {
- return xs.length;
- }
-
- public Coordinate[] toCoordinateArray() {
- Coordinate[] array = new Coordinate[xs.length];
- for (int i = 0; i < array.length; i++) {
- array[i] = new Coordinate(xs[i], ys[i]);
- }
- return array;
- }
-
- private TwoArrayCoordinateSequence(double[] xs, double[] ys) {
- this.xs = xs;
- this.ys = ys;
- }
-
- public String toString()
- {
- StringBuffer strBuf = new StringBuffer();
- strBuf.append("TwoArrayCoordinateSequence [");
- for (int i = 0; i < size(); i++) {
- if (i > 0) strBuf.append(", ");
- strBuf.append(xs[i] + " " + ys[i]);
- }
- strBuf.append("]");
- return strBuf.toString();
- }
-
- }
-
-}
diff --git a/src/com/vividsolutions/jtsexample/operation/distance/ClosestPointExample.java b/src/com/vividsolutions/jtsexample/operation/distance/ClosestPointExample.java
index 8d13170..bd6047a 100644
--- a/src/com/vividsolutions/jtsexample/operation/distance/ClosestPointExample.java
+++ b/src/com/vividsolutions/jtsexample/operation/distance/ClosestPointExample.java
@@ -41,7 +41,7 @@ import com.vividsolutions.jts.operation.distance.DistanceOp;
* Example of computing distance and closest points between geometries
* using the DistanceOp class.
*
- * @version 1.5
+ * @version 1.6
*/
public class ClosestPointExample
{
diff --git a/src/com/vividsolutions/jtsexample/operation/linemerge/LineMergeExample.java b/src/com/vividsolutions/jtsexample/operation/linemerge/LineMergeExample.java
index 401acb2..0758a9b 100644
--- a/src/com/vividsolutions/jtsexample/operation/linemerge/LineMergeExample.java
+++ b/src/com/vividsolutions/jtsexample/operation/linemerge/LineMergeExample.java
@@ -45,7 +45,7 @@ import java.util.Collection;
* Example of using the LineMerger class to sew together a set of fully noded
* linestrings.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineMergeExample {
private WKTReader reader = new WKTReader();
diff --git a/src/com/vividsolutions/jtsexample/operation/polygonize/PolygonizeExample.java b/src/com/vividsolutions/jtsexample/operation/polygonize/PolygonizeExample.java
index 247b3fe..0ab431a 100644
--- a/src/com/vividsolutions/jtsexample/operation/polygonize/PolygonizeExample.java
+++ b/src/com/vividsolutions/jtsexample/operation/polygonize/PolygonizeExample.java
@@ -43,7 +43,7 @@ import com.vividsolutions.jts.operation.polygonize.Polygonizer;
/**
* Example of using Polygonizer class to polygonize a set of fully noded linestrings
*
- * @version 1.5
+ * @version 1.6
*/
public class PolygonizeExample
{
diff --git a/src/com/vividsolutions/jtsexample/precision/EnhancedPrecisionOpExample.java b/src/com/vividsolutions/jtsexample/precision/EnhancedPrecisionOpExample.java
index cfc93b4..37fd3e1 100644
--- a/src/com/vividsolutions/jtsexample/precision/EnhancedPrecisionOpExample.java
+++ b/src/com/vividsolutions/jtsexample/precision/EnhancedPrecisionOpExample.java
@@ -42,7 +42,7 @@ import com.vividsolutions.jts.precision.EnhancedPrecisionOp;
/**
* Example of using {@link EnhancedPrecisionOp} to avoid robustness problems
*
- * @version 1.5
+ * @version 1.6
*/
public class EnhancedPrecisionOpExample
{
diff --git a/src/com/vividsolutions/jtsexample/technique/LineStringSelfIntersections.java b/src/com/vividsolutions/jtsexample/technique/LineStringSelfIntersections.java
index d29f8a4..f24fa27 100644
--- a/src/com/vividsolutions/jtsexample/technique/LineStringSelfIntersections.java
+++ b/src/com/vividsolutions/jtsexample/technique/LineStringSelfIntersections.java
@@ -8,7 +8,7 @@ import java.util.*;
* Shows a technique for identifying the location of self-intersections
* in a non-simple LineString.
*
- * @version 1.5
+ * @version 1.6
*/
public class LineStringSelfIntersections {
diff --git a/src/com/vividsolutions/jtsexample/technique/UnionUsingBuffer.java b/src/com/vividsolutions/jtsexample/technique/UnionUsingBuffer.java
index c8e0869..7e26ca0 100644
--- a/src/com/vividsolutions/jtsexample/technique/UnionUsingBuffer.java
+++ b/src/com/vividsolutions/jtsexample/technique/UnionUsingBuffer.java
@@ -18,7 +18,7 @@ import java.util.*;
* <li>may not preserve input coordinate precision in some cases
* </ul>
*
- * @version 1.5
+ * @version 1.6
*/
public class UnionUsingBuffer {
diff --git a/test/robust/TestRobustOverlayFixed.xml b/test/robust/TestRobustOverlayFixed.xml
new file mode 100644
index 0000000..1bb9e42
--- /dev/null
+++ b/test/robust/TestRobustOverlayFixed.xml
@@ -0,0 +1,18 @@
+<run>
+ <precisionModel scale="1.0" offsetx="0.0" offsety="0.0"/>
+
+<case>
+ <desc>AA</desc>
+ <a>
+POLYGON ((545 317, 617 379, 581 321, 545 317))
+ </a>
+ <b>
+POLYGON ((484 290, 558 359, 543 309, 484 290))
+
+ </b>
+<test>
+ <op name="intersection"> GEOMETRYCOLLECTION EMPTY </op>
+</test>
+</case>
+
+</run>
diff --git a/test/robust/TestRobustOverlayFloat.xml b/test/robust/TestRobustOverlayFloat.xml
new file mode 100644
index 0000000..8024e14
--- /dev/null
+++ b/test/robust/TestRobustOverlayFloat.xml
@@ -0,0 +1,94 @@
+<run>
+ <precisionModel type="FLOATING" />
+<case>
+ <desc>AA - robustness failure</desc>
+ <a>
+POLYGON ((301949.68 2767249.16, 301936.52 2767241.28, 301938.87
+2767237.43, 301952.47 2767245.59, 301950.74 2767247.81, 301949.68
+2767249.16))
+ </a>
+ <b>
+POLYGON ((302041.321 2767264.675, 301938.823 2767237.507, 301941.21 2767233.59, 301943.821 2767229.304,
+302048.886 2767243.046, 302041.321 2767264.675))
+ </b>
+<test>
+ <op name="intersection"> GEOMETRYCOLLECTION EMPTY </op>
+</test>
+</case>
+
+<case>
+ <desc>AA - robustness failure</desc>
+ <a>
+POLYGON ((301936.52 2767241.28, 301933.22 2767239.3, 301934.9
+2767236.51, 301935.54 2767235.44, 301938.87 2767237.43, 301936.52
+2767241.28))
+ </a>
+ <b>
+POLYGON ((302041.321 2767264.675, 301938.823 2767237.507, 301941.21 2767233.59, 301943.821 2767229.304,
+302048.886 2767243.046, 302041.321 2767264.675))
+</b>
+<test>
+ <op name="intersection"> GEOMETRYCOLLECTION EMPTY </op>
+</test>
+</case>
+
+<case>
+ <desc>AA - robustness failure (fails with EnhancedPrecisionOp)</desc>
+ <a>
+POLYGON ((464664.782646596 5362148.87380619, 464664.713299 5362148.758128, 464686.806220838 5362136.92416521,
+464713.650216607 5362122.5453135, 464711.113332785 5362117.30158834, 464707.408813375 5362110.21553566,
+464703.323866879 5362103.23305736, 464698.945488413 5362096.31213576, 464694.461274991 5362089.42505804,
+464625.876674576 5361951.92914952, 464622.430583893 5361944.69388208, 464535.3572 5361970.739,
+464648.194399372 5362157.89548451, 464664.782646596 5362148.87380619)) </a>
+ <b>
+POLYGON ((464769.977147523 5362187.88829332, 464765.146147008 5362180.84587461, 464754.387021019 5362169.93629911,
+464747.786455245 5362160.11104076, 464734.810564627 5362148.45253107, 464725.386626381 5362135.71065214,
+464712.646269 5362123.083073, 464727.794520848 5362149.37983229, 464738.165719397 5362165.72994593,
+464746.257208116 5362179.45514151, 464752.378040379 5362191.80978275, 464769.977147523 5362187.88829332))
+</b>
+<test>
+ <op name="intersection"> GEOMETRYCOLLECTION EMPTY </op>
+</test>
+</case>
+
+<case>
+ <desc>AA - robustness failure (fails with EnhancedPrecisionOp)</desc>
+ <a>
+POLYGON ((698400.5682737827 2388494.3828697307, 698402.3209180075
+2388497.0819257903, 698415.3598714538 2388498.764371397,
+698413.5003455497 2388495.90071853, 698400.5682737827
+2388494.3828697307))
+ </a>
+ <b>
+POLYGON ((698231.847335025 2388474.57994264, 698440.416211779
+2388499.05985776, 698432.582638943 2388300.28294705, 698386.666515791
+2388303.40346027, 698328.29462841 2388312.88889197, 698231.847335025
+2388474.57994264))
+ </b>
+<test>
+ <op name="intersection"> GEOMETRYCOLLECTION EMPTY </op>
+</test>
+</case>
+
+
+<case>
+ <desc>AA - robustness failure (fails with EnhancedPrecisionOp)</desc>
+ <a>
+POLYGON ((698265.5760207245 2388415.007869463, 698266.5171698363
+2388416.456984281, 698272.2367250263 2388406.868318228,
+698271.2748419731 2388405.3872787533, 698265.5760207245
+2388415.007869463))
+ </a>
+ <b>
+POLYGON ((698230.86813842 2388473.60074604, 698104.551776442
+2388363.93072634, 698321.933422637 2388319.86687914, 698230.86813842
+2388473.60074604))
+ </b>
+<test>
+ <op name="intersection"> GEOMETRYCOLLECTION EMPTY </op>
+</test>
+</case>
+
+
+
+</run>
diff --git a/test/robust/TestRobustRelate.xml b/test/robust/TestRobustRelate.xml
new file mode 100644
index 0000000..45a5e23
--- /dev/null
+++ b/test/robust/TestRobustRelate.xml
@@ -0,0 +1,19 @@
+<run>
+ <precisionModel scale="1.0" offsetx="0.0" offsety="0.0"/>
+
+<case>
+ <desc>PP - Point is not on line. Non-robust algorithms fail by erroneously reporting intersects=true.</desc>
+ <a>
+ LINESTRING(-123456789 -40, 381039468754763 123456789)
+ </a>
+ <b>
+ POINT(0 0)
+ </b>
+<test>
+ <op name="intersects">
+ false
+ </op>
+</test>
+</case>
+
+</run>
diff --git a/test/validate/TestRelateLL.xml b/test/validate/TestRelateLL.xml
index b0433ac..6d10521 100644
--- a/test/validate/TestRelateLL.xml
+++ b/test/validate/TestRelateLL.xml
@@ -1,1948 +1,1948 @@
<run>
<precisionModel type="FLOATING"/>
-
-<case>
-<desc>L/L.1-3-1: touching at the start points of two lines [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}]</desc>
- <a>
- LINESTRING(40 40, 120 120)
- </a>
- <b>
- LINESTRING(40 40, 60 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-3-2: start point of one line touching end point of another line [dim(0){A.L.Bdy.SP = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(40 40, 120 120)
- </a>
- <b>
- LINESTRING(60 240, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-3-3: start point of a line touching the interior of another line at a non-vertex [dim(0){A.L.Bdy.SP = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(40 40, 180 180)
- </a>
- <b>
- LINESTRING(120 120, 20 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-3-4: touching at the end points of two lines [dim(0){A.L.Bdy.EP = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(40 40, 120 120)
- </a>
- <b>
- LINESTRING(60 240, 120 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-3-5: end point of a line touching the interior of another line at a non-vertex [dim(0){A.L.Bdy.EP = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(40 40, 180 180)
- </a>
- <b>
- LINESTRING(20 180, 140 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-4-1: two lines crossing at non-vertex [dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(40 40, 120 120)
- </a>
- <b>
- LINESTRING(40 120, 120 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-1-1: equal pointwise [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100)
- </a>
- <b>
- LINESTRING(40 40, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-1-2: equal lines but points in reverse sequence [dim(1){A.L.Int.SP-EP = B.L.Int.EP-SP}]</desc>
- <a>
- LINESTRING(40 40, 100 100)
- </a>
- <b>
- LINESTRING(100 100, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-2-1: dim(1){A.L.Int.SP-EP = B.L.Ext}</desc>
- <a>
- LINESTRING(40 40, 120 120)
- </a>
- <b>
- LINESTRING(40 120, 120 160)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-5-1: line A containing line B [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(20 20, 180 180)
- </a>
- <b>
- LINESTRING(20 20, 180 180)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-5-2: line B is part of line A [dim(1){A.L.Int.SP-NV) = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(20 20, 180 180)
- </a>
- <b>
- LINESTRING(20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101F00FF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-5-3: Line B is part of line A (in the middle portion) [dim(1){A.L.Int.NV-NV = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(20 20, 180 180)
- </a>
- <b>
- LINESTRING(50 50, 140 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-6-1: start portions of two lines overlapping [dim(1){A.L.Int.SP-NV = B.L.Int.SP-NV]</desc>
- <a>
- LINESTRING(180 180, 40 40)
- </a>
- <b>
- LINESTRING(120 120, 260 260)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-6-2: end portions of two lines overlapping [dim(1){A.L.Int.NV-EP = B.L.Int.NV-EP]</desc>
- <a>
- LINESTRING(40 40, 180 180)
- </a>
- <b>
- LINESTRING(260 260, 120 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.1-6-3: end portion of line A overlapping the start portion of line B [dim(1){A.L.Int.NV-EP = B.L.Int.SP-NV]</desc>
- <a>
- LINESTRING(40 40, 180 180)
- </a>
- <b>
- LINESTRING(120 120, 260 260)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-1: two LineStrings touching at start points [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(40 40, 20 100, 40 160, 20 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-2: start point of LineStrings A touching the end point of LineString B [dim(0){A.L.Bdy.SP = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(20 200, 40 160, 20 100, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-3: two LineStrings touching at end points [dim(0){A.L.Bdy.EP = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(80 240, 200 120, 100 100, 40 40)
- </a>
- <b>
- LINESTRING(20 200, 40 160, 20 100, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-4: both the start and end points of LineString A touching the interior of LineString B at two vertices [dim(0){A.L.Bdy.SP = B.L.Int.V}, dim(0){A.L.Bdy.EP = B.L.Int.V}]</desc>
- <a>
- LINESTRING(60 60, 60 230, 140 230, 250 160)
- </a>
- <b>
- LINESTRING(20 20, 60 60, 250 160, 310 230)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10FF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-5: both the start and end points of LineString A touching the interior of LineString B at two non-vertices [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Bdy.EP = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(60 60, 60 230, 140 230, 250 160)
- </a>
- <b>
- LINESTRING(20 20, 110 110, 200 110, 320 230)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10FF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-6: the start and end points of two LineStrings touching each other [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}, dim(0){A.L.Bdy.EP = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(60 110, 60 250, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F0F1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-7: the start and end points of two LineStrings touching each other [dim(0){A.L.Bdy.SP = B.L.Bdy.EP}, dim(0){A.L.Bdy.EP = B.L.Bdy.SP}]</desc>
- <a>
- LINESTRING(60 110, 60 250, 360 210)
- </a>
- <b>
- LINESTRING(360 210, 310 160, 110 160, 60 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F0F1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-8: start point of LineString B touching LineString A at a non-vertex [dim(0){A.L.Int.NV = B.L.Bdy.SP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(160 160, 240 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-9: end point of LineString B touching LineString A at a non-vertex [dim(0){A.L.Int.NV = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(240 240, 160 160)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-10: both the start and end points of LineString B touching the interior of LineString A at two non-vertices [dim(0){A.L.Int.NV = B.L.Bdy.SP}, dim(0){A.L.Int.NV = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(60 60, 60 230, 140 230, 250 160)
- </a>
- <b>
- LINESTRING(60 150, 110 100, 170 100, 110 230)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-11: the start point of LineString B touching the interior of LineString A at a non-vertex and the end point of LineString A touching the interior of LineString B at a vertex [dim(0){A.L.Int.NV = B.L.Bdy.SP}, dim(0){A.L.Bdy.EP = B.L.Int.V}]</desc>
- <a>
- LINESTRING(60 60, 60 230, 140 230, 250 160)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-12: start point of LineString B touching LineString A at a vertex [dim(0){A.L.Int.V = B.L.Bdy.SP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(200 120, 200 190, 150 240, 200 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-13: end point of LineString B touching LineString A at a vertex [dim(0){A.L.Int.V = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(200 240, 150 240, 200 200, 200 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-3-14: both the start and end points of LineString B touching the interior of LineString A at two vertices [dim(0){A.L.Int.V = B.L.Bdy.SP}, dim(0){A.L.Int.V = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(60 60, 60 230, 140 230, 250 160)
- </a>
- <b>
- LINESTRING(60 230, 80 140, 120 140, 140 230)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-1: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(60 110, 200 110, 250 160, 300 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-2: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.SP}, dim(0){A.L.Int.V = B.L.Int.V}, dim(0){A.L.Bdy.EP = B.L.Int.EP}]</desc>
- <a>
- LINESTRING(60 110, 200 110, 250 160, 300 210, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1F0F1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-3: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(60 110, 220 110, 250 160, 280 110)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-4: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Int.SP}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Bdy.EP = B.L.Int.EP}]</desc>
- <a>
- LINESTRING(60 110, 150 110, 200 160, 250 110, 360 110, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1F0F1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-5: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(130 160, 160 110, 220 110, 250 160, 250 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-6: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(130 160, 160 110, 190 110, 230 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-7: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Bdy.SP = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(130 160, 160 110, 200 110, 230 160, 260 210, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F100F102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-8: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(130 160, 160 110, 200 110, 230 160, 260 210, 360 210, 380 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-9: two LineStrings crossing at three points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Int.NV = B.L.Bdy.EP}]</desc>
- <a>
- LINESTRING(130 160, 160 110, 200 110, 230 160, 260 210, 380 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-10: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.V}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(110 160, 160 110, 200 110, 250 160, 250 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-11: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Int.V}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(110 160, 180 110, 250 160, 320 110)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-12: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(140 160, 180 80, 220 160, 250 80)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-13: two LineStrings crossing at a vertex for one of the LineStrings [dim(0){A.L.Int.V = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 130 190)
- </a>
- <b>
- LINESTRING(20 130, 70 130, 160 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-14: two LineStrings crossing at non-vertices for both of the LineStrings [dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 130 190)
- </a>
- <b>
- LINESTRING(40 160, 40 100, 110 40, 170 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-15: two LineStrings crossing on one side [dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(130 110, 180 160, 230 110, 280 160, 330 110)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-16: two LineStrings crossing at vertices for both LineString [dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 130 190)
- </a>
- <b>
- LINESTRING(30 140, 80 140, 100 100, 200 30)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-17: two LineStrings crossing on one side [dim(0){A.L.Int.V = B.L.Int.V}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(110 110, 110 160, 180 110, 250 160, 250 110)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-18: multiple crossings [dim(0){A.L.Int.V = B.L.Int.V}, dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
- <a>
- LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
- </a>
- <b>
- LINESTRING(20 60, 60 60, 60 140, 80 80, 100 20, 140 140, 180 20, 200 80, 220 20,
- 240 80, 300 80, 270 110, 200 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-4-19: spiky LineStrings with multiple crossing [dim(0){A.L.Int.V = B.L.Int.V}]</desc>
- <a>
- LINESTRING(20 20, 230 20, 20 30, 170 30, 20 40, 230 40, 20 50, 230 60, 60 60,
- 230 70, 20 70, 180 80, 60 80, 230 90, 20 90, 230 100, 30 100, 210 110, 20 110,
- 80 120, 20 130, 170 130, 90 120, 230 130, 170 140, 230 140, 80 150, 160 140, 20 140,
- 70 150, 20 150, 230 160, 80 160, 230 170, 20 160, 180 170, 20 170, 230 180, 20 180,
- 40 190, 230 190, 20 200, 230 200)
- </a>
- <b>
- LINESTRING(30 210, 30 60, 40 210, 40 30, 50 190, 50 20, 60 160, 60 50, 70 220,
- 70 50, 80 20, 80 210, 90 50, 90 150, 100 30, 100 210, 110 20, 110 190, 120 50,
- 120 180, 130 210, 120 20, 140 210, 130 50, 150 210, 130 20, 160 210, 140 30, 170 210,
- 150 20, 180 210, 160 20, 190 210, 180 80, 170 50, 170 20, 180 70, 180 20, 190 190,
- 190 30, 200 210, 200 30, 210 210, 210 20, 220 150, 220 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="001FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-1-1: two equal LineStrings with equal pointwise [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-1-2: two equal LineStrings with points in reverse sequence [dim(1){A.L.Int.SP-EP = B.L.Int.EP-SP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(80 240, 200 120, 100 100, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-1-3: two equal LineStrings with different number of points [dim(1){A.L.Int.SP-EP = B.L.Int.EP-SP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(80 240, 120 200, 200 120, 100 100, 80 80, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-2-1: disjoint [dim(1){A.L.Int.SP-EP = B.L.Ext}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(260 210, 240 130, 280 120, 260 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-2-2: wrapping around but still disjoint [dim(1){A.L.Int.SP-EP = B.L.Ext}]</desc>
- <a>
- LINESTRING(100 20, 20 20, 20 160, 210 160, 210 20, 110 20, 50 120, 120 150, 200 150)
- </a>
- <b>
- LINESTRING(140 130, 100 110, 120 60, 170 60)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-5-1: LineString A containing LineString B, same pointwise [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-5-2: LineString A containing LineString B, LineString A with less points [dim(1){A.L.Int.SP-V = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(60 110, 110 160, 310 160, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-5-3: LineString A containing LineString B [dim(1){A.L.Int.SP-V = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </a>
- <b>
- LINESTRING(60 110, 110 160, 250 160)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101F00FF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-5-4: LineString A containing LineString B [dim(1){A.L.Int.NV-NV = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </a>
- <b>
- LINESTRING(110 160, 310 160, 340 190)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-5-5: LineString A containing LineString B [dim(1){A.L.Int.V-NV = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </a>
- <b>
- LINESTRING(140 160, 250 160, 310 160, 340 190)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-5-6: LineString A containing LineString B [dim(1){A.L.Int.V-V = B.L.Int.SP-EP}]</desc>
- <a>
- LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
- </a>
- <b>
- LINESTRING(110 160, 250 160, 310 160)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-1: start portions of two LineStrings overlapping [dim(1){A.L.Int.SP-V = B.L.Int.SP-V}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(200 120, 100 100, 40 40, 140 80, 200 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-2: start portion of LineString A overlapping end portion of LineString B, intersecting at the middle of LineString A [dim(1){A.L.Int.SP-V = B.L.Int.V-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(280 240, 240 140, 200 120, 100 100, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-3: start portion of LineString A overlapping end portion of LineString B, intersecting at the middle of LineString A [dim(1){A.L.Int.SP-V = B.L.Int.NV-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(80 190, 140 140, 40 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-4: end portions of two LineStrings overlapping [dim(1){A.L.Int.NV-EP = B.L.Int.V-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(240 200, 200 260, 80 240, 140 180)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-5: end portion of LineString A overlapping start portion of LineString B [dim(1){A.L.Int.NV-EP = B.L.Int.SP-V}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(140 180, 80 240, 200 260, 240 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-6: end portion of LineString A overlapping end portion of LineString B, intersecting at the middle of LineString A [dim(1){A.L.Int.V-EP = B.L.Int.V-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(280 240, 240 140, 200 120, 80 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-7: middle portions of two LineStrings overlapping [dim(1){A.L.Int.V-NV = B.L.Int.NV-V}]</desc>
- <a>
- LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
- </a>
- <b>
- LINESTRING(20 80, 120 80, 200 80, 260 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-8: middle portion of LineString A overlapping start portion of LineString B [dim(1){A.L.Int.V-V = B.L.Int.SP-V}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(100 100, 200 120, 240 140, 280 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-9: middle portion of LineString A overlapping end portion of LineString B [dim(1){A.L.Int.V-V = B.L.Int.V-EP}]</desc>
- <a>
- LINESTRING(40 40, 100 100, 200 120, 80 240)
- </a>
- <b>
- LINESTRING(280 240, 240 140, 200 120, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-10: middle portions of two LineStrings overlapping [dim(1){A.L.Int.V-V = B.L.Int.V-V}]</desc>
- <a>
- LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
- </a>
- <b>
- LINESTRING(80 20, 80 80, 240 80, 300 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/L.2-6-11: middle portions of two LineStrings overlapping, multiple intersects [dim(1){A.L.Int.V-V = B.L.Int.V-NV}, dim(1){A.L.Int.V-V = B.L.Int.V-NV}, dim(1){A.L.Int.V-V = B.L.Int.V-NV}]</desc>
- <a>
- LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
- </a>
- <b>
- LINESTRING(20 80, 80 80, 120 80, 140 140, 160 80, 200 80, 220 20, 240 80, 270 110,
- 300 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-3-1: a LineString touching a LinearRing [dim(0){A.L.Bdy.SP = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(100 100, 20 180, 180 180)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-4-1: a LineString crossing a LinearRing [dim(0){A.L.Int.NV = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(20 100, 180 100, 100 180)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-4-2: a LineString crossing a LinearRing [dim(0){A.L.Int.NV = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(100 40, 100 160, 180 160)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-4-3: a LineString crossing a LinearRing [dim(0){A.L.Int.V = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(20 100, 100 100, 180 100, 100 180)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-5-1: a LineString within a LinearRing [dim(1){A.L.Int.SP-EP = B.LR.Int.SP-NV}]</desc>
- <a>
- LINESTRING(100 100, 160 40)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FF0FF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-5-2: a LineString within a LinearRing [dim(1){A.L.Int.SP-EP = B.LR.Int.SP-NV}]</desc>
- <a>
- LINESTRING(100 100, 180 20)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FF0FF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-5-3: a LineString within a LinearRing [dim(1){A.L.Int.SP-V-EP = B.LR.Int.NV-CP-NV}]</desc>
- <a>
- LINESTRING(60 60, 100 100, 140 60)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FF0FF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-6-1: a LineString crossing a LinearRing [dim(1){A.L.Int.SP-NV = B.LR.Int.SP-V}]</desc>
- <a>
- LINESTRING(100 100, 190 10, 190 100)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F10F01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-6-2: a LineString crossing a LinearRing [dim(1){A.L.Int.SP-V = B.LR.Int.SP-NV}]</desc>
- <a>
- LINESTRING(100 100, 160 40, 160 100)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F10F01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/LR-6-3: a LineString crossing a LinearRing [dim(1){A.L.Int.NV-V = B.LR.Int.SP-NV}]</desc>
- <a>
- LINESTRING(60 140, 160 40, 160 140)
- </a>
- <b>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's end point with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Bdy.EPb}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(80 80, 20 80, 140 80, 80 20, 80 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's end point with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Bdy.EPo}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(80 80, 20 80, 140 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's end point with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(80 80, 140 80, 80 20, 80 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's closing point with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.CPb}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(80 80, 20 80, 140 80, 80 20, 80 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's closing point with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.CPo}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(80 80, 20 80, 140 80, 80 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's closing point with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Int.CPx}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(80 80, 20 80, 20 140, 140 20, 80 20, 80 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex [dim(0){A.L.Int.NV = B.nsL.Int.NV}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(20 140, 140 20, 100 20, 100 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.NVb}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 20 80, 120 80, 80 20, 80 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.NVo}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 20 80, 140 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Int.NVx}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 20 80, 80 140, 80 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex [dim(0){A.L.Int.NV = B.nsL.Int.V}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 80 80, 20 80, 50 140, 50 60)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.Vb}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 20 80, 120 80, 80 20, 80 80, 80 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.Vo}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 20 80, 80 80, 140 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Int.Vx}]</desc>
- <a>
- LINESTRING(20 20, 140 140)
- </a>
- <b>
- LINESTRING(140 80, 20 80, 80 140, 80 80, 80 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.1-3-1: start point of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Bdy.SP = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(130 150, 220 150, 220 240)
- </a>
- <b>
- LINESTRING(130 240, 130 150, 220 20, 50 20, 130 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.1-3-2: the interior of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Int.V = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(30 150, 130 150, 250 150)
- </a>
- <b>
- LINESTRING(130 240, 130 150, 220 20, 50 20, 130 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.1-3-3: the interior of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Int.NV = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(30 150, 250 150)
- </a>
- <b>
- LINESTRING(130 240, 130 150, 220 20, 50 20, 130 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.1-3-4: the interior of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Int.V = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(30 150, 130 150, 250 150)
- </a>
- <b>
- LINESTRING(130 240, 130 20, 30 20, 130 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.1-4: a Line crossing a non-simple LineString at non-vertices [dim(0){A.L.Int.NV = B.nsL.Int.NV}]</desc>
- <a>
- LINESTRING(30 150, 250 150)
- </a>
- <b>
- LINESTRING(120 240, 120 20, 20 20, 120 170)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL.5/L-3-1: switching the geometries for case L/nsL.5-3-1 [dim(0){A.nsL.Bdy.EPx = B.L.Bdy.SP}]</desc>
- <a>
- LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
- </a>
- <b>
- LINESTRING(110 110, 200 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.5-3-2: the start point of a line touching the self-intersecting and self-crossing point of a non-simple LineString [dim(0){A.L.Bdy.SP = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(110 110, 200 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.5-3-3: the interior of a line touching the self-intersecting and self-crossing point of a non-simple LineString [dim(0){A.L.Int.NV = B.nsL.Bdy.EPx}]</desc>
- <a>
- LINESTRING(20 110, 200 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL.5/L-3-4 touches dim(0){A.nsL.Bdy.EPx = B.L.Int.NV}</desc>
- <a>
- LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
- </a>
- <b>
- LINESTRING(20 110, 200 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.10-6-1: the middle portion of a line overlapping from the self-intersecting to the self-crossing a non-simple LineString [dim(1){A.L.Int.V-V = B.nsL.Int.EPx-NVx}]</desc>
- <a>
- LINESTRING(90 200, 90 130, 110 110, 150 200)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/nsL.10-6-2: the middle portion of a line overlapping from the self-intersecting to the self-crossing a non-simple LineString [dim(1){A.L.Int.V-V = B.nsL.Int.NVx-EPx}]</desc>
- <a>
- LINESTRING(200 110, 110 110, 90 130, 90 200)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>L/mL-3-1: a line's end point touching a non-vertex with crossing line segments of a MultiLineString [dim(0){A.L.Bdy.SP = B.mL.Int.NVx]</desc>
- <a>
- LINESTRING(80 80, 150 80, 210 80)
- </a>
- <b>
- MULTILINESTRING(
- (20 20, 140 140),
- (20 140, 140 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-1-1: two equal LinearRings, pointwise [dim(1){A.LR.Int.SP-EP = B.LR.Int.SP-EP}, dim(0){A.LR.Int.CP = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(40 80, 160 200, 260 20, 40 80)
- </a>
- <b>
- LINESTRING(40 80, 160 200, 260 20, 40 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-1-2: two equal LinearRings with points in reverse sequence [dim(1){A.LR.Int.SP-EP = B.LR.Int.EP-SP}, dim(0){A.LR.Int.CP = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(40 80, 160 200, 260 20, 40 80)
- </a>
- <b>
- LINESTRING(40 80, 260 20, 160 200, 40 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-1-3: two equal LinearRings with points in different sequence [dim(1){A.LR.Int.SP-EP = B.LR.Int.SP-EP}, dim(0){A.LR.Int.CP = B.LR.Int.V}, dim(0){A.LR.Int.V = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(40 80, 160 200, 260 20, 40 80)
- </a>
- <b>
- LINESTRING(260 20, 40 80, 160 200, 260 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-1-4: two equal LinearRings with different number of points [dim(1){A.LR.Int.SP-EP = B.LR.Int.SP-EP}, dim(0){A.LR.Int.CP = B.LR.Int.V}, dim(0){A.LR.Int.NV = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(40 80, 160 200, 260 20, 40 80)
- </a>
- <b>
- LINESTRING(100 140, 160 200, 260 20, 40 80, 100 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-4-1: two LinearRings crossing at closing points [dim(0){A.LR.Int.CP = B.LR.Int.CP}]</desc>
- <a>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </a>
- <b>
- LINESTRING(100 100, 180 180, 20 180, 100 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-4-2: two LinearRings crossing at two points [dim(0){A.LR.Int.CP = B.LR.Int.CP}, dim(0){A.LR.Int.V = B.LR.Int.V},]</desc>
- <a>
- LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
- </a>
- <b>
- LINESTRING(40 150, 150 40, 170 20, 170 190, 40 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-4-3: two LinearRings crossing at the closing and a non-vertex [dim(0){A.LR.Int.CP = B.LR.Int.NV}]</desc>
- <a>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </a>
- <b>
- LINESTRING(180 100, 20 100, 100 180, 180 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-4-4: two LinearRings crossing at the closing and a vertex [dim(0){A.LR.Int.CP = B.LR.Int.V}]</desc>
- <a>
- LINESTRING(100 100, 180 20, 20 20, 100 100)
- </a>
- <b>
- LINESTRING(180 180, 100 100, 20 180, 180 180)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-4-5: two LinearRings crossing at a vertex and a non-vertex [dim(0){A.LR.Int.V = B.LR.Int.NV}]</desc>
- <a>
- LINESTRING(20 180, 100 100, 20 20, 20 180)
- </a>
- <b>
- LINESTRING(100 20, 100 180, 180 100, 100 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-4-6: two LinearRings crossing at two points [dim(0){A.LR.Int.V = B.LR.Int.NV}, dim(0){A.LR.Int.V = B.LR.Int.NV},]</desc>
- <a>
- LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
- </a>
- <b>
- LINESTRING(170 20, 20 170, 170 170, 170 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-6-1: two LinearRings overlapping [dim(1){A.LR.Int.CP-V = B.LR.Int.CP-V}]</desc>
- <a>
- LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
- </a>
- <b>
- LINESTRING(40 150, 150 150, 90 210, 40 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-6-2: two LinearRings overlapping [dim(1){A.LR.Int.CP-V = B.LR.Int.NV-NV}]</desc>
- <a>
- LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
- </a>
- <b>
- LINESTRING(20 150, 170 150, 90 230, 20 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/LR-6-3: two LinearRings overlapping [dim(1){A.LR.Int.(V-V-V-EP) = B.LR.Int.(NV-V-V-SP)}]</desc>
- <a>
- LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
- </a>
- <b>
- LINESTRING(40 150, 150 150, 150 40, 20 40, 20 150, 40 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/nsL-3-1: a LinearRing touching a non-simple LineString [dim(0){A.nsL.Int.CP = B.nsL.Bdy.SPb}]</desc>
- <a>
- LINESTRING(110 110, 200 20, 20 20, 110 110)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 110, 20 200, 20 110, 200 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/nsL-3-1: a LinearRing touching a non-simple LineString [dim(0){A.nsL.Int.CP = B.nsL.Bdy.SPo}]</desc>
- <a>
- LINESTRING(110 110, 200 20, 20 20, 110 110)
- </a>
- <b>
- LINESTRING(110 110, 20 110, 200 110, 50 110, 110 170)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/nsL-3-1: a LinearRing touching a non-simple LineString [dim(0){A.nsL.Int.CP = B.nsL.Bdy.SPx}]</desc>
- <a>
- LINESTRING(110 110, 200 20, 20 20, 110 110)
- </a>
- <b>
- LINESTRING(110 110, 20 200, 110 200, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F01FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/nsL-6-1: a LinearRing and a non-simple LineString overlapping [dim(1){A.nsL.Int.SP-V = B.nsL.Int.NVx-SP}]</desc>
- <a>
- LINESTRING(110 110, 200 20, 20 20, 110 110)
- </a>
- <b>
- LINESTRING(200 20, 20 200, 200 200, 110 110, 110 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>LR/nsL-6-2: a LinearRing and a non-simple LineString overlapping [dim(1){A.nsL.Int.SP-V = B.nsL.Int.NVx-SP}, dim(1){A.nsL.Int.V-EP = B.nsL.Int.EP-NVx}]</desc>
- <a>
- LINESTRING(110 110, 200 20, 20 20, 110 110)
- </a>
- <b>
- LINESTRING(200 20, 20 200, 200 200, 20 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="101FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL/nsL-4-1: non-simple LineStrings crossing at closing points [dim(0){A.nsL.Int.CP = B.nsL.Int.CP}]</desc>
- <a>
- LINESTRING(110 110, 20 110, 110 20, 20 20, 110 110)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 200 110, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL/nsL-4-2: non-simple LineStrings crossing at two points without vertices [dim(0){A.nsL.Int.NV = B.nsL.Int.NV}]</desc>
- <a>
- LINESTRING(20 120, 120 120, 20 20, 120 20, 20 120)
- </a>
- <b>
- LINESTRING(170 100, 70 100, 170 170, 70 170, 170 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL/nsL-4-3: non-simple LineStrings crossing at a point [dim(0){A.nsL.Int.NV = B.nsL.Int.V}]</desc>
- <a>
- LINESTRING(20 110, 110 110, 20 20, 110 20, 20 110)
- </a>
- <b>
- LINESTRING(110 160, 70 110, 60 160, 20 130, 110 160)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL/nsL-4-4: non-simple LineStrings crossing at self-crossing points [dim(0){A.nsL.Int.NVx = B.nsL.Int.NVx}]</desc>
- <a>
- LINESTRING(20 200, 200 200, 20 20, 200 20, 20 200)
- </a>
- <b>
- LINESTRING(20 110, 200 110, 200 160, 20 60, 20 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL/nsL-4-5: non-simple LineStrings crossing at vertices [dim(0){A.nsL.Int.V = B.nsL.Int.V}]</desc>
- <a>
- LINESTRING(20 110, 110 110, 20 20, 110 20, 20 110)
- </a>
- <b>
- LINESTRING(200 200, 110 110, 200 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>nsL/nsL-4-6: non-simple LineStrings crossing at two points with vertices [dim(0){A.nsL.Int.V = B.nsL.Int.V}]</desc>
- <a>
- LINESTRING(20 120, 120 120, 20 20, 120 20, 20 120)
- </a>
- <b>
- LINESTRING(220 120, 120 20, 220 20, 120 120, 220 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-1: MultiLineString [dim(1){A.mL.Int.SP-EP = B.mL.Int.SP-EP}]</desc>
- <a>
- MULTILINESTRING(
- (70 20, 20 90, 70 170),
- (70 170, 120 90, 70 20))
- </a>
- <b>
- MULTILINESTRING(
- (70 20, 20 90, 70 170),
- (70 170, 120 90, 70 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-1-1: non-simple MultiLineString [dim(1){A.mL.Int.SP-EP = B.mL.Int.SP-EP}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-1-2: equal non-simple MultiLineString with different sequence of lines and points [dim(1){A.mL.Int.SP-EP = B.mL.Int.EP-SP}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 140, 90 60, 90 20),
- (170 20, 130 20, 20 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-1: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPb}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (170 60, 90 20, 20 60),
- (130 100, 130 60, 90 20, 50 90))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-2: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPo}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (130 140, 130 60, 90 20, 20 90, 90 20, 130 60, 170 60))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-3: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPx}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (170 60, 90 20, 20 60))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-4: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPx}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (170 60, 90 20, 20 60),
- (130 100, 90 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-5: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPx}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (170 60, 90 20, 20 60),
- (120 100, 170 100, 90 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-6: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Int.SPb}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (170 60, 90 20, 20 60),
- (120 100, 170 100, 90 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-7: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Int.SPo}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (130 140, 130 60, 90 20, 20 90, 90 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-3-8: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Int.SPx}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 20, 170 20),
- (90 20, 90 80, 90 140))
- </a>
- <b>
- MULTILINESTRING(
- (90 20, 170 100, 170 140),
- (170 60, 90 20, 20 60, 20 140, 90 20))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-4-1: non-simple MultiLineStrings crossing [dim(0){A.mL.Int.Vx = B.mL.Int.Vb}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 90, 20 160),
- (90 160, 90 20))
- </a>
- <b>
- MULTILINESTRING(
- (160 160, 90 90, 160 20),
- (160 120, 120 120, 90 90, 160 60))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-4-2: non-simple MultiLineStrings crossing [dim(0){A.mL.Int.Vx = B.mL.Int.Vo}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 90, 20 160),
- (90 160, 90 20))
- </a>
- <b>
- MULTILINESTRING(
- (160 160, 90 90, 160 20),
- (160 120, 120 120, 90 90, 120 60, 160 60))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mL/mL-4-3: non-simple MultiLineStrings crossing [dim(0){A.mL.Int.Vx = B.mL.Int.Vx}]</desc>
- <a>
- MULTILINESTRING(
- (20 20, 90 90, 20 160),
- (90 160, 90 20))
- </a>
- <b>
- MULTILINESTRING(
- (160 160, 90 90, 160 20),
- (160 120, 90 90, 160 60))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
- </test>
-</case>
-
+
+<case>
+<desc>L/L.1-3-1: touching at the start points of two lines [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}]</desc>
+ <a>
+ LINESTRING(40 40, 120 120)
+ </a>
+ <b>
+ LINESTRING(40 40, 60 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-3-2: start point of one line touching end point of another line [dim(0){A.L.Bdy.SP = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(40 40, 120 120)
+ </a>
+ <b>
+ LINESTRING(60 240, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-3-3: start point of a line touching the interior of another line at a non-vertex [dim(0){A.L.Bdy.SP = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(40 40, 180 180)
+ </a>
+ <b>
+ LINESTRING(120 120, 20 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-3-4: touching at the end points of two lines [dim(0){A.L.Bdy.EP = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(40 40, 120 120)
+ </a>
+ <b>
+ LINESTRING(60 240, 120 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-3-5: end point of a line touching the interior of another line at a non-vertex [dim(0){A.L.Bdy.EP = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(40 40, 180 180)
+ </a>
+ <b>
+ LINESTRING(20 180, 140 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-4-1: two lines crossing at non-vertex [dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(40 40, 120 120)
+ </a>
+ <b>
+ LINESTRING(40 120, 120 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-1-1: equal pointwise [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100)
+ </a>
+ <b>
+ LINESTRING(40 40, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-1-2: equal lines but points in reverse sequence [dim(1){A.L.Int.SP-EP = B.L.Int.EP-SP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100)
+ </a>
+ <b>
+ LINESTRING(100 100, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-2-1: dim(1){A.L.Int.SP-EP = B.L.Ext}</desc>
+ <a>
+ LINESTRING(40 40, 120 120)
+ </a>
+ <b>
+ LINESTRING(40 120, 120 160)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-5-1: line A containing line B [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(20 20, 180 180)
+ </a>
+ <b>
+ LINESTRING(20 20, 180 180)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-5-2: line B is part of line A [dim(1){A.L.Int.SP-NV) = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(20 20, 180 180)
+ </a>
+ <b>
+ LINESTRING(20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101F00FF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-5-3: Line B is part of line A (in the middle portion) [dim(1){A.L.Int.NV-NV = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(20 20, 180 180)
+ </a>
+ <b>
+ LINESTRING(50 50, 140 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-6-1: start portions of two lines overlapping [dim(1){A.L.Int.SP-NV = B.L.Int.SP-NV]</desc>
+ <a>
+ LINESTRING(180 180, 40 40)
+ </a>
+ <b>
+ LINESTRING(120 120, 260 260)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-6-2: end portions of two lines overlapping [dim(1){A.L.Int.NV-EP = B.L.Int.NV-EP]</desc>
+ <a>
+ LINESTRING(40 40, 180 180)
+ </a>
+ <b>
+ LINESTRING(260 260, 120 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.1-6-3: end portion of line A overlapping the start portion of line B [dim(1){A.L.Int.NV-EP = B.L.Int.SP-NV]</desc>
+ <a>
+ LINESTRING(40 40, 180 180)
+ </a>
+ <b>
+ LINESTRING(120 120, 260 260)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-1: two LineStrings touching at start points [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(40 40, 20 100, 40 160, 20 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-2: start point of LineStrings A touching the end point of LineString B [dim(0){A.L.Bdy.SP = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(20 200, 40 160, 20 100, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-3: two LineStrings touching at end points [dim(0){A.L.Bdy.EP = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(80 240, 200 120, 100 100, 40 40)
+ </a>
+ <b>
+ LINESTRING(20 200, 40 160, 20 100, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-4: both the start and end points of LineString A touching the interior of LineString B at two vertices [dim(0){A.L.Bdy.SP = B.L.Int.V}, dim(0){A.L.Bdy.EP = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(60 60, 60 230, 140 230, 250 160)
+ </a>
+ <b>
+ LINESTRING(20 20, 60 60, 250 160, 310 230)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10FF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-5: both the start and end points of LineString A touching the interior of LineString B at two non-vertices [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Bdy.EP = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(60 60, 60 230, 140 230, 250 160)
+ </a>
+ <b>
+ LINESTRING(20 20, 110 110, 200 110, 320 230)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10FF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-6: the start and end points of two LineStrings touching each other [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}, dim(0){A.L.Bdy.EP = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(60 110, 60 250, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F0F1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-7: the start and end points of two LineStrings touching each other [dim(0){A.L.Bdy.SP = B.L.Bdy.EP}, dim(0){A.L.Bdy.EP = B.L.Bdy.SP}]</desc>
+ <a>
+ LINESTRING(60 110, 60 250, 360 210)
+ </a>
+ <b>
+ LINESTRING(360 210, 310 160, 110 160, 60 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F0F1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-8: start point of LineString B touching LineString A at a non-vertex [dim(0){A.L.Int.NV = B.L.Bdy.SP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(160 160, 240 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-9: end point of LineString B touching LineString A at a non-vertex [dim(0){A.L.Int.NV = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(240 240, 160 160)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-10: both the start and end points of LineString B touching the interior of LineString A at two non-vertices [dim(0){A.L.Int.NV = B.L.Bdy.SP}, dim(0){A.L.Int.NV = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(60 60, 60 230, 140 230, 250 160)
+ </a>
+ <b>
+ LINESTRING(60 150, 110 100, 170 100, 110 230)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-11: the start point of LineString B touching the interior of LineString A at a non-vertex and the end point of LineString A touching the interior of LineString B at a vertex [dim(0){A.L.Int.NV = B.L.Bdy.SP}, dim(0){A.L.Bdy.EP = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(60 60, 60 230, 140 230, 250 160)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-12: start point of LineString B touching LineString A at a vertex [dim(0){A.L.Int.V = B.L.Bdy.SP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(200 120, 200 190, 150 240, 200 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-13: end point of LineString B touching LineString A at a vertex [dim(0){A.L.Int.V = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(200 240, 150 240, 200 200, 200 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-3-14: both the start and end points of LineString B touching the interior of LineString A at two vertices [dim(0){A.L.Int.V = B.L.Bdy.SP}, dim(0){A.L.Int.V = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(60 60, 60 230, 140 230, 250 160)
+ </a>
+ <b>
+ LINESTRING(60 230, 80 140, 120 140, 140 230)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-1: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(60 110, 200 110, 250 160, 300 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-2: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.SP}, dim(0){A.L.Int.V = B.L.Int.V}, dim(0){A.L.Bdy.EP = B.L.Int.EP}]</desc>
+ <a>
+ LINESTRING(60 110, 200 110, 250 160, 300 210, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1F0F1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-3: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Bdy.SP}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(60 110, 220 110, 250 160, 280 110)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-4: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Int.SP}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Bdy.EP = B.L.Int.EP}]</desc>
+ <a>
+ LINESTRING(60 110, 150 110, 200 160, 250 110, 360 110, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1F0F1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-5: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(130 160, 160 110, 220 110, 250 160, 250 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-6: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(130 160, 160 110, 190 110, 230 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-7: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Bdy.SP = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(130 160, 160 110, 200 110, 230 160, 260 210, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F100F102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-8: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(130 160, 160 110, 200 110, 230 160, 260 210, 360 210, 380 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-9: two LineStrings crossing at three points [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Int.NV = B.L.Bdy.EP}]</desc>
+ <a>
+ LINESTRING(130 160, 160 110, 200 110, 230 160, 260 210, 380 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-10: two LineStrings crossing at two points [dim(0){A.L.Bdy.SP = B.L.Int.V}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(110 160, 160 110, 200 110, 250 160, 250 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-11: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Int.V}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(110 160, 180 110, 250 160, 320 110)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-12: two LineStrings crossing on one side [dim(0){A.L.Bdy.SP = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(140 160, 180 80, 220 160, 250 80)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-13: two LineStrings crossing at a vertex for one of the LineStrings [dim(0){A.L.Int.V = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 130 190)
+ </a>
+ <b>
+ LINESTRING(20 130, 70 130, 160 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-14: two LineStrings crossing at non-vertices for both of the LineStrings [dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 130 190)
+ </a>
+ <b>
+ LINESTRING(40 160, 40 100, 110 40, 170 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-15: two LineStrings crossing on one side [dim(0){A.L.Int.V = B.L.Int.NV}, dim(0){A.L.Int.V = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(130 110, 180 160, 230 110, 280 160, 330 110)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-16: two LineStrings crossing at vertices for both LineString [dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 130 190)
+ </a>
+ <b>
+ LINESTRING(30 140, 80 140, 100 100, 200 30)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-17: two LineStrings crossing on one side [dim(0){A.L.Int.V = B.L.Int.V}, dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(110 110, 110 160, 180 110, 250 160, 250 110)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-18: multiple crossings [dim(0){A.L.Int.V = B.L.Int.V}, dim(0){A.L.Int.NV = B.L.Int.NV}]</desc>
+ <a>
+ LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
+ </a>
+ <b>
+ LINESTRING(20 60, 60 60, 60 140, 80 80, 100 20, 140 140, 180 20, 200 80, 220 20,
+ 240 80, 300 80, 270 110, 200 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-4-19: spiky LineStrings with multiple crossing [dim(0){A.L.Int.V = B.L.Int.V}]</desc>
+ <a>
+ LINESTRING(20 20, 230 20, 20 30, 170 30, 20 40, 230 40, 20 50, 230 60, 60 60,
+ 230 70, 20 70, 180 80, 60 80, 230 90, 20 90, 230 100, 30 100, 210 110, 20 110,
+ 80 120, 20 130, 170 130, 90 120, 230 130, 170 140, 230 140, 80 150, 160 140, 20 140,
+ 70 150, 20 150, 230 160, 80 160, 230 170, 20 160, 180 170, 20 170, 230 180, 20 180,
+ 40 190, 230 190, 20 200, 230 200)
+ </a>
+ <b>
+ LINESTRING(30 210, 30 60, 40 210, 40 30, 50 190, 50 20, 60 160, 60 50, 70 220,
+ 70 50, 80 20, 80 210, 90 50, 90 150, 100 30, 100 210, 110 20, 110 190, 120 50,
+ 120 180, 130 210, 120 20, 140 210, 130 50, 150 210, 130 20, 160 210, 140 30, 170 210,
+ 150 20, 180 210, 160 20, 190 210, 180 80, 170 50, 170 20, 180 70, 180 20, 190 190,
+ 190 30, 200 210, 200 30, 210 210, 210 20, 220 150, 220 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="001FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-1-1: two equal LineStrings with equal pointwise [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-1-2: two equal LineStrings with points in reverse sequence [dim(1){A.L.Int.SP-EP = B.L.Int.EP-SP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(80 240, 200 120, 100 100, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-1-3: two equal LineStrings with different number of points [dim(1){A.L.Int.SP-EP = B.L.Int.EP-SP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(80 240, 120 200, 200 120, 100 100, 80 80, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-2-1: disjoint [dim(1){A.L.Int.SP-EP = B.L.Ext}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(260 210, 240 130, 280 120, 260 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-2-2: wrapping around but still disjoint [dim(1){A.L.Int.SP-EP = B.L.Ext}]</desc>
+ <a>
+ LINESTRING(100 20, 20 20, 20 160, 210 160, 210 20, 110 20, 50 120, 120 150, 200 150)
+ </a>
+ <b>
+ LINESTRING(140 130, 100 110, 120 60, 170 60)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-5-1: LineString A containing LineString B, same pointwise [dim(1){A.L.Int.SP-EP = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-5-2: LineString A containing LineString B, LineString A with less points [dim(1){A.L.Int.SP-V = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(60 110, 110 160, 310 160, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-5-3: LineString A containing LineString B [dim(1){A.L.Int.SP-V = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </a>
+ <b>
+ LINESTRING(60 110, 110 160, 250 160)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101F00FF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-5-4: LineString A containing LineString B [dim(1){A.L.Int.NV-NV = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </a>
+ <b>
+ LINESTRING(110 160, 310 160, 340 190)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-5-5: LineString A containing LineString B [dim(1){A.L.Int.V-NV = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </a>
+ <b>
+ LINESTRING(140 160, 250 160, 310 160, 340 190)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-5-6: LineString A containing LineString B [dim(1){A.L.Int.V-V = B.L.Int.SP-EP}]</desc>
+ <a>
+ LINESTRING(60 110, 110 160, 250 160, 310 160, 360 210)
+ </a>
+ <b>
+ LINESTRING(110 160, 250 160, 310 160)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0FF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-1: start portions of two LineStrings overlapping [dim(1){A.L.Int.SP-V = B.L.Int.SP-V}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(200 120, 100 100, 40 40, 140 80, 200 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-2: start portion of LineString A overlapping end portion of LineString B, intersecting at the middle of LineString A [dim(1){A.L.Int.SP-V = B.L.Int.V-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(280 240, 240 140, 200 120, 100 100, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-3: start portion of LineString A overlapping end portion of LineString B, intersecting at the middle of LineString A [dim(1){A.L.Int.SP-V = B.L.Int.NV-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(80 190, 140 140, 40 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-4: end portions of two LineStrings overlapping [dim(1){A.L.Int.NV-EP = B.L.Int.V-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(240 200, 200 260, 80 240, 140 180)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-5: end portion of LineString A overlapping start portion of LineString B [dim(1){A.L.Int.NV-EP = B.L.Int.SP-V}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(140 180, 80 240, 200 260, 240 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1010F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-6: end portion of LineString A overlapping end portion of LineString B, intersecting at the middle of LineString A [dim(1){A.L.Int.V-EP = B.L.Int.V-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(280 240, 240 140, 200 120, 80 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-7: middle portions of two LineStrings overlapping [dim(1){A.L.Int.V-NV = B.L.Int.NV-V}]</desc>
+ <a>
+ LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
+ </a>
+ <b>
+ LINESTRING(20 80, 120 80, 200 80, 260 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-8: middle portion of LineString A overlapping start portion of LineString B [dim(1){A.L.Int.V-V = B.L.Int.SP-V}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(100 100, 200 120, 240 140, 280 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-9: middle portion of LineString A overlapping end portion of LineString B [dim(1){A.L.Int.V-V = B.L.Int.V-EP}]</desc>
+ <a>
+ LINESTRING(40 40, 100 100, 200 120, 80 240)
+ </a>
+ <b>
+ LINESTRING(280 240, 240 140, 200 120, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-10: middle portions of two LineStrings overlapping [dim(1){A.L.Int.V-V = B.L.Int.V-V}]</desc>
+ <a>
+ LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
+ </a>
+ <b>
+ LINESTRING(80 20, 80 80, 240 80, 300 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/L.2-6-11: middle portions of two LineStrings overlapping, multiple intersects [dim(1){A.L.Int.V-V = B.L.Int.V-NV}, dim(1){A.L.Int.V-V = B.L.Int.V-NV}, dim(1){A.L.Int.V-V = B.L.Int.V-NV}]</desc>
+ <a>
+ LINESTRING(20 20, 80 80, 160 80, 240 80, 300 140)
+ </a>
+ <b>
+ LINESTRING(20 80, 80 80, 120 80, 140 140, 160 80, 200 80, 220 20, 240 80, 270 110,
+ 300 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-3-1: a LineString touching a LinearRing [dim(0){A.L.Bdy.SP = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(100 100, 20 180, 180 180)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-4-1: a LineString crossing a LinearRing [dim(0){A.L.Int.NV = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(20 100, 180 100, 100 180)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-4-2: a LineString crossing a LinearRing [dim(0){A.L.Int.NV = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(100 40, 100 160, 180 160)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-4-3: a LineString crossing a LinearRing [dim(0){A.L.Int.V = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(20 100, 100 100, 180 100, 100 180)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-5-1: a LineString within a LinearRing [dim(1){A.L.Int.SP-EP = B.LR.Int.SP-NV}]</desc>
+ <a>
+ LINESTRING(100 100, 160 40)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FF0FF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-5-2: a LineString within a LinearRing [dim(1){A.L.Int.SP-EP = B.LR.Int.SP-NV}]</desc>
+ <a>
+ LINESTRING(100 100, 180 20)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FF0FF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-5-3: a LineString within a LinearRing [dim(1){A.L.Int.SP-V-EP = B.LR.Int.NV-CP-NV}]</desc>
+ <a>
+ LINESTRING(60 60, 100 100, 140 60)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FF0FF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-6-1: a LineString crossing a LinearRing [dim(1){A.L.Int.SP-NV = B.LR.Int.SP-V}]</desc>
+ <a>
+ LINESTRING(100 100, 190 10, 190 100)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F10F01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-6-2: a LineString crossing a LinearRing [dim(1){A.L.Int.SP-V = B.LR.Int.SP-NV}]</desc>
+ <a>
+ LINESTRING(100 100, 160 40, 160 100)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F10F01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/LR-6-3: a LineString crossing a LinearRing [dim(1){A.L.Int.NV-V = B.LR.Int.SP-NV}]</desc>
+ <a>
+ LINESTRING(60 140, 160 40, 160 140)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's end point with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Bdy.EPb}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(80 80, 20 80, 140 80, 80 20, 80 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's end point with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Bdy.EPo}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(80 80, 20 80, 140 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's end point with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(80 80, 140 80, 80 20, 80 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's closing point with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.CPb}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(80 80, 20 80, 140 80, 80 20, 80 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's closing point with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.CPo}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(80 80, 20 80, 140 80, 80 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's closing point with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Int.CPx}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(80 80, 20 80, 20 140, 140 20, 80 20, 80 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex [dim(0){A.L.Int.NV = B.nsL.Int.NV}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(20 140, 140 20, 100 20, 100 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.NVb}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 20 80, 120 80, 80 20, 80 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.NVo}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 20 80, 140 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a non-vertex with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Int.NVx}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 20 80, 80 140, 80 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex [dim(0){A.L.Int.NV = B.nsL.Int.V}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 80 80, 20 80, 50 140, 50 60)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex with both crossing and overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.Vb}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 20 80, 120 80, 80 20, 80 80, 80 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex with overlapping line segments [dim(0){A.L.Int.NV = B.nsL.Int.Vo}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 20 80, 80 80, 140 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF01F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL: A line's interior at a non-vertex intersecting a non-simple linestring's interior at a vertex with crossing line segments [dim(0){A.L.Int.NV = B.nsL.Int.Vx}]</desc>
+ <a>
+ LINESTRING(20 20, 140 140)
+ </a>
+ <b>
+ LINESTRING(140 80, 20 80, 80 140, 80 80, 80 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.1-3-1: start point of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Bdy.SP = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(130 150, 220 150, 220 240)
+ </a>
+ <b>
+ LINESTRING(130 240, 130 150, 220 20, 50 20, 130 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.1-3-2: the interior of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Int.V = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(30 150, 130 150, 250 150)
+ </a>
+ <b>
+ LINESTRING(130 240, 130 150, 220 20, 50 20, 130 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.1-3-3: the interior of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Int.NV = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(30 150, 250 150)
+ </a>
+ <b>
+ LINESTRING(130 240, 130 150, 220 20, 50 20, 130 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.1-3-4: the interior of a LineString touching the self-intersecting point of a non-simple LineString [dim(0){A.L.Int.V = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(30 150, 130 150, 250 150)
+ </a>
+ <b>
+ LINESTRING(130 240, 130 20, 30 20, 130 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.1-4: a Line crossing a non-simple LineString at non-vertices [dim(0){A.L.Int.NV = B.nsL.Int.NV}]</desc>
+ <a>
+ LINESTRING(30 150, 250 150)
+ </a>
+ <b>
+ LINESTRING(120 240, 120 20, 20 20, 120 170)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL.5/L-3-1: switching the geometries for case L/nsL.5-3-1 [dim(0){A.nsL.Bdy.EPx = B.L.Bdy.SP}]</desc>
+ <a>
+ LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.5-3-2: the start point of a line touching the self-intersecting and self-crossing point of a non-simple LineString [dim(0){A.L.Bdy.SP = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(110 110, 200 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.5-3-3: the interior of a line touching the self-intersecting and self-crossing point of a non-simple LineString [dim(0){A.L.Int.NV = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ LINESTRING(20 110, 200 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL.5/L-3-4 touches dim(0){A.nsL.Bdy.EPx = B.L.Int.NV}</desc>
+ <a>
+ LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
+ </a>
+ <b>
+ LINESTRING(20 110, 200 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.10-6-1: the middle portion of a line overlapping from the self-intersecting to the self-crossing a non-simple LineString [dim(1){A.L.Int.V-V = B.nsL.Int.EPx-NVx}]</desc>
+ <a>
+ LINESTRING(90 200, 90 130, 110 110, 150 200)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/nsL.10-6-2: the middle portion of a line overlapping from the self-intersecting to the self-crossing a non-simple LineString [dim(1){A.L.Int.V-V = B.nsL.Int.NVx-EPx}]</desc>
+ <a>
+ LINESTRING(200 110, 110 110, 90 130, 90 200)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>L/mL-3-1: a line's end point touching a non-vertex with crossing line segments of a MultiLineString [dim(0){A.L.Bdy.SP = B.mL.Int.NVx]</desc>
+ <a>
+ LINESTRING(80 80, 150 80, 210 80)
+ </a>
+ <b>
+ MULTILINESTRING(
+ (20 20, 140 140),
+ (20 140, 140 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-1-1: two equal LinearRings, pointwise [dim(1){A.LR.Int.SP-EP = B.LR.Int.SP-EP}, dim(0){A.LR.Int.CP = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(40 80, 160 200, 260 20, 40 80)
+ </a>
+ <b>
+ LINESTRING(40 80, 160 200, 260 20, 40 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-1-2: two equal LinearRings with points in reverse sequence [dim(1){A.LR.Int.SP-EP = B.LR.Int.EP-SP}, dim(0){A.LR.Int.CP = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(40 80, 160 200, 260 20, 40 80)
+ </a>
+ <b>
+ LINESTRING(40 80, 260 20, 160 200, 40 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-1-3: two equal LinearRings with points in different sequence [dim(1){A.LR.Int.SP-EP = B.LR.Int.SP-EP}, dim(0){A.LR.Int.CP = B.LR.Int.V}, dim(0){A.LR.Int.V = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(40 80, 160 200, 260 20, 40 80)
+ </a>
+ <b>
+ LINESTRING(260 20, 40 80, 160 200, 260 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-1-4: two equal LinearRings with different number of points [dim(1){A.LR.Int.SP-EP = B.LR.Int.SP-EP}, dim(0){A.LR.Int.CP = B.LR.Int.V}, dim(0){A.LR.Int.NV = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(40 80, 160 200, 260 20, 40 80)
+ </a>
+ <b>
+ LINESTRING(100 140, 160 200, 260 20, 40 80, 100 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-4-1: two LinearRings crossing at closing points [dim(0){A.LR.Int.CP = B.LR.Int.CP}]</desc>
+ <a>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </a>
+ <b>
+ LINESTRING(100 100, 180 180, 20 180, 100 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-4-2: two LinearRings crossing at two points [dim(0){A.LR.Int.CP = B.LR.Int.CP}, dim(0){A.LR.Int.V = B.LR.Int.V},]</desc>
+ <a>
+ LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
+ </a>
+ <b>
+ LINESTRING(40 150, 150 40, 170 20, 170 190, 40 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-4-3: two LinearRings crossing at the closing and a non-vertex [dim(0){A.LR.Int.CP = B.LR.Int.NV}]</desc>
+ <a>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </a>
+ <b>
+ LINESTRING(180 100, 20 100, 100 180, 180 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-4-4: two LinearRings crossing at the closing and a vertex [dim(0){A.LR.Int.CP = B.LR.Int.V}]</desc>
+ <a>
+ LINESTRING(100 100, 180 20, 20 20, 100 100)
+ </a>
+ <b>
+ LINESTRING(180 180, 100 100, 20 180, 180 180)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-4-5: two LinearRings crossing at a vertex and a non-vertex [dim(0){A.LR.Int.V = B.LR.Int.NV}]</desc>
+ <a>
+ LINESTRING(20 180, 100 100, 20 20, 20 180)
+ </a>
+ <b>
+ LINESTRING(100 20, 100 180, 180 100, 100 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-4-6: two LinearRings crossing at two points [dim(0){A.LR.Int.V = B.LR.Int.NV}, dim(0){A.LR.Int.V = B.LR.Int.NV},]</desc>
+ <a>
+ LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
+ </a>
+ <b>
+ LINESTRING(170 20, 20 170, 170 170, 170 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-6-1: two LinearRings overlapping [dim(1){A.LR.Int.CP-V = B.LR.Int.CP-V}]</desc>
+ <a>
+ LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
+ </a>
+ <b>
+ LINESTRING(40 150, 150 150, 90 210, 40 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-6-2: two LinearRings overlapping [dim(1){A.LR.Int.CP-V = B.LR.Int.NV-NV}]</desc>
+ <a>
+ LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
+ </a>
+ <b>
+ LINESTRING(20 150, 170 150, 90 230, 20 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/LR-6-3: two LinearRings overlapping [dim(1){A.LR.Int.(V-V-V-EP) = B.LR.Int.(NV-V-V-SP)}]</desc>
+ <a>
+ LINESTRING(40 150, 40 40, 150 40, 150 150, 40 150)
+ </a>
+ <b>
+ LINESTRING(40 150, 150 150, 150 40, 20 40, 20 150, 40 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/nsL-3-1: a LinearRing touching a non-simple LineString [dim(0){A.nsL.Int.CP = B.nsL.Bdy.SPb}]</desc>
+ <a>
+ LINESTRING(110 110, 200 20, 20 20, 110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 110, 20 200, 20 110, 200 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/nsL-3-1: a LinearRing touching a non-simple LineString [dim(0){A.nsL.Int.CP = B.nsL.Bdy.SPo}]</desc>
+ <a>
+ LINESTRING(110 110, 200 20, 20 20, 110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 20 110, 200 110, 50 110, 110 170)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/nsL-3-1: a LinearRing touching a non-simple LineString [dim(0){A.nsL.Int.CP = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ LINESTRING(110 110, 200 20, 20 20, 110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 20 200, 110 200, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F01FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/nsL-6-1: a LinearRing and a non-simple LineString overlapping [dim(1){A.nsL.Int.SP-V = B.nsL.Int.NVx-SP}]</desc>
+ <a>
+ LINESTRING(110 110, 200 20, 20 20, 110 110)
+ </a>
+ <b>
+ LINESTRING(200 20, 20 200, 200 200, 110 110, 110 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>LR/nsL-6-2: a LinearRing and a non-simple LineString overlapping [dim(1){A.nsL.Int.SP-V = B.nsL.Int.NVx-SP}, dim(1){A.nsL.Int.V-EP = B.nsL.Int.EP-NVx}]</desc>
+ <a>
+ LINESTRING(110 110, 200 20, 20 20, 110 110)
+ </a>
+ <b>
+ LINESTRING(200 20, 20 200, 200 200, 20 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="101FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL/nsL-4-1: non-simple LineStrings crossing at closing points [dim(0){A.nsL.Int.CP = B.nsL.Int.CP}]</desc>
+ <a>
+ LINESTRING(110 110, 20 110, 110 20, 20 20, 110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 200 110, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL/nsL-4-2: non-simple LineStrings crossing at two points without vertices [dim(0){A.nsL.Int.NV = B.nsL.Int.NV}]</desc>
+ <a>
+ LINESTRING(20 120, 120 120, 20 20, 120 20, 20 120)
+ </a>
+ <b>
+ LINESTRING(170 100, 70 100, 170 170, 70 170, 170 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL/nsL-4-3: non-simple LineStrings crossing at a point [dim(0){A.nsL.Int.NV = B.nsL.Int.V}]</desc>
+ <a>
+ LINESTRING(20 110, 110 110, 20 20, 110 20, 20 110)
+ </a>
+ <b>
+ LINESTRING(110 160, 70 110, 60 160, 20 130, 110 160)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL/nsL-4-4: non-simple LineStrings crossing at self-crossing points [dim(0){A.nsL.Int.NVx = B.nsL.Int.NVx}]</desc>
+ <a>
+ LINESTRING(20 200, 200 200, 20 20, 200 20, 20 200)
+ </a>
+ <b>
+ LINESTRING(20 110, 200 110, 200 160, 20 60, 20 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL/nsL-4-5: non-simple LineStrings crossing at vertices [dim(0){A.nsL.Int.V = B.nsL.Int.V}]</desc>
+ <a>
+ LINESTRING(20 110, 110 110, 20 20, 110 20, 20 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 110 110, 200 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>nsL/nsL-4-6: non-simple LineStrings crossing at two points with vertices [dim(0){A.nsL.Int.V = B.nsL.Int.V}]</desc>
+ <a>
+ LINESTRING(20 120, 120 120, 20 20, 120 20, 20 120)
+ </a>
+ <b>
+ LINESTRING(220 120, 120 20, 220 20, 120 120, 220 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-1: MultiLineString [dim(1){A.mL.Int.SP-EP = B.mL.Int.SP-EP}]</desc>
+ <a>
+ MULTILINESTRING(
+ (70 20, 20 90, 70 170),
+ (70 170, 120 90, 70 20))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (70 20, 20 90, 70 170),
+ (70 170, 120 90, 70 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-1-1: non-simple MultiLineString [dim(1){A.mL.Int.SP-EP = B.mL.Int.SP-EP}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-1-2: equal non-simple MultiLineString with different sequence of lines and points [dim(1){A.mL.Int.SP-EP = B.mL.Int.EP-SP}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 140, 90 60, 90 20),
+ (170 20, 130 20, 20 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="1FFF0FFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-1: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPb}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (170 60, 90 20, 20 60),
+ (130 100, 130 60, 90 20, 50 90))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-2: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPo}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (130 140, 130 60, 90 20, 20 90, 90 20, 130 60, 170 60))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-3: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPx}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (170 60, 90 20, 20 60))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF1F00102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-4: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPx}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (170 60, 90 20, 20 60),
+ (130 100, 90 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-5: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Bdy.SPx}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (170 60, 90 20, 20 60),
+ (120 100, 170 100, 90 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-6: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Int.SPb}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (170 60, 90 20, 20 60),
+ (120 100, 170 100, 90 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-7: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Int.SPo}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (130 140, 130 60, 90 20, 20 90, 90 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-3-8: non-simple MultiLineStrings touching at boundaries [dim(0){A.mL.Bdy.SPx = B.mL.Int.SPx}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 20, 170 20),
+ (90 20, 90 80, 90 140))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (90 20, 170 100, 170 140),
+ (170 60, 90 20, 20 60, 20 140, 90 20))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF10F0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-4-1: non-simple MultiLineStrings crossing [dim(0){A.mL.Int.Vx = B.mL.Int.Vb}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 90, 20 160),
+ (90 160, 90 20))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (160 160, 90 90, 160 20),
+ (160 120, 120 120, 90 90, 160 60))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-4-2: non-simple MultiLineStrings crossing [dim(0){A.mL.Int.Vx = B.mL.Int.Vo}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 90, 20 160),
+ (90 160, 90 20))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (160 160, 90 90, 160 20),
+ (160 120, 120 120, 90 90, 120 60, 160 60))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mL/mL-4-3: non-simple MultiLineStrings crossing [dim(0){A.mL.Int.Vx = B.mL.Int.Vx}]</desc>
+ <a>
+ MULTILINESTRING(
+ (20 20, 90 90, 20 160),
+ (90 160, 90 20))
+ </a>
+ <b>
+ MULTILINESTRING(
+ (160 160, 90 90, 160 20),
+ (160 120, 90 90, 160 60))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F1FF0102">true</op>
+ </test>
+</case>
+
</run>
\ No newline at end of file
diff --git a/test/validate/TestRelatePA.xml b/test/validate/TestRelatePA.xml
index 030edb9..dae0bfe 100644
--- a/test/validate/TestRelatePA.xml
+++ b/test/validate/TestRelatePA.xml
@@ -1,622 +1,622 @@
<run>
<precisionModel type="FLOATING"/>
-
-<case>
-<desc>P/A-2-1: a point outside a polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
- <a>
- POINT(20 20)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-2-2: a point outside a converx polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
- <a>
- POINT(70 170)
- </a>
- <b>
- POLYGON(
- (110 230, 80 160, 20 160, 20 20, 200 20, 200 160, 140 160, 110 230))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-2-3: a point outside a concave polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
- <a>
- POINT(110 130)
- </a>
- <b>
- POLYGON(
- (20 160, 80 160, 110 100, 140 160, 200 160, 200 20, 20 20, 20 160))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-2-4: dim(0){A.P.Int = B.A.Ext}</desc>
- <a>
- POINT(100 70)
- </a>
- <b>
- POLYGON(
- (20 150, 100 150, 40 50, 170 50, 110 150, 190 150, 190 20, 20 20, 20 150))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-2-5: a point outside a concave polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
- <a>
- POINT(100 70)
- </a>
- <b>
- POLYGON(
- (20 150, 100 150, 40 50, 160 50, 100 150, 180 150, 180 20, 20 20, 20 150))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-3-1: a point on the closing point of a polygon [dim(0){A.P.Int = B.A.Bdy.CP}]</desc>
- <a>
- POINT(60 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-3-2: a point on the boudary of a polygon at a non-vertex [dim(0){A.P.Int = B.A.Bdy.NV}]</desc>
- <a>
- POINT(110 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-3-3: a point on the boundary of a polygon at a vertex [dim(0){A.P.Int = B.A.Bdy.V]</desc>
- <a>
- POINT(160 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-3-4: a point on the touching point of boudary [dim(0){A.P.Int = B.A.Bdy.TP}]</desc>
- <a>
- POINT(100 150)
- </a>
- <b>
- POLYGON(
- (20 150, 100 150, 40 50, 160 50, 100 150, 180 150, 180 20, 20 20, 20 150))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A-5: a point on the interior of a polygon [dim(0){A.P.Int = B.A.Int}]</desc>
- <a>
- POINT(100 80)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-2-1: a point outside of polygon with a hole [dim(0){A.P.Int = B.A.Ext}]</desc>
- <a>
- POINT(60 160)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-2-2: a point inside the hole of the polygon [dim(0){A.P.Int = B.A.Ext.h}]</desc>
- <a>
- POINT(190 90)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-3-1: a point on the closing point of the outer boundary of a polygon with a hole [dim(0){A.P.Int = B.A.oBdy.CP}]</desc>
- <a>
- POINT(190 190)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-3-2: a point on the outer boundary of a polygon at a vertex [dim(0){A.P.Int = B.A.oBdy.V}]</desc>
- <a>
- POINT(360 20)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-3-3: a point on the outer boundary of a polygon at a non-vertex [dim(0){A.P.Int = B.A.oBdy.NV}]</desc>
- <a>
- POINT(130 130)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-3-4: a point on the closing point of the inner boundary of a polygon [dim(0){A.P.Int = B.A.iBdy.CP}]</desc>
- <a>
- POINT(280 50)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-3-5: a point on the inner boundary of a polygon at a non-vertex [dim(0){A.P.Int = B.A.iBdy.NV}]</desc>
- <a>
- POINT(150 100)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-3-6: a point on the inner boundary of a polygon at a vertex [dim(0){A.P.Int = B.A.iBdy.V}]</desc>
- <a>
- POINT(100 50)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/Ah-5: a point inside the interior of a polygon with a hole [dim(0){A.P.Int = B.A.Int}]</desc>
- <a>
- POINT(140 120)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A2h-3-1: a point on the touching point of two holes in a polygon [dim(0){A.P.Int = B.A.iBdy.TP}]</desc>
- <a>
- POINT(190 50)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (90 50, 150 110, 190 50, 90 50),
- (190 50, 230 110, 290 50, 190 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/A2h-3-2: a point on the touching point of two holes in a polygon [dim(0){A.P.Int = B.A.iBdy.TP}]</desc>
- <a>
- POINT(180 90)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (180 140, 180 40, 80 40, 180 140),
- (180 90, 210 140, 310 40, 230 40, 180 90))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-2: 3 points outside a polygon [dim(0){A.2P.Int = B.A.Ext}]</desc>
- <a>
- MULTIPOINT(20 80, 110 160, 20 160)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-3-1: one of 3 points on the closing point of the boundary of a polygon [dim(0){A.3P1.Int = B.A.Bdy.CP}]</desc>
- <a>
- MULTIPOINT(20 80, 60 120, 20 160)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-3-2: one of 3 points on the boundary of a polygon at a non-vertex [dim(0){A.3P3 = B.A.Bdy.NV}]</desc>
- <a>
- MULTIPOINT(10 80, 110 170, 110 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-3-3: one of 3 points on the boundary of a polygon at a vertex [dim(0){A.3P1.Int = B.A.Bdy.V}]</desc>
- <a>
- MULTIPOINT(10 80, 110 170, 160 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-3-4: 3 of the 5 points on the boundary of a polygon [dim(0){A.5P2.Int = B.A.Bdy.CP}, dim(0){A.5P3.Int = B.A.Bdy.NV}, dim(0){A.5P4.Int = B.A.Bdy.V}]</desc>
- <a>
- MULTIPOINT(20 120, 60 120, 110 120, 160 120, 200 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-3-5: all 3 points on the boundary of a polygon [dim(0){A.3P1.Int = B.A.Bdy.CP}, dim(0){A.3P2.Int = B.A.Bdy.NV}, dim(0){A.3P3.Int = B.A.Bdy.V}]</desc>
- <a>
- MULTIPOINT(60 120, 110 120, 160 120)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-3-6: all 4 points on the boundary of a polygon [dim(0){A.4P = B.A.Bdy}]</desc>
- <a>
- MULTIPOINT(60 120, 160 120, 160 40, 60 40)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-4-1: 1 point outside a polygon, 1 point on the boundary and 1 point inside [dim(0){A.3P1.Int = B.A.Ext}, dim(0){A.3P2.Int = B.A.Bdy.CP}, dim(0){A.3P3.Int = B.A.Int}]</desc>
- <a>
- MULTIPOINT(20 150, 60 120, 110 80)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-4-2: 1 point outside a polygon, 1 point on the boundary and 1 point inside [dim(0){A.3P1.Int = B.A.Ext}, dim(0){A.3P2.Int = B.A.Bdy.V}, dim(0){A.3P3.Int = B.A.Int}]</desc>
- <a>
- MULTIPOINT(110 80, 160 120, 200 160)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-4-3: 1 point outside a polygon, 1 point on the boundary and 1 point inside [dim(0){A.3P1.Int = B.A.Ext}, dim(0){A.3P2.Int = B.A.Bdy.NV}, dim(0){A.3P3.Int = B.A.Int}]</desc>
- <a>
- MULTIPOINT(110 80, 110 120, 110 160)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-4-4: 1 point outside a polygon, 1 point inside [dim(0){A.2P1.Int = B.A.Ext}, dim(0){A.2P2.Int = B.A.Int}]</desc>
- <a>
- MULTIPOINT(110 170, 110 80)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-4-5: 1 point outside a polygon, 2 points on the boundary and 1 point inside [dim(0){A.4P1.Int = B.A.Ext}, dim(0){A.4P2.Int = B.A.Bdy.CP}, dim(0){A.4P3.Int = B.A.Bdy.V}, dim(0){A.4P4.Int = B.A.Int}]</desc>
- <a>
- MULTIPOINT(60 120, 160 120, 110 80, 110 170)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-5-1: 2 points within a polygon [dim(0){A.2P.Int = B.A.Int]</desc>
- <a>
- MULTIPOINT(90 80, 130 80)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/A-5-2: 1 point on the boundary and 1 point inside a polygon [dim(0){A.2P1.Int = B.A.Bdy.CP}, dim(0){A.2P2.Int = B.A.Int}]</desc>
- <a>
- MULTIPOINT(60 120, 160 120, 110 80)
- </a>
- <b>
- POLYGON(
- (60 120, 60 40, 160 40, 160 120, 60 120))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="00FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/Ah-2-1: 3 points outside a polygon [dim(0){A.3P.Int = B.Ah.Ext}]</desc>
- <a>
- MULTIPOINT(40 170, 40 90, 130 170)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/Ah-2-2: 2 points outside a polygon and 1 point inside the hole of the polygon [dim(0){A.3P1.Int = B.Ah.Ext}, dim(0){A.3P2.Int = B.Ah.Ext}, dim(0){A.3P3.Int = B.Ah.Ext.h}]</desc>
- <a>
- MULTIPOINT(90 170, 280 170, 190 90)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/Ah-2-3: all 3 points in polygon's hole [dim(0){A.3P.Int = B.Ah.Ext.h}]</desc>
- <a>
- MULTIPOINT(190 110, 150 70, 230 70)
- </a>
- <b>
- POLYGON(
- (190 190, 360 20, 20 20, 190 190),
- (280 50, 100 50, 190 140, 280 50))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/mA-3-1: a point on the touching point of two polygons [dim(0){A.P.Int = B.2A.Bdy}]</desc>
- <a>
- POINT(100 100)
- </a>
- <b>
- MULTIPOLYGON(
- (
- (20 100, 20 20, 100 20, 100 100, 20 100)),
- (
- (100 180, 100 100, 180 100, 180 180, 100 180)))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/mA-3-2: a point on the boundary of one of the 2 polygons [dim(0){A.P.Int = B.2A1.Bdy.CP}]</desc>
- <a>
- POINT(20 100)
- </a>
- <b>
- MULTIPOLYGON(
- (
- (20 100, 20 20, 100 20, 100 100, 20 100)),
- (
- (100 180, 100 100, 180 100, 180 180, 100 180)))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/mA-3-3: a point on the boundary of one of the 2 polygons [dim(0){A.P.Int = B.2A1.Bdy.V}]</desc>
- <a>
- POINT(60 100)
- </a>
- <b>
- MULTIPOLYGON(
- (
- (20 100, 20 20, 100 20, 100 100, 20 100)),
- (
- (100 180, 100 100, 180 100, 180 180, 100 180)))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/mA-3-4: a point touching a polygon's boundary where the boundaries touch at a point [dim(0){A.P.Int = B.2A.Bdy.TP}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- MULTIPOLYGON(
- (
- (110 110, 20 200, 200 200, 110 110),
- (110 110, 80 180, 140 180, 110 110)),
- (
- (110 110, 20 20, 200 20, 110 110),
- (110 110, 80 40, 140 40, 110 110)))
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
- </test>
-</case>
-
+
+<case>
+<desc>P/A-2-1: a point outside a polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
+ <a>
+ POINT(20 20)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-2-2: a point outside a converx polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
+ <a>
+ POINT(70 170)
+ </a>
+ <b>
+ POLYGON(
+ (110 230, 80 160, 20 160, 20 20, 200 20, 200 160, 140 160, 110 230))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-2-3: a point outside a concave polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
+ <a>
+ POINT(110 130)
+ </a>
+ <b>
+ POLYGON(
+ (20 160, 80 160, 110 100, 140 160, 200 160, 200 20, 20 20, 20 160))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-2-4: dim(0){A.P.Int = B.A.Ext}</desc>
+ <a>
+ POINT(100 70)
+ </a>
+ <b>
+ POLYGON(
+ (20 150, 100 150, 40 50, 170 50, 110 150, 190 150, 190 20, 20 20, 20 150))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-2-5: a point outside a concave polygon [dim(0){A.P.Int = B.A.Ext}]</desc>
+ <a>
+ POINT(100 70)
+ </a>
+ <b>
+ POLYGON(
+ (20 150, 100 150, 40 50, 160 50, 100 150, 180 150, 180 20, 20 20, 20 150))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-3-1: a point on the closing point of a polygon [dim(0){A.P.Int = B.A.Bdy.CP}]</desc>
+ <a>
+ POINT(60 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-3-2: a point on the boudary of a polygon at a non-vertex [dim(0){A.P.Int = B.A.Bdy.NV}]</desc>
+ <a>
+ POINT(110 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-3-3: a point on the boundary of a polygon at a vertex [dim(0){A.P.Int = B.A.Bdy.V]</desc>
+ <a>
+ POINT(160 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-3-4: a point on the touching point of boudary [dim(0){A.P.Int = B.A.Bdy.TP}]</desc>
+ <a>
+ POINT(100 150)
+ </a>
+ <b>
+ POLYGON(
+ (20 150, 100 150, 40 50, 160 50, 100 150, 180 150, 180 20, 20 20, 20 150))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A-5: a point on the interior of a polygon [dim(0){A.P.Int = B.A.Int}]</desc>
+ <a>
+ POINT(100 80)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-2-1: a point outside of polygon with a hole [dim(0){A.P.Int = B.A.Ext}]</desc>
+ <a>
+ POINT(60 160)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-2-2: a point inside the hole of the polygon [dim(0){A.P.Int = B.A.Ext.h}]</desc>
+ <a>
+ POINT(190 90)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-3-1: a point on the closing point of the outer boundary of a polygon with a hole [dim(0){A.P.Int = B.A.oBdy.CP}]</desc>
+ <a>
+ POINT(190 190)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-3-2: a point on the outer boundary of a polygon at a vertex [dim(0){A.P.Int = B.A.oBdy.V}]</desc>
+ <a>
+ POINT(360 20)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-3-3: a point on the outer boundary of a polygon at a non-vertex [dim(0){A.P.Int = B.A.oBdy.NV}]</desc>
+ <a>
+ POINT(130 130)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-3-4: a point on the closing point of the inner boundary of a polygon [dim(0){A.P.Int = B.A.iBdy.CP}]</desc>
+ <a>
+ POINT(280 50)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-3-5: a point on the inner boundary of a polygon at a non-vertex [dim(0){A.P.Int = B.A.iBdy.NV}]</desc>
+ <a>
+ POINT(150 100)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-3-6: a point on the inner boundary of a polygon at a vertex [dim(0){A.P.Int = B.A.iBdy.V}]</desc>
+ <a>
+ POINT(100 50)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/Ah-5: a point inside the interior of a polygon with a hole [dim(0){A.P.Int = B.A.Int}]</desc>
+ <a>
+ POINT(140 120)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A2h-3-1: a point on the touching point of two holes in a polygon [dim(0){A.P.Int = B.A.iBdy.TP}]</desc>
+ <a>
+ POINT(190 50)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (90 50, 150 110, 190 50, 90 50),
+ (190 50, 230 110, 290 50, 190 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/A2h-3-2: a point on the touching point of two holes in a polygon [dim(0){A.P.Int = B.A.iBdy.TP}]</desc>
+ <a>
+ POINT(180 90)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (180 140, 180 40, 80 40, 180 140),
+ (180 90, 210 140, 310 40, 230 40, 180 90))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-2: 3 points outside a polygon [dim(0){A.2P.Int = B.A.Ext}]</desc>
+ <a>
+ MULTIPOINT(20 80, 110 160, 20 160)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-3-1: one of 3 points on the closing point of the boundary of a polygon [dim(0){A.3P1.Int = B.A.Bdy.CP}]</desc>
+ <a>
+ MULTIPOINT(20 80, 60 120, 20 160)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-3-2: one of 3 points on the boundary of a polygon at a non-vertex [dim(0){A.3P3 = B.A.Bdy.NV}]</desc>
+ <a>
+ MULTIPOINT(10 80, 110 170, 110 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-3-3: one of 3 points on the boundary of a polygon at a vertex [dim(0){A.3P1.Int = B.A.Bdy.V}]</desc>
+ <a>
+ MULTIPOINT(10 80, 110 170, 160 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-3-4: 3 of the 5 points on the boundary of a polygon [dim(0){A.5P2.Int = B.A.Bdy.CP}, dim(0){A.5P3.Int = B.A.Bdy.NV}, dim(0){A.5P4.Int = B.A.Bdy.V}]</desc>
+ <a>
+ MULTIPOINT(20 120, 60 120, 110 120, 160 120, 200 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F00FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-3-5: all 3 points on the boundary of a polygon [dim(0){A.3P1.Int = B.A.Bdy.CP}, dim(0){A.3P2.Int = B.A.Bdy.NV}, dim(0){A.3P3.Int = B.A.Bdy.V}]</desc>
+ <a>
+ MULTIPOINT(60 120, 110 120, 160 120)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-3-6: all 4 points on the boundary of a polygon [dim(0){A.4P = B.A.Bdy}]</desc>
+ <a>
+ MULTIPOINT(60 120, 160 120, 160 40, 60 40)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-4-1: 1 point outside a polygon, 1 point on the boundary and 1 point inside [dim(0){A.3P1.Int = B.A.Ext}, dim(0){A.3P2.Int = B.A.Bdy.CP}, dim(0){A.3P3.Int = B.A.Int}]</desc>
+ <a>
+ MULTIPOINT(20 150, 60 120, 110 80)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-4-2: 1 point outside a polygon, 1 point on the boundary and 1 point inside [dim(0){A.3P1.Int = B.A.Ext}, dim(0){A.3P2.Int = B.A.Bdy.V}, dim(0){A.3P3.Int = B.A.Int}]</desc>
+ <a>
+ MULTIPOINT(110 80, 160 120, 200 160)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-4-3: 1 point outside a polygon, 1 point on the boundary and 1 point inside [dim(0){A.3P1.Int = B.A.Ext}, dim(0){A.3P2.Int = B.A.Bdy.NV}, dim(0){A.3P3.Int = B.A.Int}]</desc>
+ <a>
+ MULTIPOINT(110 80, 110 120, 110 160)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-4-4: 1 point outside a polygon, 1 point inside [dim(0){A.2P1.Int = B.A.Ext}, dim(0){A.2P2.Int = B.A.Int}]</desc>
+ <a>
+ MULTIPOINT(110 170, 110 80)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-4-5: 1 point outside a polygon, 2 points on the boundary and 1 point inside [dim(0){A.4P1.Int = B.A.Ext}, dim(0){A.4P2.Int = B.A.Bdy.CP}, dim(0){A.4P3.Int = B.A.Bdy.V}, dim(0){A.4P4.Int = B.A.Int}]</desc>
+ <a>
+ MULTIPOINT(60 120, 160 120, 110 80, 110 170)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="000FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-5-1: 2 points within a polygon [dim(0){A.2P.Int = B.A.Int]</desc>
+ <a>
+ MULTIPOINT(90 80, 130 80)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/A-5-2: 1 point on the boundary and 1 point inside a polygon [dim(0){A.2P1.Int = B.A.Bdy.CP}, dim(0){A.2P2.Int = B.A.Int}]</desc>
+ <a>
+ MULTIPOINT(60 120, 160 120, 110 80)
+ </a>
+ <b>
+ POLYGON(
+ (60 120, 60 40, 160 40, 160 120, 60 120))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="00FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/Ah-2-1: 3 points outside a polygon [dim(0){A.3P.Int = B.Ah.Ext}]</desc>
+ <a>
+ MULTIPOINT(40 170, 40 90, 130 170)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/Ah-2-2: 2 points outside a polygon and 1 point inside the hole of the polygon [dim(0){A.3P1.Int = B.Ah.Ext}, dim(0){A.3P2.Int = B.Ah.Ext}, dim(0){A.3P3.Int = B.Ah.Ext.h}]</desc>
+ <a>
+ MULTIPOINT(90 170, 280 170, 190 90)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/Ah-2-3: all 3 points in polygon's hole [dim(0){A.3P.Int = B.Ah.Ext.h}]</desc>
+ <a>
+ MULTIPOINT(190 110, 150 70, 230 70)
+ </a>
+ <b>
+ POLYGON(
+ (190 190, 360 20, 20 20, 190 190),
+ (280 50, 100 50, 190 140, 280 50))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/mA-3-1: a point on the touching point of two polygons [dim(0){A.P.Int = B.2A.Bdy}]</desc>
+ <a>
+ POINT(100 100)
+ </a>
+ <b>
+ MULTIPOLYGON(
+ (
+ (20 100, 20 20, 100 20, 100 100, 20 100)),
+ (
+ (100 180, 100 100, 180 100, 180 180, 100 180)))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/mA-3-2: a point on the boundary of one of the 2 polygons [dim(0){A.P.Int = B.2A1.Bdy.CP}]</desc>
+ <a>
+ POINT(20 100)
+ </a>
+ <b>
+ MULTIPOLYGON(
+ (
+ (20 100, 20 20, 100 20, 100 100, 20 100)),
+ (
+ (100 180, 100 100, 180 100, 180 180, 100 180)))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/mA-3-3: a point on the boundary of one of the 2 polygons [dim(0){A.P.Int = B.2A1.Bdy.V}]</desc>
+ <a>
+ POINT(60 100)
+ </a>
+ <b>
+ MULTIPOLYGON(
+ (
+ (20 100, 20 20, 100 20, 100 100, 20 100)),
+ (
+ (100 180, 100 100, 180 100, 180 180, 100 180)))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/mA-3-4: a point touching a polygon's boundary where the boundaries touch at a point [dim(0){A.P.Int = B.2A.Bdy.TP}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ MULTIPOLYGON(
+ (
+ (110 110, 20 200, 200 200, 110 110),
+ (110 110, 80 180, 140 180, 110 110)),
+ (
+ (110 110, 20 20, 200 20, 110 110),
+ (110 110, 80 40, 140 40, 110 110)))
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF212">true</op>
+ </test>
+</case>
+
</run>
\ No newline at end of file
diff --git a/test/validate/TestRelatePL.xml b/test/validate/TestRelatePL.xml
index 57b2e77..b732216 100644
--- a/test/validate/TestRelatePL.xml
+++ b/test/validate/TestRelatePL.xml
@@ -1,1283 +1,1283 @@
<run>
<precisionModel type="FLOATING"/>
-
-<case>
-<desc>P/L-2: a point and a line disjoint [dim(0){A.P.Int = B.L.Ext}]</desc>
- <a>
- POINT(110 200)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/L-3-1: a point touching the start point of a line [dim(0){A.P.Int = B.L.Bdy.SP}]</desc>
- <a>
- POINT(90 80)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/L-3-2: a point touching the end point of a line [dim(0){A.P.Int = B.L.Bdy.EP}]</desc>
- <a>
- POINT(340 240)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/L-5-1: a point on the line at a non-vertex [dim(0){A.P.Int = B.L.Int.NV}]</desc>
- <a>
- POINT(230 150)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/L-5-2: a point on the line at a vertex [dim(0){A.P.Int = B.L.Int.V}]</desc>
- <a>
- POINT(160 150)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/LR-2-1: a point outside a LinearRing [dim(0){A.P.Int = B.LR.Ext}]</desc>
- <a>
- POINT(90 150)
- </a>
- <b>
- LINESTRING(150 150, 20 20, 280 20, 150 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/LR-2-2: a point inside a LinearRing [dim(0){A.P.Int = B.LR.Ext}]</desc>
- <a>
- POINT(150 80)
- </a>
- <b>
- LINESTRING(150 150, 20 20, 280 20, 150 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/LR-5-1: a point on the closing point of a LinearRing [dim(0){A.P.Int = B.LR.Int.CP}]</desc>
- <a>
- POINT(150 150)
- </a>
- <b>
- LINESTRING(150 150, 20 20, 280 20, 150 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/LR-5-2: a point on a LinearRing at a non-vertex [dim(0){A.P.Int = B.L.Int.NV}]</desc>
- <a>
- POINT(100 20)
- </a>
- <b>
- LINESTRING(150 150, 20 20, 280 20, 150 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/LR-5-3: a point on a LinearRing at a vertex [dim(0){A.P.Int = B.L.Int.V}]</desc>
- <a>
- POINT(20 20)
- </a>
- <b>
- LINESTRING(150 150, 20 20, 280 20, 150 150)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.1-3-1: a point on a non-simple LineString's end point [dim(0){A.P.Int = B.nsL.Bdy.EP}]</desc>
- <a>
- POINT(220 220)
- </a>
- <b>
- LINESTRING(110 110, 220 20, 20 20, 110 110, 220 220)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.1-5-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 220 20, 20 20, 110 110, 220 220)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.1-5-2: a point a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 220 20, 20 20, 220 220)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.1-5-3: a point on a non-simple LineString's interior at a non-vertex [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
- <a>
- POINT(110 20)
- </a>
- <b>
- LINESTRING(110 110, 220 20, 20 20, 220 220)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.1-5-4: a point on a non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
- <a>
- POINT(220 20)
- </a>
- <b>
- LINESTRING(110 110, 220 20, 20 20, 220 220)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.2-5-2: a point on a non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
- <a>
- POINT(110 20)
- </a>
- <b>
- LINESTRING(220 220, 20 20, 220 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.2-5-3: a point on a non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
- <a>
- POINT(20 20)
- </a>
- <b>
- LINESTRING(220 220, 20 20, 220 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.2-5-4: a point on a non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
- <a>
- POINT(20 110)
- </a>
- <b>
- LINESTRING(20 200, 20 20, 110 20, 20 110, 110 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-3-1: a point on a non-simple LineString's start point [dim(0){A.P.Int = B.nsL.Bdy.SP}]</desc>
- <a>
- POINT(20 200)
- </a>
- <b>
- LINESTRING(20 200, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-1: a point on a non-simple LineString's interior at a non-vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 200 20, 140 20, 140 80, 80 140, 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-2: a point on a non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-3: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
- <a>
- POINT(80 140)
- </a>
- <b>
- LINESTRING(20 200, 110 110, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-4: a point on a non-simple LineString's interior at a two-vertex point with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vo}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 110 110, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-5: a point on a non-simple LineString's interior at a vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vo}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-6: a point on a non-simple LineString's interior at a two-vertex point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 110 110, 200 20, 20 20, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-7: a point on a non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 200 20, 20 20, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.3-5-8: a point on a non-simple LineString's interior at a two-vertex point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 110 110, 20 20, 200 20, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-1: a point on a non-simple LineString's start point with crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 110 110, 200 20, 140 20, 140 80, 110 110, 80 140,
- 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-2: a point on a non-simple LineString's start point with crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-3:a point on a non-simple LineString's start point with crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 200 20, 140 20, 140 80, 80 140, 20 140)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-4: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-5: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 200 20, 20 20, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-6: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-7: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 110 110, 20 20, 200 20, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.4-3-8: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 110 200, 20 200, 200 20, 200 110, 110 110, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.5-3-1: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 110 110, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.5-3-2: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.5-3-3: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.5-3-4: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 110 110, 200 20, 20 20, 110 110, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.5-3-5: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 20 110, 110 110, 20 200, 110 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.6-3-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 160)
- </a>
- <b>
- LINESTRING(110 160, 200 250, 110 250, 110 160, 110 110, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.6-3-2: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(110 160)
- </a>
- <b>
- LINESTRING(110 160, 200 250, 110 250, 110 110, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.6-3-3: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 160, 200 250, 110 250, 110 160, 110 110, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.6-3-4: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 160, 200 250, 110 250, 110 160, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.7-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.7-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.7-5-3: a point on a closed non-simple LineString's interior at a non-vertex [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
- <a>
- POINT(140 200)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.7-5-4: a point on a closed non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
- <a>
- POINT(110 200)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 20 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.8-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 200 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.8-5-2: a point on the interior (at a non-vertex) of a closed non-simple LineString [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
- <a>
- POINT(140 200)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 200 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.8-5-3: a point on a closed non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
- <a>
- POINT(110 200)
- </a>
- <b>
- LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 200 20, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.9-3-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 20 130, 20 200, 90 130, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.9-5-1: a point on a non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(90 130, 20 130, 20 200, 90 130, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.10-3-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 20 130, 20 200, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.10-5-1: a point on a non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(90 130, 20 130, 20 200, 200 20, 20 20, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.11-3-1: a point on a closed non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 90 130, 20 200, 20 130, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.11-5-1: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 90 130, 20 200, 20 130, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.12-3-1: a point on a closed non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.12-5-1: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.13-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 20 130, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 200 130,
- 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.13-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 20 130, 20 200, 200 20, 20 20, 200 200, 200 130, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.14-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 80 200, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 140 200,
- 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.14-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 110, 80 200, 20 200, 200 20, 20 20, 200 200, 140 200, 110 110)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.15-5-1: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 20 20, 200 20, 20 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.15-5-2: a point on a closed non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 110 110, 20 20, 200 20, 110 110, 20 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.15-5-3: a point on a closed non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(200 200, 110 110, 200 20, 20 20, 110 110, 20 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.16-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 20 130, 20 200, 90 130, 110 110, 200 20, 20 20, 110 110, 200 200,
- 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.16-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 20 130, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.17-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 90 200, 20 200, 90 130, 110 110, 200 20, 20 20, 110 110, 200 200,
- 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.17-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 90 200, 20 200, 200 20, 20 20, 200 200, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.17-5-3: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 90 200, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.17-5-4: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
- <a>
- POINT(90 130)
- </a>
- <b>
- LINESTRING(90 130, 90 200, 20 200, 200 20, 20 20, 200 200, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.17-5-5: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(90 130, 90 200, 20 200, 200 20, 20 20, 200 200, 90 130)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.18-5-1: a point on a non-simple LineString's start point with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb)}]</desc>
- <a>
- POINT(110 200)
- </a>
- <b>
- LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.18-5-2: a point on a non-simple LineString's interior at a non-vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
- <a>
- POINT(110 150)
- </a>
- <b>
- LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.18-5-3: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.19-5-1: a point on a non-simple LineString's closing point with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.CPo}]</desc>
- <a>
- POINT(110 200)
- </a>
- <b>
- LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.19-5-2: a point on a non-simple LineString's interior at a non-vertex overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
- <a>
- POINT(110 150)
- </a>
- <b>
- LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.19-5-3: a point on a non-simple LineString interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.20-5-1: a point on a non-simple LineString's interior at a non-vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
- <a>
- POINT(110 150)
- </a>
- <b>
- LINESTRING(20 200, 110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsL.20-5-2: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
- <a>
- POINT(110 110)
- </a>
- <b>
- LINESTRING(20 200, 110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/nsl.20-5-3: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
- <a>
- POINT(110 200)
- </a>
- <b>
- LINESTRING(20 200, 110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-2-1: MultiPoint and a line disjoint (points on one side of the line) [dim(0){A.3P.Int = B.L.Ext}]</desc>
- <a>
- MULTIPOINT(50 250, 90 220, 130 190)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-2-2: MultiPoint and a line disjoint (points over the line but no intersection) [dim(0){A.3P.Int = B.L.Ext}]</desc>
- <a>
- MULTIPOINT(180 180, 230 130, 280 80)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-3-1: one of the points intersecting the start point of a line [dim(0){A.3P2.Int = B.L.Bdy.SP}]</desc>
- <a>
- MULTIPOINT(50 120, 90 80, 130 40)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F00FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-3-2: one of the points intersecting the end point of a line [dim(0){A.3P2 = B.L.Bdy.EP}]</desc>
- <a>
- MULTIPOINT(300 280, 340 240, 380 200)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="F00FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-4-1: one of the points intersecting the interior of a line at a non-vertex (points on one side of the line) [dim(0){A.3P1.Int = B.L.Int.NV]</desc>
- <a>
- MULTIPOINT(230 150, 260 120, 290 90)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-4-2: one of the points intersecting the interior of a line at a non-vertex (points over the line) [dim(0){A.3P2.Int = B.L.Int.NV]</desc>
- <a>
- MULTIPOINT(200 190, 240 150, 270 110)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-4-3: one of the points intersecting the interior of a line at a vertex (points on one side of the line) [dim(0){A.3P1.Int = B.L.Int.V]</desc>
- <a>
- MULTIPOINT(160 150, 190 120, 220 90)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-4-4: one of the points intersecting the interior of a line at a vertex (points over the line) [dim(0){A.3P2.Int = B.L.Int.V]</desc>
- <a>
- MULTIPOINT(120 190, 160 150, 200 110)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-1: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Bdy.EP}]</desc>
- <a>
- MULTIPOINT(90 80, 160 150, 340 240)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="00FFFF1F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-2: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.V}]</desc>
- <a>
- MULTIPOINT(90 80, 160 150, 300 150)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-3: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
- <a>
- MULTIPOINT(90 80, 160 150, 240 150)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-4: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.NV}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
- <a>
- MULTIPOINT(90 80, 130 120, 210 150)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-5: all the points on a line [dim(0){A.3P1.Int = B.L.Int.NV}, dim(0){A.3P2.Int = B.L.Int.NV}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
- <a>
- MULTIPOINT(130 120, 210 150, 340 200)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-6: all the points on a line [dim(0){A.3P1.Int = B.L.Int.V}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
- <a>
- MULTIPOINT(160 150, 240 150, 340 210)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-7: all the points on a line [dim(0){A.3P1.Int = B.L.Int.V}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.V}]</desc>
- <a>
- MULTIPOINT(160 150, 300 150, 340 150)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/L-5-8: all the points on a line [dim(0){A.3P1.Int = B.L.Int.V}, dim(0){A.3P2.Int = B.L.Int.NV}, dim(0){A.3P3.Int = B.Bdy.EP}]</desc>
- <a>
- MULTIPOINT(160 150, 240 150, 340 240)
- </a>
- <b>
- LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
- </test>
-</case>
-
+
+<case>
+<desc>P/L-2: a point and a line disjoint [dim(0){A.P.Int = B.L.Ext}]</desc>
+ <a>
+ POINT(110 200)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/L-3-1: a point touching the start point of a line [dim(0){A.P.Int = B.L.Bdy.SP}]</desc>
+ <a>
+ POINT(90 80)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/L-3-2: a point touching the end point of a line [dim(0){A.P.Int = B.L.Bdy.EP}]</desc>
+ <a>
+ POINT(340 240)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/L-5-1: a point on the line at a non-vertex [dim(0){A.P.Int = B.L.Int.NV}]</desc>
+ <a>
+ POINT(230 150)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/L-5-2: a point on the line at a vertex [dim(0){A.P.Int = B.L.Int.V}]</desc>
+ <a>
+ POINT(160 150)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/LR-2-1: a point outside a LinearRing [dim(0){A.P.Int = B.LR.Ext}]</desc>
+ <a>
+ POINT(90 150)
+ </a>
+ <b>
+ LINESTRING(150 150, 20 20, 280 20, 150 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/LR-2-2: a point inside a LinearRing [dim(0){A.P.Int = B.LR.Ext}]</desc>
+ <a>
+ POINT(150 80)
+ </a>
+ <b>
+ LINESTRING(150 150, 20 20, 280 20, 150 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/LR-5-1: a point on the closing point of a LinearRing [dim(0){A.P.Int = B.LR.Int.CP}]</desc>
+ <a>
+ POINT(150 150)
+ </a>
+ <b>
+ LINESTRING(150 150, 20 20, 280 20, 150 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/LR-5-2: a point on a LinearRing at a non-vertex [dim(0){A.P.Int = B.L.Int.NV}]</desc>
+ <a>
+ POINT(100 20)
+ </a>
+ <b>
+ LINESTRING(150 150, 20 20, 280 20, 150 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/LR-5-3: a point on a LinearRing at a vertex [dim(0){A.P.Int = B.L.Int.V}]</desc>
+ <a>
+ POINT(20 20)
+ </a>
+ <b>
+ LINESTRING(150 150, 20 20, 280 20, 150 150)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.1-3-1: a point on a non-simple LineString's end point [dim(0){A.P.Int = B.nsL.Bdy.EP}]</desc>
+ <a>
+ POINT(220 220)
+ </a>
+ <b>
+ LINESTRING(110 110, 220 20, 20 20, 110 110, 220 220)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.1-5-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 220 20, 20 20, 110 110, 220 220)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.1-5-2: a point a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 220 20, 20 20, 220 220)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.1-5-3: a point on a non-simple LineString's interior at a non-vertex [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
+ <a>
+ POINT(110 20)
+ </a>
+ <b>
+ LINESTRING(110 110, 220 20, 20 20, 220 220)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.1-5-4: a point on a non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
+ <a>
+ POINT(220 20)
+ </a>
+ <b>
+ LINESTRING(110 110, 220 20, 20 20, 220 220)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.2-5-2: a point on a non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
+ <a>
+ POINT(110 20)
+ </a>
+ <b>
+ LINESTRING(220 220, 20 20, 220 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.2-5-3: a point on a non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
+ <a>
+ POINT(20 20)
+ </a>
+ <b>
+ LINESTRING(220 220, 20 20, 220 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.2-5-4: a point on a non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
+ <a>
+ POINT(20 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 20 20, 110 20, 20 110, 110 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-3-1: a point on a non-simple LineString's start point [dim(0){A.P.Int = B.nsL.Bdy.SP}]</desc>
+ <a>
+ POINT(20 200)
+ </a>
+ <b>
+ LINESTRING(20 200, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-1: a point on a non-simple LineString's interior at a non-vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 200 20, 140 20, 140 80, 80 140, 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-2: a point on a non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-3: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
+ <a>
+ POINT(80 140)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 110, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-4: a point on a non-simple LineString's interior at a two-vertex point with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vo}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 110, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-5: a point on a non-simple LineString's interior at a vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vo}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-6: a point on a non-simple LineString's interior at a two-vertex point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 110, 200 20, 20 20, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-7: a point on a non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 200 20, 20 20, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.3-5-8: a point on a non-simple LineString's interior at a two-vertex point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 110, 20 20, 200 20, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-1: a point on a non-simple LineString's start point with crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 110 110, 200 20, 140 20, 140 80, 110 110, 80 140,
+ 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-2: a point on a non-simple LineString's start point with crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 200 20, 140 20, 140 80, 110 110, 80 140, 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-3:a point on a non-simple LineString's start point with crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 200 20, 140 20, 140 80, 80 140, 20 140)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-4: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-5: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 200 20, 20 20, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-6: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-7: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 110 110, 20 20, 200 20, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.4-3-8: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 110 200, 20 200, 200 20, 200 110, 110 110, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.5-3-1: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 110 110, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.5-3-2: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 110 110, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.5-3-3: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.5-3-4: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 110 110, 200 20, 20 20, 110 110, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.5-3-5: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 20 110, 110 110, 20 200, 110 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.6-3-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 160)
+ </a>
+ <b>
+ LINESTRING(110 160, 200 250, 110 250, 110 160, 110 110, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.6-3-2: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(110 160)
+ </a>
+ <b>
+ LINESTRING(110 160, 200 250, 110 250, 110 110, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.6-3-3: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 160, 200 250, 110 250, 110 160, 110 110, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.6-3-4: a point on a non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 160, 200 250, 110 250, 110 160, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.7-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.7-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.7-5-3: a point on a closed non-simple LineString's interior at a non-vertex [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
+ <a>
+ POINT(140 200)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.7-5-4: a point on a closed non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
+ <a>
+ POINT(110 200)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 20 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.8-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 200 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.8-5-2: a point on the interior (at a non-vertex) of a closed non-simple LineString [dim(0){A.P.Int = B.nsL.Int.NV}]</desc>
+ <a>
+ POINT(140 200)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 200 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.8-5-3: a point on a closed non-simple LineString's interior at a vertex [dim(0){A.P.Int = B.nsL.Int.V}]</desc>
+ <a>
+ POINT(110 200)
+ </a>
+ <b>
+ LINESTRING(110 110, 200 200, 110 200, 110 110, 110 20, 200 20, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.9-3-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 20 130, 20 200, 90 130, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.9-5-1: a point on a non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(90 130, 20 130, 20 200, 90 130, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.10-3-1: a point on a non-simple LineString's start point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 20 130, 20 200, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.10-5-1: a point on a non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(90 130, 20 130, 20 200, 200 20, 20 20, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.11-3-1: a point on a closed non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.EPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 90 130, 20 200, 20 130, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.11-5-1: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 90 130, 20 200, 20 130, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.12-3-1: a point on a closed non-simple LineString's end point with crossing line segments [dim(0){A.P.Int = B.nsL.Bdy.SPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.12-5-1: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 20 200, 20 130, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.13-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 20 130, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 200 130,
+ 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.13-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 20 130, 20 200, 200 20, 20 20, 200 200, 200 130, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.14-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 80 200, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 140 200,
+ 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.14-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 110, 80 200, 20 200, 200 20, 20 20, 200 200, 140 200, 110 110)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.15-5-1: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 20 20, 200 20, 20 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.15-5-2: a point on a closed non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 110 110, 20 20, 200 20, 110 110, 20 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.15-5-3: a point on a closed non-simple LineString's interior at a vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.Vx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(200 200, 110 110, 200 20, 20 20, 110 110, 20 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.16-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 20 130, 20 200, 90 130, 110 110, 200 20, 20 20, 110 110, 200 200,
+ 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.16-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 20 130, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.17-5-1: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 90 200, 20 200, 90 130, 110 110, 200 20, 20 20, 110 110, 200 200,
+ 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.17-5-2: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 90 200, 20 200, 200 20, 20 20, 200 200, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.17-5-3: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 90 200, 20 200, 110 110, 200 20, 20 20, 110 110, 200 200, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.17-5-4: a point on a closed non-simple LineString's closing point with crossing line segments [dim(0){A.P.Int = B.nsL.Int.CPx}]</desc>
+ <a>
+ POINT(90 130)
+ </a>
+ <b>
+ LINESTRING(90 130, 90 200, 20 200, 200 20, 20 20, 200 200, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.17-5-5: a point on a closed non-simple LineString's interior at a non-vertex with crossing line segments [dim(0){A.P.Int = B.nsL.Int.NVx}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(90 130, 90 200, 20 200, 200 20, 20 20, 200 200, 90 130)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.18-5-1: a point on a non-simple LineString's start point with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Bdy.SPb)}]</desc>
+ <a>
+ POINT(110 200)
+ </a>
+ <b>
+ LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F0FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.18-5-2: a point on a non-simple LineString's interior at a non-vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
+ <a>
+ POINT(110 150)
+ </a>
+ <b>
+ LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.18-5-3: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.19-5-1: a point on a non-simple LineString's closing point with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.CPo}]</desc>
+ <a>
+ POINT(110 200)
+ </a>
+ <b>
+ LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.19-5-2: a point on a non-simple LineString's interior at a non-vertex overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
+ <a>
+ POINT(110 150)
+ </a>
+ <b>
+ LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.19-5-3: a point on a non-simple LineString interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(110 200, 110 110, 20 20, 200 20, 110 110, 110 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.20-5-1: a point on a non-simple LineString's interior at a non-vertex with overlapping line segments [dim(0){A.P.Int = B.nsL.Int.NVo}]</desc>
+ <a>
+ POINT(110 150)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsL.20-5-2: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
+ <a>
+ POINT(110 110)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/nsl.20-5-3: a point on a non-simple LineString's interior at a vertex with both crossing and overlapping line segments [dim(0){A.P.Int = B.nsL.Int.Vb}]</desc>
+ <a>
+ POINT(110 200)
+ </a>
+ <b>
+ LINESTRING(20 200, 110 200, 110 110, 20 20, 200 20, 110 110, 110 200, 200 200)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-2-1: MultiPoint and a line disjoint (points on one side of the line) [dim(0){A.3P.Int = B.L.Ext}]</desc>
+ <a>
+ MULTIPOINT(50 250, 90 220, 130 190)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-2-2: MultiPoint and a line disjoint (points over the line but no intersection) [dim(0){A.3P.Int = B.L.Ext}]</desc>
+ <a>
+ MULTIPOINT(180 180, 230 130, 280 80)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-3-1: one of the points intersecting the start point of a line [dim(0){A.3P2.Int = B.L.Bdy.SP}]</desc>
+ <a>
+ MULTIPOINT(50 120, 90 80, 130 40)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F00FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-3-2: one of the points intersecting the end point of a line [dim(0){A.3P2 = B.L.Bdy.EP}]</desc>
+ <a>
+ MULTIPOINT(300 280, 340 240, 380 200)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="F00FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-4-1: one of the points intersecting the interior of a line at a non-vertex (points on one side of the line) [dim(0){A.3P1.Int = B.L.Int.NV]</desc>
+ <a>
+ MULTIPOINT(230 150, 260 120, 290 90)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-4-2: one of the points intersecting the interior of a line at a non-vertex (points over the line) [dim(0){A.3P2.Int = B.L.Int.NV]</desc>
+ <a>
+ MULTIPOINT(200 190, 240 150, 270 110)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-4-3: one of the points intersecting the interior of a line at a vertex (points on one side of the line) [dim(0){A.3P1.Int = B.L.Int.V]</desc>
+ <a>
+ MULTIPOINT(160 150, 190 120, 220 90)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-4-4: one of the points intersecting the interior of a line at a vertex (points over the line) [dim(0){A.3P2.Int = B.L.Int.V]</desc>
+ <a>
+ MULTIPOINT(120 190, 160 150, 200 110)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-1: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Bdy.EP}]</desc>
+ <a>
+ MULTIPOINT(90 80, 160 150, 340 240)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="00FFFF1F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-2: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.V}]</desc>
+ <a>
+ MULTIPOINT(90 80, 160 150, 300 150)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-3: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
+ <a>
+ MULTIPOINT(90 80, 160 150, 240 150)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-4: all the points on a line [dim(0){A.3P1.Int = B.L.Bdy.SP}, dim(0){A.3P2.Int = B.L.Int.NV}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
+ <a>
+ MULTIPOINT(90 80, 130 120, 210 150)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-5: all the points on a line [dim(0){A.3P1.Int = B.L.Int.NV}, dim(0){A.3P2.Int = B.L.Int.NV}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
+ <a>
+ MULTIPOINT(130 120, 210 150, 340 200)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-6: all the points on a line [dim(0){A.3P1.Int = B.L.Int.V}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.NV}]</desc>
+ <a>
+ MULTIPOINT(160 150, 240 150, 340 210)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-7: all the points on a line [dim(0){A.3P1.Int = B.L.Int.V}, dim(0){A.3P2.Int = B.L.Int.V}, dim(0){A.3P3.Int = B.Int.V}]</desc>
+ <a>
+ MULTIPOINT(160 150, 300 150, 340 150)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF102">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/L-5-8: all the points on a line [dim(0){A.3P1.Int = B.L.Int.V}, dim(0){A.3P2.Int = B.L.Int.NV}, dim(0){A.3P3.Int = B.Bdy.EP}]</desc>
+ <a>
+ MULTIPOINT(160 150, 240 150, 340 240)
+ </a>
+ <b>
+ LINESTRING(90 80, 160 150, 300 150, 340 150, 340 240)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="00FFFF102">true</op>
+ </test>
+</case>
+
</run>
\ No newline at end of file
diff --git a/test/validate/TestRelatePP.xml b/test/validate/TestRelatePP.xml
index 47360d2..67b14e9 100644
--- a/test/validate/TestRelatePP.xml
+++ b/test/validate/TestRelatePP.xml
@@ -1,173 +1,173 @@
<run>
<precisionModel type="FLOATING"/>
-
-<case>
-<desc>P/P: same point [dim(0){A.P.Int = B.P.Int}]</desc>
- <a>
- POINT(20 20)
- </a>
- <b>
- POINT(20 20)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/P: different point [dim(0){A.P.Int = B.P.Ext}]</desc>
- <a>
- POINT(20 20)
- </a>
- <b>
- POINT(40 60)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF0F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/mP: different points [dim(0){A.P.Int = B.3P.Ext}]</desc>
- <a>
- POINT(40 40)
- </a>
- <b>
- MULTIPOINT(20 20, 80 80, 20 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF0F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>P/mP: point A within one of B points [dim(0){A.P.Int = B.3P1.Int}]</desc>
- <a>
- POINT(20 20)
- </a>
- <b>
- MULTIPOINT(20 20, 80 80, 20 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFF0F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-1-1: same points [dim(0){A.3P1.Int = B.3P1.Int}, dim(0){A.3P2.Int = B.3P2.Int}, dim(0){A.3P3.Int = B.3P3.Int}]</desc>
- <a>
- MULTIPOINT(40 40, 80 60, 120 100)
- </a>
- <b>
- MULTIPOINT(40 40, 80 60, 120 100)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-1-2: same but different sequence of points [dim(0){A.3P1.Int = B.3P1.Int}, dim(0){A.3P1.Int = B.3P3.Int}, dim(0){A.3P3.Int = B.3P2.Int}]</desc>
- <a>
- MULTIPOINT(40 40, 80 60, 120 100)
- </a>
- <b>
- MULTIPOINT(40 40, 120 100, 80 60)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-2: different points [dim(0){A.4P.Int = B.4P.Ext}]</desc>
- <a>
- MULTIPOINT(40 40, 60 100, 100 60, 120 120)
- </a>
- <b>
- MULTIPOINT(20 120, 60 60, 100 100, 140 40)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="FF0FFF0F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-5-1: same points [dim(0){A.4P.Int = B.4P.Int}]</desc>
- <a>
- MULTIPOINT(20 20, 80 70, 140 120, 200 170)
- </a>
- <b>
- MULTIPOINT(20 20, 80 70, 140 120, 200 170)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-5-2: same points but different sequence [dim(0){A.4P.Int = B.4P.Int}]</desc>
- <a>
- MULTIPOINT(20 20, 140 120, 80 70, 200 170)
- </a>
- <b>
- MULTIPOINT(80 70, 20 20, 200 170, 140 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-5-3: some points same [dim(0){A.4P2.Int = B.2P1.Int}, dim(0){A.4P3.Int = B.2P2.Int}]</desc>
- <a>
- MULTIPOINT(20 20, 80 70, 140 120, 200 170)
- </a>
- <b>
- MULTIPOINT(80 70, 140 120)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-5-4: some points same, in a different sequence [dim(0){A.4P1.Int = B.2P2.Int}, dim(0){A.4P4.Int = B.2P1.Int}]</desc>
- <a>
- MULTIPOINT(80 70, 20 20, 200 170, 140 120)
- </a>
- <b>
- MULTIPOINT(140 120, 80 70)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFFFF2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-6-1: some points same, some different [dim(0){A.4P4.Int = B.3P2.Int}]</desc>
- <a>
- MULTIPOINT(80 70, 20 20, 200 170, 140 120)
- </a>
- <b>
- MULTIPOINT(80 170, 140 120, 200 80)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF0F2">true</op>
- </test>
-</case>
-
-<case>
-<desc>mP/mP-6-2: dim(0){A.4P1.Int = B.4P4.Int}, dim(0){A.4P4.Int = B.4P2.Int}</desc>
- <a>
- MULTIPOINT(80 70, 20 20, 200 170, 140 120)
- </a>
- <b>
- MULTIPOINT(80 170, 140 120, 200 80, 80 70)
- </b>
- <test>
- <op name="relate" arg1="A" arg2="B" arg3="0F0FFF0F2">true</op>
- </test>
-</case>
-
+
+<case>
+<desc>P/P: same point [dim(0){A.P.Int = B.P.Int}]</desc>
+ <a>
+ POINT(20 20)
+ </a>
+ <b>
+ POINT(20 20)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/P: different point [dim(0){A.P.Int = B.P.Ext}]</desc>
+ <a>
+ POINT(20 20)
+ </a>
+ <b>
+ POINT(40 60)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF0F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/mP: different points [dim(0){A.P.Int = B.3P.Ext}]</desc>
+ <a>
+ POINT(40 40)
+ </a>
+ <b>
+ MULTIPOINT(20 20, 80 80, 20 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF0F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>P/mP: point A within one of B points [dim(0){A.P.Int = B.3P1.Int}]</desc>
+ <a>
+ POINT(20 20)
+ </a>
+ <b>
+ MULTIPOINT(20 20, 80 80, 20 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFF0F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-1-1: same points [dim(0){A.3P1.Int = B.3P1.Int}, dim(0){A.3P2.Int = B.3P2.Int}, dim(0){A.3P3.Int = B.3P3.Int}]</desc>
+ <a>
+ MULTIPOINT(40 40, 80 60, 120 100)
+ </a>
+ <b>
+ MULTIPOINT(40 40, 80 60, 120 100)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-1-2: same but different sequence of points [dim(0){A.3P1.Int = B.3P1.Int}, dim(0){A.3P1.Int = B.3P3.Int}, dim(0){A.3P3.Int = B.3P2.Int}]</desc>
+ <a>
+ MULTIPOINT(40 40, 80 60, 120 100)
+ </a>
+ <b>
+ MULTIPOINT(40 40, 120 100, 80 60)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-2: different points [dim(0){A.4P.Int = B.4P.Ext}]</desc>
+ <a>
+ MULTIPOINT(40 40, 60 100, 100 60, 120 120)
+ </a>
+ <b>
+ MULTIPOINT(20 120, 60 60, 100 100, 140 40)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="FF0FFF0F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-5-1: same points [dim(0){A.4P.Int = B.4P.Int}]</desc>
+ <a>
+ MULTIPOINT(20 20, 80 70, 140 120, 200 170)
+ </a>
+ <b>
+ MULTIPOINT(20 20, 80 70, 140 120, 200 170)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-5-2: same points but different sequence [dim(0){A.4P.Int = B.4P.Int}]</desc>
+ <a>
+ MULTIPOINT(20 20, 140 120, 80 70, 200 170)
+ </a>
+ <b>
+ MULTIPOINT(80 70, 20 20, 200 170, 140 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0FFFFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-5-3: some points same [dim(0){A.4P2.Int = B.2P1.Int}, dim(0){A.4P3.Int = B.2P2.Int}]</desc>
+ <a>
+ MULTIPOINT(20 20, 80 70, 140 120, 200 170)
+ </a>
+ <b>
+ MULTIPOINT(80 70, 140 120)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-5-4: some points same, in a different sequence [dim(0){A.4P1.Int = B.2P2.Int}, dim(0){A.4P4.Int = B.2P1.Int}]</desc>
+ <a>
+ MULTIPOINT(80 70, 20 20, 200 170, 140 120)
+ </a>
+ <b>
+ MULTIPOINT(140 120, 80 70)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFFFF2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-6-1: some points same, some different [dim(0){A.4P4.Int = B.3P2.Int}]</desc>
+ <a>
+ MULTIPOINT(80 70, 20 20, 200 170, 140 120)
+ </a>
+ <b>
+ MULTIPOINT(80 170, 140 120, 200 80)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF0F2">true</op>
+ </test>
+</case>
+
+<case>
+<desc>mP/mP-6-2: dim(0){A.4P1.Int = B.4P4.Int}, dim(0){A.4P4.Int = B.4P2.Int}</desc>
+ <a>
+ MULTIPOINT(80 70, 20 20, 200 170, 140 120)
+ </a>
+ <b>
+ MULTIPOINT(80 170, 140 120, 200 80, 80 70)
+ </b>
+ <test>
+ <op name="relate" arg1="A" arg2="B" arg3="0F0FFF0F2">true</op>
+ </test>
+</case>
+
</run>
\ No newline at end of file
diff --git a/test/vivid/TestBoundary.xml b/test/vivid/TestBoundary.xml
index f1071f0..a291c5f 100644
--- a/test/vivid/TestBoundary.xml
+++ b/test/vivid/TestBoundary.xml
@@ -141,8 +141,7 @@
</a>
<test>
<op name="getboundary" arg1="A">
- MULTILINESTRING(
- (40 60, 420 60, 420 320, 40 320, 40 60))
+ LINESTRING(40 60, 420 60, 420 320, 40 320, 40 60)
</op>
</test>
</case>
diff --git a/test/vivid/TestCentroid.xml b/test/vivid/TestCentroid.xml
index 2a25a94..d5f740d 100644
--- a/test/vivid/TestCentroid.xml
+++ b/test/vivid/TestCentroid.xml
@@ -84,7 +84,7 @@
<a> POLYGON ((0 0, 0 200, 200 200, 200 0, 0 0),
(60 180, 20 180, 20 140, 60 140, 60 180))
</a>
-<test><op name="getCentroid" arg1="A" > POINT (102 98) </op></test>
+<test><op name="getCentroid" arg1="A" > POINT (103 98) </op></test>
</case>
<case>
@@ -109,7 +109,7 @@
<a> GEOMETRYCOLLECTION (POLYGON ((0 200, 20 180, 20 140, 60 140, 200 0, 0 0, 0 200)),
POLYGON ((200 200, 0 200, 20 180, 60 180, 60 140, 200 0, 200 200)))
</a>
-<test><op name="getCentroid" arg1="A" > POINT (102 98) </op></test>
+<test><op name="getCentroid" arg1="A" > POINT (103 98) </op></test>
</case>
<case>
diff --git a/test/vivid/TestFunctionAA.xml b/test/vivid/TestFunctionAA.xml
index cf66868..4ea6cb2 100644
--- a/test/vivid/TestFunctionAA.xml
+++ b/test/vivid/TestFunctionAA.xml
@@ -335,6 +335,41 @@
</case>
<case>
+ <desc>AA - simple polygons with hole touching shell</desc>
+ <a>
+ POLYGON ((20 0, 20 160, 200 160, 200 0, 20 0))
+ </a>
+ <b>
+ POLYGON ((220 80, 0 80, 0 240, 220 240, 220 80),
+ (100 80, 120 120, 80 120, 100 80))
+ </b>
+<test>
+ <op name="intersection" arg1="A" arg2="B">
+ POLYGON ((20 80, 20 160, 200 160, 200 80, 100 80, 20 80),
+ (100 80, 120 120, 80 120, 100 80))
+ </op>
+</test>
+<test>
+ <op name="union" arg1="A" arg2="B">
+ POLYGON ((20 0, 20 80, 0 80, 0 240, 220 240, 220 80, 200 80, 200 0, 20 0))
+ </op>
+</test>
+<test>
+ <op name="difference" arg1="A" arg2="B">
+ MULTIPOLYGON (((20 0, 20 80, 100 80, 200 80, 200 0, 20 0)),
+ ((100 80, 80 120, 120 120, 100 80)))
+ </op>
+</test>
+<test>
+ <op name="symdifference" arg1="A" arg2="B">
+ MULTIPOLYGON (((20 0, 20 80, 100 80, 200 80, 200 0, 20 0)),
+ ((200 80, 200 160, 20 160, 20 80, 0 80, 0 240, 220 240, 220 80, 200 80)),
+ ((100 80, 80 120, 120 120, 100 80)))
+ </op>
+</test>
+</case>
+
+<case>
<desc>mAmA - complex polygons touching and overlapping</desc>
<a>
MULTIPOLYGON(
@@ -554,8 +589,7 @@
</b>
<test>
<op name="getboundary" arg1="A">
- MULTILINESTRING(
- (60 160, 140 160, 140 60, 60 60, 60 160))
+ LINESTRING(60 160, 140 160, 140 60, 60 60, 60 160)
</op>
</test>
<test>
diff --git a/test/vivid/TestFunctionAAPrec.xml b/test/vivid/TestFunctionAAPrec.xml
index c42e94a..841a7a9 100644
--- a/test/vivid/TestFunctionAAPrec.xml
+++ b/test/vivid/TestFunctionAAPrec.xml
@@ -781,8 +781,7 @@ GEOMETRYCOLLECTION(
</b>
<test>
<op name="getboundary" arg1="A">
- MULTILINESTRING(
- (83 33, 62 402, 68 402, 83 33))
+ LINESTRING(83 33, 62 402, 68 402, 83 33)
</op>
</test>
<test>
diff --git a/test/vivid/TestFunctionLAPrec.xml b/test/vivid/TestFunctionLAPrec.xml
index 04d8617..72e8426 100644
--- a/test/vivid/TestFunctionLAPrec.xml
+++ b/test/vivid/TestFunctionLAPrec.xml
@@ -12,8 +12,7 @@
</b>
<test>
<op name="getboundary" arg1="A">
- MULTILINESTRING(
- (95 9, 81 414, 87 414, 95 9))
+ LINESTRING(95 9, 81 414, 87 414, 95 9)
</op>
</test>
<test>
diff --git a/test/vivid/TestFunctionLLPrec.xml b/test/vivid/TestFunctionLLPrec.xml
index f13a0fe..4796658 100644
--- a/test/vivid/TestFunctionLLPrec.xml
+++ b/test/vivid/TestFunctionLLPrec.xml
@@ -1,6 +1,6 @@
<run>
<precisionModel scale="1.0" offsetx="0.0" offsety="0.0"/>
-
+
<case>
<desc>LL - narrow V</desc>
<a>
@@ -16,13 +16,13 @@
</test>
<test>
<op name="union" arg1="A" arg2="B">
- MULTILINESTRING(
- (0 10, 400 10),
- (400 10, 620 10, 400 10),
- (400 10, 0 11),
+ MULTILINESTRING(
+ (0 10, 400 10),
+ (400 10, 620 10, 400 10),
+ (400 10, 0 11),
(400 60, 400 10))
</op>
</test>
</case>
-
+
</run>
\ No newline at end of file
diff --git a/test/vivid/TestRectanglePredicate.xml b/test/vivid/TestRectanglePredicate.xml
new file mode 100644
index 0000000..64282a0
--- /dev/null
+++ b/test/vivid/TestRectanglePredicate.xml
@@ -0,0 +1,101 @@
+<run>
+ <precisionModel scale="1.0" offsetx="0.0" offsety="0.0"/>
+
+<case>
+ <desc>A disjoint</desc>
+ <a>
+ POLYGON(
+ (0 0, 80 0, 80 80, 0 80, 0 0))
+ </a>
+ <b>
+ POLYGON(
+ (100 200, 100 140, 180 140, 180 200, 100 200))
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> false </op> </test>
+<test> <op name="contains" arg1="A" arg2="B"> false </op> </test>
+</case>
+
+<case>
+ <desc>A contained in rectangle</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ POLYGON((10 10, 10 90, 90 90, 90 10, 10 10))
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+<test> <op name="contains" arg1="A" arg2="B"> true </op> </test>
+</case>
+
+<case>
+ <desc>A containing rectangle</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ POLYGON ((60 180, -100 120, -140 60, -40 20, -100 -80, 40 -20, 140 -100, 140 40, 260 160, 80 120, 60 180))
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+<test> <op name="contains" arg1="A" arg2="B"> false </op> </test>
+</case>
+
+<case>
+ <desc>mA containing rectangle</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ MULTIPOLYGON (((-60 180, -60 -60, 40 -20, 140 -100, 180 120, -20 140, -60 180)),
+ ((20 280, 0 180, 180 160, 200 280, 20 280)))
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+<test> <op name="contains" arg1="A" arg2="B"> false </op> </test>
+</case>
+
+<case>
+ <desc>L overlaps thru Y axis side</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ LINESTRING(10 10, 200 10)
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+</case>
+
+<case>
+ <desc>L overlaps thru X axis side</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ LINESTRING(10 10, 10 2000)
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+</case>
+
+<case>
+ <desc>L line intersection</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ LINESTRING( 10 10, -10 -20 )
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+</case>
+
+<case>
+ <desc>mL with one component contained</desc>
+ <a>
+ POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))
+ </a>
+ <b>
+ MULTILINESTRING( (10 10, 10 20), (200 10, 200 20) )
+ </b>
+<test> <op name="intersects" arg1="A" arg2="B"> true </op> </test>
+<test> <op name="contains" arg1="A" arg2="B"> false </op> </test>
+</case>
+
+
+</run>
diff --git a/test/vivid/TestValid.xml b/test/vivid/TestValid.xml
index e08c014..87447bf 100644
--- a/test/vivid/TestValid.xml
+++ b/test/vivid/TestValid.xml
@@ -94,7 +94,7 @@ LINESTRING (40 180, 120 120, 140 200, 140 200, 200 140, 240 200)
</case>
<case>
- <desc>A - polygon with repeatd point </desc>
+ <desc>A - polygon with repeated point </desc>
<a>POLYGON ((107 246, 107 246, 250 285, 294 137, 151 90, 15 125, 157 174, 107 246))</a>
<test>
<op name="isValid" arg1="A"> true </op>
@@ -102,6 +102,15 @@ LINESTRING (40 180, 120 120, 140 200, 140 200, 200 140, 240 200)
</case>
<case>
+ <desc>A - polygon with degenerate hole ring (A-B-A) </desc>
+ <a>POLYGON ((0 0, 0 240, 260 240, 260 0, 0 0),
+ (220 200, 40 200, 40 20, 40 200, 220 200, 220 200))</a>
+ <test>
+ <op name="isValid" arg1="A"> false </op>
+ </test>
+ </case>
+
+ <case>
<desc>mA - multipolygon with component with too few points </desc>
<a>MULTIPOLYGON ( ((100 20, 180 20, 180 100, 100 100, 100 20)),
((20 100, 100 100, 100 180, 20 180, 20 100)),
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/jts.git
More information about the Pkg-grass-devel
mailing list