node-red-contrib-tak-registration 0.11.5 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/node_modules/@types/node/README.md +1 -1
  2. package/node_modules/@types/node/buffer.d.ts +8 -7
  3. package/node_modules/@types/node/crypto.d.ts +38 -7
  4. package/node_modules/@types/node/dgram.d.ts +10 -0
  5. package/node_modules/@types/node/diagnostics_channel.d.ts +355 -1
  6. package/node_modules/@types/node/fs.d.ts +28 -8
  7. package/node_modules/@types/node/globals.d.ts +26 -0
  8. package/node_modules/@types/node/http.d.ts +6 -7
  9. package/node_modules/@types/node/module.d.ts +14 -0
  10. package/node_modules/@types/node/net.d.ts +8 -3
  11. package/node_modules/@types/node/package.json +3 -4
  12. package/node_modules/@types/node/perf_hooks.d.ts +12 -6
  13. package/node_modules/@types/node/process.d.ts +25 -3
  14. package/node_modules/@types/node/querystring.d.ts +3 -3
  15. package/node_modules/@types/node/stream/web.d.ts +17 -1
  16. package/node_modules/@types/node/string_decoder.d.ts +2 -2
  17. package/node_modules/@types/node/test.d.ts +98 -15
  18. package/node_modules/@types/node/tls.d.ts +1 -1
  19. package/node_modules/@types/node/ts4.8/buffer.d.ts +8 -7
  20. package/node_modules/@types/node/ts4.8/crypto.d.ts +41 -9
  21. package/node_modules/@types/node/ts4.8/dgram.d.ts +10 -0
  22. package/node_modules/@types/node/ts4.8/diagnostics_channel.d.ts +355 -1
  23. package/node_modules/@types/node/ts4.8/fs.d.ts +28 -8
  24. package/node_modules/@types/node/ts4.8/globals.d.ts +26 -0
  25. package/node_modules/@types/node/ts4.8/http.d.ts +6 -7
  26. package/node_modules/@types/node/ts4.8/module.d.ts +14 -0
  27. package/node_modules/@types/node/ts4.8/net.d.ts +8 -3
  28. package/node_modules/@types/node/ts4.8/perf_hooks.d.ts +13 -7
  29. package/node_modules/@types/node/ts4.8/process.d.ts +25 -3
  30. package/node_modules/@types/node/ts4.8/querystring.d.ts +3 -3
  31. package/node_modules/@types/node/ts4.8/stream/web.d.ts +17 -1
  32. package/node_modules/@types/node/ts4.8/string_decoder.d.ts +2 -2
  33. package/node_modules/@types/node/ts4.8/test.d.ts +98 -15
  34. package/node_modules/@types/node/ts4.8/tls.d.ts +1 -1
  35. package/node_modules/@types/node/ts4.8/url.d.ts +59 -42
  36. package/node_modules/@types/node/ts4.8/util.d.ts +1 -1
  37. package/node_modules/@types/node/ts4.8/v8.d.ts +134 -5
  38. package/node_modules/@types/node/ts4.8/wasi.d.ts +26 -5
  39. package/node_modules/@types/node/url.d.ts +59 -42
  40. package/node_modules/@types/node/v8.d.ts +134 -5
  41. package/node_modules/@types/node/wasi.d.ts +26 -5
  42. package/node_modules/axios/CHANGELOG.md +53 -0
  43. package/node_modules/axios/README.md +47 -5
  44. package/node_modules/axios/dist/axios.js +368 -4
  45. package/node_modules/axios/dist/axios.js.map +1 -1
  46. package/node_modules/axios/dist/axios.min.js +1 -1
  47. package/node_modules/axios/dist/axios.min.js.map +1 -1
  48. package/node_modules/axios/dist/browser/axios.cjs +28 -4
  49. package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  50. package/node_modules/axios/dist/esm/axios.js +28 -4
  51. package/node_modules/axios/dist/esm/axios.js.map +1 -1
  52. package/node_modules/axios/dist/esm/axios.min.js +1 -1
  53. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  54. package/node_modules/axios/dist/node/axios.cjs +34 -6
  55. package/node_modules/axios/dist/node/axios.cjs.map +1 -1
  56. package/node_modules/axios/index.d.cts +1 -1
  57. package/node_modules/axios/index.d.ts +1 -1
  58. package/node_modules/axios/lib/adapters/http.js +6 -2
  59. package/node_modules/axios/lib/core/Axios.js +22 -1
  60. package/node_modules/axios/lib/env/data.js +1 -1
  61. package/node_modules/axios/lib/helpers/combineURLs.js +1 -1
  62. package/node_modules/axios/lib/helpers/formDataToJSON.js +3 -0
  63. package/node_modules/axios/package.json +2 -2
  64. package/node_modules/call-bind/CHANGELOG.md +16 -0
  65. package/node_modules/call-bind/index.js +2 -11
  66. package/node_modules/call-bind/package.json +11 -6
  67. package/node_modules/define-data-property/CHANGELOG.md +29 -0
  68. package/node_modules/define-data-property/index.d.ts +12 -3
  69. package/node_modules/define-data-property/index.js +4 -16
  70. package/node_modules/define-data-property/package.json +26 -33
  71. package/node_modules/define-data-property/test/index.js +10 -10
  72. package/node_modules/es-define-property/.eslintrc +13 -0
  73. package/node_modules/es-define-property/.github/FUNDING.yml +12 -0
  74. package/node_modules/es-define-property/.nycrc +9 -0
  75. package/node_modules/es-define-property/CHANGELOG.md +15 -0
  76. package/node_modules/es-define-property/LICENSE +21 -0
  77. package/node_modules/es-define-property/README.md +49 -0
  78. package/node_modules/es-define-property/index.d.ts +3 -0
  79. package/node_modules/es-define-property/index.js +16 -0
  80. package/node_modules/es-define-property/package.json +81 -0
  81. package/node_modules/es-define-property/test/index.js +55 -0
  82. package/node_modules/es-define-property/tsconfig.json +50 -0
  83. package/node_modules/es-errors/.eslintrc +5 -0
  84. package/node_modules/es-errors/.github/FUNDING.yml +12 -0
  85. package/node_modules/es-errors/CHANGELOG.md +40 -0
  86. package/node_modules/es-errors/LICENSE +21 -0
  87. package/node_modules/es-errors/README.md +55 -0
  88. package/node_modules/es-errors/eval.d.ts +3 -0
  89. package/node_modules/es-errors/eval.js +4 -0
  90. package/node_modules/es-errors/index.d.ts +3 -0
  91. package/node_modules/es-errors/index.js +4 -0
  92. package/node_modules/es-errors/package.json +80 -0
  93. package/node_modules/es-errors/range.d.ts +3 -0
  94. package/node_modules/es-errors/range.js +4 -0
  95. package/node_modules/es-errors/ref.d.ts +3 -0
  96. package/node_modules/es-errors/ref.js +4 -0
  97. package/node_modules/es-errors/syntax.d.ts +3 -0
  98. package/node_modules/es-errors/syntax.js +4 -0
  99. package/node_modules/es-errors/test/index.js +19 -0
  100. package/node_modules/es-errors/tsconfig.json +49 -0
  101. package/node_modules/es-errors/type.d.ts +3 -0
  102. package/node_modules/es-errors/type.js +4 -0
  103. package/node_modules/es-errors/uri.d.ts +3 -0
  104. package/node_modules/es-errors/uri.js +4 -0
  105. package/node_modules/fast-xml-parser/CHANGELOG.md +3 -0
  106. package/node_modules/fast-xml-parser/README.md +2 -1
  107. package/node_modules/fast-xml-parser/package.json +4 -1
  108. package/node_modules/fast-xml-parser/src/fxp.d.ts +363 -69
  109. package/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js +5 -5
  110. package/node_modules/follow-redirects/index.js +114 -75
  111. package/node_modules/follow-redirects/package.json +1 -1
  112. package/node_modules/get-intrinsic/CHANGELOG.md +18 -0
  113. package/node_modules/get-intrinsic/index.js +15 -7
  114. package/node_modules/get-intrinsic/package.json +12 -12
  115. package/node_modules/has-property-descriptors/CHANGELOG.md +8 -0
  116. package/node_modules/has-property-descriptors/index.js +3 -14
  117. package/node_modules/has-property-descriptors/package.json +5 -5
  118. package/node_modules/has-proto/CHANGELOG.md +15 -0
  119. package/node_modules/has-proto/index.d.ts +3 -0
  120. package/node_modules/has-proto/index.js +5 -1
  121. package/node_modules/has-proto/package.json +9 -5
  122. package/node_modules/has-proto/tsconfig.json +49 -0
  123. package/node_modules/has-tostringtag/.eslintrc +0 -6
  124. package/node_modules/has-tostringtag/.nycrc +13 -0
  125. package/node_modules/has-tostringtag/CHANGELOG.md +22 -0
  126. package/node_modules/has-tostringtag/index.d.ts +3 -0
  127. package/node_modules/has-tostringtag/index.js +1 -0
  128. package/node_modules/has-tostringtag/package.json +37 -13
  129. package/node_modules/has-tostringtag/shams.d.ts +3 -0
  130. package/node_modules/has-tostringtag/shams.js +1 -0
  131. package/node_modules/has-tostringtag/test/shams/core-js.js +3 -0
  132. package/node_modules/has-tostringtag/test/shams/get-own-property-symbols.js +2 -0
  133. package/node_modules/has-tostringtag/test/tests.js +2 -1
  134. package/node_modules/has-tostringtag/tsconfig.json +49 -0
  135. package/node_modules/hasown/CHANGELOG.md +8 -0
  136. package/node_modules/hasown/index.d.ts +3 -3
  137. package/node_modules/hasown/index.js +1 -1
  138. package/node_modules/hasown/package.json +13 -15
  139. package/node_modules/polygon-clipping/README.md +29 -26
  140. package/node_modules/polygon-clipping/dist/polygon-clipping.cjs.js +1398 -1421
  141. package/node_modules/polygon-clipping/dist/polygon-clipping.d.ts +13 -10
  142. package/node_modules/polygon-clipping/dist/polygon-clipping.esm.js +1139 -1427
  143. package/node_modules/polygon-clipping/dist/polygon-clipping.umd.js +1770 -1831
  144. package/node_modules/polygon-clipping/dist/polygon-clipping.umd.min.js +22 -8
  145. package/node_modules/polygon-clipping/dist/polygon-clipping.umd.min.js.map +1 -1
  146. package/node_modules/polygon-clipping/node_modules/robust-predicates/LICENSE +24 -0
  147. package/node_modules/polygon-clipping/node_modules/robust-predicates/README.md +82 -0
  148. package/node_modules/polygon-clipping/node_modules/robust-predicates/esm/incircle.js +765 -0
  149. package/node_modules/polygon-clipping/node_modules/robust-predicates/esm/insphere.js +766 -0
  150. package/node_modules/polygon-clipping/node_modules/robust-predicates/esm/orient2d.js +184 -0
  151. package/node_modules/polygon-clipping/node_modules/robust-predicates/esm/orient3d.js +462 -0
  152. package/node_modules/polygon-clipping/node_modules/robust-predicates/esm/util.js +138 -0
  153. package/node_modules/polygon-clipping/node_modules/robust-predicates/index.d.ts +49 -0
  154. package/node_modules/polygon-clipping/node_modules/robust-predicates/index.js +5 -0
  155. package/node_modules/polygon-clipping/node_modules/robust-predicates/package.json +75 -0
  156. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/incircle.js +908 -0
  157. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/incircle.min.js +1 -0
  158. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/insphere.js +914 -0
  159. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/insphere.min.js +1 -0
  160. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/orient2d.js +280 -0
  161. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/orient2d.min.js +1 -0
  162. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/orient3d.js +601 -0
  163. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/orient3d.min.js +1 -0
  164. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/predicates.js +2328 -0
  165. package/node_modules/polygon-clipping/node_modules/robust-predicates/umd/predicates.min.js +1 -0
  166. package/node_modules/polygon-clipping/package.json +30 -25
  167. package/node_modules/protobufjs/dist/light/protobuf.js +4 -4
  168. package/node_modules/protobufjs/dist/light/protobuf.js.map +1 -1
  169. package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
  170. package/node_modules/protobufjs/dist/light/protobuf.min.js.map +1 -1
  171. package/node_modules/protobufjs/dist/minimal/protobuf.js +2 -2
  172. package/node_modules/protobufjs/dist/minimal/protobuf.min.js +2 -2
  173. package/node_modules/protobufjs/dist/protobuf.js +4 -4
  174. package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
  175. package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
  176. package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
  177. package/node_modules/protobufjs/package.json +1 -1
  178. package/node_modules/protobufjs/src/root.js +2 -2
  179. package/node_modules/regexp.prototype.flags/CHANGELOG.md +13 -0
  180. package/node_modules/regexp.prototype.flags/implementation.js +2 -2
  181. package/node_modules/regexp.prototype.flags/package.json +11 -10
  182. package/node_modules/regexp.prototype.flags/test/tests.js +13 -13
  183. package/node_modules/set-function-length/CHANGELOG.md +18 -0
  184. package/node_modules/set-function-length/env.d.ts +6 -0
  185. package/node_modules/set-function-length/env.d.ts.map +1 -0
  186. package/node_modules/set-function-length/env.js +9 -4
  187. package/node_modules/set-function-length/index.d.ts +7 -0
  188. package/node_modules/set-function-length/index.d.ts.map +1 -0
  189. package/node_modules/set-function-length/index.js +6 -3
  190. package/node_modules/set-function-length/package.json +33 -13
  191. package/node_modules/set-function-length/tsconfig.json +59 -0
  192. package/node_modules/set-function-name/.eslintrc +1 -0
  193. package/node_modules/set-function-name/CHANGELOG.md +9 -0
  194. package/node_modules/set-function-name/index.d.ts +5 -0
  195. package/node_modules/set-function-name/index.js +4 -3
  196. package/node_modules/set-function-name/package.json +28 -9
  197. package/node_modules/set-function-name/tsconfig.json +59 -0
  198. package/package.json +4 -4
  199. package/tak-ingest.js +4 -0
  200. package/node_modules/define-data-property/index.d.ts.map +0 -1
  201. package/node_modules/hasown/index.d.ts.map +0 -1
  202. package/node_modules/polygon-clipping/CHANGELOG.md +0 -129
@@ -1,26 +1,5 @@
1
1
  import SplayTree from 'splaytree';
2
-
3
- function _classCallCheck(instance, Constructor) {
4
- if (!(instance instanceof Constructor)) {
5
- throw new TypeError("Cannot call a class as a function");
6
- }
7
- }
8
-
9
- function _defineProperties(target, props) {
10
- for (var i = 0; i < props.length; i++) {
11
- var descriptor = props[i];
12
- descriptor.enumerable = descriptor.enumerable || false;
13
- descriptor.configurable = true;
14
- if ("value" in descriptor) descriptor.writable = true;
15
- Object.defineProperty(target, descriptor.key, descriptor);
16
- }
17
- }
18
-
19
- function _createClass(Constructor, protoProps, staticProps) {
20
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
21
- if (staticProps) _defineProperties(Constructor, staticProps);
22
- return Constructor;
23
- }
2
+ import { orient2d } from 'robust-predicates';
24
3
 
25
4
  /**
26
5
  * A bounding box has the format:
@@ -28,23 +7,27 @@ function _createClass(Constructor, protoProps, staticProps) {
28
7
  * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }
29
8
  *
30
9
  */
31
- var isInBbox = function isInBbox(bbox, point) {
10
+
11
+ const isInBbox = (bbox, point) => {
32
12
  return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;
33
13
  };
14
+
34
15
  /* Returns either null, or a bbox (aka an ordered pair of points)
35
16
  * If there is only one point of overlap, a bbox with identical points
36
17
  * will be returned */
37
-
38
- var getBboxOverlap = function getBboxOverlap(b1, b2) {
18
+ const getBboxOverlap = (b1, b2) => {
39
19
  // check if the bboxes overlap at all
40
- if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null; // find the middle two X values
20
+ if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null;
41
21
 
42
- var lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;
43
- var upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x; // find the middle two Y values
22
+ // find the middle two X values
23
+ const lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;
24
+ const upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x;
44
25
 
45
- var lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;
46
- var upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y; // put those middle values together to get the overlap
26
+ // find the middle two Y values
27
+ const lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;
28
+ const upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y;
47
29
 
30
+ // put those middle values together to get the overlap
48
31
  return {
49
32
  ll: {
50
33
  x: lowerX,
@@ -62,28 +45,29 @@ var getBboxOverlap = function getBboxOverlap(b1, b2) {
62
45
  *
63
46
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
64
47
  */
65
- var epsilon = Number.EPSILON; // IE Polyfill
66
48
 
49
+ let epsilon = Number.EPSILON;
50
+
51
+ // IE Polyfill
67
52
  if (epsilon === undefined) epsilon = Math.pow(2, -52);
68
- var EPSILON_SQ = epsilon * epsilon;
69
- /* FLP comparator */
53
+ const EPSILON_SQ = epsilon * epsilon;
70
54
 
71
- var cmp = function cmp(a, b) {
55
+ /* FLP comparator */
56
+ const cmp = (a, b) => {
72
57
  // check if they're both 0
73
58
  if (-epsilon < a && a < epsilon) {
74
59
  if (-epsilon < b && b < epsilon) {
75
60
  return 0;
76
61
  }
77
- } // check if they're flp equal
78
-
79
-
80
- var ab = a - b;
62
+ }
81
63
 
64
+ // check if they're flp equal
65
+ const ab = a - b;
82
66
  if (ab * ab < EPSILON_SQ * a * b) {
83
67
  return 0;
84
- } // normal comparison
85
-
68
+ }
86
69
 
70
+ // normal comparison
87
71
  return a < b ? -1 : 1;
88
72
  };
89
73
 
@@ -100,467 +84,414 @@ var cmp = function cmp(a, b) {
100
84
  * stored in any data structures in the rest of this algorithm.
101
85
  */
102
86
 
103
- var PtRounder = /*#__PURE__*/function () {
104
- function PtRounder() {
105
- _classCallCheck(this, PtRounder);
106
-
87
+ class PtRounder {
88
+ constructor() {
107
89
  this.reset();
108
90
  }
109
-
110
- _createClass(PtRounder, [{
111
- key: "reset",
112
- value: function reset() {
113
- this.xRounder = new CoordRounder();
114
- this.yRounder = new CoordRounder();
115
- }
116
- }, {
117
- key: "round",
118
- value: function round(x, y) {
119
- return {
120
- x: this.xRounder.round(x),
121
- y: this.yRounder.round(y)
122
- };
123
- }
124
- }]);
125
-
126
- return PtRounder;
127
- }();
128
-
129
- var CoordRounder = /*#__PURE__*/function () {
130
- function CoordRounder() {
131
- _classCallCheck(this, CoordRounder);
132
-
133
- this.tree = new SplayTree(); // preseed with 0 so we don't end up with values < Number.EPSILON
134
-
91
+ reset() {
92
+ this.xRounder = new CoordRounder();
93
+ this.yRounder = new CoordRounder();
94
+ }
95
+ round(x, y) {
96
+ return {
97
+ x: this.xRounder.round(x),
98
+ y: this.yRounder.round(y)
99
+ };
100
+ }
101
+ }
102
+ class CoordRounder {
103
+ constructor() {
104
+ this.tree = new SplayTree();
105
+ // preseed with 0 so we don't end up with values < Number.EPSILON
135
106
  this.round(0);
136
- } // Note: this can rounds input values backwards or forwards.
107
+ }
108
+
109
+ // Note: this can rounds input values backwards or forwards.
137
110
  // You might ask, why not restrict this to just rounding
138
111
  // forwards? Wouldn't that allow left endpoints to always
139
112
  // remain left endpoints during splitting (never change to
140
113
  // right). No - it wouldn't, because we snap intersections
141
114
  // to endpoints (to establish independence from the segment
142
115
  // angle for t-intersections).
143
-
144
-
145
- _createClass(CoordRounder, [{
146
- key: "round",
147
- value: function round(coord) {
148
- var node = this.tree.add(coord);
149
- var prevNode = this.tree.prev(node);
150
-
151
- if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {
152
- this.tree.remove(coord);
153
- return prevNode.key;
154
- }
155
-
156
- var nextNode = this.tree.next(node);
157
-
158
- if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {
159
- this.tree.remove(coord);
160
- return nextNode.key;
161
- }
162
-
163
- return coord;
116
+ round(coord) {
117
+ const node = this.tree.add(coord);
118
+ const prevNode = this.tree.prev(node);
119
+ if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {
120
+ this.tree.remove(coord);
121
+ return prevNode.key;
164
122
  }
165
- }]);
166
-
167
- return CoordRounder;
168
- }(); // singleton available by import
169
-
123
+ const nextNode = this.tree.next(node);
124
+ if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {
125
+ this.tree.remove(coord);
126
+ return nextNode.key;
127
+ }
128
+ return coord;
129
+ }
130
+ }
170
131
 
171
- var rounder = new PtRounder();
132
+ // singleton available by import
133
+ const rounder = new PtRounder();
172
134
 
173
135
  /* Cross Product of two vectors with first point at origin */
136
+ const crossProduct = (a, b) => a.x * b.y - a.y * b.x;
174
137
 
175
- var crossProduct = function crossProduct(a, b) {
176
- return a.x * b.y - a.y * b.x;
177
- };
178
138
  /* Dot Product of two vectors with first point at origin */
139
+ const dotProduct = (a, b) => a.x * b.x + a.y * b.y;
179
140
 
180
- var dotProduct = function dotProduct(a, b) {
181
- return a.x * b.x + a.y * b.y;
182
- };
183
141
  /* Comparator for two vectors with same starting point */
184
-
185
- var compareVectorAngles = function compareVectorAngles(basePt, endPt1, endPt2) {
186
- var v1 = {
187
- x: endPt1.x - basePt.x,
188
- y: endPt1.y - basePt.y
189
- };
190
- var v2 = {
191
- x: endPt2.x - basePt.x,
192
- y: endPt2.y - basePt.y
193
- };
194
- var kross = crossProduct(v1, v2);
195
- return cmp(kross, 0);
142
+ const compareVectorAngles = (basePt, endPt1, endPt2) => {
143
+ const res = orient2d(basePt.x, basePt.y, endPt1.x, endPt1.y, endPt2.x, endPt2.y);
144
+ if (res > 0) return -1;
145
+ if (res < 0) return 1;
146
+ return 0;
196
147
  };
197
- var length = function length(v) {
198
- return Math.sqrt(dotProduct(v, v));
199
- };
200
- /* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */
148
+ const length = v => Math.sqrt(dotProduct(v, v));
201
149
 
202
- var sineOfAngle = function sineOfAngle(pShared, pBase, pAngle) {
203
- var vBase = {
150
+ /* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */
151
+ const sineOfAngle = (pShared, pBase, pAngle) => {
152
+ const vBase = {
204
153
  x: pBase.x - pShared.x,
205
154
  y: pBase.y - pShared.y
206
155
  };
207
- var vAngle = {
156
+ const vAngle = {
208
157
  x: pAngle.x - pShared.x,
209
158
  y: pAngle.y - pShared.y
210
159
  };
211
160
  return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);
212
161
  };
213
- /* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
214
162
 
215
- var cosineOfAngle = function cosineOfAngle(pShared, pBase, pAngle) {
216
- var vBase = {
163
+ /* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
164
+ const cosineOfAngle = (pShared, pBase, pAngle) => {
165
+ const vBase = {
217
166
  x: pBase.x - pShared.x,
218
167
  y: pBase.y - pShared.y
219
168
  };
220
- var vAngle = {
169
+ const vAngle = {
221
170
  x: pAngle.x - pShared.x,
222
171
  y: pAngle.y - pShared.y
223
172
  };
224
173
  return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);
225
174
  };
175
+
226
176
  /* Get the x coordinate where the given line (defined by a point and vector)
227
177
  * crosses the horizontal line with the given y coordiante.
228
178
  * In the case of parrallel lines (including overlapping ones) returns null. */
229
-
230
- var horizontalIntersection = function horizontalIntersection(pt, v, y) {
179
+ const horizontalIntersection = (pt, v, y) => {
231
180
  if (v.y === 0) return null;
232
181
  return {
233
182
  x: pt.x + v.x / v.y * (y - pt.y),
234
183
  y: y
235
184
  };
236
185
  };
186
+
237
187
  /* Get the y coordinate where the given line (defined by a point and vector)
238
188
  * crosses the vertical line with the given x coordiante.
239
189
  * In the case of parrallel lines (including overlapping ones) returns null. */
240
-
241
- var verticalIntersection = function verticalIntersection(pt, v, x) {
190
+ const verticalIntersection = (pt, v, x) => {
242
191
  if (v.x === 0) return null;
243
192
  return {
244
193
  x: x,
245
194
  y: pt.y + v.y / v.x * (x - pt.x)
246
195
  };
247
196
  };
197
+
248
198
  /* Get the intersection of two lines, each defined by a base point and a vector.
249
199
  * In the case of parrallel lines (including overlapping ones) returns null. */
250
-
251
- var intersection = function intersection(pt1, v1, pt2, v2) {
200
+ const intersection$1 = (pt1, v1, pt2, v2) => {
252
201
  // take some shortcuts for vertical and horizontal lines
253
202
  // this also ensures we don't calculate an intersection and then discover
254
203
  // it's actually outside the bounding box of the line
255
204
  if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);
256
205
  if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);
257
206
  if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);
258
- if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y); // General case for non-overlapping segments.
207
+ if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y);
208
+
209
+ // General case for non-overlapping segments.
259
210
  // This algorithm is based on Schneider and Eberly.
260
211
  // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244
261
212
 
262
- var kross = crossProduct(v1, v2);
213
+ const kross = crossProduct(v1, v2);
263
214
  if (kross == 0) return null;
264
- var ve = {
215
+ const ve = {
265
216
  x: pt2.x - pt1.x,
266
217
  y: pt2.y - pt1.y
267
218
  };
268
- var d1 = crossProduct(ve, v1) / kross;
269
- var d2 = crossProduct(ve, v2) / kross; // take the average of the two calculations to minimize rounding error
270
-
271
- var x1 = pt1.x + d2 * v1.x,
272
- x2 = pt2.x + d1 * v2.x;
273
- var y1 = pt1.y + d2 * v1.y,
274
- y2 = pt2.y + d1 * v2.y;
275
- var x = (x1 + x2) / 2;
276
- var y = (y1 + y2) / 2;
219
+ const d1 = crossProduct(ve, v1) / kross;
220
+ const d2 = crossProduct(ve, v2) / kross;
221
+
222
+ // take the average of the two calculations to minimize rounding error
223
+ const x1 = pt1.x + d2 * v1.x,
224
+ x2 = pt2.x + d1 * v2.x;
225
+ const y1 = pt1.y + d2 * v1.y,
226
+ y2 = pt2.y + d1 * v2.y;
227
+ const x = (x1 + x2) / 2;
228
+ const y = (y1 + y2) / 2;
277
229
  return {
278
230
  x: x,
279
231
  y: y
280
232
  };
281
233
  };
282
234
 
283
- var SweepEvent = /*#__PURE__*/function () {
284
- _createClass(SweepEvent, null, [{
285
- key: "compare",
286
- // for ordering sweep events in the sweep event queue
287
- value: function compare(a, b) {
288
- // favor event with a point that the sweep line hits first
289
- var ptCmp = SweepEvent.comparePoints(a.point, b.point);
290
- if (ptCmp !== 0) return ptCmp; // the points are the same, so link them if needed
291
-
292
- if (a.point !== b.point) a.link(b); // favor right events over left
293
-
294
- if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1; // we have two matching left or right endpoints
295
- // ordering of this case is the same as for their segments
296
-
297
- return Segment.compare(a.segment, b.segment);
298
- } // for ordering points in sweep line order
299
-
300
- }, {
301
- key: "comparePoints",
302
- value: function comparePoints(aPt, bPt) {
303
- if (aPt.x < bPt.x) return -1;
304
- if (aPt.x > bPt.x) return 1;
305
- if (aPt.y < bPt.y) return -1;
306
- if (aPt.y > bPt.y) return 1;
307
- return 0;
308
- } // Warning: 'point' input will be modified and re-used (for performance)
235
+ class SweepEvent {
236
+ // for ordering sweep events in the sweep event queue
237
+ static compare(a, b) {
238
+ // favor event with a point that the sweep line hits first
239
+ const ptCmp = SweepEvent.comparePoints(a.point, b.point);
240
+ if (ptCmp !== 0) return ptCmp;
309
241
 
310
- }]);
242
+ // the points are the same, so link them if needed
243
+ if (a.point !== b.point) a.link(b);
311
244
 
312
- function SweepEvent(point, isLeft) {
313
- _classCallCheck(this, SweepEvent);
245
+ // favor right events over left
246
+ if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1;
314
247
 
315
- if (point.events === undefined) point.events = [this];else point.events.push(this);
316
- this.point = point;
317
- this.isLeft = isLeft; // this.segment, this.otherSE set by factory
248
+ // we have two matching left or right endpoints
249
+ // ordering of this case is the same as for their segments
250
+ return Segment.compare(a.segment, b.segment);
318
251
  }
319
252
 
320
- _createClass(SweepEvent, [{
321
- key: "link",
322
- value: function link(other) {
323
- if (other.point === this.point) {
324
- throw new Error('Tried to link already linked events');
325
- }
253
+ // for ordering points in sweep line order
254
+ static comparePoints(aPt, bPt) {
255
+ if (aPt.x < bPt.x) return -1;
256
+ if (aPt.x > bPt.x) return 1;
257
+ if (aPt.y < bPt.y) return -1;
258
+ if (aPt.y > bPt.y) return 1;
259
+ return 0;
260
+ }
326
261
 
327
- var otherEvents = other.point.events;
262
+ // Warning: 'point' input will be modified and re-used (for performance)
263
+ constructor(point, isLeft) {
264
+ if (point.events === undefined) point.events = [this];else point.events.push(this);
265
+ this.point = point;
266
+ this.isLeft = isLeft;
267
+ // this.segment, this.otherSE set by factory
268
+ }
269
+ link(other) {
270
+ if (other.point === this.point) {
271
+ throw new Error("Tried to link already linked events");
272
+ }
273
+ const otherEvents = other.point.events;
274
+ for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {
275
+ const evt = otherEvents[i];
276
+ this.point.events.push(evt);
277
+ evt.point = this.point;
278
+ }
279
+ this.checkForConsuming();
280
+ }
328
281
 
329
- for (var i = 0, iMax = otherEvents.length; i < iMax; i++) {
330
- var evt = otherEvents[i];
331
- this.point.events.push(evt);
332
- evt.point = this.point;
282
+ /* Do a pass over our linked events and check to see if any pair
283
+ * of segments match, and should be consumed. */
284
+ checkForConsuming() {
285
+ // FIXME: The loops in this method run O(n^2) => no good.
286
+ // Maintain little ordered sweep event trees?
287
+ // Can we maintaining an ordering that avoids the need
288
+ // for the re-sorting with getLeftmostComparator in geom-out?
289
+
290
+ // Compare each pair of events to see if other events also match
291
+ const numEvents = this.point.events.length;
292
+ for (let i = 0; i < numEvents; i++) {
293
+ const evt1 = this.point.events[i];
294
+ if (evt1.segment.consumedBy !== undefined) continue;
295
+ for (let j = i + 1; j < numEvents; j++) {
296
+ const evt2 = this.point.events[j];
297
+ if (evt2.consumedBy !== undefined) continue;
298
+ if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
299
+ evt1.segment.consume(evt2.segment);
333
300
  }
334
-
335
- this.checkForConsuming();
336
301
  }
337
- /* Do a pass over our linked events and check to see if any pair
338
- * of segments match, and should be consumed. */
339
-
340
- }, {
341
- key: "checkForConsuming",
342
- value: function checkForConsuming() {
343
- // FIXME: The loops in this method run O(n^2) => no good.
344
- // Maintain little ordered sweep event trees?
345
- // Can we maintaining an ordering that avoids the need
346
- // for the re-sorting with getLeftmostComparator in geom-out?
347
- // Compare each pair of events to see if other events also match
348
- var numEvents = this.point.events.length;
349
-
350
- for (var i = 0; i < numEvents; i++) {
351
- var evt1 = this.point.events[i];
352
- if (evt1.segment.consumedBy !== undefined) continue;
353
-
354
- for (var j = i + 1; j < numEvents; j++) {
355
- var evt2 = this.point.events[j];
356
- if (evt2.consumedBy !== undefined) continue;
357
- if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
358
- evt1.segment.consume(evt2.segment);
359
- }
302
+ }
303
+ getAvailableLinkedEvents() {
304
+ // point.events is always of length 2 or greater
305
+ const events = [];
306
+ for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {
307
+ const evt = this.point.events[i];
308
+ if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
309
+ events.push(evt);
360
310
  }
361
311
  }
362
- }, {
363
- key: "getAvailableLinkedEvents",
364
- value: function getAvailableLinkedEvents() {
365
- // point.events is always of length 2 or greater
366
- var events = [];
367
-
368
- for (var i = 0, iMax = this.point.events.length; i < iMax; i++) {
369
- var evt = this.point.events[i];
312
+ return events;
313
+ }
370
314
 
371
- if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
372
- events.push(evt);
373
- }
315
+ /**
316
+ * Returns a comparator function for sorting linked events that will
317
+ * favor the event that will give us the smallest left-side angle.
318
+ * All ring construction starts as low as possible heading to the right,
319
+ * so by always turning left as sharp as possible we'll get polygons
320
+ * without uncessary loops & holes.
321
+ *
322
+ * The comparator function has a compute cache such that it avoids
323
+ * re-computing already-computed values.
324
+ */
325
+ getLeftmostComparator(baseEvent) {
326
+ const cache = new Map();
327
+ const fillCache = linkedEvent => {
328
+ const nextEvent = linkedEvent.otherSE;
329
+ cache.set(linkedEvent, {
330
+ sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),
331
+ cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point)
332
+ });
333
+ };
334
+ return (a, b) => {
335
+ if (!cache.has(a)) fillCache(a);
336
+ if (!cache.has(b)) fillCache(b);
337
+ const {
338
+ sine: asine,
339
+ cosine: acosine
340
+ } = cache.get(a);
341
+ const {
342
+ sine: bsine,
343
+ cosine: bcosine
344
+ } = cache.get(b);
345
+
346
+ // both on or above x-axis
347
+ if (asine >= 0 && bsine >= 0) {
348
+ if (acosine < bcosine) return 1;
349
+ if (acosine > bcosine) return -1;
350
+ return 0;
374
351
  }
375
352
 
376
- return events;
377
- }
378
- /**
379
- * Returns a comparator function for sorting linked events that will
380
- * favor the event that will give us the smallest left-side angle.
381
- * All ring construction starts as low as possible heading to the right,
382
- * so by always turning left as sharp as possible we'll get polygons
383
- * without uncessary loops & holes.
384
- *
385
- * The comparator function has a compute cache such that it avoids
386
- * re-computing already-computed values.
387
- */
388
-
389
- }, {
390
- key: "getLeftmostComparator",
391
- value: function getLeftmostComparator(baseEvent) {
392
- var _this = this;
393
-
394
- var cache = new Map();
395
-
396
- var fillCache = function fillCache(linkedEvent) {
397
- var nextEvent = linkedEvent.otherSE;
398
- cache.set(linkedEvent, {
399
- sine: sineOfAngle(_this.point, baseEvent.point, nextEvent.point),
400
- cosine: cosineOfAngle(_this.point, baseEvent.point, nextEvent.point)
401
- });
402
- };
403
-
404
- return function (a, b) {
405
- if (!cache.has(a)) fillCache(a);
406
- if (!cache.has(b)) fillCache(b);
407
-
408
- var _cache$get = cache.get(a),
409
- asine = _cache$get.sine,
410
- acosine = _cache$get.cosine;
411
-
412
- var _cache$get2 = cache.get(b),
413
- bsine = _cache$get2.sine,
414
- bcosine = _cache$get2.cosine; // both on or above x-axis
415
-
416
-
417
- if (asine >= 0 && bsine >= 0) {
418
- if (acosine < bcosine) return 1;
419
- if (acosine > bcosine) return -1;
420
- return 0;
421
- } // both below x-axis
422
-
423
-
424
- if (asine < 0 && bsine < 0) {
425
- if (acosine < bcosine) return -1;
426
- if (acosine > bcosine) return 1;
427
- return 0;
428
- } // one above x-axis, one below
429
-
430
-
431
- if (bsine < asine) return -1;
432
- if (bsine > asine) return 1;
353
+ // both below x-axis
354
+ if (asine < 0 && bsine < 0) {
355
+ if (acosine < bcosine) return -1;
356
+ if (acosine > bcosine) return 1;
433
357
  return 0;
434
- };
435
- }
436
- }]);
358
+ }
437
359
 
438
- return SweepEvent;
439
- }();
360
+ // one above x-axis, one below
361
+ if (bsine < asine) return -1;
362
+ if (bsine > asine) return 1;
363
+ return 0;
364
+ };
365
+ }
366
+ }
440
367
 
368
+ // Give segments unique ID's to get consistent sorting of
441
369
  // segments and sweep events when all else is identical
370
+ let segmentId = 0;
371
+ class Segment {
372
+ /* This compare() function is for ordering segments in the sweep
373
+ * line tree, and does so according to the following criteria:
374
+ *
375
+ * Consider the vertical line that lies an infinestimal step to the
376
+ * right of the right-more of the two left endpoints of the input
377
+ * segments. Imagine slowly moving a point up from negative infinity
378
+ * in the increasing y direction. Which of the two segments will that
379
+ * point intersect first? That segment comes 'before' the other one.
380
+ *
381
+ * If neither segment would be intersected by such a line, (if one
382
+ * or more of the segments are vertical) then the line to be considered
383
+ * is directly on the right-more of the two left inputs.
384
+ */
385
+ static compare(a, b) {
386
+ const alx = a.leftSE.point.x;
387
+ const blx = b.leftSE.point.x;
388
+ const arx = a.rightSE.point.x;
389
+ const brx = b.rightSE.point.x;
390
+
391
+ // check if they're even in the same vertical plane
392
+ if (brx < alx) return 1;
393
+ if (arx < blx) return -1;
394
+ const aly = a.leftSE.point.y;
395
+ const bly = b.leftSE.point.y;
396
+ const ary = a.rightSE.point.y;
397
+ const bry = b.rightSE.point.y;
398
+
399
+ // is left endpoint of segment B the right-more?
400
+ if (alx < blx) {
401
+ // are the two segments in the same horizontal plane?
402
+ if (bly < aly && bly < ary) return 1;
403
+ if (bly > aly && bly > ary) return -1;
404
+
405
+ // is the B left endpoint colinear to segment A?
406
+ const aCmpBLeft = a.comparePoint(b.leftSE.point);
407
+ if (aCmpBLeft < 0) return 1;
408
+ if (aCmpBLeft > 0) return -1;
409
+
410
+ // is the A right endpoint colinear to segment B ?
411
+ const bCmpARight = b.comparePoint(a.rightSE.point);
412
+ if (bCmpARight !== 0) return bCmpARight;
413
+
414
+ // colinear segments, consider the one with left-more
415
+ // left endpoint to be first (arbitrary?)
416
+ return -1;
417
+ }
442
418
 
443
- var segmentId = 0;
444
-
445
- var Segment = /*#__PURE__*/function () {
446
- _createClass(Segment, null, [{
447
- key: "compare",
448
-
449
- /* This compare() function is for ordering segments in the sweep
450
- * line tree, and does so according to the following criteria:
451
- *
452
- * Consider the vertical line that lies an infinestimal step to the
453
- * right of the right-more of the two left endpoints of the input
454
- * segments. Imagine slowly moving a point up from negative infinity
455
- * in the increasing y direction. Which of the two segments will that
456
- * point intersect first? That segment comes 'before' the other one.
457
- *
458
- * If neither segment would be intersected by such a line, (if one
459
- * or more of the segments are vertical) then the line to be considered
460
- * is directly on the right-more of the two left inputs.
461
- */
462
- value: function compare(a, b) {
463
- var alx = a.leftSE.point.x;
464
- var blx = b.leftSE.point.x;
465
- var arx = a.rightSE.point.x;
466
- var brx = b.rightSE.point.x; // check if they're even in the same vertical plane
467
-
468
- if (brx < alx) return 1;
469
- if (arx < blx) return -1;
470
- var aly = a.leftSE.point.y;
471
- var bly = b.leftSE.point.y;
472
- var ary = a.rightSE.point.y;
473
- var bry = b.rightSE.point.y; // is left endpoint of segment B the right-more?
474
-
475
- if (alx < blx) {
476
- // are the two segments in the same horizontal plane?
477
- if (bly < aly && bly < ary) return 1;
478
- if (bly > aly && bly > ary) return -1; // is the B left endpoint colinear to segment A?
479
-
480
- var aCmpBLeft = a.comparePoint(b.leftSE.point);
481
- if (aCmpBLeft < 0) return 1;
482
- if (aCmpBLeft > 0) return -1; // is the A right endpoint colinear to segment B ?
483
-
484
- var bCmpARight = b.comparePoint(a.rightSE.point);
485
- if (bCmpARight !== 0) return bCmpARight; // colinear segments, consider the one with left-more
486
- // left endpoint to be first (arbitrary?)
487
-
488
- return -1;
489
- } // is left endpoint of segment A the right-more?
490
-
491
-
492
- if (alx > blx) {
493
- if (aly < bly && aly < bry) return -1;
494
- if (aly > bly && aly > bry) return 1; // is the A left endpoint colinear to segment B?
495
-
496
- var bCmpALeft = b.comparePoint(a.leftSE.point);
497
- if (bCmpALeft !== 0) return bCmpALeft; // is the B right endpoint colinear to segment A?
498
-
499
- var aCmpBRight = a.comparePoint(b.rightSE.point);
500
- if (aCmpBRight < 0) return 1;
501
- if (aCmpBRight > 0) return -1; // colinear segments, consider the one with left-more
502
- // left endpoint to be first (arbitrary?)
503
-
504
- return 1;
505
- } // if we get here, the two left endpoints are in the same
506
- // vertical plane, ie alx === blx
507
- // consider the lower left-endpoint to come first
508
-
509
-
510
- if (aly < bly) return -1;
511
- if (aly > bly) return 1; // left endpoints are identical
512
- // check for colinearity by using the left-more right endpoint
513
- // is the A right endpoint more left-more?
514
-
515
- if (arx < brx) {
516
- var _bCmpARight = b.comparePoint(a.rightSE.point);
517
-
518
- if (_bCmpARight !== 0) return _bCmpARight;
519
- } // is the B right endpoint more left-more?
520
-
521
-
522
- if (arx > brx) {
523
- var _aCmpBRight = a.comparePoint(b.rightSE.point);
524
-
525
- if (_aCmpBRight < 0) return 1;
526
- if (_aCmpBRight > 0) return -1;
527
- }
419
+ // is left endpoint of segment A the right-more?
420
+ if (alx > blx) {
421
+ if (aly < bly && aly < bry) return -1;
422
+ if (aly > bly && aly > bry) return 1;
423
+
424
+ // is the A left endpoint colinear to segment B?
425
+ const bCmpALeft = b.comparePoint(a.leftSE.point);
426
+ if (bCmpALeft !== 0) return bCmpALeft;
528
427
 
529
- if (arx !== brx) {
530
- // are these two [almost] vertical segments with opposite orientation?
531
- // if so, the one with the lower right endpoint comes first
532
- var ay = ary - aly;
533
- var ax = arx - alx;
534
- var by = bry - bly;
535
- var bx = brx - blx;
536
- if (ay > ax && by < bx) return 1;
537
- if (ay < ax && by > bx) return -1;
538
- } // we have colinear segments with matching orientation
539
- // consider the one with more left-more right endpoint to be first
428
+ // is the B right endpoint colinear to segment A?
429
+ const aCmpBRight = a.comparePoint(b.rightSE.point);
430
+ if (aCmpBRight < 0) return 1;
431
+ if (aCmpBRight > 0) return -1;
540
432
 
433
+ // colinear segments, consider the one with left-more
434
+ // left endpoint to be first (arbitrary?)
435
+ return 1;
436
+ }
541
437
 
542
- if (arx > brx) return 1;
543
- if (arx < brx) return -1; // if we get here, two two right endpoints are in the same
544
- // vertical plane, ie arx === brx
545
- // consider the lower right-endpoint to come first
438
+ // if we get here, the two left endpoints are in the same
439
+ // vertical plane, ie alx === blx
546
440
 
547
- if (ary < bry) return -1;
548
- if (ary > bry) return 1; // right endpoints identical as well, so the segments are idential
549
- // fall back on creation order as consistent tie-breaker
441
+ // consider the lower left-endpoint to come first
442
+ if (aly < bly) return -1;
443
+ if (aly > bly) return 1;
550
444
 
551
- if (a.id < b.id) return -1;
552
- if (a.id > b.id) return 1; // identical segment, ie a === b
445
+ // left endpoints are identical
446
+ // check for colinearity by using the left-more right endpoint
553
447
 
554
- return 0;
448
+ // is the A right endpoint more left-more?
449
+ if (arx < brx) {
450
+ const bCmpARight = b.comparePoint(a.rightSE.point);
451
+ if (bCmpARight !== 0) return bCmpARight;
452
+ }
453
+
454
+ // is the B right endpoint more left-more?
455
+ if (arx > brx) {
456
+ const aCmpBRight = a.comparePoint(b.rightSE.point);
457
+ if (aCmpBRight < 0) return 1;
458
+ if (aCmpBRight > 0) return -1;
459
+ }
460
+ if (arx !== brx) {
461
+ // are these two [almost] vertical segments with opposite orientation?
462
+ // if so, the one with the lower right endpoint comes first
463
+ const ay = ary - aly;
464
+ const ax = arx - alx;
465
+ const by = bry - bly;
466
+ const bx = brx - blx;
467
+ if (ay > ax && by < bx) return 1;
468
+ if (ay < ax && by > bx) return -1;
555
469
  }
556
- /* Warning: a reference to ringWindings input will be stored,
557
- * and possibly will be later modified */
558
470
 
559
- }]);
471
+ // we have colinear segments with matching orientation
472
+ // consider the one with more left-more right endpoint to be first
473
+ if (arx > brx) return 1;
474
+ if (arx < brx) return -1;
475
+
476
+ // if we get here, two two right endpoints are in the same
477
+ // vertical plane, ie arx === brx
560
478
 
561
- function Segment(leftSE, rightSE, rings, windings) {
562
- _classCallCheck(this, Segment);
479
+ // consider the lower right-endpoint to come first
480
+ if (ary < bry) return -1;
481
+ if (ary > bry) return 1;
482
+
483
+ // right endpoints identical as well, so the segments are idential
484
+ // fall back on creation order as consistent tie-breaker
485
+ if (a.id < b.id) return -1;
486
+ if (a.id > b.id) return 1;
487
+
488
+ // identical segment, ie a === b
489
+ return 0;
490
+ }
563
491
 
492
+ /* Warning: a reference to ringWindings input will be stored,
493
+ * and possibly will be later modified */
494
+ constructor(leftSE, rightSE, rings, windings) {
564
495
  this.id = ++segmentId;
565
496
  this.leftSE = leftSE;
566
497
  leftSE.segment = this;
@@ -569,481 +500,425 @@ var Segment = /*#__PURE__*/function () {
569
500
  rightSE.segment = this;
570
501
  rightSE.otherSE = leftSE;
571
502
  this.rings = rings;
572
- this.windings = windings; // left unset for performance, set later in algorithm
503
+ this.windings = windings;
504
+ // left unset for performance, set later in algorithm
573
505
  // this.ringOut, this.consumedBy, this.prev
574
506
  }
507
+ static fromRing(pt1, pt2, ring) {
508
+ let leftPt, rightPt, winding;
509
+
510
+ // ordering the two points according to sweep line ordering
511
+ const cmpPts = SweepEvent.comparePoints(pt1, pt2);
512
+ if (cmpPts < 0) {
513
+ leftPt = pt1;
514
+ rightPt = pt2;
515
+ winding = 1;
516
+ } else if (cmpPts > 0) {
517
+ leftPt = pt2;
518
+ rightPt = pt1;
519
+ winding = -1;
520
+ } else throw new Error(`Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`);
521
+ const leftSE = new SweepEvent(leftPt, true);
522
+ const rightSE = new SweepEvent(rightPt, false);
523
+ return new Segment(leftSE, rightSE, [ring], [winding]);
524
+ }
575
525
 
576
- _createClass(Segment, [{
577
- key: "replaceRightSE",
578
-
579
- /* When a segment is split, the rightSE is replaced with a new sweep event */
580
- value: function replaceRightSE(newRightSE) {
581
- this.rightSE = newRightSE;
582
- this.rightSE.segment = this;
583
- this.rightSE.otherSE = this.leftSE;
584
- this.leftSE.otherSE = this.rightSE;
585
- }
586
- }, {
587
- key: "bbox",
588
- value: function bbox() {
589
- var y1 = this.leftSE.point.y;
590
- var y2 = this.rightSE.point.y;
591
- return {
592
- ll: {
593
- x: this.leftSE.point.x,
594
- y: y1 < y2 ? y1 : y2
595
- },
596
- ur: {
597
- x: this.rightSE.point.x,
598
- y: y1 > y2 ? y1 : y2
599
- }
600
- };
601
- }
602
- /* A vector from the left point to the right */
603
-
604
- }, {
605
- key: "vector",
606
- value: function vector() {
607
- return {
608
- x: this.rightSE.point.x - this.leftSE.point.x,
609
- y: this.rightSE.point.y - this.leftSE.point.y
610
- };
611
- }
612
- }, {
613
- key: "isAnEndpoint",
614
- value: function isAnEndpoint(pt) {
615
- return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;
616
- }
617
- /* Compare this segment with a point.
618
- *
619
- * A point P is considered to be colinear to a segment if there
620
- * exists a distance D such that if we travel along the segment
621
- * from one * endpoint towards the other a distance D, we find
622
- * ourselves at point P.
623
- *
624
- * Return value indicates:
625
- *
626
- * 1: point lies above the segment (to the left of vertical)
627
- * 0: point is colinear to segment
628
- * -1: point lies below the segment (to the right of vertical)
629
- */
630
-
631
- }, {
632
- key: "comparePoint",
633
- value: function comparePoint(point) {
634
- if (this.isAnEndpoint(point)) return 0;
635
- var lPt = this.leftSE.point;
636
- var rPt = this.rightSE.point;
637
- var v = this.vector(); // Exactly vertical segments.
638
-
639
- if (lPt.x === rPt.x) {
640
- if (point.x === lPt.x) return 0;
641
- return point.x < lPt.x ? 1 : -1;
642
- } // Nearly vertical segments with an intersection.
643
- // Check to see where a point on the line with matching Y coordinate is.
644
-
645
-
646
- var yDist = (point.y - lPt.y) / v.y;
647
- var xFromYDist = lPt.x + yDist * v.x;
648
- if (point.x === xFromYDist) return 0; // General case.
649
- // Check to see where a point on the line with matching X coordinate is.
650
-
651
- var xDist = (point.x - lPt.x) / v.x;
652
- var yFromXDist = lPt.y + xDist * v.y;
653
- if (point.y === yFromXDist) return 0;
654
- return point.y < yFromXDist ? -1 : 1;
655
- }
656
- /**
657
- * Given another segment, returns the first non-trivial intersection
658
- * between the two segments (in terms of sweep line ordering), if it exists.
659
- *
660
- * A 'non-trivial' intersection is one that will cause one or both of the
661
- * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
662
- *
663
- * * endpoint of segA with endpoint of segB --> trivial
664
- * * endpoint of segA with point along segB --> non-trivial
665
- * * endpoint of segB with point along segA --> non-trivial
666
- * * point along segA with point along segB --> non-trivial
667
- *
668
- * If no non-trivial intersection exists, return null
669
- * Else, return null.
670
- */
671
-
672
- }, {
673
- key: "getIntersection",
674
- value: function getIntersection(other) {
675
- // If bboxes don't overlap, there can't be any intersections
676
- var tBbox = this.bbox();
677
- var oBbox = other.bbox();
678
- var bboxOverlap = getBboxOverlap(tBbox, oBbox);
679
- if (bboxOverlap === null) return null; // We first check to see if the endpoints can be considered intersections.
680
- // This will 'snap' intersections to endpoints if possible, and will
681
- // handle cases of colinearity.
682
-
683
- var tlp = this.leftSE.point;
684
- var trp = this.rightSE.point;
685
- var olp = other.leftSE.point;
686
- var orp = other.rightSE.point; // does each endpoint touch the other segment?
687
- // note that we restrict the 'touching' definition to only allow segments
688
- // to touch endpoints that lie forward from where we are in the sweep line pass
689
-
690
- var touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
691
- var touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
692
- var touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
693
- var touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0; // do left endpoints match?
694
-
695
- if (touchesThisLSE && touchesOtherLSE) {
696
- // these two cases are for colinear segments with matching left
697
- // endpoints, and one segment being longer than the other
698
- if (touchesThisRSE && !touchesOtherRSE) return trp;
699
- if (!touchesThisRSE && touchesOtherRSE) return orp; // either the two segments match exactly (two trival intersections)
700
- // or just on their left endpoint (one trivial intersection
701
-
702
- return null;
703
- } // does this left endpoint matches (other doesn't)
704
-
705
-
706
- if (touchesThisLSE) {
707
- // check for segments that just intersect on opposing endpoints
708
- if (touchesOtherRSE) {
709
- if (tlp.x === orp.x && tlp.y === orp.y) return null;
710
- } // t-intersection on left endpoint
711
-
712
-
713
- return tlp;
714
- } // does other left endpoint matches (this doesn't)
715
-
716
-
717
- if (touchesOtherLSE) {
718
- // check for segments that just intersect on opposing endpoints
719
- if (touchesThisRSE) {
720
- if (trp.x === olp.x && trp.y === olp.y) return null;
721
- } // t-intersection on left endpoint
722
-
723
-
724
- return olp;
725
- } // trivial intersection on right endpoints
726
-
727
-
728
- if (touchesThisRSE && touchesOtherRSE) return null; // t-intersections on just one right endpoint
729
-
730
- if (touchesThisRSE) return trp;
731
- if (touchesOtherRSE) return orp; // None of our endpoints intersect. Look for a general intersection between
732
- // infinite lines laid over the segments
733
-
734
- var pt = intersection(tlp, this.vector(), olp, other.vector()); // are the segments parrallel? Note that if they were colinear with overlap,
735
- // they would have an endpoint intersection and that case was already handled above
736
-
737
- if (pt === null) return null; // is the intersection found between the lines not on the segments?
738
-
739
- if (!isInBbox(bboxOverlap, pt)) return null; // round the the computed point if needed
740
-
741
- return rounder.round(pt.x, pt.y);
742
- }
743
- /**
744
- * Split the given segment into multiple segments on the given points.
745
- * * Each existing segment will retain its leftSE and a new rightSE will be
746
- * generated for it.
747
- * * A new segment will be generated which will adopt the original segment's
748
- * rightSE, and a new leftSE will be generated for it.
749
- * * If there are more than two points given to split on, new segments
750
- * in the middle will be generated with new leftSE and rightSE's.
751
- * * An array of the newly generated SweepEvents will be returned.
752
- *
753
- * Warning: input array of points is modified
754
- */
755
-
756
- }, {
757
- key: "split",
758
- value: function split(point) {
759
- var newEvents = [];
760
- var alreadyLinked = point.events !== undefined;
761
- var newLeftSE = new SweepEvent(point, true);
762
- var newRightSE = new SweepEvent(point, false);
763
- var oldRightSE = this.rightSE;
764
- this.replaceRightSE(newRightSE);
765
- newEvents.push(newRightSE);
766
- newEvents.push(newLeftSE);
767
- var newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice()); // when splitting a nearly vertical downward-facing segment,
768
- // sometimes one of the resulting new segments is vertical, in which
769
- // case its left and right events may need to be swapped
770
-
771
- if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
772
- newSeg.swapEvents();
526
+ /* When a segment is split, the rightSE is replaced with a new sweep event */
527
+ replaceRightSE(newRightSE) {
528
+ this.rightSE = newRightSE;
529
+ this.rightSE.segment = this;
530
+ this.rightSE.otherSE = this.leftSE;
531
+ this.leftSE.otherSE = this.rightSE;
532
+ }
533
+ bbox() {
534
+ const y1 = this.leftSE.point.y;
535
+ const y2 = this.rightSE.point.y;
536
+ return {
537
+ ll: {
538
+ x: this.leftSE.point.x,
539
+ y: y1 < y2 ? y1 : y2
540
+ },
541
+ ur: {
542
+ x: this.rightSE.point.x,
543
+ y: y1 > y2 ? y1 : y2
773
544
  }
545
+ };
546
+ }
774
547
 
775
- if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
776
- this.swapEvents();
777
- } // in the point we just used to create new sweep events with was already
778
- // linked to other events, we need to check if either of the affected
779
- // segments should be consumed
548
+ /* A vector from the left point to the right */
549
+ vector() {
550
+ return {
551
+ x: this.rightSE.point.x - this.leftSE.point.x,
552
+ y: this.rightSE.point.y - this.leftSE.point.y
553
+ };
554
+ }
555
+ isAnEndpoint(pt) {
556
+ return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;
557
+ }
780
558
 
559
+ /* Compare this segment with a point.
560
+ *
561
+ * A point P is considered to be colinear to a segment if there
562
+ * exists a distance D such that if we travel along the segment
563
+ * from one * endpoint towards the other a distance D, we find
564
+ * ourselves at point P.
565
+ *
566
+ * Return value indicates:
567
+ *
568
+ * 1: point lies above the segment (to the left of vertical)
569
+ * 0: point is colinear to segment
570
+ * -1: point lies below the segment (to the right of vertical)
571
+ */
572
+ comparePoint(point) {
573
+ if (this.isAnEndpoint(point)) return 0;
574
+ const lPt = this.leftSE.point;
575
+ const rPt = this.rightSE.point;
576
+ const v = this.vector();
577
+
578
+ // Exactly vertical segments.
579
+ if (lPt.x === rPt.x) {
580
+ if (point.x === lPt.x) return 0;
581
+ return point.x < lPt.x ? 1 : -1;
582
+ }
781
583
 
782
- if (alreadyLinked) {
783
- newLeftSE.checkForConsuming();
784
- newRightSE.checkForConsuming();
785
- }
584
+ // Nearly vertical segments with an intersection.
585
+ // Check to see where a point on the line with matching Y coordinate is.
586
+ const yDist = (point.y - lPt.y) / v.y;
587
+ const xFromYDist = lPt.x + yDist * v.x;
588
+ if (point.x === xFromYDist) return 0;
589
+
590
+ // General case.
591
+ // Check to see where a point on the line with matching X coordinate is.
592
+ const xDist = (point.x - lPt.x) / v.x;
593
+ const yFromXDist = lPt.y + xDist * v.y;
594
+ if (point.y === yFromXDist) return 0;
595
+ return point.y < yFromXDist ? -1 : 1;
596
+ }
786
597
 
787
- return newEvents;
788
- }
789
- /* Swap which event is left and right */
790
-
791
- }, {
792
- key: "swapEvents",
793
- value: function swapEvents() {
794
- var tmpEvt = this.rightSE;
795
- this.rightSE = this.leftSE;
796
- this.leftSE = tmpEvt;
797
- this.leftSE.isLeft = true;
798
- this.rightSE.isLeft = false;
799
-
800
- for (var i = 0, iMax = this.windings.length; i < iMax; i++) {
801
- this.windings[i] *= -1;
802
- }
598
+ /**
599
+ * Given another segment, returns the first non-trivial intersection
600
+ * between the two segments (in terms of sweep line ordering), if it exists.
601
+ *
602
+ * A 'non-trivial' intersection is one that will cause one or both of the
603
+ * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
604
+ *
605
+ * * endpoint of segA with endpoint of segB --> trivial
606
+ * * endpoint of segA with point along segB --> non-trivial
607
+ * * endpoint of segB with point along segA --> non-trivial
608
+ * * point along segA with point along segB --> non-trivial
609
+ *
610
+ * If no non-trivial intersection exists, return null
611
+ * Else, return null.
612
+ */
613
+ getIntersection(other) {
614
+ // If bboxes don't overlap, there can't be any intersections
615
+ const tBbox = this.bbox();
616
+ const oBbox = other.bbox();
617
+ const bboxOverlap = getBboxOverlap(tBbox, oBbox);
618
+ if (bboxOverlap === null) return null;
619
+
620
+ // We first check to see if the endpoints can be considered intersections.
621
+ // This will 'snap' intersections to endpoints if possible, and will
622
+ // handle cases of colinearity.
623
+
624
+ const tlp = this.leftSE.point;
625
+ const trp = this.rightSE.point;
626
+ const olp = other.leftSE.point;
627
+ const orp = other.rightSE.point;
628
+
629
+ // does each endpoint touch the other segment?
630
+ // note that we restrict the 'touching' definition to only allow segments
631
+ // to touch endpoints that lie forward from where we are in the sweep line pass
632
+ const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
633
+ const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
634
+ const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
635
+ const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;
636
+
637
+ // do left endpoints match?
638
+ if (touchesThisLSE && touchesOtherLSE) {
639
+ // these two cases are for colinear segments with matching left
640
+ // endpoints, and one segment being longer than the other
641
+ if (touchesThisRSE && !touchesOtherRSE) return trp;
642
+ if (!touchesThisRSE && touchesOtherRSE) return orp;
643
+ // either the two segments match exactly (two trival intersections)
644
+ // or just on their left endpoint (one trivial intersection
645
+ return null;
803
646
  }
804
- /* Consume another segment. We take their rings under our wing
805
- * and mark them as consumed. Use for perfectly overlapping segments */
806
-
807
- }, {
808
- key: "consume",
809
- value: function consume(other) {
810
- var consumer = this;
811
- var consumee = other;
812
647
 
813
- while (consumer.consumedBy) {
814
- consumer = consumer.consumedBy;
648
+ // does this left endpoint matches (other doesn't)
649
+ if (touchesThisLSE) {
650
+ // check for segments that just intersect on opposing endpoints
651
+ if (touchesOtherRSE) {
652
+ if (tlp.x === orp.x && tlp.y === orp.y) return null;
815
653
  }
654
+ // t-intersection on left endpoint
655
+ return tlp;
656
+ }
816
657
 
817
- while (consumee.consumedBy) {
818
- consumee = consumee.consumedBy;
658
+ // does other left endpoint matches (this doesn't)
659
+ if (touchesOtherLSE) {
660
+ // check for segments that just intersect on opposing endpoints
661
+ if (touchesThisRSE) {
662
+ if (trp.x === olp.x && trp.y === olp.y) return null;
819
663
  }
664
+ // t-intersection on left endpoint
665
+ return olp;
666
+ }
820
667
 
821
- var cmp = Segment.compare(consumer, consumee);
822
- if (cmp === 0) return; // already consumed
823
- // the winner of the consumption is the earlier segment
824
- // according to sweep line ordering
825
-
826
- if (cmp > 0) {
827
- var tmp = consumer;
828
- consumer = consumee;
829
- consumee = tmp;
830
- } // make sure a segment doesn't consume it's prev
668
+ // trivial intersection on right endpoints
669
+ if (touchesThisRSE && touchesOtherRSE) return null;
831
670
 
671
+ // t-intersections on just one right endpoint
672
+ if (touchesThisRSE) return trp;
673
+ if (touchesOtherRSE) return orp;
832
674
 
833
- if (consumer.prev === consumee) {
834
- var _tmp = consumer;
835
- consumer = consumee;
836
- consumee = _tmp;
837
- }
675
+ // None of our endpoints intersect. Look for a general intersection between
676
+ // infinite lines laid over the segments
677
+ const pt = intersection$1(tlp, this.vector(), olp, other.vector());
838
678
 
839
- for (var i = 0, iMax = consumee.rings.length; i < iMax; i++) {
840
- var ring = consumee.rings[i];
841
- var winding = consumee.windings[i];
842
- var index = consumer.rings.indexOf(ring);
679
+ // are the segments parrallel? Note that if they were colinear with overlap,
680
+ // they would have an endpoint intersection and that case was already handled above
681
+ if (pt === null) return null;
843
682
 
844
- if (index === -1) {
845
- consumer.rings.push(ring);
846
- consumer.windings.push(winding);
847
- } else consumer.windings[index] += winding;
848
- }
683
+ // is the intersection found between the lines not on the segments?
684
+ if (!isInBbox(bboxOverlap, pt)) return null;
849
685
 
850
- consumee.rings = null;
851
- consumee.windings = null;
852
- consumee.consumedBy = consumer; // mark sweep events consumed as to maintain ordering in sweep event queue
686
+ // round the the computed point if needed
687
+ return rounder.round(pt.x, pt.y);
688
+ }
853
689
 
854
- consumee.leftSE.consumedBy = consumer.leftSE;
855
- consumee.rightSE.consumedBy = consumer.rightSE;
856
- }
857
- /* The first segment previous segment chain that is in the result */
858
-
859
- }, {
860
- key: "prevInResult",
861
- value: function prevInResult() {
862
- if (this._prevInResult !== undefined) return this._prevInResult;
863
- if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
864
- return this._prevInResult;
690
+ /**
691
+ * Split the given segment into multiple segments on the given points.
692
+ * * Each existing segment will retain its leftSE and a new rightSE will be
693
+ * generated for it.
694
+ * * A new segment will be generated which will adopt the original segment's
695
+ * rightSE, and a new leftSE will be generated for it.
696
+ * * If there are more than two points given to split on, new segments
697
+ * in the middle will be generated with new leftSE and rightSE's.
698
+ * * An array of the newly generated SweepEvents will be returned.
699
+ *
700
+ * Warning: input array of points is modified
701
+ */
702
+ split(point) {
703
+ const newEvents = [];
704
+ const alreadyLinked = point.events !== undefined;
705
+ const newLeftSE = new SweepEvent(point, true);
706
+ const newRightSE = new SweepEvent(point, false);
707
+ const oldRightSE = this.rightSE;
708
+ this.replaceRightSE(newRightSE);
709
+ newEvents.push(newRightSE);
710
+ newEvents.push(newLeftSE);
711
+ const newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice());
712
+
713
+ // when splitting a nearly vertical downward-facing segment,
714
+ // sometimes one of the resulting new segments is vertical, in which
715
+ // case its left and right events may need to be swapped
716
+ if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
717
+ newSeg.swapEvents();
865
718
  }
866
- }, {
867
- key: "beforeState",
868
- value: function beforeState() {
869
- if (this._beforeState !== undefined) return this._beforeState;
870
- if (!this.prev) this._beforeState = {
871
- rings: [],
872
- windings: [],
873
- multiPolys: []
874
- };else {
875
- var seg = this.prev.consumedBy || this.prev;
876
- this._beforeState = seg.afterState();
877
- }
878
- return this._beforeState;
719
+ if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
720
+ this.swapEvents();
879
721
  }
880
- }, {
881
- key: "afterState",
882
- value: function afterState() {
883
- if (this._afterState !== undefined) return this._afterState;
884
- var beforeState = this.beforeState();
885
- this._afterState = {
886
- rings: beforeState.rings.slice(0),
887
- windings: beforeState.windings.slice(0),
888
- multiPolys: []
889
- };
890
- var ringsAfter = this._afterState.rings;
891
- var windingsAfter = this._afterState.windings;
892
- var mpsAfter = this._afterState.multiPolys; // calculate ringsAfter, windingsAfter
893
-
894
- for (var i = 0, iMax = this.rings.length; i < iMax; i++) {
895
- var ring = this.rings[i];
896
- var winding = this.windings[i];
897
- var index = ringsAfter.indexOf(ring);
898
-
899
- if (index === -1) {
900
- ringsAfter.push(ring);
901
- windingsAfter.push(winding);
902
- } else windingsAfter[index] += winding;
903
- } // calcualte polysAfter
904
-
905
-
906
- var polysAfter = [];
907
- var polysExclude = [];
908
-
909
- for (var _i = 0, _iMax = ringsAfter.length; _i < _iMax; _i++) {
910
- if (windingsAfter[_i] === 0) continue; // non-zero rule
911
-
912
- var _ring = ringsAfter[_i];
913
- var poly = _ring.poly;
914
- if (polysExclude.indexOf(poly) !== -1) continue;
915
- if (_ring.isExterior) polysAfter.push(poly);else {
916
- if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
917
-
918
- var _index = polysAfter.indexOf(_ring.poly);
919
-
920
- if (_index !== -1) polysAfter.splice(_index, 1);
921
- }
922
- } // calculate multiPolysAfter
923
-
924
722
 
925
- for (var _i2 = 0, _iMax2 = polysAfter.length; _i2 < _iMax2; _i2++) {
926
- var mp = polysAfter[_i2].multiPoly;
927
- if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
928
- }
929
-
930
- return this._afterState;
723
+ // in the point we just used to create new sweep events with was already
724
+ // linked to other events, we need to check if either of the affected
725
+ // segments should be consumed
726
+ if (alreadyLinked) {
727
+ newLeftSE.checkForConsuming();
728
+ newRightSE.checkForConsuming();
931
729
  }
932
- /* Is this segment part of the final result? */
933
-
934
- }, {
935
- key: "isInResult",
936
- value: function isInResult() {
937
- // if we've been consumed, we're not in the result
938
- if (this.consumedBy) return false;
939
- if (this._isInResult !== undefined) return this._isInResult;
940
- var mpsBefore = this.beforeState().multiPolys;
941
- var mpsAfter = this.afterState().multiPolys;
942
-
943
- switch (operation.type) {
944
- case 'union':
945
- {
946
- // UNION - included iff:
947
- // * On one side of us there is 0 poly interiors AND
948
- // * On the other side there is 1 or more.
949
- var noBefores = mpsBefore.length === 0;
950
- var noAfters = mpsAfter.length === 0;
951
- this._isInResult = noBefores !== noAfters;
952
- break;
953
- }
730
+ return newEvents;
731
+ }
954
732
 
955
- case 'intersection':
956
- {
957
- // INTERSECTION - included iff:
958
- // * on one side of us all multipolys are rep. with poly interiors AND
959
- // * on the other side of us, not all multipolys are repsented
960
- // with poly interiors
961
- var least;
962
- var most;
963
-
964
- if (mpsBefore.length < mpsAfter.length) {
965
- least = mpsBefore.length;
966
- most = mpsAfter.length;
967
- } else {
968
- least = mpsAfter.length;
969
- most = mpsBefore.length;
970
- }
733
+ /* Swap which event is left and right */
734
+ swapEvents() {
735
+ const tmpEvt = this.rightSE;
736
+ this.rightSE = this.leftSE;
737
+ this.leftSE = tmpEvt;
738
+ this.leftSE.isLeft = true;
739
+ this.rightSE.isLeft = false;
740
+ for (let i = 0, iMax = this.windings.length; i < iMax; i++) {
741
+ this.windings[i] *= -1;
742
+ }
743
+ }
971
744
 
972
- this._isInResult = most === operation.numMultiPolys && least < most;
973
- break;
974
- }
745
+ /* Consume another segment. We take their rings under our wing
746
+ * and mark them as consumed. Use for perfectly overlapping segments */
747
+ consume(other) {
748
+ let consumer = this;
749
+ let consumee = other;
750
+ while (consumer.consumedBy) consumer = consumer.consumedBy;
751
+ while (consumee.consumedBy) consumee = consumee.consumedBy;
752
+ const cmp = Segment.compare(consumer, consumee);
753
+ if (cmp === 0) return; // already consumed
754
+ // the winner of the consumption is the earlier segment
755
+ // according to sweep line ordering
756
+ if (cmp > 0) {
757
+ const tmp = consumer;
758
+ consumer = consumee;
759
+ consumee = tmp;
760
+ }
975
761
 
976
- case 'xor':
977
- {
978
- // XOR - included iff:
979
- // * the difference between the number of multipolys represented
980
- // with poly interiors on our two sides is an odd number
981
- var diff = Math.abs(mpsBefore.length - mpsAfter.length);
982
- this._isInResult = diff % 2 === 1;
983
- break;
984
- }
762
+ // make sure a segment doesn't consume it's prev
763
+ if (consumer.prev === consumee) {
764
+ const tmp = consumer;
765
+ consumer = consumee;
766
+ consumee = tmp;
767
+ }
768
+ for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {
769
+ const ring = consumee.rings[i];
770
+ const winding = consumee.windings[i];
771
+ const index = consumer.rings.indexOf(ring);
772
+ if (index === -1) {
773
+ consumer.rings.push(ring);
774
+ consumer.windings.push(winding);
775
+ } else consumer.windings[index] += winding;
776
+ }
777
+ consumee.rings = null;
778
+ consumee.windings = null;
779
+ consumee.consumedBy = consumer;
985
780
 
986
- case 'difference':
987
- {
988
- // DIFFERENCE included iff:
989
- // * on exactly one side, we have just the subject
990
- var isJustSubject = function isJustSubject(mps) {
991
- return mps.length === 1 && mps[0].isSubject;
992
- };
781
+ // mark sweep events consumed as to maintain ordering in sweep event queue
782
+ consumee.leftSE.consumedBy = consumer.leftSE;
783
+ consumee.rightSE.consumedBy = consumer.rightSE;
784
+ }
993
785
 
994
- this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
995
- break;
996
- }
786
+ /* The first segment previous segment chain that is in the result */
787
+ prevInResult() {
788
+ if (this._prevInResult !== undefined) return this._prevInResult;
789
+ if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
790
+ return this._prevInResult;
791
+ }
792
+ beforeState() {
793
+ if (this._beforeState !== undefined) return this._beforeState;
794
+ if (!this.prev) this._beforeState = {
795
+ rings: [],
796
+ windings: [],
797
+ multiPolys: []
798
+ };else {
799
+ const seg = this.prev.consumedBy || this.prev;
800
+ this._beforeState = seg.afterState();
801
+ }
802
+ return this._beforeState;
803
+ }
804
+ afterState() {
805
+ if (this._afterState !== undefined) return this._afterState;
806
+ const beforeState = this.beforeState();
807
+ this._afterState = {
808
+ rings: beforeState.rings.slice(0),
809
+ windings: beforeState.windings.slice(0),
810
+ multiPolys: []
811
+ };
812
+ const ringsAfter = this._afterState.rings;
813
+ const windingsAfter = this._afterState.windings;
814
+ const mpsAfter = this._afterState.multiPolys;
815
+
816
+ // calculate ringsAfter, windingsAfter
817
+ for (let i = 0, iMax = this.rings.length; i < iMax; i++) {
818
+ const ring = this.rings[i];
819
+ const winding = this.windings[i];
820
+ const index = ringsAfter.indexOf(ring);
821
+ if (index === -1) {
822
+ ringsAfter.push(ring);
823
+ windingsAfter.push(winding);
824
+ } else windingsAfter[index] += winding;
825
+ }
997
826
 
998
- default:
999
- throw new Error("Unrecognized operation type found ".concat(operation.type));
827
+ // calcualte polysAfter
828
+ const polysAfter = [];
829
+ const polysExclude = [];
830
+ for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {
831
+ if (windingsAfter[i] === 0) continue; // non-zero rule
832
+ const ring = ringsAfter[i];
833
+ const poly = ring.poly;
834
+ if (polysExclude.indexOf(poly) !== -1) continue;
835
+ if (ring.isExterior) polysAfter.push(poly);else {
836
+ if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
837
+ const index = polysAfter.indexOf(ring.poly);
838
+ if (index !== -1) polysAfter.splice(index, 1);
1000
839
  }
1001
-
1002
- return this._isInResult;
1003
840
  }
1004
- }], [{
1005
- key: "fromRing",
1006
- value: function fromRing(pt1, pt2, ring) {
1007
- var leftPt, rightPt, winding; // ordering the two points according to sweep line ordering
1008
-
1009
- var cmpPts = SweepEvent.comparePoints(pt1, pt2);
1010
-
1011
- if (cmpPts < 0) {
1012
- leftPt = pt1;
1013
- rightPt = pt2;
1014
- winding = 1;
1015
- } else if (cmpPts > 0) {
1016
- leftPt = pt2;
1017
- rightPt = pt1;
1018
- winding = -1;
1019
- } else throw new Error("Tried to create degenerate segment at [".concat(pt1.x, ", ").concat(pt1.y, "]"));
1020
-
1021
- var leftSE = new SweepEvent(leftPt, true);
1022
- var rightSE = new SweepEvent(rightPt, false);
1023
- return new Segment(leftSE, rightSE, [ring], [winding]);
1024
- }
1025
- }]);
1026
841
 
1027
- return Segment;
1028
- }();
842
+ // calculate multiPolysAfter
843
+ for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {
844
+ const mp = polysAfter[i].multiPoly;
845
+ if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
846
+ }
847
+ return this._afterState;
848
+ }
1029
849
 
1030
- var RingIn = /*#__PURE__*/function () {
1031
- function RingIn(geomRing, poly, isExterior) {
1032
- _classCallCheck(this, RingIn);
850
+ /* Is this segment part of the final result? */
851
+ isInResult() {
852
+ // if we've been consumed, we're not in the result
853
+ if (this.consumedBy) return false;
854
+ if (this._isInResult !== undefined) return this._isInResult;
855
+ const mpsBefore = this.beforeState().multiPolys;
856
+ const mpsAfter = this.afterState().multiPolys;
857
+ switch (operation.type) {
858
+ case "union":
859
+ {
860
+ // UNION - included iff:
861
+ // * On one side of us there is 0 poly interiors AND
862
+ // * On the other side there is 1 or more.
863
+ const noBefores = mpsBefore.length === 0;
864
+ const noAfters = mpsAfter.length === 0;
865
+ this._isInResult = noBefores !== noAfters;
866
+ break;
867
+ }
868
+ case "intersection":
869
+ {
870
+ // INTERSECTION - included iff:
871
+ // * on one side of us all multipolys are rep. with poly interiors AND
872
+ // * on the other side of us, not all multipolys are repsented
873
+ // with poly interiors
874
+ let least;
875
+ let most;
876
+ if (mpsBefore.length < mpsAfter.length) {
877
+ least = mpsBefore.length;
878
+ most = mpsAfter.length;
879
+ } else {
880
+ least = mpsAfter.length;
881
+ most = mpsBefore.length;
882
+ }
883
+ this._isInResult = most === operation.numMultiPolys && least < most;
884
+ break;
885
+ }
886
+ case "xor":
887
+ {
888
+ // XOR - included iff:
889
+ // * the difference between the number of multipolys represented
890
+ // with poly interiors on our two sides is an odd number
891
+ const diff = Math.abs(mpsBefore.length - mpsAfter.length);
892
+ this._isInResult = diff % 2 === 1;
893
+ break;
894
+ }
895
+ case "difference":
896
+ {
897
+ // DIFFERENCE included iff:
898
+ // * on exactly one side, we have just the subject
899
+ const isJustSubject = mps => mps.length === 1 && mps[0].isSubject;
900
+ this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
901
+ break;
902
+ }
903
+ default:
904
+ throw new Error(`Unrecognized operation type found ${operation.type}`);
905
+ }
906
+ return this._isInResult;
907
+ }
908
+ }
1033
909
 
910
+ class RingIn {
911
+ constructor(geomRing, poly, isExterior) {
1034
912
  if (!Array.isArray(geomRing) || geomRing.length === 0) {
1035
- throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
913
+ throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
1036
914
  }
1037
-
1038
915
  this.poly = poly;
1039
916
  this.isExterior = isExterior;
1040
917
  this.segments = [];
1041
-
1042
- if (typeof geomRing[0][0] !== 'number' || typeof geomRing[0][1] !== 'number') {
1043
- throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
918
+ if (typeof geomRing[0][0] !== "number" || typeof geomRing[0][1] !== "number") {
919
+ throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
1044
920
  }
1045
-
1046
- var firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);
921
+ const firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);
1047
922
  this.bbox = {
1048
923
  ll: {
1049
924
  x: firstPoint.x,
@@ -1054,15 +929,13 @@ var RingIn = /*#__PURE__*/function () {
1054
929
  y: firstPoint.y
1055
930
  }
1056
931
  };
1057
- var prevPoint = firstPoint;
1058
-
1059
- for (var i = 1, iMax = geomRing.length; i < iMax; i++) {
1060
- if (typeof geomRing[i][0] !== 'number' || typeof geomRing[i][1] !== 'number') {
1061
- throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
932
+ let prevPoint = firstPoint;
933
+ for (let i = 1, iMax = geomRing.length; i < iMax; i++) {
934
+ if (typeof geomRing[i][0] !== "number" || typeof geomRing[i][1] !== "number") {
935
+ throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
1062
936
  }
1063
-
1064
- var point = rounder.round(geomRing[i][0], geomRing[i][1]); // skip repeated points
1065
-
937
+ let point = rounder.round(geomRing[i][0], geomRing[i][1]);
938
+ // skip repeated points
1066
939
  if (point.x === prevPoint.x && point.y === prevPoint.y) continue;
1067
940
  this.segments.push(Segment.fromRing(prevPoint, point, this));
1068
941
  if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;
@@ -1070,41 +943,29 @@ var RingIn = /*#__PURE__*/function () {
1070
943
  if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;
1071
944
  if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;
1072
945
  prevPoint = point;
1073
- } // add segment from last to first if last is not the same as first
1074
-
1075
-
946
+ }
947
+ // add segment from last to first if last is not the same as first
1076
948
  if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {
1077
949
  this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));
1078
950
  }
1079
951
  }
1080
-
1081
- _createClass(RingIn, [{
1082
- key: "getSweepEvents",
1083
- value: function getSweepEvents() {
1084
- var sweepEvents = [];
1085
-
1086
- for (var i = 0, iMax = this.segments.length; i < iMax; i++) {
1087
- var segment = this.segments[i];
1088
- sweepEvents.push(segment.leftSE);
1089
- sweepEvents.push(segment.rightSE);
1090
- }
1091
-
1092
- return sweepEvents;
952
+ getSweepEvents() {
953
+ const sweepEvents = [];
954
+ for (let i = 0, iMax = this.segments.length; i < iMax; i++) {
955
+ const segment = this.segments[i];
956
+ sweepEvents.push(segment.leftSE);
957
+ sweepEvents.push(segment.rightSE);
1093
958
  }
1094
- }]);
1095
-
1096
- return RingIn;
1097
- }();
1098
- var PolyIn = /*#__PURE__*/function () {
1099
- function PolyIn(geomPoly, multiPoly) {
1100
- _classCallCheck(this, PolyIn);
1101
-
959
+ return sweepEvents;
960
+ }
961
+ }
962
+ class PolyIn {
963
+ constructor(geomPoly, multiPoly) {
1102
964
  if (!Array.isArray(geomPoly)) {
1103
- throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
965
+ throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
1104
966
  }
1105
-
1106
- this.exteriorRing = new RingIn(geomPoly[0], this, true); // copy by value
1107
-
967
+ this.exteriorRing = new RingIn(geomPoly[0], this, true);
968
+ // copy by value
1108
969
  this.bbox = {
1109
970
  ll: {
1110
971
  x: this.exteriorRing.bbox.ll.x,
@@ -1116,53 +977,39 @@ var PolyIn = /*#__PURE__*/function () {
1116
977
  }
1117
978
  };
1118
979
  this.interiorRings = [];
1119
-
1120
- for (var i = 1, iMax = geomPoly.length; i < iMax; i++) {
1121
- var ring = new RingIn(geomPoly[i], this, false);
980
+ for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {
981
+ const ring = new RingIn(geomPoly[i], this, false);
1122
982
  if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;
1123
983
  if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;
1124
984
  if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;
1125
985
  if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;
1126
986
  this.interiorRings.push(ring);
1127
987
  }
1128
-
1129
988
  this.multiPoly = multiPoly;
1130
989
  }
1131
-
1132
- _createClass(PolyIn, [{
1133
- key: "getSweepEvents",
1134
- value: function getSweepEvents() {
1135
- var sweepEvents = this.exteriorRing.getSweepEvents();
1136
-
1137
- for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
1138
- var ringSweepEvents = this.interiorRings[i].getSweepEvents();
1139
-
1140
- for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
1141
- sweepEvents.push(ringSweepEvents[j]);
1142
- }
990
+ getSweepEvents() {
991
+ const sweepEvents = this.exteriorRing.getSweepEvents();
992
+ for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
993
+ const ringSweepEvents = this.interiorRings[i].getSweepEvents();
994
+ for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
995
+ sweepEvents.push(ringSweepEvents[j]);
1143
996
  }
1144
-
1145
- return sweepEvents;
1146
997
  }
1147
- }]);
1148
-
1149
- return PolyIn;
1150
- }();
1151
- var MultiPolyIn = /*#__PURE__*/function () {
1152
- function MultiPolyIn(geom, isSubject) {
1153
- _classCallCheck(this, MultiPolyIn);
1154
-
998
+ return sweepEvents;
999
+ }
1000
+ }
1001
+ class MultiPolyIn {
1002
+ constructor(geom, isSubject) {
1155
1003
  if (!Array.isArray(geom)) {
1156
- throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
1004
+ throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
1157
1005
  }
1158
-
1159
1006
  try {
1160
1007
  // if the input looks like a polygon, convert it to a multipolygon
1161
- if (typeof geom[0][0][0] === 'number') geom = [geom];
1162
- } catch (ex) {// The input is either malformed or has empty arrays.
1008
+ if (typeof geom[0][0][0] === "number") geom = [geom];
1009
+ } catch (ex) {
1010
+ // The input is either malformed or has empty arrays.
1163
1011
  // In either case, it will be handled later on.
1164
1012
  }
1165
-
1166
1013
  this.polys = [];
1167
1014
  this.bbox = {
1168
1015
  ll: {
@@ -1174,311 +1021,234 @@ var MultiPolyIn = /*#__PURE__*/function () {
1174
1021
  y: Number.NEGATIVE_INFINITY
1175
1022
  }
1176
1023
  };
1177
-
1178
- for (var i = 0, iMax = geom.length; i < iMax; i++) {
1179
- var poly = new PolyIn(geom[i], this);
1024
+ for (let i = 0, iMax = geom.length; i < iMax; i++) {
1025
+ const poly = new PolyIn(geom[i], this);
1180
1026
  if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;
1181
1027
  if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;
1182
1028
  if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;
1183
1029
  if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;
1184
1030
  this.polys.push(poly);
1185
1031
  }
1186
-
1187
1032
  this.isSubject = isSubject;
1188
1033
  }
1189
-
1190
- _createClass(MultiPolyIn, [{
1191
- key: "getSweepEvents",
1192
- value: function getSweepEvents() {
1193
- var sweepEvents = [];
1194
-
1195
- for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
1196
- var polySweepEvents = this.polys[i].getSweepEvents();
1197
-
1198
- for (var j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
1199
- sweepEvents.push(polySweepEvents[j]);
1200
- }
1034
+ getSweepEvents() {
1035
+ const sweepEvents = [];
1036
+ for (let i = 0, iMax = this.polys.length; i < iMax; i++) {
1037
+ const polySweepEvents = this.polys[i].getSweepEvents();
1038
+ for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
1039
+ sweepEvents.push(polySweepEvents[j]);
1201
1040
  }
1202
-
1203
- return sweepEvents;
1204
1041
  }
1205
- }]);
1206
-
1207
- return MultiPolyIn;
1208
- }();
1209
-
1210
- var RingOut = /*#__PURE__*/function () {
1211
- _createClass(RingOut, null, [{
1212
- key: "factory",
1213
-
1214
- /* Given the segments from the sweep line pass, compute & return a series
1215
- * of closed rings from all the segments marked to be part of the result */
1216
- value: function factory(allSegments) {
1217
- var ringsOut = [];
1218
-
1219
- for (var i = 0, iMax = allSegments.length; i < iMax; i++) {
1220
- var segment = allSegments[i];
1221
- if (!segment.isInResult() || segment.ringOut) continue;
1222
- var prevEvent = null;
1223
- var event = segment.leftSE;
1224
- var nextEvent = segment.rightSE;
1225
- var events = [event];
1226
- var startingPoint = event.point;
1227
- var intersectionLEs = [];
1228
- /* Walk the chain of linked events to form a closed ring */
1042
+ return sweepEvents;
1043
+ }
1044
+ }
1045
+
1046
+ class RingOut {
1047
+ /* Given the segments from the sweep line pass, compute & return a series
1048
+ * of closed rings from all the segments marked to be part of the result */
1049
+ static factory(allSegments) {
1050
+ const ringsOut = [];
1051
+ for (let i = 0, iMax = allSegments.length; i < iMax; i++) {
1052
+ const segment = allSegments[i];
1053
+ if (!segment.isInResult() || segment.ringOut) continue;
1054
+ let prevEvent = null;
1055
+ let event = segment.leftSE;
1056
+ let nextEvent = segment.rightSE;
1057
+ const events = [event];
1058
+ const startingPoint = event.point;
1059
+ const intersectionLEs = [];
1060
+
1061
+ /* Walk the chain of linked events to form a closed ring */
1062
+ while (true) {
1063
+ prevEvent = event;
1064
+ event = nextEvent;
1065
+ events.push(event);
1229
1066
 
1067
+ /* Is the ring complete? */
1068
+ if (event.point === startingPoint) break;
1230
1069
  while (true) {
1231
- prevEvent = event;
1232
- event = nextEvent;
1233
- events.push(event);
1234
- /* Is the ring complete? */
1235
-
1236
- if (event.point === startingPoint) break;
1237
-
1238
- while (true) {
1239
- var availableLEs = event.getAvailableLinkedEvents();
1240
- /* Did we hit a dead end? This shouldn't happen. Indicates some earlier
1241
- * part of the algorithm malfunctioned... please file a bug report. */
1242
-
1243
- if (availableLEs.length === 0) {
1244
- var firstPt = events[0].point;
1245
- var lastPt = events[events.length - 1].point;
1246
- throw new Error("Unable to complete output ring starting at [".concat(firstPt.x, ",") + " ".concat(firstPt.y, "]. Last matching segment found ends at") + " [".concat(lastPt.x, ", ").concat(lastPt.y, "]."));
1247
- }
1248
- /* Only one way to go, so cotinue on the path */
1070
+ const availableLEs = event.getAvailableLinkedEvents();
1071
+
1072
+ /* Did we hit a dead end? This shouldn't happen.
1073
+ * Indicates some earlier part of the algorithm malfunctioned. */
1074
+ if (availableLEs.length === 0) {
1075
+ const firstPt = events[0].point;
1076
+ const lastPt = events[events.length - 1].point;
1077
+ throw new Error(`Unable to complete output ring starting at [${firstPt.x},` + ` ${firstPt.y}]. Last matching segment found ends at` + ` [${lastPt.x}, ${lastPt.y}].`);
1078
+ }
1249
1079
 
1080
+ /* Only one way to go, so cotinue on the path */
1081
+ if (availableLEs.length === 1) {
1082
+ nextEvent = availableLEs[0].otherSE;
1083
+ break;
1084
+ }
1250
1085
 
1251
- if (availableLEs.length === 1) {
1252
- nextEvent = availableLEs[0].otherSE;
1086
+ /* We must have an intersection. Check for a completed loop */
1087
+ let indexLE = null;
1088
+ for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
1089
+ if (intersectionLEs[j].point === event.point) {
1090
+ indexLE = j;
1253
1091
  break;
1254
1092
  }
1255
- /* We must have an intersection. Check for a completed loop */
1256
-
1257
-
1258
- var indexLE = null;
1259
-
1260
- for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
1261
- if (intersectionLEs[j].point === event.point) {
1262
- indexLE = j;
1263
- break;
1264
- }
1265
- }
1266
- /* Found a completed loop. Cut that off and make a ring */
1267
-
1268
-
1269
- if (indexLE !== null) {
1270
- var intersectionLE = intersectionLEs.splice(indexLE)[0];
1271
- var ringEvents = events.splice(intersectionLE.index);
1272
- ringEvents.unshift(ringEvents[0].otherSE);
1273
- ringsOut.push(new RingOut(ringEvents.reverse()));
1274
- continue;
1275
- }
1276
- /* register the intersection */
1277
-
1278
-
1279
- intersectionLEs.push({
1280
- index: events.length,
1281
- point: event.point
1282
- });
1283
- /* Choose the left-most option to continue the walk */
1284
-
1285
- var comparator = event.getLeftmostComparator(prevEvent);
1286
- nextEvent = availableLEs.sort(comparator)[0].otherSE;
1287
- break;
1288
1093
  }
1094
+ /* Found a completed loop. Cut that off and make a ring */
1095
+ if (indexLE !== null) {
1096
+ const intersectionLE = intersectionLEs.splice(indexLE)[0];
1097
+ const ringEvents = events.splice(intersectionLE.index);
1098
+ ringEvents.unshift(ringEvents[0].otherSE);
1099
+ ringsOut.push(new RingOut(ringEvents.reverse()));
1100
+ continue;
1101
+ }
1102
+ /* register the intersection */
1103
+ intersectionLEs.push({
1104
+ index: events.length,
1105
+ point: event.point
1106
+ });
1107
+ /* Choose the left-most option to continue the walk */
1108
+ const comparator = event.getLeftmostComparator(prevEvent);
1109
+ nextEvent = availableLEs.sort(comparator)[0].otherSE;
1110
+ break;
1289
1111
  }
1290
-
1291
- ringsOut.push(new RingOut(events));
1292
1112
  }
1293
-
1294
- return ringsOut;
1113
+ ringsOut.push(new RingOut(events));
1295
1114
  }
1296
- }]);
1297
-
1298
- function RingOut(events) {
1299
- _classCallCheck(this, RingOut);
1300
-
1115
+ return ringsOut;
1116
+ }
1117
+ constructor(events) {
1301
1118
  this.events = events;
1302
-
1303
- for (var i = 0, iMax = events.length; i < iMax; i++) {
1119
+ for (let i = 0, iMax = events.length; i < iMax; i++) {
1304
1120
  events[i].segment.ringOut = this;
1305
1121
  }
1306
-
1307
1122
  this.poly = null;
1308
1123
  }
1309
-
1310
- _createClass(RingOut, [{
1311
- key: "getGeom",
1312
- value: function getGeom() {
1313
- // Remove superfluous points (ie extra points along a straight line),
1314
- var prevPt = this.events[0].point;
1315
- var points = [prevPt];
1316
-
1317
- for (var i = 1, iMax = this.events.length - 1; i < iMax; i++) {
1318
- var _pt = this.events[i].point;
1319
- var _nextPt = this.events[i + 1].point;
1320
- if (compareVectorAngles(_pt, prevPt, _nextPt) === 0) continue;
1321
- points.push(_pt);
1322
- prevPt = _pt;
1323
- } // ring was all (within rounding error of angle calc) colinear points
1324
-
1325
-
1326
- if (points.length === 1) return null; // check if the starting point is necessary
1327
-
1328
- var pt = points[0];
1329
- var nextPt = points[1];
1330
- if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();
1331
- points.push(points[0]);
1332
- var step = this.isExteriorRing() ? 1 : -1;
1333
- var iStart = this.isExteriorRing() ? 0 : points.length - 1;
1334
- var iEnd = this.isExteriorRing() ? points.length : -1;
1335
- var orderedPoints = [];
1336
-
1337
- for (var _i = iStart; _i != iEnd; _i += step) {
1338
- orderedPoints.push([points[_i].x, points[_i].y]);
1339
- }
1340
-
1341
- return orderedPoints;
1124
+ getGeom() {
1125
+ // Remove superfluous points (ie extra points along a straight line),
1126
+ let prevPt = this.events[0].point;
1127
+ const points = [prevPt];
1128
+ for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {
1129
+ const pt = this.events[i].point;
1130
+ const nextPt = this.events[i + 1].point;
1131
+ if (compareVectorAngles(pt, prevPt, nextPt) === 0) continue;
1132
+ points.push(pt);
1133
+ prevPt = pt;
1342
1134
  }
1343
- }, {
1344
- key: "isExteriorRing",
1345
- value: function isExteriorRing() {
1346
- if (this._isExteriorRing === undefined) {
1347
- var enclosing = this.enclosingRing();
1348
- this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
1349
- }
1350
1135
 
1351
- return this._isExteriorRing;
1136
+ // ring was all (within rounding error of angle calc) colinear points
1137
+ if (points.length === 1) return null;
1138
+
1139
+ // check if the starting point is necessary
1140
+ const pt = points[0];
1141
+ const nextPt = points[1];
1142
+ if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();
1143
+ points.push(points[0]);
1144
+ const step = this.isExteriorRing() ? 1 : -1;
1145
+ const iStart = this.isExteriorRing() ? 0 : points.length - 1;
1146
+ const iEnd = this.isExteriorRing() ? points.length : -1;
1147
+ const orderedPoints = [];
1148
+ for (let i = iStart; i != iEnd; i += step) orderedPoints.push([points[i].x, points[i].y]);
1149
+ return orderedPoints;
1150
+ }
1151
+ isExteriorRing() {
1152
+ if (this._isExteriorRing === undefined) {
1153
+ const enclosing = this.enclosingRing();
1154
+ this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
1352
1155
  }
1353
- }, {
1354
- key: "enclosingRing",
1355
- value: function enclosingRing() {
1356
- if (this._enclosingRing === undefined) {
1357
- this._enclosingRing = this._calcEnclosingRing();
1358
- }
1156
+ return this._isExteriorRing;
1157
+ }
1158
+ enclosingRing() {
1159
+ if (this._enclosingRing === undefined) {
1160
+ this._enclosingRing = this._calcEnclosingRing();
1161
+ }
1162
+ return this._enclosingRing;
1163
+ }
1359
1164
 
1360
- return this._enclosingRing;
1165
+ /* Returns the ring that encloses this one, if any */
1166
+ _calcEnclosingRing() {
1167
+ // start with the ealier sweep line event so that the prevSeg
1168
+ // chain doesn't lead us inside of a loop of ours
1169
+ let leftMostEvt = this.events[0];
1170
+ for (let i = 1, iMax = this.events.length; i < iMax; i++) {
1171
+ const evt = this.events[i];
1172
+ if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
1361
1173
  }
1362
- /* Returns the ring that encloses this one, if any */
1363
-
1364
- }, {
1365
- key: "_calcEnclosingRing",
1366
- value: function _calcEnclosingRing() {
1367
- // start with the ealier sweep line event so that the prevSeg
1368
- // chain doesn't lead us inside of a loop of ours
1369
- var leftMostEvt = this.events[0];
1370
-
1371
- for (var i = 1, iMax = this.events.length; i < iMax; i++) {
1372
- var evt = this.events[i];
1373
- if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
1174
+ let prevSeg = leftMostEvt.segment.prevInResult();
1175
+ let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
1176
+ while (true) {
1177
+ // no segment found, thus no ring can enclose us
1178
+ if (!prevSeg) return null;
1179
+
1180
+ // no segments below prev segment found, thus the ring of the prev
1181
+ // segment must loop back around and enclose us
1182
+ if (!prevPrevSeg) return prevSeg.ringOut;
1183
+
1184
+ // if the two segments are of different rings, the ring of the prev
1185
+ // segment must either loop around us or the ring of the prev prev
1186
+ // seg, which would make us and the ring of the prev peers
1187
+ if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
1188
+ if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {
1189
+ return prevSeg.ringOut;
1190
+ } else return prevSeg.ringOut.enclosingRing();
1374
1191
  }
1375
1192
 
1376
- var prevSeg = leftMostEvt.segment.prevInResult();
1377
- var prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
1378
-
1379
- while (true) {
1380
- // no segment found, thus no ring can enclose us
1381
- if (!prevSeg) return null; // no segments below prev segment found, thus the ring of the prev
1382
- // segment must loop back around and enclose us
1383
-
1384
- if (!prevPrevSeg) return prevSeg.ringOut; // if the two segments are of different rings, the ring of the prev
1385
- // segment must either loop around us or the ring of the prev prev
1386
- // seg, which would make us and the ring of the prev peers
1387
-
1388
- if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
1389
- if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {
1390
- return prevSeg.ringOut;
1391
- } else return prevSeg.ringOut.enclosingRing();
1392
- } // two segments are from the same ring, so this was a penisula
1393
- // of that ring. iterate downward, keep searching
1394
-
1395
-
1396
- prevSeg = prevPrevSeg.prevInResult();
1397
- prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
1398
- }
1193
+ // two segments are from the same ring, so this was a penisula
1194
+ // of that ring. iterate downward, keep searching
1195
+ prevSeg = prevPrevSeg.prevInResult();
1196
+ prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
1399
1197
  }
1400
- }]);
1401
-
1402
- return RingOut;
1403
- }();
1404
- var PolyOut = /*#__PURE__*/function () {
1405
- function PolyOut(exteriorRing) {
1406
- _classCallCheck(this, PolyOut);
1407
-
1198
+ }
1199
+ }
1200
+ class PolyOut {
1201
+ constructor(exteriorRing) {
1408
1202
  this.exteriorRing = exteriorRing;
1409
1203
  exteriorRing.poly = this;
1410
1204
  this.interiorRings = [];
1411
1205
  }
1412
-
1413
- _createClass(PolyOut, [{
1414
- key: "addInterior",
1415
- value: function addInterior(ring) {
1416
- this.interiorRings.push(ring);
1417
- ring.poly = this;
1418
- }
1419
- }, {
1420
- key: "getGeom",
1421
- value: function getGeom() {
1422
- var geom = [this.exteriorRing.getGeom()]; // exterior ring was all (within rounding error of angle calc) colinear points
1423
-
1424
- if (geom[0] === null) return null;
1425
-
1426
- for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
1427
- var ringGeom = this.interiorRings[i].getGeom(); // interior ring was all (within rounding error of angle calc) colinear points
1428
-
1429
- if (ringGeom === null) continue;
1430
- geom.push(ringGeom);
1431
- }
1432
-
1433
- return geom;
1206
+ addInterior(ring) {
1207
+ this.interiorRings.push(ring);
1208
+ ring.poly = this;
1209
+ }
1210
+ getGeom() {
1211
+ const geom = [this.exteriorRing.getGeom()];
1212
+ // exterior ring was all (within rounding error of angle calc) colinear points
1213
+ if (geom[0] === null) return null;
1214
+ for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
1215
+ const ringGeom = this.interiorRings[i].getGeom();
1216
+ // interior ring was all (within rounding error of angle calc) colinear points
1217
+ if (ringGeom === null) continue;
1218
+ geom.push(ringGeom);
1434
1219
  }
1435
- }]);
1436
-
1437
- return PolyOut;
1438
- }();
1439
- var MultiPolyOut = /*#__PURE__*/function () {
1440
- function MultiPolyOut(rings) {
1441
- _classCallCheck(this, MultiPolyOut);
1442
-
1220
+ return geom;
1221
+ }
1222
+ }
1223
+ class MultiPolyOut {
1224
+ constructor(rings) {
1443
1225
  this.rings = rings;
1444
1226
  this.polys = this._composePolys(rings);
1445
1227
  }
1446
-
1447
- _createClass(MultiPolyOut, [{
1448
- key: "getGeom",
1449
- value: function getGeom() {
1450
- var geom = [];
1451
-
1452
- for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
1453
- var polyGeom = this.polys[i].getGeom(); // exterior ring was all (within rounding error of angle calc) colinear points
1454
-
1455
- if (polyGeom === null) continue;
1456
- geom.push(polyGeom);
1457
- }
1458
-
1459
- return geom;
1228
+ getGeom() {
1229
+ const geom = [];
1230
+ for (let i = 0, iMax = this.polys.length; i < iMax; i++) {
1231
+ const polyGeom = this.polys[i].getGeom();
1232
+ // exterior ring was all (within rounding error of angle calc) colinear points
1233
+ if (polyGeom === null) continue;
1234
+ geom.push(polyGeom);
1460
1235
  }
1461
- }, {
1462
- key: "_composePolys",
1463
- value: function _composePolys(rings) {
1464
- var polys = [];
1465
-
1466
- for (var i = 0, iMax = rings.length; i < iMax; i++) {
1467
- var ring = rings[i];
1468
- if (ring.poly) continue;
1469
- if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {
1470
- var enclosingRing = ring.enclosingRing();
1471
- if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));
1472
- enclosingRing.poly.addInterior(ring);
1473
- }
1236
+ return geom;
1237
+ }
1238
+ _composePolys(rings) {
1239
+ const polys = [];
1240
+ for (let i = 0, iMax = rings.length; i < iMax; i++) {
1241
+ const ring = rings[i];
1242
+ if (ring.poly) continue;
1243
+ if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {
1244
+ const enclosingRing = ring.enclosingRing();
1245
+ if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));
1246
+ enclosingRing.poly.addInterior(ring);
1474
1247
  }
1475
-
1476
- return polys;
1477
1248
  }
1478
- }]);
1479
-
1480
- return MultiPolyOut;
1481
- }();
1249
+ return polys;
1250
+ }
1251
+ }
1482
1252
 
1483
1253
  /**
1484
1254
  * NOTE: We must be careful not to change any segments while
@@ -1491,330 +1261,272 @@ var MultiPolyOut = /*#__PURE__*/function () {
1491
1261
  * it sometimes does.)
1492
1262
  */
1493
1263
 
1494
- var SweepLine = /*#__PURE__*/function () {
1495
- function SweepLine(queue) {
1496
- var comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;
1497
-
1498
- _classCallCheck(this, SweepLine);
1499
-
1264
+ class SweepLine {
1265
+ constructor(queue) {
1266
+ let comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;
1500
1267
  this.queue = queue;
1501
1268
  this.tree = new SplayTree(comparator);
1502
1269
  this.segments = [];
1503
1270
  }
1271
+ process(event) {
1272
+ const segment = event.segment;
1273
+ const newEvents = [];
1274
+
1275
+ // if we've already been consumed by another segment,
1276
+ // clean up our body parts and get out
1277
+ if (event.consumedBy) {
1278
+ if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);
1279
+ return newEvents;
1280
+ }
1281
+ const node = event.isLeft ? this.tree.add(segment) : this.tree.find(segment);
1282
+ if (!node) throw new Error(`Unable to find segment #${segment.id} ` + `[${segment.leftSE.point.x}, ${segment.leftSE.point.y}] -> ` + `[${segment.rightSE.point.x}, ${segment.rightSE.point.y}] ` + "in SweepLine tree.");
1283
+ let prevNode = node;
1284
+ let nextNode = node;
1285
+ let prevSeg = undefined;
1286
+ let nextSeg = undefined;
1287
+
1288
+ // skip consumed segments still in tree
1289
+ while (prevSeg === undefined) {
1290
+ prevNode = this.tree.prev(prevNode);
1291
+ if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;
1292
+ }
1504
1293
 
1505
- _createClass(SweepLine, [{
1506
- key: "process",
1507
- value: function process(event) {
1508
- var segment = event.segment;
1509
- var newEvents = []; // if we've already been consumed by another segment,
1510
- // clean up our body parts and get out
1511
-
1512
- if (event.consumedBy) {
1513
- if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);
1514
- return newEvents;
1515
- }
1516
-
1517
- var node = event.isLeft ? this.tree.insert(segment) : this.tree.find(segment);
1518
- if (!node) throw new Error("Unable to find segment #".concat(segment.id, " ") + "[".concat(segment.leftSE.point.x, ", ").concat(segment.leftSE.point.y, "] -> ") + "[".concat(segment.rightSE.point.x, ", ").concat(segment.rightSE.point.y, "] ") + 'in SweepLine tree. Please submit a bug report.');
1519
- var prevNode = node;
1520
- var nextNode = node;
1521
- var prevSeg = undefined;
1522
- var nextSeg = undefined; // skip consumed segments still in tree
1523
-
1524
- while (prevSeg === undefined) {
1525
- prevNode = this.tree.prev(prevNode);
1526
- if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;
1527
- } // skip consumed segments still in tree
1528
-
1529
-
1530
- while (nextSeg === undefined) {
1531
- nextNode = this.tree.next(nextNode);
1532
- if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;
1533
- }
1534
-
1535
- if (event.isLeft) {
1536
- // Check for intersections against the previous segment in the sweep line
1537
- var prevMySplitter = null;
1538
-
1539
- if (prevSeg) {
1540
- var prevInter = prevSeg.getIntersection(segment);
1541
-
1542
- if (prevInter !== null) {
1543
- if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
1544
-
1545
- if (!prevSeg.isAnEndpoint(prevInter)) {
1546
- var newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
1547
-
1548
- for (var i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
1549
- newEvents.push(newEventsFromSplit[i]);
1550
- }
1294
+ // skip consumed segments still in tree
1295
+ while (nextSeg === undefined) {
1296
+ nextNode = this.tree.next(nextNode);
1297
+ if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;
1298
+ }
1299
+ if (event.isLeft) {
1300
+ // Check for intersections against the previous segment in the sweep line
1301
+ let prevMySplitter = null;
1302
+ if (prevSeg) {
1303
+ const prevInter = prevSeg.getIntersection(segment);
1304
+ if (prevInter !== null) {
1305
+ if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
1306
+ if (!prevSeg.isAnEndpoint(prevInter)) {
1307
+ const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
1308
+ for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
1309
+ newEvents.push(newEventsFromSplit[i]);
1551
1310
  }
1552
1311
  }
1553
- } // Check for intersections against the next segment in the sweep line
1554
-
1555
-
1556
- var nextMySplitter = null;
1557
-
1558
- if (nextSeg) {
1559
- var nextInter = nextSeg.getIntersection(segment);
1560
-
1561
- if (nextInter !== null) {
1562
- if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
1563
-
1564
- if (!nextSeg.isAnEndpoint(nextInter)) {
1565
- var _newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
1312
+ }
1313
+ }
1566
1314
 
1567
- for (var _i = 0, _iMax = _newEventsFromSplit.length; _i < _iMax; _i++) {
1568
- newEvents.push(_newEventsFromSplit[_i]);
1569
- }
1315
+ // Check for intersections against the next segment in the sweep line
1316
+ let nextMySplitter = null;
1317
+ if (nextSeg) {
1318
+ const nextInter = nextSeg.getIntersection(segment);
1319
+ if (nextInter !== null) {
1320
+ if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
1321
+ if (!nextSeg.isAnEndpoint(nextInter)) {
1322
+ const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
1323
+ for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
1324
+ newEvents.push(newEventsFromSplit[i]);
1570
1325
  }
1571
1326
  }
1572
- } // For simplicity, even if we find more than one intersection we only
1573
- // spilt on the 'earliest' (sweep-line style) of the intersections.
1574
- // The other intersection will be handled in a future process().
1575
-
1576
-
1577
- if (prevMySplitter !== null || nextMySplitter !== null) {
1578
- var mySplitter = null;
1579
- if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
1580
- var cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
1581
- mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
1582
- } // Rounding errors can cause changes in ordering,
1583
- // so remove afected segments and right sweep events before splitting
1584
-
1585
- this.queue.remove(segment.rightSE);
1586
- newEvents.push(segment.rightSE);
1587
-
1588
- var _newEventsFromSplit2 = segment.split(mySplitter);
1327
+ }
1328
+ }
1589
1329
 
1590
- for (var _i2 = 0, _iMax2 = _newEventsFromSplit2.length; _i2 < _iMax2; _i2++) {
1591
- newEvents.push(_newEventsFromSplit2[_i2]);
1592
- }
1330
+ // For simplicity, even if we find more than one intersection we only
1331
+ // spilt on the 'earliest' (sweep-line style) of the intersections.
1332
+ // The other intersection will be handled in a future process().
1333
+ if (prevMySplitter !== null || nextMySplitter !== null) {
1334
+ let mySplitter = null;
1335
+ if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
1336
+ const cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
1337
+ mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
1593
1338
  }
1594
1339
 
1595
- if (newEvents.length > 0) {
1596
- // We found some intersections, so re-do the current event to
1597
- // make sure sweep line ordering is totally consistent for later
1598
- // use with the segment 'prev' pointers
1599
- this.tree.remove(segment);
1600
- newEvents.push(event);
1601
- } else {
1602
- // done with left event
1603
- this.segments.push(segment);
1604
- segment.prev = prevSeg;
1340
+ // Rounding errors can cause changes in ordering,
1341
+ // so remove afected segments and right sweep events before splitting
1342
+ this.queue.remove(segment.rightSE);
1343
+ newEvents.push(segment.rightSE);
1344
+ const newEventsFromSplit = segment.split(mySplitter);
1345
+ for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
1346
+ newEvents.push(newEventsFromSplit[i]);
1605
1347
  }
1348
+ }
1349
+ if (newEvents.length > 0) {
1350
+ // We found some intersections, so re-do the current event to
1351
+ // make sure sweep line ordering is totally consistent for later
1352
+ // use with the segment 'prev' pointers
1353
+ this.tree.remove(segment);
1354
+ newEvents.push(event);
1606
1355
  } else {
1607
- // event.isRight
1608
- // since we're about to be removed from the sweep line, check for
1609
- // intersections between our previous and next segments
1610
- if (prevSeg && nextSeg) {
1611
- var inter = prevSeg.getIntersection(nextSeg);
1612
-
1613
- if (inter !== null) {
1614
- if (!prevSeg.isAnEndpoint(inter)) {
1615
- var _newEventsFromSplit3 = this._splitSafely(prevSeg, inter);
1616
-
1617
- for (var _i3 = 0, _iMax3 = _newEventsFromSplit3.length; _i3 < _iMax3; _i3++) {
1618
- newEvents.push(_newEventsFromSplit3[_i3]);
1619
- }
1356
+ // done with left event
1357
+ this.segments.push(segment);
1358
+ segment.prev = prevSeg;
1359
+ }
1360
+ } else {
1361
+ // event.isRight
1362
+
1363
+ // since we're about to be removed from the sweep line, check for
1364
+ // intersections between our previous and next segments
1365
+ if (prevSeg && nextSeg) {
1366
+ const inter = prevSeg.getIntersection(nextSeg);
1367
+ if (inter !== null) {
1368
+ if (!prevSeg.isAnEndpoint(inter)) {
1369
+ const newEventsFromSplit = this._splitSafely(prevSeg, inter);
1370
+ for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
1371
+ newEvents.push(newEventsFromSplit[i]);
1620
1372
  }
1621
-
1622
- if (!nextSeg.isAnEndpoint(inter)) {
1623
- var _newEventsFromSplit4 = this._splitSafely(nextSeg, inter);
1624
-
1625
- for (var _i4 = 0, _iMax4 = _newEventsFromSplit4.length; _i4 < _iMax4; _i4++) {
1626
- newEvents.push(_newEventsFromSplit4[_i4]);
1627
- }
1373
+ }
1374
+ if (!nextSeg.isAnEndpoint(inter)) {
1375
+ const newEventsFromSplit = this._splitSafely(nextSeg, inter);
1376
+ for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
1377
+ newEvents.push(newEventsFromSplit[i]);
1628
1378
  }
1629
1379
  }
1630
1380
  }
1631
-
1632
- this.tree.remove(segment);
1633
1381
  }
1634
-
1635
- return newEvents;
1636
- }
1637
- /* Safely split a segment that is currently in the datastructures
1638
- * IE - a segment other than the one that is currently being processed. */
1639
-
1640
- }, {
1641
- key: "_splitSafely",
1642
- value: function _splitSafely(seg, pt) {
1643
- // Rounding errors can cause changes in ordering,
1644
- // so remove afected segments and right sweep events before splitting
1645
- // removeNode() doesn't work, so have re-find the seg
1646
- // https://github.com/w8r/splay-tree/pull/5
1647
- this.tree.remove(seg);
1648
- var rightSE = seg.rightSE;
1649
- this.queue.remove(rightSE);
1650
- var newEvents = seg.split(pt);
1651
- newEvents.push(rightSE); // splitting can trigger consumption
1652
-
1653
- if (seg.consumedBy === undefined) this.tree.insert(seg);
1654
- return newEvents;
1382
+ this.tree.remove(segment);
1655
1383
  }
1656
- }]);
1657
-
1658
- return SweepLine;
1659
- }();
1660
-
1661
- var POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
1662
- var POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
1663
- var Operation = /*#__PURE__*/function () {
1664
- function Operation() {
1665
- _classCallCheck(this, Operation);
1384
+ return newEvents;
1666
1385
  }
1667
1386
 
1668
- _createClass(Operation, [{
1669
- key: "run",
1670
- value: function run(type, geom, moreGeoms) {
1671
- operation.type = type;
1672
- rounder.reset();
1673
- /* Convert inputs to MultiPoly objects */
1674
-
1675
- var multipolys = [new MultiPolyIn(geom, true)];
1676
-
1677
- for (var i = 0, iMax = moreGeoms.length; i < iMax; i++) {
1678
- multipolys.push(new MultiPolyIn(moreGeoms[i], false));
1679
- }
1680
-
1681
- operation.numMultiPolys = multipolys.length;
1682
- /* BBox optimization for difference operation
1683
- * If the bbox of a multipolygon that's part of the clipping doesn't
1684
- * intersect the bbox of the subject at all, we can just drop that
1685
- * multiploygon. */
1686
-
1687
- if (operation.type === 'difference') {
1688
- // in place removal
1689
- var subject = multipolys[0];
1690
- var _i = 1;
1691
-
1692
- while (_i < multipolys.length) {
1693
- if (getBboxOverlap(multipolys[_i].bbox, subject.bbox) !== null) _i++;else multipolys.splice(_i, 1);
1694
- }
1695
- }
1696
- /* BBox optimization for intersection operation
1697
- * If we can find any pair of multipolygons whose bbox does not overlap,
1698
- * then the result will be empty. */
1699
-
1700
-
1701
- if (operation.type === 'intersection') {
1702
- // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,
1703
- // it could be optimized to O(n * ln(n))
1704
- for (var _i2 = 0, _iMax = multipolys.length; _i2 < _iMax; _i2++) {
1705
- var mpA = multipolys[_i2];
1387
+ /* Safely split a segment that is currently in the datastructures
1388
+ * IE - a segment other than the one that is currently being processed. */
1389
+ _splitSafely(seg, pt) {
1390
+ // Rounding errors can cause changes in ordering,
1391
+ // so remove afected segments and right sweep events before splitting
1392
+ // removeNode() doesn't work, so have re-find the seg
1393
+ // https://github.com/w8r/splay-tree/pull/5
1394
+ this.tree.remove(seg);
1395
+ const rightSE = seg.rightSE;
1396
+ this.queue.remove(rightSE);
1397
+ const newEvents = seg.split(pt);
1398
+ newEvents.push(rightSE);
1399
+ // splitting can trigger consumption
1400
+ if (seg.consumedBy === undefined) this.tree.add(seg);
1401
+ return newEvents;
1402
+ }
1403
+ }
1706
1404
 
1707
- for (var j = _i2 + 1, jMax = multipolys.length; j < jMax; j++) {
1708
- if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
1709
- }
1710
- }
1405
+ // Limits on iterative processes to prevent infinite loops - usually caused by floating-point math round-off errors.
1406
+ const POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== "undefined" && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
1407
+ const POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== "undefined" && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
1408
+ class Operation {
1409
+ run(type, geom, moreGeoms) {
1410
+ operation.type = type;
1411
+ rounder.reset();
1412
+
1413
+ /* Convert inputs to MultiPoly objects */
1414
+ const multipolys = [new MultiPolyIn(geom, true)];
1415
+ for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {
1416
+ multipolys.push(new MultiPolyIn(moreGeoms[i], false));
1417
+ }
1418
+ operation.numMultiPolys = multipolys.length;
1419
+
1420
+ /* BBox optimization for difference operation
1421
+ * If the bbox of a multipolygon that's part of the clipping doesn't
1422
+ * intersect the bbox of the subject at all, we can just drop that
1423
+ * multiploygon. */
1424
+ if (operation.type === "difference") {
1425
+ // in place removal
1426
+ const subject = multipolys[0];
1427
+ let i = 1;
1428
+ while (i < multipolys.length) {
1429
+ if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null) i++;else multipolys.splice(i, 1);
1711
1430
  }
1712
- /* Put segment endpoints in a priority queue */
1713
-
1714
-
1715
- var queue = new SplayTree(SweepEvent.compare);
1716
-
1717
- for (var _i3 = 0, _iMax2 = multipolys.length; _i3 < _iMax2; _i3++) {
1718
- var sweepEvents = multipolys[_i3].getSweepEvents();
1719
-
1720
- for (var _j = 0, _jMax = sweepEvents.length; _j < _jMax; _j++) {
1721
- queue.insert(sweepEvents[_j]);
1431
+ }
1722
1432
 
1723
- if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
1724
- // prevents an infinite loop, an otherwise common manifestation of bugs
1725
- throw new Error('Infinite loop when putting segment endpoints in a priority queue ' + '(queue size too big). Please file a bug report.');
1726
- }
1433
+ /* BBox optimization for intersection operation
1434
+ * If we can find any pair of multipolygons whose bbox does not overlap,
1435
+ * then the result will be empty. */
1436
+ if (operation.type === "intersection") {
1437
+ // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,
1438
+ // it could be optimized to O(n * ln(n))
1439
+ for (let i = 0, iMax = multipolys.length; i < iMax; i++) {
1440
+ const mpA = multipolys[i];
1441
+ for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {
1442
+ if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
1727
1443
  }
1728
1444
  }
1729
- /* Pass the sweep line over those endpoints */
1730
-
1731
-
1732
- var sweepLine = new SweepLine(queue);
1733
- var prevQueueSize = queue.size;
1734
- var node = queue.pop();
1735
-
1736
- while (node) {
1737
- var evt = node.key;
1738
-
1739
- if (queue.size === prevQueueSize) {
1740
- // prevents an infinite loop, an otherwise common manifestation of bugs
1741
- var seg = evt.segment;
1742
- throw new Error("Unable to pop() ".concat(evt.isLeft ? 'left' : 'right', " SweepEvent ") + "[".concat(evt.point.x, ", ").concat(evt.point.y, "] from segment #").concat(seg.id, " ") + "[".concat(seg.leftSE.point.x, ", ").concat(seg.leftSE.point.y, "] -> ") + "[".concat(seg.rightSE.point.x, ", ").concat(seg.rightSE.point.y, "] from queue. ") + 'Please file a bug report.');
1743
- }
1445
+ }
1744
1446
 
1447
+ /* Put segment endpoints in a priority queue */
1448
+ const queue = new SplayTree(SweepEvent.compare);
1449
+ for (let i = 0, iMax = multipolys.length; i < iMax; i++) {
1450
+ const sweepEvents = multipolys[i].getSweepEvents();
1451
+ for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {
1452
+ queue.insert(sweepEvents[j]);
1745
1453
  if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
1746
1454
  // prevents an infinite loop, an otherwise common manifestation of bugs
1747
- throw new Error('Infinite loop when passing sweep line over endpoints ' + '(queue size too big). Please file a bug report.');
1748
- }
1749
-
1750
- if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
1751
- // prevents an infinite loop, an otherwise common manifestation of bugs
1752
- throw new Error('Infinite loop when passing sweep line over endpoints ' + '(too many sweep line segments). Please file a bug report.');
1455
+ throw new Error("Infinite loop when putting segment endpoints in a priority queue " + "(queue size too big).");
1753
1456
  }
1457
+ }
1458
+ }
1754
1459
 
1755
- var newEvents = sweepLine.process(evt);
1756
-
1757
- for (var _i4 = 0, _iMax3 = newEvents.length; _i4 < _iMax3; _i4++) {
1758
- var _evt = newEvents[_i4];
1759
- if (_evt.consumedBy === undefined) queue.insert(_evt);
1760
- }
1761
-
1762
- prevQueueSize = queue.size;
1763
- node = queue.pop();
1764
- } // free some memory we don't need anymore
1765
-
1766
-
1767
- rounder.reset();
1768
- /* Collect and compile segments we're keeping into a multipolygon */
1769
-
1770
- var ringsOut = RingOut.factory(sweepLine.segments);
1771
- var result = new MultiPolyOut(ringsOut);
1772
- return result.getGeom();
1460
+ /* Pass the sweep line over those endpoints */
1461
+ const sweepLine = new SweepLine(queue);
1462
+ let prevQueueSize = queue.size;
1463
+ let node = queue.pop();
1464
+ while (node) {
1465
+ const evt = node.key;
1466
+ if (queue.size === prevQueueSize) {
1467
+ // prevents an infinite loop, an otherwise common manifestation of bugs
1468
+ const seg = evt.segment;
1469
+ throw new Error(`Unable to pop() ${evt.isLeft ? "left" : "right"} SweepEvent ` + `[${evt.point.x}, ${evt.point.y}] from segment #${seg.id} ` + `[${seg.leftSE.point.x}, ${seg.leftSE.point.y}] -> ` + `[${seg.rightSE.point.x}, ${seg.rightSE.point.y}] from queue.`);
1470
+ }
1471
+ if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
1472
+ // prevents an infinite loop, an otherwise common manifestation of bugs
1473
+ throw new Error("Infinite loop when passing sweep line over endpoints " + "(queue size too big).");
1474
+ }
1475
+ if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
1476
+ // prevents an infinite loop, an otherwise common manifestation of bugs
1477
+ throw new Error("Infinite loop when passing sweep line over endpoints " + "(too many sweep line segments).");
1478
+ }
1479
+ const newEvents = sweepLine.process(evt);
1480
+ for (let i = 0, iMax = newEvents.length; i < iMax; i++) {
1481
+ const evt = newEvents[i];
1482
+ if (evt.consumedBy === undefined) queue.insert(evt);
1483
+ }
1484
+ prevQueueSize = queue.size;
1485
+ node = queue.pop();
1773
1486
  }
1774
- }]);
1775
1487
 
1776
- return Operation;
1777
- }(); // singleton available by import
1488
+ // free some memory we don't need anymore
1489
+ rounder.reset();
1778
1490
 
1779
- var operation = new Operation();
1491
+ /* Collect and compile segments we're keeping into a multipolygon */
1492
+ const ringsOut = RingOut.factory(sweepLine.segments);
1493
+ const result = new MultiPolyOut(ringsOut);
1494
+ return result.getGeom();
1495
+ }
1496
+ }
1497
+
1498
+ // singleton available by import
1499
+ const operation = new Operation();
1780
1500
 
1781
- var union = function union(geom) {
1501
+ const union = function (geom) {
1782
1502
  for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1783
1503
  moreGeoms[_key - 1] = arguments[_key];
1784
1504
  }
1785
-
1786
- return operation.run('union', geom, moreGeoms);
1505
+ return operation.run("union", geom, moreGeoms);
1787
1506
  };
1788
-
1789
- var intersection$1 = function intersection(geom) {
1507
+ const intersection = function (geom) {
1790
1508
  for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1791
1509
  moreGeoms[_key2 - 1] = arguments[_key2];
1792
1510
  }
1793
-
1794
- return operation.run('intersection', geom, moreGeoms);
1511
+ return operation.run("intersection", geom, moreGeoms);
1795
1512
  };
1796
-
1797
- var xor = function xor(geom) {
1513
+ const xor = function (geom) {
1798
1514
  for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
1799
1515
  moreGeoms[_key3 - 1] = arguments[_key3];
1800
1516
  }
1801
-
1802
- return operation.run('xor', geom, moreGeoms);
1517
+ return operation.run("xor", geom, moreGeoms);
1803
1518
  };
1804
-
1805
- var difference = function difference(subjectGeom) {
1519
+ const difference = function (subjectGeom) {
1806
1520
  for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
1807
1521
  clippingGeoms[_key4 - 1] = arguments[_key4];
1808
1522
  }
1809
-
1810
- return operation.run('difference', subjectGeom, clippingGeoms);
1523
+ return operation.run("difference", subjectGeom, clippingGeoms);
1811
1524
  };
1812
-
1813
1525
  var index = {
1814
1526
  union: union,
1815
- intersection: intersection$1,
1527
+ intersection: intersection,
1816
1528
  xor: xor,
1817
1529
  difference: difference
1818
1530
  };
1819
1531
 
1820
- export default index;
1532
+ export { index as default };