jsts-rails 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/jsts-rails/version.rb +1 -1
- data/vendor/assets/javascripts/javascript.util.js +33 -1
- data/vendor/assets/javascripts/jsts-original.js +164 -1573
- data/vendor/assets/javascripts/jsts.js +197 -0
- data/vendor/assets/javascripts/jsts/algorithm/Angle.js +387 -0
- data/vendor/assets/javascripts/jsts/algorithm/BoundaryNodeRule.js +67 -0
- data/vendor/assets/javascripts/jsts/algorithm/CGAlgorithms.js +596 -0
- data/vendor/assets/javascripts/jsts/algorithm/CentralEndpointIntersector.js +118 -0
- data/vendor/assets/javascripts/jsts/algorithm/CentroidArea.js +225 -0
- data/vendor/assets/javascripts/jsts/algorithm/CentroidLine.js +85 -0
- data/vendor/assets/javascripts/jsts/algorithm/CentroidPoint.js +77 -0
- data/vendor/assets/javascripts/jsts/algorithm/ConvexHull.js +409 -0
- data/vendor/assets/javascripts/jsts/algorithm/HCoordinate.js +234 -0
- data/vendor/assets/javascripts/jsts/algorithm/LineIntersector.js +502 -0
- data/vendor/assets/javascripts/jsts/algorithm/MCPointInRing.js +124 -0
- data/vendor/assets/javascripts/jsts/algorithm/PointLocator.js +247 -0
- data/vendor/assets/javascripts/jsts/algorithm/RayCrossingCounter.js +215 -0
- data/vendor/assets/javascripts/jsts/algorithm/RobustDeterminant.js +353 -0
- data/vendor/assets/javascripts/jsts/algorithm/RobustLineIntersector.js +477 -0
- data/vendor/assets/javascripts/jsts/algorithm/distance/DiscreteHausdorffDistance.js +228 -0
- data/vendor/assets/javascripts/jsts/algorithm/distance/DistanceToPoint.js +68 -0
- data/vendor/assets/javascripts/jsts/algorithm/distance/PointPairDistance.js +104 -0
- data/vendor/assets/javascripts/jsts/algorithm/locate/PointOnGeometryLocator.js +7 -0
- data/vendor/assets/javascripts/jsts/algorithm/locate/SimplePointInAreaLocator.js +102 -0
- data/vendor/assets/javascripts/jsts/geom/Coordinate.js +158 -0
- data/vendor/assets/javascripts/jsts/geom/CoordinateArrays.js +148 -0
- data/vendor/assets/javascripts/jsts/geom/CoordinateFilter.js +29 -0
- data/vendor/assets/javascripts/jsts/geom/CoordinateList.js +157 -0
- data/vendor/assets/javascripts/jsts/geom/CoordinateSequenceFilter.js +63 -0
- data/vendor/assets/javascripts/jsts/geom/Dimension.js +137 -0
- data/vendor/assets/javascripts/jsts/geom/Envelope.js +833 -0
- data/vendor/assets/javascripts/jsts/geom/Geometry.js +1535 -0
- data/vendor/assets/javascripts/jsts/geom/GeometryCollection.js +230 -0
- data/vendor/assets/javascripts/jsts/geom/GeometryComponentFilter.js +36 -0
- data/vendor/assets/javascripts/jsts/geom/GeometryFactory.js +263 -0
- data/vendor/assets/javascripts/jsts/geom/GeometryFilter.js +29 -0
- data/vendor/assets/javascripts/jsts/geom/IntersectionMatrix.js +650 -0
- data/vendor/assets/javascripts/jsts/geom/LineSegment.js +275 -0
- data/vendor/assets/javascripts/jsts/geom/LineString.js +299 -0
- data/vendor/assets/javascripts/jsts/geom/LinearRing.js +69 -0
- data/vendor/assets/javascripts/jsts/geom/Location.js +83 -0
- data/vendor/assets/javascripts/jsts/geom/MultiLineString.js +47 -0
- data/vendor/assets/javascripts/jsts/geom/MultiPoint.js +64 -0
- data/vendor/assets/javascripts/jsts/geom/MultiPolygon.js +64 -0
- data/vendor/assets/javascripts/jsts/geom/Point.js +197 -0
- data/vendor/assets/javascripts/jsts/geom/Polygon.js +263 -0
- data/vendor/assets/javascripts/jsts/geom/PrecisionModel.js +187 -0
- data/vendor/assets/javascripts/jsts/geom/Triangle.js +313 -0
- data/vendor/assets/javascripts/jsts/geom/util/GeometryCombiner.js +143 -0
- data/vendor/assets/javascripts/jsts/geom/util/GeometryExtracter.js +76 -0
- data/vendor/assets/javascripts/jsts/geom/util/GeometryTransformer.js +295 -0
- data/vendor/assets/javascripts/jsts/geom/util/LinearComponentExtracter.js +207 -0
- data/vendor/assets/javascripts/jsts/geom/util/PointExtracter.js +67 -0
- data/vendor/assets/javascripts/jsts/geom/util/PolygonExtracter.js +71 -0
- data/vendor/assets/javascripts/jsts/geomgraph/Depth.js +145 -0
- data/vendor/assets/javascripts/jsts/geomgraph/DirectedEdge.js +270 -0
- data/vendor/assets/javascripts/jsts/geomgraph/DirectedEdgeStar.js +388 -0
- data/vendor/assets/javascripts/jsts/geomgraph/Edge.js +291 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeEnd.js +188 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeEndStar.js +322 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeIntersection.js +122 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeIntersectionList.js +146 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeList.js +111 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeNodingValidator.js +76 -0
- data/vendor/assets/javascripts/jsts/geomgraph/EdgeRing.js +230 -0
- data/vendor/assets/javascripts/jsts/geomgraph/GeometryGraph.js +469 -0
- data/vendor/assets/javascripts/jsts/geomgraph/GraphComponent.js +181 -0
- data/vendor/assets/javascripts/jsts/geomgraph/Label.js +316 -0
- data/vendor/assets/javascripts/jsts/geomgraph/Node.js +105 -0
- data/vendor/assets/javascripts/jsts/geomgraph/NodeFactory.js +22 -0
- data/vendor/assets/javascripts/jsts/geomgraph/NodeMap.js +128 -0
- data/vendor/assets/javascripts/jsts/geomgraph/PlanarGraph.js +214 -0
- data/vendor/assets/javascripts/jsts/geomgraph/Position.js +63 -0
- data/vendor/assets/javascripts/jsts/geomgraph/Quadrant.js +143 -0
- data/vendor/assets/javascripts/jsts/geomgraph/TopologyLocation.js +251 -0
- data/vendor/assets/javascripts/jsts/geomgraph/index/EdgeSetIntersector.js +47 -0
- data/vendor/assets/javascripts/jsts/geomgraph/index/SegmentIntersector.js +298 -0
- data/vendor/assets/javascripts/jsts/geomgraph/index/SimpleEdgeSetIntersector.js +107 -0
- data/vendor/assets/javascripts/jsts/geomgraph/index/SimpleMCSweepLineIntersector.js +29 -0
- data/vendor/assets/javascripts/jsts/index/ArrayListVisitor.js +37 -0
- data/vendor/assets/javascripts/jsts/index/DoubleBits.js +132 -0
- data/vendor/assets/javascripts/jsts/index/IntervalSize.js +55 -0
- data/vendor/assets/javascripts/jsts/index/ItemVisitor.js +23 -0
- data/vendor/assets/javascripts/jsts/index/SpatialIndex.js +67 -0
- data/vendor/assets/javascripts/jsts/index/bintree/Bintree.js +224 -0
- data/vendor/assets/javascripts/jsts/index/bintree/Interval.js +160 -0
- data/vendor/assets/javascripts/jsts/index/bintree/Key.js +110 -0
- data/vendor/assets/javascripts/jsts/index/bintree/Node.js +204 -0
- data/vendor/assets/javascripts/jsts/index/bintree/NodeBase.js +220 -0
- data/vendor/assets/javascripts/jsts/index/bintree/Root.js +113 -0
- data/vendor/assets/javascripts/jsts/index/chain/MonotoneChain.js +244 -0
- data/vendor/assets/javascripts/jsts/index/chain/MonotoneChainBuilder.js +106 -0
- data/vendor/assets/javascripts/jsts/index/chain/MonotoneChainOverlapAction.js +56 -0
- data/vendor/assets/javascripts/jsts/index/chain/MonotoneChainSelectAction.js +44 -0
- data/vendor/assets/javascripts/jsts/index/kdtree/KdNode.js +171 -0
- data/vendor/assets/javascripts/jsts/index/kdtree/KdTree.js +218 -0
- data/vendor/assets/javascripts/jsts/index/quadtree/Key.js +134 -0
- data/vendor/assets/javascripts/jsts/index/quadtree/Node.js +220 -0
- data/vendor/assets/javascripts/jsts/index/quadtree/NodeBase.js +330 -0
- data/vendor/assets/javascripts/jsts/index/quadtree/Quadtree.js +228 -0
- data/vendor/assets/javascripts/jsts/index/quadtree/Root.js +105 -0
- data/vendor/assets/javascripts/jsts/index/strtree/AbstractNode.js +107 -0
- data/vendor/assets/javascripts/jsts/index/strtree/AbstractSTRtree.js +594 -0
- data/vendor/assets/javascripts/jsts/index/strtree/Boundable.js +37 -0
- data/vendor/assets/javascripts/jsts/index/strtree/BoundablePair.js +0 -0
- data/vendor/assets/javascripts/jsts/index/strtree/Interval.js +94 -0
- data/vendor/assets/javascripts/jsts/index/strtree/ItemBoundable.js +60 -0
- data/vendor/assets/javascripts/jsts/index/strtree/SIRtree.js +122 -0
- data/vendor/assets/javascripts/jsts/index/strtree/STRtree.js +450 -0
- data/vendor/assets/javascripts/jsts/io/GeoJSONParser.js +471 -0
- data/vendor/assets/javascripts/jsts/io/GeoJSONReader.js +58 -0
- data/vendor/assets/javascripts/jsts/io/GeoJSONWriter.js +38 -0
- data/vendor/assets/javascripts/jsts/io/OpenLayersParser.js +245 -0
- data/vendor/assets/javascripts/jsts/io/WKTParser.js +421 -0
- data/vendor/assets/javascripts/jsts/io/WKTReader.js +68 -0
- data/vendor/assets/javascripts/jsts/io/WKTWriter.js +61 -0
- data/vendor/assets/javascripts/jsts/noding/BasicSegmentString.js +87 -0
- data/vendor/assets/javascripts/jsts/noding/FastNodingValidator.js +127 -0
- data/vendor/assets/javascripts/jsts/noding/InteriorIntersectionFinder.js +171 -0
- data/vendor/assets/javascripts/jsts/noding/IntersectionAdder.js +198 -0
- data/vendor/assets/javascripts/jsts/noding/IntersectionFinderAdder.js +79 -0
- data/vendor/assets/javascripts/jsts/noding/MCIndexNoder.js +147 -0
- data/vendor/assets/javascripts/jsts/noding/NodableSegmentString.js +35 -0
- data/vendor/assets/javascripts/jsts/noding/NodedSegmentString.js +235 -0
- data/vendor/assets/javascripts/jsts/noding/Noder.js +41 -0
- data/vendor/assets/javascripts/jsts/noding/NodingValidator.js +5 -0
- data/vendor/assets/javascripts/jsts/noding/Octant.js +84 -0
- data/vendor/assets/javascripts/jsts/noding/OrientedCoordinateArray.js +94 -0
- data/vendor/assets/javascripts/jsts/noding/ScaledNoder.js +105 -0
- data/vendor/assets/javascripts/jsts/noding/SegmentIntersector.js +45 -0
- data/vendor/assets/javascripts/jsts/noding/SegmentNode.js +70 -0
- data/vendor/assets/javascripts/jsts/noding/SegmentNodeList.js +262 -0
- data/vendor/assets/javascripts/jsts/noding/SegmentPointComparator.js +78 -0
- data/vendor/assets/javascripts/jsts/noding/SegmentString.js +61 -0
- data/vendor/assets/javascripts/jsts/noding/SinglePassNoder.js +51 -0
- data/vendor/assets/javascripts/jsts/noding/snapround/HotPixel.js +271 -0
- data/vendor/assets/javascripts/jsts/noding/snapround/MCIndexPointSnapper.js +96 -0
- data/vendor/assets/javascripts/jsts/noding/snapround/MCIndexSnapRounder.js +147 -0
- data/vendor/assets/javascripts/jsts/operation/BoundaryOp.js +166 -0
- data/vendor/assets/javascripts/jsts/operation/GeometryGraphOperation.js +90 -0
- data/vendor/assets/javascripts/jsts/operation/IsSimpleOp.js +293 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/BufferBuilder.js +317 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/BufferInputLineSimplifier.js +294 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/BufferOp.js +340 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/BufferParameters.js +328 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/BufferSubgraph.js +296 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/OffsetCurveBuilder.js +369 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/OffsetCurveSetBuilder.js +301 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/OffsetSegmentGenerator.js +777 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/OffsetSegmentString.js +109 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/RightmostEdgeFinder.js +164 -0
- data/vendor/assets/javascripts/jsts/operation/buffer/SubgraphDepthLocater.js +220 -0
- data/vendor/assets/javascripts/jsts/operation/distance/ConnectedElementLocationFilter.js +67 -0
- data/vendor/assets/javascripts/jsts/operation/distance/DistanceOp.js +506 -0
- data/vendor/assets/javascripts/jsts/operation/distance/GeometryLocation.js +102 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/LineBuilder.js +194 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/MaximalEdgeRing.js +72 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/MinimalEdgeRing.js +33 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/OverlayNodeFactory.js +26 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/OverlayOp.js +584 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/PointBuilder.js +103 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/PolygonBuilder.js +282 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/snap/GeometrySnapper.js +228 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/snap/LineStringSnapper.js +228 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/snap/SnapIfNeededOverlayOp.js +85 -0
- data/vendor/assets/javascripts/jsts/operation/overlay/snap/SnapOverlayOp.js +134 -0
- data/vendor/assets/javascripts/jsts/operation/polygonize/EdgeRing.js +259 -0
- data/vendor/assets/javascripts/jsts/operation/polygonize/PolygonizeDirectedEdge.js +94 -0
- data/vendor/assets/javascripts/jsts/operation/polygonize/PolygonizeEdge.js +31 -0
- data/vendor/assets/javascripts/jsts/operation/polygonize/PolygonizeGraph.js +507 -0
- data/vendor/assets/javascripts/jsts/operation/polygonize/Polygonizer.js +259 -0
- data/vendor/assets/javascripts/jsts/operation/relate/EdgeEndBuilder.js +140 -0
- data/vendor/assets/javascripts/jsts/operation/relate/EdgeEndBundle.js +183 -0
- data/vendor/assets/javascripts/jsts/operation/relate/EdgeEndBundleStar.js +48 -0
- data/vendor/assets/javascripts/jsts/operation/relate/RelateComputer.js +444 -0
- data/vendor/assets/javascripts/jsts/operation/relate/RelateNode.js +46 -0
- data/vendor/assets/javascripts/jsts/operation/relate/RelateNodeFactory.js +25 -0
- data/vendor/assets/javascripts/jsts/operation/relate/RelateNodeGraph.js +118 -0
- data/vendor/assets/javascripts/jsts/operation/relate/RelateOp.js +75 -0
- data/vendor/assets/javascripts/jsts/operation/union/CascadedPolygonUnion.js +319 -0
- data/vendor/assets/javascripts/jsts/operation/union/PointGeometryUnion.js +118 -0
- data/vendor/assets/javascripts/jsts/operation/union/UnaryUnionOp.js +244 -0
- data/vendor/assets/javascripts/jsts/operation/union/UnionInteracting.js +156 -0
- data/vendor/assets/javascripts/jsts/operation/valid/ConnectedInteriorTester.js +259 -0
- data/vendor/assets/javascripts/jsts/operation/valid/ConsistentAreaTester.js +127 -0
- data/vendor/assets/javascripts/jsts/operation/valid/IndexedNestedRingTester.js +89 -0
- data/vendor/assets/javascripts/jsts/operation/valid/IsValidOp.js +619 -0
- data/vendor/assets/javascripts/jsts/operation/valid/TopologyValidationError.js +199 -0
- data/vendor/assets/javascripts/jsts/planargraph/DirectedEdge.js +232 -0
- data/vendor/assets/javascripts/jsts/planargraph/DirectedEdgeStar.js +168 -0
- data/vendor/assets/javascripts/jsts/planargraph/Edge.js +124 -0
- data/vendor/assets/javascripts/jsts/planargraph/GraphComponent.js +182 -0
- data/vendor/assets/javascripts/jsts/planargraph/Node.js +127 -0
- data/vendor/assets/javascripts/jsts/planargraph/NodeMap.js +76 -0
- data/vendor/assets/javascripts/jsts/planargraph/PlanarGraph.js +246 -0
- data/vendor/assets/javascripts/jsts/simplify/LineSegmentIndex.js +101 -0
- data/vendor/assets/javascripts/jsts/triangulate/DelaunayTriangulationBuilder.js +224 -0
- data/vendor/assets/javascripts/jsts/triangulate/IncrementalDelaunayTriangulator.js +111 -0
- data/vendor/assets/javascripts/jsts/triangulate/VoronoiDiagramBuilder.js +172 -0
- data/vendor/assets/javascripts/jsts/triangulate/quadedge/LastFoundQuadEdgeLocator.js +52 -0
- data/vendor/assets/javascripts/jsts/triangulate/quadedge/QuadEdge.js +437 -0
- data/vendor/assets/javascripts/jsts/triangulate/quadedge/QuadEdgeSubdivision.js +1064 -0
- data/vendor/assets/javascripts/jsts/triangulate/quadedge/TrianglePredicate.js +350 -0
- data/vendor/assets/javascripts/jsts/triangulate/quadedge/Vertex.js +496 -0
- data/vendor/assets/javascripts/jsts/util/Assert.js +80 -0
- data/vendor/assets/javascripts/jsts/util/AssertionFailedException.js +23 -0
- data/vendor/assets/javascripts/jsts/util/UniqueCoordinateArrayFilter.js +52 -0
- metadata +204 -1
@@ -0,0 +1,102 @@
|
|
1
|
+
/* Copyright (c) 2011 by The Authors.
|
2
|
+
* Published under the LGPL 2.1 license.
|
3
|
+
* See /license-notice.txt for the full text of the license notice.
|
4
|
+
* See /license.txt for the full text of the license.
|
5
|
+
*/
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Represents the location of a point on a Geometry.
|
9
|
+
* Maintains both the actual point location
|
10
|
+
* (which may not be exact, if the point is not a vertex)
|
11
|
+
* as well as information about the component
|
12
|
+
* and segment index where the point occurs.
|
13
|
+
* Locations inside area Geometrys will not have an associated segment index,
|
14
|
+
* so in this case the segment index will have the sentinel value of
|
15
|
+
* {@link #INSIDE_AREA}.
|
16
|
+
*/
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Constructs a GeometryLocation specifying a point on a geometry, as well as
|
22
|
+
* the segment that the point is on (or {@link INSIDE_AREA} if the point is not
|
23
|
+
* on a segment).
|
24
|
+
*
|
25
|
+
* @param {Geometry}
|
26
|
+
* component the component of the geometry containing the point.
|
27
|
+
* @param {int}
|
28
|
+
* segIndex the segment index of the location, or INSIDE_AREA.
|
29
|
+
* @param {Coordinate}
|
30
|
+
* pt the coordinate of the location.
|
31
|
+
* @constructor
|
32
|
+
*/
|
33
|
+
jsts.operation.distance.GeometryLocation = function(component, segIndex, pt) {
|
34
|
+
this.component = component;
|
35
|
+
this.segIndex = segIndex;
|
36
|
+
this.pt = pt;
|
37
|
+
};
|
38
|
+
|
39
|
+
|
40
|
+
/**
|
41
|
+
* A special value of segmentIndex used for locations inside area geometries.
|
42
|
+
* These locations are not located on a segment, and thus do not have an
|
43
|
+
* associated segment index.
|
44
|
+
*
|
45
|
+
* @type {int}
|
46
|
+
*/
|
47
|
+
jsts.operation.distance.GeometryLocation.INSIDE_AREA = -1;
|
48
|
+
|
49
|
+
|
50
|
+
/**
|
51
|
+
* @type {Geometry}
|
52
|
+
*/
|
53
|
+
jsts.operation.distance.GeometryLocation.prototype.component = null;
|
54
|
+
|
55
|
+
|
56
|
+
/**
|
57
|
+
* @type {int}
|
58
|
+
*/
|
59
|
+
jsts.operation.distance.GeometryLocation.prototype.segIndex = null;
|
60
|
+
|
61
|
+
|
62
|
+
/**
|
63
|
+
* @type {Coordinate}
|
64
|
+
*/
|
65
|
+
jsts.operation.distance.GeometryLocation.prototype.pt = null;
|
66
|
+
|
67
|
+
|
68
|
+
/**
|
69
|
+
* @return {Geometry} the geometry component on (or in) which this location
|
70
|
+
* occurs.
|
71
|
+
*/
|
72
|
+
jsts.operation.distance.GeometryLocation.prototype.getGeometryComponent = function() {
|
73
|
+
return this.component;
|
74
|
+
};
|
75
|
+
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Returns the segment index for this location. If the location is inside an
|
79
|
+
* area, the index will have the value {@link INSIDE_AREA};
|
80
|
+
*
|
81
|
+
* @return {int} the segment index for the location, or INSIDE_AREA.
|
82
|
+
*/
|
83
|
+
jsts.operation.distance.GeometryLocation.prototype.getSegmentIndex = function() {
|
84
|
+
return this.segIndex;
|
85
|
+
};
|
86
|
+
|
87
|
+
|
88
|
+
/**
|
89
|
+
* @return {Coordinate} the {@link Coordinate} of this location.
|
90
|
+
*/
|
91
|
+
jsts.operation.distance.GeometryLocation.prototype.getCoordinate = function() {
|
92
|
+
return this.pt;
|
93
|
+
};
|
94
|
+
|
95
|
+
|
96
|
+
/**
|
97
|
+
* @return {boolean} whether this location represents a point inside an area
|
98
|
+
* geometry.
|
99
|
+
*/
|
100
|
+
jsts.operation.distance.GeometryLocation.prototype.isInsideArea = function() {
|
101
|
+
return this.segIndex === jsts.operation.distance.GeometryLocation.INSIDE_AREA;
|
102
|
+
};
|
@@ -0,0 +1,194 @@
|
|
1
|
+
/* Copyright (c) 2011 by The Authors.
|
2
|
+
* Published under the LGPL 2.1 license.
|
3
|
+
* See /license-notice.txt for the full text of the license notice.
|
4
|
+
* See /license.txt for the full text of the license.
|
5
|
+
*/
|
6
|
+
|
7
|
+
(function() {
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @requires jsts/util/Assert.js
|
11
|
+
*/
|
12
|
+
|
13
|
+
var Assert = jsts.util.Assert;
|
14
|
+
var ArrayList = javascript.util.ArrayList;
|
15
|
+
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Forms JTS LineStrings out of a the graph of {@link DirectedEdge}s created
|
19
|
+
* by an {@link OverlayOp}.
|
20
|
+
*/
|
21
|
+
var LineBuilder = function(op, geometryFactory, ptLocator) {
|
22
|
+
this.lineEdgesList = new ArrayList();
|
23
|
+
this.resultLineList = new ArrayList();
|
24
|
+
|
25
|
+
this.op = op;
|
26
|
+
this.geometryFactory = geometryFactory;
|
27
|
+
this.ptLocator = ptLocator;
|
28
|
+
};
|
29
|
+
|
30
|
+
LineBuilder.prototype.op = null;
|
31
|
+
LineBuilder.prototype.geometryFactory = null;
|
32
|
+
LineBuilder.prototype.ptLocator = null;
|
33
|
+
|
34
|
+
LineBuilder.prototype.lineEdgesList = null;
|
35
|
+
LineBuilder.prototype.resultLineList = null;
|
36
|
+
|
37
|
+
/**
|
38
|
+
* @return a list of the LineStrings in the result of the specified overlay
|
39
|
+
* operation.
|
40
|
+
*/
|
41
|
+
LineBuilder.prototype.build = function(opCode) {
|
42
|
+
this.findCoveredLineEdges();
|
43
|
+
this.collectLines(opCode);
|
44
|
+
this.buildLines(opCode);
|
45
|
+
return this.resultLineList;
|
46
|
+
};
|
47
|
+
/**
|
48
|
+
* Find and mark L edges which are "covered" by the result area (if any). L
|
49
|
+
* edges at nodes which also have A edges can be checked by checking their
|
50
|
+
* depth at that node. L edges at nodes which do not have A edges can be
|
51
|
+
* checked by doing a point-in-polygon test with the previously computed
|
52
|
+
* result areas.
|
53
|
+
*
|
54
|
+
* @private
|
55
|
+
*/
|
56
|
+
LineBuilder.prototype.findCoveredLineEdges = function() {
|
57
|
+
// first set covered for all L edges at nodes which have A edges too
|
58
|
+
for (var nodeit = this.op.getGraph().getNodes().iterator(); nodeit
|
59
|
+
.hasNext();) {
|
60
|
+
var node = nodeit.next();
|
61
|
+
node.getEdges().findCoveredLineEdges();
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* For all L edges which weren't handled by the above, use a point-in-poly
|
66
|
+
* test to determine whether they are covered
|
67
|
+
*/
|
68
|
+
for (var it = this.op.getGraph().getEdgeEnds().iterator(); it.hasNext();) {
|
69
|
+
var de = it.next();
|
70
|
+
var e = de.getEdge();
|
71
|
+
if (de.isLineEdge() && !e.isCoveredSet()) {
|
72
|
+
var isCovered = this.op.isCoveredByA(de.getCoordinate());
|
73
|
+
e.setCovered(isCovered);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
};
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @private
|
80
|
+
*/
|
81
|
+
LineBuilder.prototype.collectLines = function(opCode) {
|
82
|
+
for (var it = this.op.getGraph().getEdgeEnds().iterator(); it.hasNext();) {
|
83
|
+
var de = it.next();
|
84
|
+
this.collectLineEdge(de, opCode, this.lineEdgesList);
|
85
|
+
this.collectBoundaryTouchEdge(de, opCode, this.lineEdgesList);
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Collect line edges which are in the result. Line edges are in the result if
|
91
|
+
* they are not part of an area boundary, if they are in the result of the
|
92
|
+
* overlay operation, and if they are not covered by a result area.
|
93
|
+
*
|
94
|
+
* @param de
|
95
|
+
* the directed edge to test.
|
96
|
+
* @param opCode
|
97
|
+
* the overlap operation.
|
98
|
+
* @param edges
|
99
|
+
* the list of included line edges.
|
100
|
+
* @private
|
101
|
+
*/
|
102
|
+
LineBuilder.prototype.collectLineEdge = function(de, opCode, edges) {
|
103
|
+
var label = de.getLabel();
|
104
|
+
var e = de.getEdge();
|
105
|
+
// include L edges which are in the result
|
106
|
+
if (de.isLineEdge()) {
|
107
|
+
if (!de.isVisited() && jsts.operation.overlay.OverlayOp.isResultOfOp(label, opCode) &&
|
108
|
+
!e.isCovered()) {
|
109
|
+
|
110
|
+
edges.add(e);
|
111
|
+
de.setVisitedEdge(true);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
};
|
115
|
+
|
116
|
+
/**
|
117
|
+
* Collect edges from Area inputs which should be in the result but which have
|
118
|
+
* not been included in a result area. This happens ONLY:
|
119
|
+
* <ul>
|
120
|
+
* <li>during an intersection when the boundaries of two areas touch in a
|
121
|
+
* line segment
|
122
|
+
* <li> OR as a result of a dimensional collapse.
|
123
|
+
* </ul>
|
124
|
+
*
|
125
|
+
* @private
|
126
|
+
*/
|
127
|
+
LineBuilder.prototype.collectBoundaryTouchEdge = function(de, opCode, edges) {
|
128
|
+
var label = de.getLabel();
|
129
|
+
if (de.isLineEdge())
|
130
|
+
return; // only interested in area edges
|
131
|
+
if (de.isVisited())
|
132
|
+
return; // already processed
|
133
|
+
if (de.isInteriorAreaEdge())
|
134
|
+
return; // added to handle dimensional collapses
|
135
|
+
if (de.getEdge().isInResult())
|
136
|
+
return; // if the edge linework is already included, don't include it
|
137
|
+
// again
|
138
|
+
|
139
|
+
// sanity check for labelling of result edgerings
|
140
|
+
Assert.isTrue(!(de.isInResult() || de.getSym().isInResult()) ||
|
141
|
+
!de.getEdge().isInResult());
|
142
|
+
|
143
|
+
// include the linework if it's in the result of the operation
|
144
|
+
if (jsts.operation.overlay.OverlayOp.isResultOfOp(label, opCode) &&
|
145
|
+
opCode === jsts.operation.overlay.OverlayOp.INTERSECTION) {
|
146
|
+
edges.add(de.getEdge());
|
147
|
+
de.setVisitedEdge(true);
|
148
|
+
}
|
149
|
+
};
|
150
|
+
|
151
|
+
/**
|
152
|
+
* @private
|
153
|
+
*/
|
154
|
+
LineBuilder.prototype.buildLines = function(opCode) {
|
155
|
+
for (var it = this.lineEdgesList.iterator(); it.hasNext();) {
|
156
|
+
var e = it.next();
|
157
|
+
var label = e.getLabel();
|
158
|
+
var line = this.geometryFactory.createLineString(e.getCoordinates());
|
159
|
+
this.resultLineList.add(line);
|
160
|
+
e.setInResult(true);
|
161
|
+
}
|
162
|
+
};
|
163
|
+
|
164
|
+
/**
|
165
|
+
* @private
|
166
|
+
*/
|
167
|
+
LineBuilder.prototype.labelIsolatedLines = function(edgesList) {
|
168
|
+
for (var it = edgesList.iterator(); it.hasNext();) {
|
169
|
+
var e = it.next();
|
170
|
+
var label = e.getLabel();
|
171
|
+
// n.print(System.out);
|
172
|
+
if (e.isIsolated()) {
|
173
|
+
if (label.isNull(0))
|
174
|
+
this.labelIsolatedLine(e, 0);
|
175
|
+
else
|
176
|
+
this.labelIsolatedLine(e, 1);
|
177
|
+
}
|
178
|
+
}
|
179
|
+
};
|
180
|
+
|
181
|
+
/**
|
182
|
+
* Label an isolated node with its relationship to the target geometry.
|
183
|
+
*
|
184
|
+
* @private
|
185
|
+
*/
|
186
|
+
LineBuilder.prototype.labelIsolatedLine = function(e, targetIndex) {
|
187
|
+
var loc = ptLocator.locate(e.getCoordinate(), op
|
188
|
+
.getArgGeometry(targetIndex));
|
189
|
+
e.getLabel().setLocation(targetIndex, loc);
|
190
|
+
};
|
191
|
+
|
192
|
+
jsts.operation.overlay.LineBuilder = LineBuilder;
|
193
|
+
|
194
|
+
})();
|
@@ -0,0 +1,72 @@
|
|
1
|
+
/* Copyright (c) 2011 by The Authors.
|
2
|
+
* Published under the LGPL 2.1 license.
|
3
|
+
* See /license-notice.txt for the full text of the license notice.
|
4
|
+
* See /license.txt for the full text of the license.
|
5
|
+
*/
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @requires jsts/geomgraph/EdgeRing.js
|
9
|
+
*/
|
10
|
+
|
11
|
+
/**
|
12
|
+
* A ring of {@link DirectedEdge}s which may contain nodes of degree > 2.
|
13
|
+
* A <tt>MaximalEdgeRing</tt> may represent two different spatial entities:
|
14
|
+
* <ul>
|
15
|
+
* <li>a single polygon possibly containing inversions (if the ring is oriented CW)
|
16
|
+
* <li>a single hole possibly containing exversions (if the ring is oriented CCW)
|
17
|
+
* </ul>
|
18
|
+
* If the MaximalEdgeRing represents a polygon,
|
19
|
+
* the interior of the polygon is strongly connected.
|
20
|
+
* <p>
|
21
|
+
* These are the form of rings used to define polygons under some spatial data models.
|
22
|
+
* However, under the OGC SFS model, {@link MinimalEdgeRing}s are required.
|
23
|
+
* A MaximalEdgeRing can be converted to a list of MinimalEdgeRings using the
|
24
|
+
* {@link #buildMinimalRings() } method.
|
25
|
+
*
|
26
|
+
* @extends jsts.geomgraph.EdgeRing
|
27
|
+
* @constructor
|
28
|
+
*/
|
29
|
+
jsts.operation.overlay.MaximalEdgeRing = function(start, geometryFactory) {
|
30
|
+
jsts.geomgraph.EdgeRing.call(this, start, geometryFactory);
|
31
|
+
|
32
|
+
};
|
33
|
+
jsts.operation.overlay.MaximalEdgeRing.prototype = new jsts.geomgraph.EdgeRing();
|
34
|
+
jsts.operation.overlay.MaximalEdgeRing.constructor = jsts.operation.overlay.MaximalEdgeRing;
|
35
|
+
|
36
|
+
|
37
|
+
jsts.operation.overlay.MaximalEdgeRing.prototype.getNext = function(de)
|
38
|
+
{
|
39
|
+
return de.getNext();
|
40
|
+
};
|
41
|
+
jsts.operation.overlay.MaximalEdgeRing.prototype.setEdgeRing = function(de, er)
|
42
|
+
{
|
43
|
+
de.setEdgeRing(er);
|
44
|
+
};
|
45
|
+
|
46
|
+
/**
|
47
|
+
* For all nodes in this EdgeRing,
|
48
|
+
* link the DirectedEdges at the node to form minimalEdgeRings
|
49
|
+
*/
|
50
|
+
jsts.operation.overlay.MaximalEdgeRing.prototype.linkDirectedEdgesForMinimalEdgeRings = function()
|
51
|
+
{
|
52
|
+
var de = this.startDe;
|
53
|
+
do {
|
54
|
+
var node = de.getNode();
|
55
|
+
node.getEdges().linkMinimalDirectedEdges(this);
|
56
|
+
de = de.getNext();
|
57
|
+
} while (de != this.startDe);
|
58
|
+
};
|
59
|
+
|
60
|
+
jsts.operation.overlay.MaximalEdgeRing.prototype.buildMinimalRings = function()
|
61
|
+
{
|
62
|
+
var minEdgeRings = [];
|
63
|
+
var de = this.startDe;
|
64
|
+
do {
|
65
|
+
if (de.getMinEdgeRing() === null) {
|
66
|
+
var minEr = new jsts.operation.overlay.MinimalEdgeRing(de, this.geometryFactory);
|
67
|
+
minEdgeRings.push(minEr);
|
68
|
+
}
|
69
|
+
de = de.getNext();
|
70
|
+
} while (de != this.startDe);
|
71
|
+
return minEdgeRings;
|
72
|
+
};
|
@@ -0,0 +1,33 @@
|
|
1
|
+
/* Copyright (c) 2011 by The Authors.
|
2
|
+
* Published under the LGPL 2.1 license.
|
3
|
+
* See /license-notice.txt for the full text of the license notice.
|
4
|
+
* See /license.txt for the full text of the license.
|
5
|
+
*/
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @requires jsts/geomgraph/EdgeRing.js
|
9
|
+
*/
|
10
|
+
|
11
|
+
/**
|
12
|
+
* A ring of {@link Edge}s with the property that no node has degree greater
|
13
|
+
* than 2. These are the form of rings required to represent polygons under the
|
14
|
+
* OGC SFS spatial data model.
|
15
|
+
*
|
16
|
+
* Port source: com.vividsolutions.jts.operation.overlay.MinimalEdgeRing r6
|
17
|
+
*
|
18
|
+
* @extends jsts.geomgraph.EdgeRing
|
19
|
+
* @constructor
|
20
|
+
*/
|
21
|
+
jsts.operation.overlay.MinimalEdgeRing = function(start, geometryFactory) {
|
22
|
+
jsts.geomgraph.EdgeRing.call(this, start, geometryFactory);
|
23
|
+
|
24
|
+
};
|
25
|
+
jsts.operation.overlay.MinimalEdgeRing.prototype = new jsts.geomgraph.EdgeRing();
|
26
|
+
jsts.operation.overlay.MinimalEdgeRing.constructor = jsts.operation.overlay.MinimalEdgeRing;
|
27
|
+
|
28
|
+
jsts.operation.overlay.MinimalEdgeRing.prototype.getNext = function(de) {
|
29
|
+
return de.getNextMin();
|
30
|
+
};
|
31
|
+
jsts.operation.overlay.MinimalEdgeRing.prototype.setEdgeRing = function(de, er) {
|
32
|
+
de.setMinEdgeRing(er);
|
33
|
+
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
/* Copyright (c) 2011 by The Authors.
|
2
|
+
* Published under the LGPL 2.1 license.
|
3
|
+
* See /license-notice.txt for the full text of the license notice.
|
4
|
+
* See /license.txt for the full text of the license.
|
5
|
+
*/
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @requires jsts/geomgraph/NodeFactory.js
|
9
|
+
*/
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Creates nodes for use in the {@link PlanarGraph}s constructed during overlay
|
13
|
+
* operations.
|
14
|
+
*
|
15
|
+
* @constructor
|
16
|
+
* @extends jsts.geomgraph.NodeFactory
|
17
|
+
*/
|
18
|
+
jsts.operation.overlay.OverlayNodeFactory = function() {
|
19
|
+
|
20
|
+
};
|
21
|
+
jsts.operation.overlay.OverlayNodeFactory.prototype = new jsts.geomgraph.NodeFactory();
|
22
|
+
jsts.operation.overlay.OverlayNodeFactory.constructor = jsts.operation.overlay.OverlayNodeFactory;
|
23
|
+
|
24
|
+
jsts.operation.overlay.OverlayNodeFactory.prototype.createNode = function(coord) {
|
25
|
+
return new jsts.geomgraph.Node(coord, new jsts.geomgraph.DirectedEdgeStar());
|
26
|
+
};
|
@@ -0,0 +1,584 @@
|
|
1
|
+
/* Copyright (c) 2011 by The Authors.
|
2
|
+
* Published under the LGPL 2.1 license.
|
3
|
+
* See /license-notice.txt for the full text of the license notice.
|
4
|
+
* See /license.txt for the full text of the license.
|
5
|
+
*/
|
6
|
+
|
7
|
+
(function() {
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @requires jsts/algorithm/PointLocator.js
|
11
|
+
* @requires jsts/geom/Location.js
|
12
|
+
* @requires jsts/geomgraph/EdgeList.js
|
13
|
+
* @requires jsts/geomgraph/Label.js
|
14
|
+
* @requires jsts/geomgraph/PlanarGraph.js
|
15
|
+
* @requires jsts/geomgraph/Position.js
|
16
|
+
* @requires jsts/geomgraph/EdgeNodingValidator.js
|
17
|
+
* @requires jsts/operation/GeometryGraphOperation.js
|
18
|
+
* @requires jsts/operation/overlay/OverlayNodeFactory.js
|
19
|
+
* @requires jsts/operation/overlay/PolygonBuilder.js
|
20
|
+
* @requires jsts/operation/overlay/LineBuilder.js
|
21
|
+
* @requires jsts/operation/overlay/PointBuilder.js
|
22
|
+
* @requires jsts/util/Assert.js
|
23
|
+
*/
|
24
|
+
|
25
|
+
var PointLocator = jsts.algorithm.PointLocator;
|
26
|
+
var Location = jsts.geom.Location;
|
27
|
+
var EdgeList = jsts.geomgraph.EdgeList;
|
28
|
+
var Label = jsts.geomgraph.Label;
|
29
|
+
var PlanarGraph = jsts.geomgraph.PlanarGraph;
|
30
|
+
var Position = jsts.geomgraph.Position;
|
31
|
+
var EdgeNodingValidator = jsts.geomgraph.EdgeNodingValidator;
|
32
|
+
var GeometryGraphOperation = jsts.operation.GeometryGraphOperation;
|
33
|
+
var OverlayNodeFactory = jsts.operation.overlay.OverlayNodeFactory;
|
34
|
+
var PolygonBuilder = jsts.operation.overlay.PolygonBuilder;
|
35
|
+
var LineBuilder = jsts.operation.overlay.LineBuilder;
|
36
|
+
var PointBuilder = jsts.operation.overlay.PointBuilder;
|
37
|
+
var Assert = jsts.util.Assert;
|
38
|
+
var ArrayList = javascript.util.ArrayList;
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Computes the overlay of two {@link Geometry}s. The overlay can be used to
|
42
|
+
* determine any boolean combination of the geometries.
|
43
|
+
*/
|
44
|
+
jsts.operation.overlay.OverlayOp = function(g0, g1) {
|
45
|
+
this.ptLocator = new PointLocator();
|
46
|
+
this.edgeList = new EdgeList();
|
47
|
+
this.resultPolyList = new ArrayList();
|
48
|
+
this.resultLineList = new ArrayList();
|
49
|
+
this.resultPointList = new ArrayList();
|
50
|
+
|
51
|
+
GeometryGraphOperation.call(this, g0, g1);
|
52
|
+
this.graph = new PlanarGraph(new OverlayNodeFactory());
|
53
|
+
/**
|
54
|
+
* Use factory of primary geometry. Note that this does NOT handle
|
55
|
+
* mixed-precision arguments where the second arg has greater precision than
|
56
|
+
* the first.
|
57
|
+
*/
|
58
|
+
this.geomFact = g0.getFactory();
|
59
|
+
};
|
60
|
+
jsts.operation.overlay.OverlayOp.prototype = new GeometryGraphOperation();
|
61
|
+
jsts.operation.overlay.OverlayOp.constructor = jsts.operation.overlay.OverlayOp;
|
62
|
+
|
63
|
+
/**
|
64
|
+
* The spatial functions supported by this class. These operations implement
|
65
|
+
* various boolean combinations of the resultants of the overlay.
|
66
|
+
*/
|
67
|
+
jsts.operation.overlay.OverlayOp.INTERSECTION = 1;
|
68
|
+
jsts.operation.overlay.OverlayOp.UNION = 2;
|
69
|
+
jsts.operation.overlay.OverlayOp.DIFFERENCE = 3;
|
70
|
+
jsts.operation.overlay.OverlayOp.SYMDIFFERENCE = 4;
|
71
|
+
|
72
|
+
jsts.operation.overlay.OverlayOp.overlayOp = function(geom0, geom1, opCode) {
|
73
|
+
var gov = new jsts.operation.overlay.OverlayOp(geom0, geom1);
|
74
|
+
var geomOv = gov.getResultGeometry(opCode);
|
75
|
+
return geomOv;
|
76
|
+
}
|
77
|
+
|
78
|
+
jsts.operation.overlay.OverlayOp.isResultOfOp = function(label, opCode) {
|
79
|
+
if (arguments.length === 3) {
|
80
|
+
return jsts.operation.overlay.OverlayOp.isResultOfOp2.apply(this,
|
81
|
+
arguments);
|
82
|
+
}
|
83
|
+
var loc0 = label.getLocation(0);
|
84
|
+
var loc1 = label.getLocation(1);
|
85
|
+
return jsts.operation.overlay.OverlayOp.isResultOfOp2(loc0, loc1, opCode);
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* This method will handle arguments of Location.NONE correctly
|
90
|
+
*
|
91
|
+
* @return true if the locations correspond to the opCode.
|
92
|
+
*/
|
93
|
+
jsts.operation.overlay.OverlayOp.isResultOfOp2 = function(loc0, loc1, opCode) {
|
94
|
+
if (loc0 == Location.BOUNDARY)
|
95
|
+
loc0 = Location.INTERIOR;
|
96
|
+
if (loc1 == Location.BOUNDARY)
|
97
|
+
loc1 = Location.INTERIOR;
|
98
|
+
switch (opCode) {
|
99
|
+
case jsts.operation.overlay.OverlayOp.INTERSECTION:
|
100
|
+
return loc0 == Location.INTERIOR && loc1 == Location.INTERIOR;
|
101
|
+
case jsts.operation.overlay.OverlayOp.UNION:
|
102
|
+
return loc0 == Location.INTERIOR || loc1 == Location.INTERIOR;
|
103
|
+
case jsts.operation.overlay.OverlayOp.DIFFERENCE:
|
104
|
+
return loc0 == Location.INTERIOR && loc1 != Location.INTERIOR;
|
105
|
+
case jsts.operation.overlay.OverlayOp.SYMDIFFERENCE:
|
106
|
+
return (loc0 == Location.INTERIOR && loc1 != Location.INTERIOR) ||
|
107
|
+
(loc0 != Location.INTERIOR && loc1 == Location.INTERIOR);
|
108
|
+
}
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
|
112
|
+
jsts.operation.overlay.OverlayOp.prototype.ptLocator = null;
|
113
|
+
jsts.operation.overlay.OverlayOp.prototype.geomFact = null;
|
114
|
+
jsts.operation.overlay.OverlayOp.prototype.resultGeom = null;
|
115
|
+
|
116
|
+
jsts.operation.overlay.OverlayOp.prototype.graph = null;
|
117
|
+
jsts.operation.overlay.OverlayOp.prototype.edgeList = null;
|
118
|
+
|
119
|
+
jsts.operation.overlay.OverlayOp.prototype.resultPolyList = null;
|
120
|
+
jsts.operation.overlay.OverlayOp.prototype.resultLineList = null;
|
121
|
+
jsts.operation.overlay.OverlayOp.prototype.resultPointList = null;
|
122
|
+
|
123
|
+
|
124
|
+
jsts.operation.overlay.OverlayOp.prototype.getResultGeometry = function(
|
125
|
+
funcCode) {
|
126
|
+
this.computeOverlay(funcCode);
|
127
|
+
return this.resultGeom;
|
128
|
+
}
|
129
|
+
|
130
|
+
jsts.operation.overlay.OverlayOp.prototype.getGraph = function() {
|
131
|
+
return this.graph;
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
* @private
|
136
|
+
*/
|
137
|
+
jsts.operation.overlay.OverlayOp.prototype.computeOverlay = function(opCode) {
|
138
|
+
// copy points from input Geometries.
|
139
|
+
// This ensures that any Point geometries
|
140
|
+
// in the input are considered for inclusion in the result set
|
141
|
+
this.copyPoints(0);
|
142
|
+
this.copyPoints(1);
|
143
|
+
|
144
|
+
// node the input Geometries
|
145
|
+
this.arg[0].computeSelfNodes(this.li, false);
|
146
|
+
this.arg[1].computeSelfNodes(this.li, false);
|
147
|
+
|
148
|
+
// compute intersections between edges of the two input geometries
|
149
|
+
this.arg[0].computeEdgeIntersections(this.arg[1], this.li, true);
|
150
|
+
|
151
|
+
var baseSplitEdges = new ArrayList();
|
152
|
+
this.arg[0].computeSplitEdges(baseSplitEdges);
|
153
|
+
this.arg[1].computeSplitEdges(baseSplitEdges);
|
154
|
+
var splitEdges = baseSplitEdges;
|
155
|
+
// add the noded edges to this result graph
|
156
|
+
this.insertUniqueEdges(baseSplitEdges);
|
157
|
+
|
158
|
+
this.computeLabelsFromDepths();
|
159
|
+
this.replaceCollapsedEdges();
|
160
|
+
|
161
|
+
/**
|
162
|
+
* Check that the noding completed correctly.
|
163
|
+
*
|
164
|
+
* This test is slow, but necessary in order to catch robustness failure
|
165
|
+
* situations. If an exception is thrown because of a noding failure, then
|
166
|
+
* snapping will be performed, which will hopefully avoid the problem. In
|
167
|
+
* the future hopefully a faster check can be developed.
|
168
|
+
*
|
169
|
+
*/
|
170
|
+
EdgeNodingValidator.checkValid(this.edgeList.getEdges());
|
171
|
+
|
172
|
+
this.graph.addEdges(this.edgeList.getEdges());
|
173
|
+
this.computeLabelling();
|
174
|
+
this.labelIncompleteNodes();
|
175
|
+
|
176
|
+
/**
|
177
|
+
* The ordering of building the result Geometries is important. Areas must
|
178
|
+
* be built before lines, which must be built before points. This is so that
|
179
|
+
* lines which are covered by areas are not included explicitly, and
|
180
|
+
* similarly for points.
|
181
|
+
*/
|
182
|
+
this.findResultAreaEdges(opCode);
|
183
|
+
this.cancelDuplicateResultEdges();
|
184
|
+
|
185
|
+
var polyBuilder = new PolygonBuilder(this.geomFact);
|
186
|
+
polyBuilder.add(this.graph);
|
187
|
+
this.resultPolyList = polyBuilder.getPolygons();
|
188
|
+
|
189
|
+
var lineBuilder = new LineBuilder(this, this.geomFact, this.ptLocator);
|
190
|
+
this.resultLineList = lineBuilder.build(opCode);
|
191
|
+
|
192
|
+
var pointBuilder = new PointBuilder(this, this.geomFact, this.ptLocator);
|
193
|
+
this.resultPointList = pointBuilder.build(opCode);
|
194
|
+
|
195
|
+
// gather the results from all calculations into a single Geometry for the
|
196
|
+
// result set
|
197
|
+
this.resultGeom = this.computeGeometry(this.resultPointList,
|
198
|
+
this.resultLineList, this.resultPolyList, opCode);
|
199
|
+
}
|
200
|
+
|
201
|
+
/**
|
202
|
+
* @private
|
203
|
+
*/
|
204
|
+
jsts.operation.overlay.OverlayOp.prototype.insertUniqueEdges = function(edges) {
|
205
|
+
for (var i = edges.iterator(); i.hasNext();) {
|
206
|
+
var e = i.next();
|
207
|
+
this.insertUniqueEdge(e);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
/**
|
211
|
+
* Insert an edge from one of the noded input graphs. Checks edges that are
|
212
|
+
* inserted to see if an identical edge already exists. If so, the edge is not
|
213
|
+
* inserted, but its label is merged with the existing edge.
|
214
|
+
*
|
215
|
+
* @protected
|
216
|
+
*/
|
217
|
+
jsts.operation.overlay.OverlayOp.prototype.insertUniqueEdge = function(e) {
|
218
|
+
// <FIX> MD 8 Oct 03 speed up identical edge lookup
|
219
|
+
// fast lookup
|
220
|
+
var existingEdge = this.edgeList.findEqualEdge(e);
|
221
|
+
|
222
|
+
// If an identical edge already exists, simply update its label
|
223
|
+
if (existingEdge !== null) {
|
224
|
+
var existingLabel = existingEdge.getLabel();
|
225
|
+
|
226
|
+
var labelToMerge = e.getLabel();
|
227
|
+
// check if new edge is in reverse direction to existing edge
|
228
|
+
// if so, must flip the label before merging it
|
229
|
+
if (!existingEdge.isPointwiseEqual(e)) {
|
230
|
+
labelToMerge = new Label(e.getLabel());
|
231
|
+
labelToMerge.flip();
|
232
|
+
}
|
233
|
+
var depth = existingEdge.getDepth();
|
234
|
+
// if this is the first duplicate found for this edge, initialize the
|
235
|
+
// depths
|
236
|
+
// /*
|
237
|
+
if (depth.isNull()) {
|
238
|
+
depth.add(existingLabel);
|
239
|
+
}
|
240
|
+
// */
|
241
|
+
depth.add(labelToMerge);
|
242
|
+
existingLabel.merge(labelToMerge);
|
243
|
+
|
244
|
+
} else { // no matching existing edge was found
|
245
|
+
// add this new edge to the list of edges in this graph
|
246
|
+
// e.setName(name + edges.size());
|
247
|
+
// e.getDepth().add(e.getLabel());
|
248
|
+
this.edgeList.add(e);
|
249
|
+
}
|
250
|
+
};
|
251
|
+
|
252
|
+
|
253
|
+
/**
|
254
|
+
* Update the labels for edges according to their depths. For each edge, the
|
255
|
+
* depths are first normalized. Then, if the depths for the edge are equal,
|
256
|
+
* this edge must have collapsed into a line edge. If the depths are not
|
257
|
+
* equal, update the label with the locations corresponding to the depths
|
258
|
+
* (i.e. a depth of 0 corresponds to a Location of EXTERIOR, a depth of 1
|
259
|
+
* corresponds to INTERIOR)
|
260
|
+
*
|
261
|
+
* @private
|
262
|
+
*/
|
263
|
+
jsts.operation.overlay.OverlayOp.prototype.computeLabelsFromDepths = function() {
|
264
|
+
for (var it = this.edgeList.iterator(); it.hasNext();) {
|
265
|
+
var e = it.next();
|
266
|
+
var lbl = e.getLabel();
|
267
|
+
var depth = e.getDepth();
|
268
|
+
/**
|
269
|
+
* Only check edges for which there were duplicates, since these are the
|
270
|
+
* only ones which might be the result of dimensional collapses.
|
271
|
+
*/
|
272
|
+
if (!depth.isNull()) {
|
273
|
+
depth.normalize();
|
274
|
+
for (var i = 0; i < 2; i++) {
|
275
|
+
if (!lbl.isNull(i) && lbl.isArea() && !depth.isNull(i)) {
|
276
|
+
/**
|
277
|
+
* if the depths are equal, this edge is the result of the
|
278
|
+
* dimensional collapse of two or more edges. It has the same
|
279
|
+
* location on both sides of the edge, so it has collapsed to a
|
280
|
+
* line.
|
281
|
+
*/
|
282
|
+
if (depth.getDelta(i) == 0) {
|
283
|
+
lbl.toLine(i);
|
284
|
+
} else {
|
285
|
+
/**
|
286
|
+
* This edge may be the result of a dimensional collapse, but it
|
287
|
+
* still has different locations on both sides. The label of the
|
288
|
+
* edge must be updated to reflect the resultant side locations
|
289
|
+
* indicated by the depth values.
|
290
|
+
*/
|
291
|
+
Assert.isTrue(!depth.isNull(i, Position.LEFT),
|
292
|
+
'depth of LEFT side has not been initialized');
|
293
|
+
lbl.setLocation(i, Position.LEFT, depth.getLocation(i,
|
294
|
+
Position.LEFT));
|
295
|
+
Assert.isTrue(!depth.isNull(i, Position.RIGHT),
|
296
|
+
'depth of RIGHT side has not been initialized');
|
297
|
+
lbl.setLocation(i, Position.RIGHT, depth.getLocation(i,
|
298
|
+
Position.RIGHT));
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
}
|
303
|
+
}
|
304
|
+
}
|
305
|
+
/**
|
306
|
+
* If edges which have undergone dimensional collapse are found, replace them
|
307
|
+
* with a new edge which is a L edge
|
308
|
+
*
|
309
|
+
* @private
|
310
|
+
*/
|
311
|
+
jsts.operation.overlay.OverlayOp.prototype.replaceCollapsedEdges = function() {
|
312
|
+
var newEdges = new ArrayList();
|
313
|
+
for (var it = this.edgeList.iterator(); it.hasNext();) {
|
314
|
+
var e = it.next();
|
315
|
+
if (e.isCollapsed()) {
|
316
|
+
it.remove();
|
317
|
+
newEdges.add(e.getCollapsedEdge());
|
318
|
+
}
|
319
|
+
}
|
320
|
+
this.edgeList.addAll(newEdges);
|
321
|
+
}
|
322
|
+
/**
|
323
|
+
* Copy all nodes from an arg geometry into this graph. The node label in the
|
324
|
+
* arg geometry overrides any previously computed label for that argIndex.
|
325
|
+
* (E.g. a node may be an intersection node with a previously computed label
|
326
|
+
* of BOUNDARY, but in the original arg Geometry it is actually in the
|
327
|
+
* interior due to the Boundary Determination Rule)
|
328
|
+
*
|
329
|
+
* @private
|
330
|
+
*/
|
331
|
+
jsts.operation.overlay.OverlayOp.prototype.copyPoints = function(argIndex) {
|
332
|
+
for (var i = this.arg[argIndex].getNodeIterator(); i.hasNext();) {
|
333
|
+
var graphNode = i.next();
|
334
|
+
var newNode = this.graph.addNode(graphNode.getCoordinate());
|
335
|
+
newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex));
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
/**
|
340
|
+
* Compute initial labelling for all DirectedEdges at each node. In this step,
|
341
|
+
* DirectedEdges will acquire a complete labelling (i.e. one with labels for
|
342
|
+
* both Geometries) only if they are incident on a node which has edges for
|
343
|
+
* both Geometries
|
344
|
+
*
|
345
|
+
* @private
|
346
|
+
*/
|
347
|
+
jsts.operation.overlay.OverlayOp.prototype.computeLabelling = function() {
|
348
|
+
for (var nodeit = this.graph.getNodes().iterator(); nodeit.hasNext();) {
|
349
|
+
var node = nodeit.next();
|
350
|
+
node.getEdges().computeLabelling(this.arg);
|
351
|
+
}
|
352
|
+
this.mergeSymLabels();
|
353
|
+
this.updateNodeLabelling();
|
354
|
+
}
|
355
|
+
/**
|
356
|
+
* For nodes which have edges from only one Geometry incident on them, the
|
357
|
+
* previous step will have left their dirEdges with no labelling for the other
|
358
|
+
* Geometry. However, the sym dirEdge may have a labelling for the other
|
359
|
+
* Geometry, so merge the two labels.
|
360
|
+
*
|
361
|
+
* @private
|
362
|
+
*/
|
363
|
+
jsts.operation.overlay.OverlayOp.prototype.mergeSymLabels = function() {
|
364
|
+
for (var nodeit = this.graph.getNodes().iterator(); nodeit.hasNext();) {
|
365
|
+
var node = nodeit.next();
|
366
|
+
node.getEdges().mergeSymLabels();
|
367
|
+
}
|
368
|
+
}
|
369
|
+
|
370
|
+
/**
|
371
|
+
* @private
|
372
|
+
*/
|
373
|
+
jsts.operation.overlay.OverlayOp.prototype.updateNodeLabelling = function() {
|
374
|
+
// update the labels for nodes
|
375
|
+
// The label for a node is updated from the edges incident on it
|
376
|
+
// (Note that a node may have already been labelled
|
377
|
+
// because it is a point in one of the input geometries)
|
378
|
+
for (var nodeit = this.graph.getNodes().iterator(); nodeit.hasNext();) {
|
379
|
+
var node = nodeit.next();
|
380
|
+
var lbl = node.getEdges().getLabel();
|
381
|
+
node.getLabel().merge(lbl);
|
382
|
+
}
|
383
|
+
}
|
384
|
+
|
385
|
+
/**
|
386
|
+
* Incomplete nodes are nodes whose labels are incomplete. (e.g. the location
|
387
|
+
* for one Geometry is null). These are either isolated nodes, or nodes which
|
388
|
+
* have edges from only a single Geometry incident on them.
|
389
|
+
*
|
390
|
+
* Isolated nodes are found because nodes in one graph which don't intersect
|
391
|
+
* nodes in the other are not completely labelled by the initial process of
|
392
|
+
* adding nodes to the nodeList. To complete the labelling we need to check
|
393
|
+
* for nodes that lie in the interior of edges, and in the interior of areas.
|
394
|
+
* <p>
|
395
|
+
* When each node labelling is completed, the labelling of the incident edges
|
396
|
+
* is updated, to complete their labelling as well.
|
397
|
+
*
|
398
|
+
* @private
|
399
|
+
*/
|
400
|
+
jsts.operation.overlay.OverlayOp.prototype.labelIncompleteNodes = function() {
|
401
|
+
var nodeCount = 0;
|
402
|
+
for (var ni = this.graph.getNodes().iterator(); ni.hasNext();) {
|
403
|
+
var n = ni.next();
|
404
|
+
var label = n.getLabel();
|
405
|
+
if (n.isIsolated()) {
|
406
|
+
nodeCount++;
|
407
|
+
if (label.isNull(0))
|
408
|
+
this.labelIncompleteNode(n, 0);
|
409
|
+
else
|
410
|
+
this.labelIncompleteNode(n, 1);
|
411
|
+
}
|
412
|
+
// now update the labelling for the DirectedEdges incident on this node
|
413
|
+
n.getEdges().updateLabelling(label);
|
414
|
+
}
|
415
|
+
};
|
416
|
+
|
417
|
+
/**
|
418
|
+
* Label an isolated node with its relationship to the target geometry.
|
419
|
+
*
|
420
|
+
* @private
|
421
|
+
*/
|
422
|
+
jsts.operation.overlay.OverlayOp.prototype.labelIncompleteNode = function(n,
|
423
|
+
targetIndex) {
|
424
|
+
var loc = this.ptLocator.locate(n.getCoordinate(), this.arg[targetIndex]
|
425
|
+
.getGeometry());
|
426
|
+
|
427
|
+
// MD - 2008-10-24 - experimental for now
|
428
|
+
// int loc = arg[targetIndex].locate(n.getCoordinate());
|
429
|
+
n.getLabel().setLocation(targetIndex, loc);
|
430
|
+
};
|
431
|
+
|
432
|
+
/**
|
433
|
+
* Find all edges whose label indicates that they are in the result area(s),
|
434
|
+
* according to the operation being performed. Since we want polygon shells to
|
435
|
+
* be oriented CW, choose dirEdges with the interior of the result on the RHS.
|
436
|
+
* Mark them as being in the result. Interior Area edges are the result of
|
437
|
+
* dimensional collapses. They do not form part of the result area boundary.
|
438
|
+
*
|
439
|
+
* @private
|
440
|
+
*/
|
441
|
+
jsts.operation.overlay.OverlayOp.prototype.findResultAreaEdges = function(
|
442
|
+
opCode) {
|
443
|
+
for (var it = this.graph.getEdgeEnds().iterator(); it.hasNext();) {
|
444
|
+
var de = it.next();
|
445
|
+
// mark all dirEdges with the appropriate label
|
446
|
+
var label = de.getLabel();
|
447
|
+
if (label.isArea() &&
|
448
|
+
!de.isInteriorAreaEdge() &&
|
449
|
+
jsts.operation.overlay.OverlayOp.isResultOfOp(label.getLocation(0,
|
450
|
+
Position.RIGHT), label.getLocation(1, Position.RIGHT), opCode)) {
|
451
|
+
de.setInResult(true);
|
452
|
+
}
|
453
|
+
}
|
454
|
+
};
|
455
|
+
/**
|
456
|
+
* If both a dirEdge and its sym are marked as being in the result, cancel
|
457
|
+
* them out.
|
458
|
+
*
|
459
|
+
* @private
|
460
|
+
*/
|
461
|
+
jsts.operation.overlay.OverlayOp.prototype.cancelDuplicateResultEdges = function() {
|
462
|
+
// remove any dirEdges whose sym is also included
|
463
|
+
// (they "cancel each other out")
|
464
|
+
for (var it = this.graph.getEdgeEnds().iterator(); it.hasNext();) {
|
465
|
+
var de = it.next();
|
466
|
+
var sym = de.getSym();
|
467
|
+
if (de.isInResult() && sym.isInResult()) {
|
468
|
+
de.setInResult(false);
|
469
|
+
sym.setInResult(false);
|
470
|
+
}
|
471
|
+
}
|
472
|
+
};
|
473
|
+
/**
|
474
|
+
* This method is used to decide if a point node should be included in the
|
475
|
+
* result or not.
|
476
|
+
*
|
477
|
+
* @return {boolean} true if the coord point is covered by a result Line or
|
478
|
+
* Area geometry.
|
479
|
+
*/
|
480
|
+
jsts.operation.overlay.OverlayOp.prototype.isCoveredByLA = function(coord) {
|
481
|
+
if (this.isCovered(coord, this.resultLineList))
|
482
|
+
return true;
|
483
|
+
if (this.isCovered(coord, this.resultPolyList))
|
484
|
+
return true;
|
485
|
+
return false;
|
486
|
+
};
|
487
|
+
/**
|
488
|
+
* This method is used to decide if an L edge should be included in the result
|
489
|
+
* or not.
|
490
|
+
*
|
491
|
+
* @return true if the coord point is covered by a result Area geometry.
|
492
|
+
*/
|
493
|
+
jsts.operation.overlay.OverlayOp.prototype.isCoveredByA = function(coord) {
|
494
|
+
if (this.isCovered(coord, this.resultPolyList))
|
495
|
+
return true;
|
496
|
+
return false;
|
497
|
+
};
|
498
|
+
/**
|
499
|
+
* @return true if the coord is located in the interior or boundary of a
|
500
|
+
* geometry in the list.
|
501
|
+
* @private
|
502
|
+
*/
|
503
|
+
jsts.operation.overlay.OverlayOp.prototype.isCovered = function(coord,
|
504
|
+
geomList) {
|
505
|
+
for (var it = geomList.iterator(); it.hasNext();) {
|
506
|
+
var geom = it.next();
|
507
|
+
var loc = this.ptLocator.locate(coord, geom);
|
508
|
+
if (loc != Location.EXTERIOR)
|
509
|
+
return true;
|
510
|
+
}
|
511
|
+
return false;
|
512
|
+
};
|
513
|
+
|
514
|
+
/**
|
515
|
+
* @private
|
516
|
+
*/
|
517
|
+
jsts.operation.overlay.OverlayOp.prototype.computeGeometry = function(
|
518
|
+
resultPointList, resultLineList, resultPolyList, opcode) {
|
519
|
+
var geomList = new ArrayList();
|
520
|
+
// element geometries of the result are always in the order P,L,A
|
521
|
+
geomList.addAll(resultPointList);
|
522
|
+
geomList.addAll(resultLineList);
|
523
|
+
geomList.addAll(resultPolyList);
|
524
|
+
|
525
|
+
/*
|
526
|
+
if (geomList.isEmpty())
|
527
|
+
return createEmptyResult(opcode);
|
528
|
+
*/
|
529
|
+
|
530
|
+
// build the most specific geometry possible
|
531
|
+
return this.geomFact.buildGeometry(geomList);
|
532
|
+
};
|
533
|
+
|
534
|
+
/**
|
535
|
+
* @private
|
536
|
+
*/
|
537
|
+
jsts.operation.overlay.OverlayOp.prototype.createEmptyResult = function(
|
538
|
+
opCode) {
|
539
|
+
var result = null;
|
540
|
+
switch (resultDimension(opCode, this.arg[0].getGeometry(), this.arg[1]
|
541
|
+
.getGeometry())) {
|
542
|
+
case -1:
|
543
|
+
result = geomFact.createGeometryCollection();
|
544
|
+
break;
|
545
|
+
case 0:
|
546
|
+
result = geomFact.createPoint(null);
|
547
|
+
break;
|
548
|
+
case 1:
|
549
|
+
result = geomFact.createLineString(null);
|
550
|
+
break;
|
551
|
+
case 2:
|
552
|
+
result = geomFact.createPolygon(null, null);
|
553
|
+
break;
|
554
|
+
}
|
555
|
+
return result;
|
556
|
+
};
|
557
|
+
|
558
|
+
/**
|
559
|
+
* @private
|
560
|
+
*/
|
561
|
+
jsts.operation.overlay.OverlayOp.prototype.resultDimension = function(opCode,
|
562
|
+
g0, g1) {
|
563
|
+
var dim0 = g0.getDimension();
|
564
|
+
var dim1 = g1.getDimension();
|
565
|
+
|
566
|
+
var resultDimension = -1;
|
567
|
+
switch (opCode) {
|
568
|
+
case jsts.operation.overlay.OverlayOp.INTERSECTION:
|
569
|
+
resultDimension = Math.min(dim0, dim1);
|
570
|
+
break;
|
571
|
+
case jsts.operation.overlay.OverlayOp.UNION:
|
572
|
+
resultDimension = Math.max(dim0, dim1);
|
573
|
+
break;
|
574
|
+
case jsts.operation.overlay.OverlayOp.DIFFERENCE:
|
575
|
+
resultDimension = dim0;
|
576
|
+
break;
|
577
|
+
case jsts.operation.overlay.OverlayOp.SYMDIFFERENCE:
|
578
|
+
resultDimension = Math.max(dim0, dim1);
|
579
|
+
break;
|
580
|
+
}
|
581
|
+
return resultDimension;
|
582
|
+
};
|
583
|
+
|
584
|
+
})();
|