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