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.
Files changed (209) hide show
  1. checksums.yaml +8 -8
  2. data/lib/jsts-rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/javascript.util.js +33 -1
  4. data/vendor/assets/javascripts/jsts-original.js +164 -1573
  5. data/vendor/assets/javascripts/jsts.js +197 -0
  6. data/vendor/assets/javascripts/jsts/algorithm/Angle.js +387 -0
  7. data/vendor/assets/javascripts/jsts/algorithm/BoundaryNodeRule.js +67 -0
  8. data/vendor/assets/javascripts/jsts/algorithm/CGAlgorithms.js +596 -0
  9. data/vendor/assets/javascripts/jsts/algorithm/CentralEndpointIntersector.js +118 -0
  10. data/vendor/assets/javascripts/jsts/algorithm/CentroidArea.js +225 -0
  11. data/vendor/assets/javascripts/jsts/algorithm/CentroidLine.js +85 -0
  12. data/vendor/assets/javascripts/jsts/algorithm/CentroidPoint.js +77 -0
  13. data/vendor/assets/javascripts/jsts/algorithm/ConvexHull.js +409 -0
  14. data/vendor/assets/javascripts/jsts/algorithm/HCoordinate.js +234 -0
  15. data/vendor/assets/javascripts/jsts/algorithm/LineIntersector.js +502 -0
  16. data/vendor/assets/javascripts/jsts/algorithm/MCPointInRing.js +124 -0
  17. data/vendor/assets/javascripts/jsts/algorithm/PointLocator.js +247 -0
  18. data/vendor/assets/javascripts/jsts/algorithm/RayCrossingCounter.js +215 -0
  19. data/vendor/assets/javascripts/jsts/algorithm/RobustDeterminant.js +353 -0
  20. data/vendor/assets/javascripts/jsts/algorithm/RobustLineIntersector.js +477 -0
  21. data/vendor/assets/javascripts/jsts/algorithm/distance/DiscreteHausdorffDistance.js +228 -0
  22. data/vendor/assets/javascripts/jsts/algorithm/distance/DistanceToPoint.js +68 -0
  23. data/vendor/assets/javascripts/jsts/algorithm/distance/PointPairDistance.js +104 -0
  24. data/vendor/assets/javascripts/jsts/algorithm/locate/PointOnGeometryLocator.js +7 -0
  25. data/vendor/assets/javascripts/jsts/algorithm/locate/SimplePointInAreaLocator.js +102 -0
  26. data/vendor/assets/javascripts/jsts/geom/Coordinate.js +158 -0
  27. data/vendor/assets/javascripts/jsts/geom/CoordinateArrays.js +148 -0
  28. data/vendor/assets/javascripts/jsts/geom/CoordinateFilter.js +29 -0
  29. data/vendor/assets/javascripts/jsts/geom/CoordinateList.js +157 -0
  30. data/vendor/assets/javascripts/jsts/geom/CoordinateSequenceFilter.js +63 -0
  31. data/vendor/assets/javascripts/jsts/geom/Dimension.js +137 -0
  32. data/vendor/assets/javascripts/jsts/geom/Envelope.js +833 -0
  33. data/vendor/assets/javascripts/jsts/geom/Geometry.js +1535 -0
  34. data/vendor/assets/javascripts/jsts/geom/GeometryCollection.js +230 -0
  35. data/vendor/assets/javascripts/jsts/geom/GeometryComponentFilter.js +36 -0
  36. data/vendor/assets/javascripts/jsts/geom/GeometryFactory.js +263 -0
  37. data/vendor/assets/javascripts/jsts/geom/GeometryFilter.js +29 -0
  38. data/vendor/assets/javascripts/jsts/geom/IntersectionMatrix.js +650 -0
  39. data/vendor/assets/javascripts/jsts/geom/LineSegment.js +275 -0
  40. data/vendor/assets/javascripts/jsts/geom/LineString.js +299 -0
  41. data/vendor/assets/javascripts/jsts/geom/LinearRing.js +69 -0
  42. data/vendor/assets/javascripts/jsts/geom/Location.js +83 -0
  43. data/vendor/assets/javascripts/jsts/geom/MultiLineString.js +47 -0
  44. data/vendor/assets/javascripts/jsts/geom/MultiPoint.js +64 -0
  45. data/vendor/assets/javascripts/jsts/geom/MultiPolygon.js +64 -0
  46. data/vendor/assets/javascripts/jsts/geom/Point.js +197 -0
  47. data/vendor/assets/javascripts/jsts/geom/Polygon.js +263 -0
  48. data/vendor/assets/javascripts/jsts/geom/PrecisionModel.js +187 -0
  49. data/vendor/assets/javascripts/jsts/geom/Triangle.js +313 -0
  50. data/vendor/assets/javascripts/jsts/geom/util/GeometryCombiner.js +143 -0
  51. data/vendor/assets/javascripts/jsts/geom/util/GeometryExtracter.js +76 -0
  52. data/vendor/assets/javascripts/jsts/geom/util/GeometryTransformer.js +295 -0
  53. data/vendor/assets/javascripts/jsts/geom/util/LinearComponentExtracter.js +207 -0
  54. data/vendor/assets/javascripts/jsts/geom/util/PointExtracter.js +67 -0
  55. data/vendor/assets/javascripts/jsts/geom/util/PolygonExtracter.js +71 -0
  56. data/vendor/assets/javascripts/jsts/geomgraph/Depth.js +145 -0
  57. data/vendor/assets/javascripts/jsts/geomgraph/DirectedEdge.js +270 -0
  58. data/vendor/assets/javascripts/jsts/geomgraph/DirectedEdgeStar.js +388 -0
  59. data/vendor/assets/javascripts/jsts/geomgraph/Edge.js +291 -0
  60. data/vendor/assets/javascripts/jsts/geomgraph/EdgeEnd.js +188 -0
  61. data/vendor/assets/javascripts/jsts/geomgraph/EdgeEndStar.js +322 -0
  62. data/vendor/assets/javascripts/jsts/geomgraph/EdgeIntersection.js +122 -0
  63. data/vendor/assets/javascripts/jsts/geomgraph/EdgeIntersectionList.js +146 -0
  64. data/vendor/assets/javascripts/jsts/geomgraph/EdgeList.js +111 -0
  65. data/vendor/assets/javascripts/jsts/geomgraph/EdgeNodingValidator.js +76 -0
  66. data/vendor/assets/javascripts/jsts/geomgraph/EdgeRing.js +230 -0
  67. data/vendor/assets/javascripts/jsts/geomgraph/GeometryGraph.js +469 -0
  68. data/vendor/assets/javascripts/jsts/geomgraph/GraphComponent.js +181 -0
  69. data/vendor/assets/javascripts/jsts/geomgraph/Label.js +316 -0
  70. data/vendor/assets/javascripts/jsts/geomgraph/Node.js +105 -0
  71. data/vendor/assets/javascripts/jsts/geomgraph/NodeFactory.js +22 -0
  72. data/vendor/assets/javascripts/jsts/geomgraph/NodeMap.js +128 -0
  73. data/vendor/assets/javascripts/jsts/geomgraph/PlanarGraph.js +214 -0
  74. data/vendor/assets/javascripts/jsts/geomgraph/Position.js +63 -0
  75. data/vendor/assets/javascripts/jsts/geomgraph/Quadrant.js +143 -0
  76. data/vendor/assets/javascripts/jsts/geomgraph/TopologyLocation.js +251 -0
  77. data/vendor/assets/javascripts/jsts/geomgraph/index/EdgeSetIntersector.js +47 -0
  78. data/vendor/assets/javascripts/jsts/geomgraph/index/SegmentIntersector.js +298 -0
  79. data/vendor/assets/javascripts/jsts/geomgraph/index/SimpleEdgeSetIntersector.js +107 -0
  80. data/vendor/assets/javascripts/jsts/geomgraph/index/SimpleMCSweepLineIntersector.js +29 -0
  81. data/vendor/assets/javascripts/jsts/index/ArrayListVisitor.js +37 -0
  82. data/vendor/assets/javascripts/jsts/index/DoubleBits.js +132 -0
  83. data/vendor/assets/javascripts/jsts/index/IntervalSize.js +55 -0
  84. data/vendor/assets/javascripts/jsts/index/ItemVisitor.js +23 -0
  85. data/vendor/assets/javascripts/jsts/index/SpatialIndex.js +67 -0
  86. data/vendor/assets/javascripts/jsts/index/bintree/Bintree.js +224 -0
  87. data/vendor/assets/javascripts/jsts/index/bintree/Interval.js +160 -0
  88. data/vendor/assets/javascripts/jsts/index/bintree/Key.js +110 -0
  89. data/vendor/assets/javascripts/jsts/index/bintree/Node.js +204 -0
  90. data/vendor/assets/javascripts/jsts/index/bintree/NodeBase.js +220 -0
  91. data/vendor/assets/javascripts/jsts/index/bintree/Root.js +113 -0
  92. data/vendor/assets/javascripts/jsts/index/chain/MonotoneChain.js +244 -0
  93. data/vendor/assets/javascripts/jsts/index/chain/MonotoneChainBuilder.js +106 -0
  94. data/vendor/assets/javascripts/jsts/index/chain/MonotoneChainOverlapAction.js +56 -0
  95. data/vendor/assets/javascripts/jsts/index/chain/MonotoneChainSelectAction.js +44 -0
  96. data/vendor/assets/javascripts/jsts/index/kdtree/KdNode.js +171 -0
  97. data/vendor/assets/javascripts/jsts/index/kdtree/KdTree.js +218 -0
  98. data/vendor/assets/javascripts/jsts/index/quadtree/Key.js +134 -0
  99. data/vendor/assets/javascripts/jsts/index/quadtree/Node.js +220 -0
  100. data/vendor/assets/javascripts/jsts/index/quadtree/NodeBase.js +330 -0
  101. data/vendor/assets/javascripts/jsts/index/quadtree/Quadtree.js +228 -0
  102. data/vendor/assets/javascripts/jsts/index/quadtree/Root.js +105 -0
  103. data/vendor/assets/javascripts/jsts/index/strtree/AbstractNode.js +107 -0
  104. data/vendor/assets/javascripts/jsts/index/strtree/AbstractSTRtree.js +594 -0
  105. data/vendor/assets/javascripts/jsts/index/strtree/Boundable.js +37 -0
  106. data/vendor/assets/javascripts/jsts/index/strtree/BoundablePair.js +0 -0
  107. data/vendor/assets/javascripts/jsts/index/strtree/Interval.js +94 -0
  108. data/vendor/assets/javascripts/jsts/index/strtree/ItemBoundable.js +60 -0
  109. data/vendor/assets/javascripts/jsts/index/strtree/SIRtree.js +122 -0
  110. data/vendor/assets/javascripts/jsts/index/strtree/STRtree.js +450 -0
  111. data/vendor/assets/javascripts/jsts/io/GeoJSONParser.js +471 -0
  112. data/vendor/assets/javascripts/jsts/io/GeoJSONReader.js +58 -0
  113. data/vendor/assets/javascripts/jsts/io/GeoJSONWriter.js +38 -0
  114. data/vendor/assets/javascripts/jsts/io/OpenLayersParser.js +245 -0
  115. data/vendor/assets/javascripts/jsts/io/WKTParser.js +421 -0
  116. data/vendor/assets/javascripts/jsts/io/WKTReader.js +68 -0
  117. data/vendor/assets/javascripts/jsts/io/WKTWriter.js +61 -0
  118. data/vendor/assets/javascripts/jsts/noding/BasicSegmentString.js +87 -0
  119. data/vendor/assets/javascripts/jsts/noding/FastNodingValidator.js +127 -0
  120. data/vendor/assets/javascripts/jsts/noding/InteriorIntersectionFinder.js +171 -0
  121. data/vendor/assets/javascripts/jsts/noding/IntersectionAdder.js +198 -0
  122. data/vendor/assets/javascripts/jsts/noding/IntersectionFinderAdder.js +79 -0
  123. data/vendor/assets/javascripts/jsts/noding/MCIndexNoder.js +147 -0
  124. data/vendor/assets/javascripts/jsts/noding/NodableSegmentString.js +35 -0
  125. data/vendor/assets/javascripts/jsts/noding/NodedSegmentString.js +235 -0
  126. data/vendor/assets/javascripts/jsts/noding/Noder.js +41 -0
  127. data/vendor/assets/javascripts/jsts/noding/NodingValidator.js +5 -0
  128. data/vendor/assets/javascripts/jsts/noding/Octant.js +84 -0
  129. data/vendor/assets/javascripts/jsts/noding/OrientedCoordinateArray.js +94 -0
  130. data/vendor/assets/javascripts/jsts/noding/ScaledNoder.js +105 -0
  131. data/vendor/assets/javascripts/jsts/noding/SegmentIntersector.js +45 -0
  132. data/vendor/assets/javascripts/jsts/noding/SegmentNode.js +70 -0
  133. data/vendor/assets/javascripts/jsts/noding/SegmentNodeList.js +262 -0
  134. data/vendor/assets/javascripts/jsts/noding/SegmentPointComparator.js +78 -0
  135. data/vendor/assets/javascripts/jsts/noding/SegmentString.js +61 -0
  136. data/vendor/assets/javascripts/jsts/noding/SinglePassNoder.js +51 -0
  137. data/vendor/assets/javascripts/jsts/noding/snapround/HotPixel.js +271 -0
  138. data/vendor/assets/javascripts/jsts/noding/snapround/MCIndexPointSnapper.js +96 -0
  139. data/vendor/assets/javascripts/jsts/noding/snapround/MCIndexSnapRounder.js +147 -0
  140. data/vendor/assets/javascripts/jsts/operation/BoundaryOp.js +166 -0
  141. data/vendor/assets/javascripts/jsts/operation/GeometryGraphOperation.js +90 -0
  142. data/vendor/assets/javascripts/jsts/operation/IsSimpleOp.js +293 -0
  143. data/vendor/assets/javascripts/jsts/operation/buffer/BufferBuilder.js +317 -0
  144. data/vendor/assets/javascripts/jsts/operation/buffer/BufferInputLineSimplifier.js +294 -0
  145. data/vendor/assets/javascripts/jsts/operation/buffer/BufferOp.js +340 -0
  146. data/vendor/assets/javascripts/jsts/operation/buffer/BufferParameters.js +328 -0
  147. data/vendor/assets/javascripts/jsts/operation/buffer/BufferSubgraph.js +296 -0
  148. data/vendor/assets/javascripts/jsts/operation/buffer/OffsetCurveBuilder.js +369 -0
  149. data/vendor/assets/javascripts/jsts/operation/buffer/OffsetCurveSetBuilder.js +301 -0
  150. data/vendor/assets/javascripts/jsts/operation/buffer/OffsetSegmentGenerator.js +777 -0
  151. data/vendor/assets/javascripts/jsts/operation/buffer/OffsetSegmentString.js +109 -0
  152. data/vendor/assets/javascripts/jsts/operation/buffer/RightmostEdgeFinder.js +164 -0
  153. data/vendor/assets/javascripts/jsts/operation/buffer/SubgraphDepthLocater.js +220 -0
  154. data/vendor/assets/javascripts/jsts/operation/distance/ConnectedElementLocationFilter.js +67 -0
  155. data/vendor/assets/javascripts/jsts/operation/distance/DistanceOp.js +506 -0
  156. data/vendor/assets/javascripts/jsts/operation/distance/GeometryLocation.js +102 -0
  157. data/vendor/assets/javascripts/jsts/operation/overlay/LineBuilder.js +194 -0
  158. data/vendor/assets/javascripts/jsts/operation/overlay/MaximalEdgeRing.js +72 -0
  159. data/vendor/assets/javascripts/jsts/operation/overlay/MinimalEdgeRing.js +33 -0
  160. data/vendor/assets/javascripts/jsts/operation/overlay/OverlayNodeFactory.js +26 -0
  161. data/vendor/assets/javascripts/jsts/operation/overlay/OverlayOp.js +584 -0
  162. data/vendor/assets/javascripts/jsts/operation/overlay/PointBuilder.js +103 -0
  163. data/vendor/assets/javascripts/jsts/operation/overlay/PolygonBuilder.js +282 -0
  164. data/vendor/assets/javascripts/jsts/operation/overlay/snap/GeometrySnapper.js +228 -0
  165. data/vendor/assets/javascripts/jsts/operation/overlay/snap/LineStringSnapper.js +228 -0
  166. data/vendor/assets/javascripts/jsts/operation/overlay/snap/SnapIfNeededOverlayOp.js +85 -0
  167. data/vendor/assets/javascripts/jsts/operation/overlay/snap/SnapOverlayOp.js +134 -0
  168. data/vendor/assets/javascripts/jsts/operation/polygonize/EdgeRing.js +259 -0
  169. data/vendor/assets/javascripts/jsts/operation/polygonize/PolygonizeDirectedEdge.js +94 -0
  170. data/vendor/assets/javascripts/jsts/operation/polygonize/PolygonizeEdge.js +31 -0
  171. data/vendor/assets/javascripts/jsts/operation/polygonize/PolygonizeGraph.js +507 -0
  172. data/vendor/assets/javascripts/jsts/operation/polygonize/Polygonizer.js +259 -0
  173. data/vendor/assets/javascripts/jsts/operation/relate/EdgeEndBuilder.js +140 -0
  174. data/vendor/assets/javascripts/jsts/operation/relate/EdgeEndBundle.js +183 -0
  175. data/vendor/assets/javascripts/jsts/operation/relate/EdgeEndBundleStar.js +48 -0
  176. data/vendor/assets/javascripts/jsts/operation/relate/RelateComputer.js +444 -0
  177. data/vendor/assets/javascripts/jsts/operation/relate/RelateNode.js +46 -0
  178. data/vendor/assets/javascripts/jsts/operation/relate/RelateNodeFactory.js +25 -0
  179. data/vendor/assets/javascripts/jsts/operation/relate/RelateNodeGraph.js +118 -0
  180. data/vendor/assets/javascripts/jsts/operation/relate/RelateOp.js +75 -0
  181. data/vendor/assets/javascripts/jsts/operation/union/CascadedPolygonUnion.js +319 -0
  182. data/vendor/assets/javascripts/jsts/operation/union/PointGeometryUnion.js +118 -0
  183. data/vendor/assets/javascripts/jsts/operation/union/UnaryUnionOp.js +244 -0
  184. data/vendor/assets/javascripts/jsts/operation/union/UnionInteracting.js +156 -0
  185. data/vendor/assets/javascripts/jsts/operation/valid/ConnectedInteriorTester.js +259 -0
  186. data/vendor/assets/javascripts/jsts/operation/valid/ConsistentAreaTester.js +127 -0
  187. data/vendor/assets/javascripts/jsts/operation/valid/IndexedNestedRingTester.js +89 -0
  188. data/vendor/assets/javascripts/jsts/operation/valid/IsValidOp.js +619 -0
  189. data/vendor/assets/javascripts/jsts/operation/valid/TopologyValidationError.js +199 -0
  190. data/vendor/assets/javascripts/jsts/planargraph/DirectedEdge.js +232 -0
  191. data/vendor/assets/javascripts/jsts/planargraph/DirectedEdgeStar.js +168 -0
  192. data/vendor/assets/javascripts/jsts/planargraph/Edge.js +124 -0
  193. data/vendor/assets/javascripts/jsts/planargraph/GraphComponent.js +182 -0
  194. data/vendor/assets/javascripts/jsts/planargraph/Node.js +127 -0
  195. data/vendor/assets/javascripts/jsts/planargraph/NodeMap.js +76 -0
  196. data/vendor/assets/javascripts/jsts/planargraph/PlanarGraph.js +246 -0
  197. data/vendor/assets/javascripts/jsts/simplify/LineSegmentIndex.js +101 -0
  198. data/vendor/assets/javascripts/jsts/triangulate/DelaunayTriangulationBuilder.js +224 -0
  199. data/vendor/assets/javascripts/jsts/triangulate/IncrementalDelaunayTriangulator.js +111 -0
  200. data/vendor/assets/javascripts/jsts/triangulate/VoronoiDiagramBuilder.js +172 -0
  201. data/vendor/assets/javascripts/jsts/triangulate/quadedge/LastFoundQuadEdgeLocator.js +52 -0
  202. data/vendor/assets/javascripts/jsts/triangulate/quadedge/QuadEdge.js +437 -0
  203. data/vendor/assets/javascripts/jsts/triangulate/quadedge/QuadEdgeSubdivision.js +1064 -0
  204. data/vendor/assets/javascripts/jsts/triangulate/quadedge/TrianglePredicate.js +350 -0
  205. data/vendor/assets/javascripts/jsts/triangulate/quadedge/Vertex.js +496 -0
  206. data/vendor/assets/javascripts/jsts/util/Assert.js +80 -0
  207. data/vendor/assets/javascripts/jsts/util/AssertionFailedException.js +23 -0
  208. data/vendor/assets/javascripts/jsts/util/UniqueCoordinateArrayFilter.js +52 -0
  209. metadata +204 -1
@@ -0,0 +1,777 @@
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
+ /**
9
+ * Generates segments which form an offset curve. Supports all end cap and join
10
+ * options provided for buffering. Implements various heuristics to produce
11
+ * smoother, simpler curves which are still within a reasonable tolerance of the
12
+ * true curve.
13
+ * @constructor
14
+ */
15
+ jsts.operation.buffer.OffsetSegmentGenerator = function(precisionModel,
16
+ bufParams, distance) {
17
+ this.seg0 = new jsts.geom.LineSegment();
18
+ this.seg1 = new jsts.geom.LineSegment();
19
+ this.offset0 = new jsts.geom.LineSegment();
20
+ this.offset1 = new jsts.geom.LineSegment();
21
+
22
+ this.precisionModel = precisionModel;
23
+ this.bufParams = bufParams;
24
+
25
+ // compute intersections in full precision, to provide accuracy
26
+ // the points are rounded as they are inserted into the curve line
27
+ this.li = new jsts.algorithm.RobustLineIntersector();
28
+ this.filletAngleQuantum = Math.PI / 2.0 / bufParams.getQuadrantSegments();
29
+
30
+ /**
31
+ * Non-round joins cause issues with short closing segments, so don't use
32
+ * them. In any case, non-round joins only really make sense for relatively
33
+ * small buffer distances.
34
+ */
35
+ if (this.bufParams.getQuadrantSegments() >= 8 &&
36
+ this.bufParams.getJoinStyle() === jsts.operation.buffer.BufferParameters.JOIN_ROUND) {
37
+ this.closingSegLengthFactor = jsts.operation.buffer.OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR;
38
+ }
39
+ this.init(distance);
40
+ };
41
+
42
+
43
+ /**
44
+ * Factor which controls how close offset segments can be to skip adding a
45
+ * filler or mitre.
46
+ *
47
+ * @private
48
+ */
49
+ jsts.operation.buffer.OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR = 1.0E-3;
50
+
51
+
52
+ /**
53
+ * Factor which controls how close curve vertices on inside turns can be to be
54
+ * snapped
55
+ *
56
+ * @private
57
+ */
58
+ jsts.operation.buffer.OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-3;
59
+
60
+
61
+ /**
62
+ * Factor which controls how close curve vertices can be to be snapped
63
+ *
64
+ * @private
65
+ */
66
+ jsts.operation.buffer.OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-6;
67
+
68
+
69
+ /**
70
+ * Factor which determines how short closing segs can be for round buffers *
71
+ *
72
+ * @private
73
+ */
74
+ jsts.operation.buffer.OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR = 80;
75
+
76
+
77
+ /**
78
+ * the max error of approximation (distance) between a quad segment and the true
79
+ * fillet curve
80
+ *
81
+ * @private
82
+ */
83
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.maxCurveSegmentError = 0.0;
84
+
85
+
86
+ /**
87
+ * The angle quantum with which to approximate a fillet curve (based on the
88
+ * input # of quadrant segments)
89
+ *
90
+ * @private
91
+ */
92
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.filletAngleQuantum = null;
93
+
94
+
95
+ /**
96
+ * The Closing Segment Length Factor controls how long "closing segments" are.
97
+ * Closing segments are added at the middle of inside corners to ensure a
98
+ * smoother boundary for the buffer offset curve. In some cases (particularly
99
+ * for round joins with default-or-better quantization) the closing segments can
100
+ * be made quite short. This substantially improves performance (due to fewer
101
+ * intersections being created).
102
+ *
103
+ * A closingSegFactor of 0 results in lines to the corner vertex A
104
+ * closingSegFactor of 1 results in lines halfway to the corner vertex A
105
+ * closingSegFactor of 80 results in lines 1/81 of the way to the corner vertex
106
+ * (this option is reasonable for the very common default situation of round
107
+ * joins and quadrantSegs >= 8)
108
+ *
109
+ * @private
110
+ */
111
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.closingSegLengthFactor = 1;
112
+
113
+
114
+ /**
115
+ * @type {OffsetSegmentString}
116
+ * @private
117
+ */
118
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.segList = null;
119
+
120
+
121
+ /**
122
+ * @private
123
+ */
124
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.distance = 0.0;
125
+
126
+
127
+ /**
128
+ * @private
129
+ */
130
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.precisionModel = null;
131
+
132
+
133
+ /**
134
+ * @private
135
+ */
136
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.bufParams = null;
137
+
138
+
139
+ /**
140
+ * @private
141
+ */
142
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.li = null;
143
+
144
+
145
+ /**
146
+ * @type {Coordinate}
147
+ * @private
148
+ */
149
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.s0 = null;
150
+
151
+
152
+ /**
153
+ * @type {Coordinate}
154
+ * @private
155
+ */
156
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.s1 = null;
157
+
158
+
159
+ /**
160
+ * @type {Coordinate}
161
+ * @private
162
+ */
163
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.s2 = null;
164
+
165
+
166
+ /**
167
+ * @type {LineSegment}
168
+ * @private
169
+ */
170
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.seg0 = null;
171
+
172
+
173
+ /**
174
+ * @type {LineSegment}
175
+ * @private
176
+ */
177
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.seg1 = null;
178
+
179
+
180
+ /**
181
+ * @type {LineSegment}
182
+ * @private
183
+ */
184
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.offset0 = null;
185
+
186
+
187
+ /**
188
+ * @type {LineSegment}
189
+ * @private
190
+ */
191
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.offset1 = null;
192
+
193
+
194
+ /**
195
+ * @type {number}
196
+ * @private
197
+ */
198
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.side = 0;
199
+
200
+
201
+ /**
202
+ * @type {boolean}
203
+ * @private
204
+ */
205
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.hasNarrowConcaveAngle = false;
206
+
207
+
208
+ /**
209
+ * Tests whether the input has a narrow concave angle (relative to the offset
210
+ * distance). In this case the generated offset curve will contain
211
+ * self-intersections and heuristic closing segments. This is expected behaviour
212
+ * in the case of buffer curves. For pure offset curves, the output needs to be
213
+ * further treated before it can be used.
214
+ *
215
+ * @return true if the input has a narrow concave angle.
216
+ */
217
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.hasNarrowConcaveAngle = function() {
218
+ return this.hasNarrowConcaveAngle;
219
+ };
220
+
221
+
222
+ /**
223
+ * @private
224
+ */
225
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.init = function(distance) {
226
+ this.distance = distance;
227
+ this.maxCurveSegmentError = this.distance *
228
+ (1 - Math.cos(this.filletAngleQuantum / 2.0));
229
+ this.segList = new jsts.operation.buffer.OffsetSegmentString();
230
+ this.segList.setPrecisionModel(this.precisionModel);
231
+ /**
232
+ * Choose the min vertex separation as a small fraction of the offset
233
+ * distance.
234
+ */
235
+ this.segList
236
+ .setMinimumVertexDistance(this.distance *
237
+ jsts.operation.buffer.OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR);
238
+ };
239
+
240
+
241
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.initSideSegments = function(
242
+ s1, s2, side) {
243
+ this.s1 = s1;
244
+ this.s2 = s2;
245
+ this.side = side;
246
+ this.seg1.setCoordinates(this.s1, this.s2);
247
+ this.computeOffsetSegment(this.seg1, this.side, this.distance, this.offset1);
248
+ };
249
+
250
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.getCoordinates = function() {
251
+ return this.segList.getCoordinates();
252
+ };
253
+
254
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.closeRing = function() {
255
+ this.segList.closeRing();
256
+ };
257
+
258
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addSegments = function(
259
+ pt, isForward) {
260
+ this.segList.addPts(pt, isForward);
261
+ };
262
+
263
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addFirstSegment = function() {
264
+ this.segList.addPt(this.offset1.p0);
265
+ };
266
+
267
+
268
+ /**
269
+ * Add last offset point
270
+ */
271
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addLastSegment = function() {
272
+ this.segList.addPt(this.offset1.p1);
273
+ };
274
+
275
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addNextSegment = function(
276
+ p, addStartPoint) {
277
+ // s0-s1-s2 are the coordinates of the previous segment and the current one
278
+ this.s0 = this.s1;
279
+ this.s1 = this.s2;
280
+ this.s2 = p;
281
+ this.seg0.setCoordinates(this.s0, this.s1);
282
+ this.computeOffsetSegment(this.seg0, this.side, this.distance, this.offset0);
283
+ this.seg1.setCoordinates(this.s1, this.s2);
284
+ this.computeOffsetSegment(this.seg1, this.side, this.distance, this.offset1);
285
+
286
+ // do nothing if points are equal
287
+ if (this.s1.equals(this.s2))
288
+ return;
289
+
290
+ var orientation = jsts.algorithm.CGAlgorithms.computeOrientation(this.s0,
291
+ this.s1, this.s2);
292
+ var outsideTurn = (orientation === jsts.algorithm.CGAlgorithms.CLOCKWISE && this.side === jsts.geomgraph.Position.LEFT) ||
293
+ (orientation === jsts.algorithm.CGAlgorithms.COUNTERCLOCKWISE && this.side === jsts.geomgraph.Position.RIGHT);
294
+
295
+ if (orientation == 0) { // lines are collinear
296
+ this.addCollinear(addStartPoint);
297
+ } else if (outsideTurn) {
298
+ this.addOutsideTurn(orientation, addStartPoint);
299
+ } else { // inside turn
300
+ this.addInsideTurn(orientation, addStartPoint);
301
+ }
302
+ };
303
+
304
+
305
+ /**
306
+ * @private
307
+ */
308
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addCollinear = function(
309
+ addStartPoint) {
310
+ /**
311
+ * This test could probably be done more efficiently, but the situation of
312
+ * exact collinearity should be fairly rare.
313
+ */
314
+ this.li.computeIntersection(this.s0, this.s1, this.s1, this.s2);
315
+ var numInt = this.li.getIntersectionNum();
316
+ /**
317
+ * if numInt is < 2, the lines are parallel and in the same direction. In this
318
+ * case the point can be ignored, since the offset lines will also be
319
+ * parallel.
320
+ */
321
+ if (numInt >= 2) {
322
+ /**
323
+ * segments are collinear but reversing. Add an "end-cap" fillet all the way
324
+ * around to other direction This case should ONLY happen for LineStrings,
325
+ * so the orientation is always CW. (Polygons can never have two consecutive
326
+ * segments which are parallel but reversed, because that would be a self
327
+ * intersection.
328
+ *
329
+ */
330
+ if (this.bufParams.getJoinStyle() === jsts.operation.buffer.BufferParameters.JOIN_BEVEL ||
331
+ this.bufParams.getJoinStyle() === jsts.operation.buffer.BufferParameters.JOIN_MITRE) {
332
+ if (addStartPoint)
333
+ this.segList.addPt(this.offset0.p1);
334
+ this.segList.addPt(this.offset1.p0);
335
+ } else {
336
+ this.addFillet(this.s1, this.offset0.p1, this.offset1.p0,
337
+ jsts.algorithm.CGAlgorithms.CLOCKWISE, this.distance);
338
+ }
339
+ }
340
+ };
341
+
342
+
343
+ /**
344
+ * Adds the offset points for an outside (convex) turn
345
+ *
346
+ * @param orientation
347
+ * @param addStartPoint
348
+ * @private
349
+ */
350
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addOutsideTurn = function(
351
+ orientation, addStartPoint) {
352
+ /**
353
+ * Heuristic: If offset endpoints are very close together, just use one of
354
+ * them as the corner vertex. This avoids problems with computing mitre
355
+ * corners in the case where the two segments are almost parallel (which is
356
+ * hard to compute a robust intersection for).
357
+ */
358
+ if (this.offset0.p1.distance(this.offset1.p0) < this.distance *
359
+ jsts.operation.buffer.OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR) {
360
+ this.segList.addPt(this.offset0.p1);
361
+ return;
362
+ }
363
+
364
+ if (this.bufParams.getJoinStyle() === jsts.operation.buffer.BufferParameters.JOIN_MITRE) {
365
+ this.addMitreJoin(this.s1, this.offset0, this.offset1, this.distance);
366
+ } else if (this.bufParams.getJoinStyle() === jsts.operation.buffer.BufferParameters.JOIN_BEVEL) {
367
+ this.addBevelJoin(this.offset0, this.offset1);
368
+ } else {
369
+ // add a circular fillet connecting the endpoints of the offset segments
370
+ if (addStartPoint)
371
+ this.segList.addPt(this.offset0.p1);
372
+ // TESTING - comment out to produce beveled joins
373
+ this.addFillet(this.s1, this.offset0.p1, this.offset1.p0, orientation,
374
+ this.distance);
375
+ this.segList.addPt(this.offset1.p0);
376
+ }
377
+ };
378
+
379
+
380
+ /**
381
+ * Adds the offset points for an inside (concave) turn.
382
+ *
383
+ * @param orientation
384
+ * @param addStartPoint
385
+ * @private
386
+ */
387
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addInsideTurn = function(
388
+ orientation, addStartPoint) {
389
+ /**
390
+ * add intersection point of offset segments (if any)
391
+ */
392
+ this.li.computeIntersection(this.offset0.p0, this.offset0.p1, this.offset1.p0, this.offset1.p1);
393
+ if (this.li.hasIntersection()) {
394
+ this.segList.addPt(this.li.getIntersection(0));
395
+ } else {
396
+ /**
397
+ * If no intersection is detected, it means the angle is so small and/or the
398
+ * offset so large that the offsets segments don't intersect. In this case
399
+ * we must add a "closing segment" to make sure the buffer curve is
400
+ * continuous, fairly smooth (e.g. no sharp reversals in direction) and
401
+ * tracks the buffer correctly around the corner. The curve connects the
402
+ * endpoints of the segment offsets to points which lie toward the centre
403
+ * point of the corner. The joining curve will not appear in the final
404
+ * buffer outline, since it is completely internal to the buffer polygon.
405
+ *
406
+ * In complex buffer cases the closing segment may cut across many other
407
+ * segments in the generated offset curve. In order to improve the
408
+ * performance of the noding, the closing segment should be kept as short as
409
+ * possible. (But not too short, since that would defeat its purpose). This
410
+ * is the purpose of the closingSegFactor heuristic value.
411
+ */
412
+
413
+ /**
414
+ * The intersection test above is vulnerable to robustness errors; i.e. it
415
+ * may be that the offsets should intersect very close to their endpoints,
416
+ * but aren't reported as such due to rounding. To handle this situation
417
+ * appropriately, we use the following test: If the offset points are very
418
+ * close, don't add closing segments but simply use one of the offset points
419
+ */
420
+ this.hasNarrowConcaveAngle = true;
421
+ // System.out.println("NARROW ANGLE - distance = " + distance);
422
+ if (this.offset0.p1.distance(this.offset1.p0) < this.distance *
423
+ jsts.operation.buffer.OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) {
424
+ this.segList.addPt(this.offset0.p1);
425
+ } else {
426
+ // add endpoint of this segment offset
427
+ this.segList.addPt(this.offset0.p1);
428
+
429
+ /**
430
+ * Add "closing segment" of required length.
431
+ */
432
+ if (this.closingSegLengthFactor > 0) {
433
+ var mid0 = new jsts.geom.Coordinate((this.closingSegLengthFactor *
434
+ this.offset0.p1.x + this.s1.x) /
435
+ (this.closingSegLengthFactor + 1), (this.closingSegLengthFactor *
436
+ this.offset0.p1.y + this.s1.y) /
437
+ (this.closingSegLengthFactor + 1));
438
+ this.segList.addPt(mid0);
439
+ var mid1 = new jsts.geom.Coordinate((this.closingSegLengthFactor *
440
+ this.offset1.p0.x + this.s1.x) /
441
+ (this.closingSegLengthFactor + 1), (this.closingSegLengthFactor *
442
+ this.offset1.p0.y + this.s1.y) /
443
+ (this.closingSegLengthFactor + 1));
444
+ this.segList.addPt(mid1);
445
+ } else {
446
+ /**
447
+ * This branch is not expected to be used except for testing purposes.
448
+ * It is equivalent to the JTS 1.9 logic for closing segments (which
449
+ * results in very poor performance for large buffer distances)
450
+ */
451
+ this.segList.addPt(this.s1);
452
+ }
453
+
454
+ // */
455
+ // add start point of next segment offset
456
+ this.segList.addPt(this.offset1.p0);
457
+ }
458
+ }
459
+ };
460
+
461
+
462
+ /**
463
+ * Compute an offset segment for an input segment on a given side and at a given
464
+ * distance. The offset points are computed in full double precision, for
465
+ * accuracy.
466
+ *
467
+ * @param seg
468
+ * the segment to offset.
469
+ * @param side
470
+ * the side of the segment ( {@link Position} ) the offset lies on.
471
+ * @param distance
472
+ * the offset distance.
473
+ * @param offset
474
+ * the points computed for the offset segment.
475
+ * @private
476
+ */
477
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.computeOffsetSegment = function(
478
+ seg, side, distance, offset) {
479
+ var sideSign = side === jsts.geomgraph.Position.LEFT ? 1 : -1;
480
+ var dx = seg.p1.x - seg.p0.x;
481
+ var dy = seg.p1.y - seg.p0.y;
482
+ var len = Math.sqrt(dx * dx + dy * dy);
483
+ // u is the vector that is the length of the offset, in the direction of the
484
+ // segment
485
+ var ux = sideSign * distance * dx / len;
486
+ var uy = sideSign * distance * dy / len;
487
+ offset.p0.x = seg.p0.x - uy;
488
+ offset.p0.y = seg.p0.y + ux;
489
+ offset.p1.x = seg.p1.x - uy;
490
+ offset.p1.y = seg.p1.y + ux;
491
+ };
492
+
493
+
494
+ /**
495
+ * Add an end cap around point p1, terminating a line segment coming from p0
496
+ */
497
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addLineEndCap = function(
498
+ p0, p1) {
499
+ var seg = new jsts.geom.LineSegment(p0, p1);
500
+
501
+ var offsetL = new jsts.geom.LineSegment();
502
+ this.computeOffsetSegment(seg, jsts.geomgraph.Position.LEFT, this.distance,
503
+ offsetL);
504
+ var offsetR = new jsts.geom.LineSegment();
505
+ this.computeOffsetSegment(seg, jsts.geomgraph.Position.RIGHT, this.distance,
506
+ offsetR);
507
+
508
+ var dx = p1.x - p0.x;
509
+ var dy = p1.y - p0.y;
510
+ var angle = Math.atan2(dy, dx);
511
+
512
+ switch (this.bufParams.getEndCapStyle()) {
513
+ case jsts.operation.buffer.BufferParameters.CAP_ROUND:
514
+ // add offset seg points with a fillet between them
515
+ this.segList.addPt(offsetL.p1);
516
+ this.addFillet(p1, angle + Math.PI / 2, angle - Math.PI / 2,
517
+ jsts.algorithm.CGAlgorithms.CLOCKWISE, this.distance);
518
+ this.segList.addPt(offsetR.p1);
519
+ break;
520
+ case jsts.operation.buffer.BufferParameters.CAP_FLAT:
521
+ // only offset segment points are added
522
+ this.segList.addPt(offsetL.p1);
523
+ this.segList.addPt(offsetR.p1);
524
+ break;
525
+ case jsts.operation.buffer.BufferParameters.CAP_SQUARE:
526
+ // add a square defined by extensions of the offset segment endpoints
527
+ var squareCapSideOffset = new jsts.geom.Coordinate();
528
+ squareCapSideOffset.x = Math.abs(this.distance) * Math.cos(angle);
529
+ squareCapSideOffset.y = Math.abs(this.distance) * Math.sin(angle);
530
+
531
+ var squareCapLOffset = new jsts.geom.Coordinate(offsetL.p1.x +
532
+ squareCapSideOffset.x, offsetL.p1.y + squareCapSideOffset.y);
533
+ var squareCapROffset = new jsts.geom.Coordinate(offsetR.p1.x +
534
+ squareCapSideOffset.x, offsetR.p1.y + squareCapSideOffset.y);
535
+ this.segList.addPt(squareCapLOffset);
536
+ this.segList.addPt(squareCapROffset);
537
+ break;
538
+
539
+ }
540
+ };
541
+
542
+
543
+ /**
544
+ * Adds a mitre join connecting the two reflex offset segments. The mitre will
545
+ * be beveled if it exceeds the mitre ratio limit.
546
+ *
547
+ * @param offset0
548
+ * the first offset segment.
549
+ * @param offset1
550
+ * the second offset segment.
551
+ * @param distance
552
+ * the offset distance.
553
+ * @private
554
+ */
555
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addMitreJoin = function(
556
+ p, offset0, offset1, distance) {
557
+ var isMitreWithinLimit = true;
558
+ var intPt = null;
559
+
560
+ /**
561
+ * This computation is unstable if the offset segments are nearly collinear.
562
+ * Howver, this situation should have been eliminated earlier by the check for
563
+ * whether the offset segment endpoints are almost coincident
564
+ */
565
+ try {
566
+ intPt = jsts.algorithm.HCoordinate.intersection(offset0.p0, offset0.p1,
567
+ offset1.p0, offset1.p1);
568
+
569
+ var mitreRatio = distance <= 0.0 ? 1.0 : intPt.distance(p) /
570
+ Math.abs(distance);
571
+
572
+ if (mitreRatio > this.bufParams.getMitreLimit())
573
+ this.isMitreWithinLimit = false;
574
+ } catch (e) {
575
+ if (e instanceof jsts.error.NotRepresentableError) {
576
+ intPt = new jsts.geom.Coordinate(0, 0);
577
+ this.isMitreWithinLimit = false;
578
+ }
579
+ }
580
+
581
+ if (isMitreWithinLimit) {
582
+ this.segList.addPt(intPt);
583
+ } else {
584
+ this.addLimitedMitreJoin(offset0, offset1, distance, bufParams
585
+ .getMitreLimit());
586
+ // addBevelJoin(offset0, offset1);
587
+ }
588
+ };
589
+
590
+
591
+ /**
592
+ * Adds a limited mitre join connecting the two reflex offset segments. A
593
+ * limited mitre is a mitre which is beveled at the distance determined by the
594
+ * mitre ratio limit.
595
+ *
596
+ * @param offset0
597
+ * the first offset segment.
598
+ * @param offset1
599
+ * the second offset segment.
600
+ * @param distance
601
+ * the offset distance.
602
+ * @param mitreLimit
603
+ * the mitre limit ratio.
604
+ * @private
605
+ */
606
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addLimitedMitreJoin = function(
607
+ offset0, offset1, distance, mitreLimit) {
608
+ var basePt = this.seg0.p1;
609
+
610
+ var ang0 = jsts.algorithm.Angle.angle(basePt, this.seg0.p0);
611
+ var ang1 = jsts.algorithm.Angle.angle(basePt, this.seg1.p1);
612
+
613
+ // oriented angle between segments
614
+ var angDiff = jsts.algorithm.Angle.angleBetweenOriented(this.seg0.p0, basePt,
615
+ this.seg1.p1);
616
+ // half of the interior angle
617
+ var angDiffHalf = angDiff / 2;
618
+
619
+ // angle for bisector of the interior angle between the segments
620
+ var midAng = jsts.algorithm.Angle.normalize(ang0 + angDiffHalf);
621
+ // rotating this by PI gives the bisector of the reflex angle
622
+ var mitreMidAng = jsts.algorithm.Angle.normalize(midAng + Math.PI);
623
+
624
+ // the miterLimit determines the distance to the mitre bevel
625
+ var mitreDist = mitreLimit * distance;
626
+ // the bevel delta is the difference between the buffer distance
627
+ // and half of the length of the bevel segment
628
+ var bevelDelta = mitreDist * Math.abs(Math.sin(angDiffHalf));
629
+ var bevelHalfLen = distance - bevelDelta;
630
+
631
+ // compute the midpoint of the bevel segment
632
+ var bevelMidX = basePt.x + mitreDist * Math.cos(mitreMidAng);
633
+ var bevelMidY = basePt.y + mitreDist * Math.sin(mitreMidAng);
634
+ var bevelMidPt = new jsts.geom.Coordinate(bevelMidX, bevelMidY);
635
+
636
+ // compute the mitre midline segment from the corner point to the bevel
637
+ // segment midpoint
638
+ var mitreMidLine = new jsts.geom.LineSegment(basePt, bevelMidPt);
639
+
640
+ // finally the bevel segment endpoints are computed as offsets from
641
+ // the mitre midline
642
+ var bevelEndLeft = mitreMidLine.pointAlongOffset(1.0, bevelHalfLen);
643
+ var bevelEndRight = mitreMidLine.pointAlongOffset(1.0, -bevelHalfLen);
644
+
645
+ if (this.side == jsts.geomgraph.Position.LEFT) {
646
+ this.segList.addPt(bevelEndLeft);
647
+ this.segList.addPt(bevelEndRight);
648
+ } else {
649
+ this.segList.addPt(bevelEndRight);
650
+ this.segList.addPt(bevelEndLeft);
651
+ }
652
+ };
653
+
654
+
655
+ /**
656
+ * Adds a bevel join connecting the two offset segments around a reflex corner.
657
+ *
658
+ * @param {LineSegment}
659
+ * offset0 the first offset segment.
660
+ * @param {LineSegment}
661
+ * offset1 the second offset segment.
662
+ * @private
663
+ */
664
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addBevelJoin = function(
665
+ offset0, offset1) {
666
+ this.segList.addPt(offset0.p1);
667
+ this.segList.addPt(offset1.p0);
668
+ };
669
+
670
+
671
+ /**
672
+ * Add points for a circular fillet around a reflex corner. Adds the start and
673
+ * end points
674
+ *
675
+ * @param p
676
+ * base point of curve.
677
+ * @param p0
678
+ * start point of fillet curve.
679
+ * @param p1
680
+ * endpoint of fillet curve.
681
+ * @param direction
682
+ * the orientation of the fillet.
683
+ * @param radius
684
+ * the radius of the fillet.
685
+ * @private
686
+ */
687
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addFillet = function(p,
688
+ p0, p1, direction, radius) {
689
+ if (!(p1 instanceof jsts.geom.Coordinate)) {
690
+ this.addFillet2.apply(this, arguments);
691
+ return;
692
+ }
693
+
694
+ var dx0 = p0.x - p.x;
695
+ var dy0 = p0.y - p.y;
696
+ var startAngle = Math.atan2(dy0, dx0);
697
+ var dx1 = p1.x - p.x;
698
+ var dy1 = p1.y - p.y;
699
+ var endAngle = Math.atan2(dy1, dx1);
700
+
701
+ if (direction === jsts.algorithm.CGAlgorithms.CLOCKWISE) {
702
+ if (startAngle <= endAngle)
703
+ startAngle += 2.0 * Math.PI;
704
+ } else { // direction == COUNTERCLOCKWISE
705
+ if (startAngle >= endAngle)
706
+ startAngle -= 2.0 * Math.PI;
707
+ }
708
+ this.segList.addPt(p0);
709
+ this.addFillet(p, startAngle, endAngle, direction, radius);
710
+ this.segList.addPt(p1);
711
+ };
712
+
713
+
714
+ /**
715
+ * Adds points for a circular fillet arc between two specified angles. The start
716
+ * and end point for the fillet are not added - the caller must add them if
717
+ * required.
718
+ *
719
+ * @param direction
720
+ * is -1 for a CW angle, 1 for a CCW angle.
721
+ * @param radius
722
+ * the radius of the fillet.
723
+ * @private
724
+ */
725
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.addFillet2 = function(p,
726
+ startAngle, endAngle, direction, radius) {
727
+ var directionFactor = direction === jsts.algorithm.CGAlgorithms.CLOCKWISE ? -1
728
+ : 1;
729
+
730
+ var totalAngle = Math.abs(startAngle - endAngle);
731
+ var nSegs = parseInt((totalAngle / this.filletAngleQuantum + 0.5));
732
+
733
+ if (nSegs < 1)
734
+ return; // no segments because angle is less than increment - nothing to do!
735
+
736
+ var initAngle, currAngleInc;
737
+
738
+ // choose angle increment so that each segment has equal length
739
+ initAngle = 0.0;
740
+ currAngleInc = totalAngle / nSegs;
741
+
742
+ var currAngle = initAngle;
743
+ var pt = new jsts.geom.Coordinate();
744
+ while (currAngle < totalAngle) {
745
+ var angle = startAngle + directionFactor * currAngle;
746
+ pt.x = p.x + radius * Math.cos(angle);
747
+ pt.y = p.y + radius * Math.sin(angle);
748
+ this.segList.addPt(pt);
749
+ currAngle += currAngleInc;
750
+ }
751
+ };
752
+
753
+
754
+ /**
755
+ * Creates a CW circle around a point
756
+ */
757
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.createCircle = function(
758
+ p) {
759
+ // add start point
760
+ var pt = new jsts.geom.Coordinate(p.x + this.distance, p.y);
761
+ this.segList.addPt(pt);
762
+ this.addFillet(p, 0.0, 2.0 * Math.PI, -1, this.distance);
763
+ this.segList.closeRing();
764
+ };
765
+
766
+
767
+ /**
768
+ * Creates a CW square around a point
769
+ */
770
+ jsts.operation.buffer.OffsetSegmentGenerator.prototype.createSquare = function(
771
+ p) {
772
+ this.segList.addPt(new jsts.geom.Coordinate(p.x + distance, p.y + distance));
773
+ this.segList.addPt(new jsts.geom.Coordinate(p.x + distance, p.y - distance));
774
+ this.segList.addPt(new jsts.geom.Coordinate(p.x - distance, p.y - distance));
775
+ this.segList.addPt(new jsts.geom.Coordinate(p.x - distance, p.y + distance));
776
+ this.segList.closeRing();
777
+ };