xy-map 1.1.75 → 1.1.77
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.
- package/package.json +1 -1
- package/xy-map.common.js +1630 -1393
- package/xy-map.umd.js +1630 -1393
- package/xy-map.umd.min.js +18 -6
package/xy-map.umd.js
CHANGED
|
@@ -234,7 +234,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, ".snow[data-v-20664206]{position:absolu
|
|
|
234
234
|
|
|
235
235
|
/***/ }),
|
|
236
236
|
|
|
237
|
-
/***/
|
|
237
|
+
/***/ 313:
|
|
238
238
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
239
239
|
|
|
240
240
|
"use strict";
|
|
@@ -248,7 +248,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
248
248
|
|
|
249
249
|
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
|
|
250
250
|
// Module
|
|
251
|
-
___CSS_LOADER_EXPORT___.push([module.id, ".tools[data-v-
|
|
251
|
+
___CSS_LOADER_EXPORT___.push([module.id, ".tools[data-v-45cab0e4]{position:absolute;left:0;top:0;margin:15px;background-color:hsla(0,0%,100%,.9);padding:14px;border-radius:5px}.tools .tools-bar[data-v-45cab0e4]{cursor:pointer}.right-fixed[data-v-45cab0e4]{position:absolute;right:0;top:0;margin:15px}.split-tooltip[data-v-45cab0e4]{position:fixed;background-color:rgba(0,0,0,.8);color:#fff;padding:5px 10px;border-radius:4px;font-size:12px;pointer-events:none;z-index:1000}", ""]);
|
|
252
252
|
// Exports
|
|
253
253
|
/* harmony default export */ __webpack_exports__["default"] = (___CSS_LOADER_EXPORT___);
|
|
254
254
|
|
|
@@ -8977,25 +8977,6 @@ module.exports = typeof Reflect !== 'undefined' && Reflect && Reflect.apply;
|
|
|
8977
8977
|
|
|
8978
8978
|
/***/ }),
|
|
8979
8979
|
|
|
8980
|
-
/***/ 3313:
|
|
8981
|
-
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
8982
|
-
|
|
8983
|
-
"use strict";
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
var GetIntrinsic = __webpack_require__(531);
|
|
8987
|
-
var callBind = __webpack_require__(8197);
|
|
8988
|
-
var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));
|
|
8989
|
-
module.exports = function callBoundIntrinsic(name, allowMissing) {
|
|
8990
|
-
var intrinsic = GetIntrinsic(name, !!allowMissing);
|
|
8991
|
-
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
|
|
8992
|
-
return callBind(intrinsic);
|
|
8993
|
-
}
|
|
8994
|
-
return intrinsic;
|
|
8995
|
-
};
|
|
8996
|
-
|
|
8997
|
-
/***/ }),
|
|
8998
|
-
|
|
8999
8980
|
/***/ 8197:
|
|
9000
8981
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
9001
8982
|
|
|
@@ -28035,25 +28016,32 @@ module.exports = bind.call(call, $hasOwn);
|
|
|
28035
28016
|
|
|
28036
28017
|
|
|
28037
28018
|
var hasToStringTag = __webpack_require__(8157)();
|
|
28038
|
-
var callBound = __webpack_require__(
|
|
28019
|
+
var callBound = __webpack_require__(4114);
|
|
28039
28020
|
var $toString = callBound('Object.prototype.toString');
|
|
28021
|
+
|
|
28022
|
+
/** @type {import('.')} */
|
|
28040
28023
|
var isStandardArguments = function isArguments(value) {
|
|
28041
28024
|
if (hasToStringTag && value && typeof value === 'object' && Symbol.toStringTag in value) {
|
|
28042
28025
|
return false;
|
|
28043
28026
|
}
|
|
28044
28027
|
return $toString(value) === '[object Arguments]';
|
|
28045
28028
|
};
|
|
28029
|
+
|
|
28030
|
+
/** @type {import('.')} */
|
|
28046
28031
|
var isLegacyArguments = function isArguments(value) {
|
|
28047
28032
|
if (isStandardArguments(value)) {
|
|
28048
28033
|
return true;
|
|
28049
28034
|
}
|
|
28050
|
-
return value !== null && typeof value === 'object' && typeof value.length === 'number' && value.length >= 0 && $toString(value) !== '[object Array]' && $toString(value.callee) === '[object Function]';
|
|
28035
|
+
return value !== null && typeof value === 'object' && 'length' in value && typeof value.length === 'number' && value.length >= 0 && $toString(value) !== '[object Array]' && 'callee' in value && $toString(value.callee) === '[object Function]';
|
|
28051
28036
|
};
|
|
28052
28037
|
var supportsStandardArguments = function () {
|
|
28053
28038
|
return isStandardArguments(arguments);
|
|
28054
28039
|
}();
|
|
28040
|
+
|
|
28041
|
+
// @ts-expect-error TODO make this not error
|
|
28055
28042
|
isStandardArguments.isLegacyArguments = isLegacyArguments; // for tests
|
|
28056
28043
|
|
|
28044
|
+
/** @type {import('.')} */
|
|
28057
28045
|
module.exports = supportsStandardArguments ? isStandardArguments : isLegacyArguments;
|
|
28058
28046
|
|
|
28059
28047
|
/***/ }),
|
|
@@ -28685,36 +28673,116 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28685
28673
|
})(this, function () {
|
|
28686
28674
|
'use strict';
|
|
28687
28675
|
|
|
28688
|
-
function _classCallCheck(instance, Constructor) {
|
|
28689
|
-
if (!(instance instanceof Constructor)) {
|
|
28690
|
-
throw new TypeError("Cannot call a class as a function");
|
|
28691
|
-
}
|
|
28692
|
-
}
|
|
28693
|
-
function _defineProperties(target, props) {
|
|
28694
|
-
for (var i = 0; i < props.length; i++) {
|
|
28695
|
-
var descriptor = props[i];
|
|
28696
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
|
28697
|
-
descriptor.configurable = true;
|
|
28698
|
-
if ("value" in descriptor) descriptor.writable = true;
|
|
28699
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
28700
|
-
}
|
|
28701
|
-
}
|
|
28702
|
-
function _createClass(Constructor, protoProps, staticProps) {
|
|
28703
|
-
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
28704
|
-
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
28705
|
-
return Constructor;
|
|
28706
|
-
}
|
|
28707
|
-
|
|
28708
28676
|
/**
|
|
28709
|
-
* splaytree v3.1.
|
|
28677
|
+
* splaytree v3.1.2
|
|
28710
28678
|
* Fast Splay tree for Node and browser
|
|
28711
28679
|
*
|
|
28712
28680
|
* @author Alexander Milevski <info@w8r.name>
|
|
28713
28681
|
* @license MIT
|
|
28714
28682
|
* @preserve
|
|
28715
28683
|
*/
|
|
28716
|
-
|
|
28717
|
-
|
|
28684
|
+
|
|
28685
|
+
/*! *****************************************************************************
|
|
28686
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
28687
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
28688
|
+
this file except in compliance with the License. You may obtain a copy of the
|
|
28689
|
+
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
28690
|
+
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
28691
|
+
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
28692
|
+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
28693
|
+
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
28694
|
+
See the Apache Version 2.0 License for specific language governing permissions
|
|
28695
|
+
and limitations under the License.
|
|
28696
|
+
***************************************************************************** */
|
|
28697
|
+
function __generator(thisArg, body) {
|
|
28698
|
+
var _ = {
|
|
28699
|
+
label: 0,
|
|
28700
|
+
sent: function () {
|
|
28701
|
+
if (t[0] & 1) throw t[1];
|
|
28702
|
+
return t[1];
|
|
28703
|
+
},
|
|
28704
|
+
trys: [],
|
|
28705
|
+
ops: []
|
|
28706
|
+
},
|
|
28707
|
+
f,
|
|
28708
|
+
y,
|
|
28709
|
+
t,
|
|
28710
|
+
g;
|
|
28711
|
+
return g = {
|
|
28712
|
+
next: verb(0),
|
|
28713
|
+
"throw": verb(1),
|
|
28714
|
+
"return": verb(2)
|
|
28715
|
+
}, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
|
|
28716
|
+
return this;
|
|
28717
|
+
}), g;
|
|
28718
|
+
function verb(n) {
|
|
28719
|
+
return function (v) {
|
|
28720
|
+
return step([n, v]);
|
|
28721
|
+
};
|
|
28722
|
+
}
|
|
28723
|
+
function step(op) {
|
|
28724
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28725
|
+
while (_) try {
|
|
28726
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
28727
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
28728
|
+
switch (op[0]) {
|
|
28729
|
+
case 0:
|
|
28730
|
+
case 1:
|
|
28731
|
+
t = op;
|
|
28732
|
+
break;
|
|
28733
|
+
case 4:
|
|
28734
|
+
_.label++;
|
|
28735
|
+
return {
|
|
28736
|
+
value: op[1],
|
|
28737
|
+
done: false
|
|
28738
|
+
};
|
|
28739
|
+
case 5:
|
|
28740
|
+
_.label++;
|
|
28741
|
+
y = op[1];
|
|
28742
|
+
op = [0];
|
|
28743
|
+
continue;
|
|
28744
|
+
case 7:
|
|
28745
|
+
op = _.ops.pop();
|
|
28746
|
+
_.trys.pop();
|
|
28747
|
+
continue;
|
|
28748
|
+
default:
|
|
28749
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
28750
|
+
_ = 0;
|
|
28751
|
+
continue;
|
|
28752
|
+
}
|
|
28753
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
28754
|
+
_.label = op[1];
|
|
28755
|
+
break;
|
|
28756
|
+
}
|
|
28757
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
28758
|
+
_.label = t[1];
|
|
28759
|
+
t = op;
|
|
28760
|
+
break;
|
|
28761
|
+
}
|
|
28762
|
+
if (t && _.label < t[2]) {
|
|
28763
|
+
_.label = t[2];
|
|
28764
|
+
_.ops.push(op);
|
|
28765
|
+
break;
|
|
28766
|
+
}
|
|
28767
|
+
if (t[2]) _.ops.pop();
|
|
28768
|
+
_.trys.pop();
|
|
28769
|
+
continue;
|
|
28770
|
+
}
|
|
28771
|
+
op = body.call(thisArg, _);
|
|
28772
|
+
} catch (e) {
|
|
28773
|
+
op = [6, e];
|
|
28774
|
+
y = 0;
|
|
28775
|
+
} finally {
|
|
28776
|
+
f = t = 0;
|
|
28777
|
+
}
|
|
28778
|
+
if (op[0] & 5) throw op[1];
|
|
28779
|
+
return {
|
|
28780
|
+
value: op[0] ? op[1] : void 0,
|
|
28781
|
+
done: true
|
|
28782
|
+
};
|
|
28783
|
+
}
|
|
28784
|
+
}
|
|
28785
|
+
var Node = /** @class */function () {
|
|
28718
28786
|
function Node(key, data) {
|
|
28719
28787
|
this.next = null;
|
|
28720
28788
|
this.key = key;
|
|
@@ -28724,62 +28792,53 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28724
28792
|
}
|
|
28725
28793
|
return Node;
|
|
28726
28794
|
}();
|
|
28795
|
+
|
|
28727
28796
|
/* follows "An implementation of top-down splaying"
|
|
28728
28797
|
* by D. Sleator <sleator@cs.cmu.edu> March 1992
|
|
28729
28798
|
*/
|
|
28730
|
-
|
|
28731
28799
|
function DEFAULT_COMPARE(a, b) {
|
|
28732
28800
|
return a > b ? 1 : a < b ? -1 : 0;
|
|
28733
28801
|
}
|
|
28734
28802
|
/**
|
|
28735
28803
|
* Simple top down splay, not requiring i to be in the tree t.
|
|
28736
28804
|
*/
|
|
28737
|
-
|
|
28738
28805
|
function splay(i, t, comparator) {
|
|
28739
28806
|
var N = new Node(null, null);
|
|
28740
28807
|
var l = N;
|
|
28741
28808
|
var r = N;
|
|
28742
28809
|
while (true) {
|
|
28743
|
-
var cmp = comparator(i, t.key);
|
|
28744
|
-
|
|
28810
|
+
var cmp = comparator(i, t.key);
|
|
28811
|
+
//if (i < t.key) {
|
|
28745
28812
|
if (cmp < 0) {
|
|
28746
|
-
if (t.left === null) break;
|
|
28747
|
-
|
|
28813
|
+
if (t.left === null) break;
|
|
28814
|
+
//if (i < t.left.key) {
|
|
28748
28815
|
if (comparator(i, t.left.key) < 0) {
|
|
28749
|
-
var y = t.left;
|
|
28750
|
-
/* rotate right */
|
|
28751
|
-
|
|
28816
|
+
var y = t.left; /* rotate right */
|
|
28752
28817
|
t.left = y.right;
|
|
28753
28818
|
y.right = t;
|
|
28754
28819
|
t = y;
|
|
28755
28820
|
if (t.left === null) break;
|
|
28756
28821
|
}
|
|
28757
|
-
r.left = t;
|
|
28758
|
-
/* link right */
|
|
28759
|
-
|
|
28822
|
+
r.left = t; /* link right */
|
|
28760
28823
|
r = t;
|
|
28761
|
-
t = t.left;
|
|
28824
|
+
t = t.left;
|
|
28825
|
+
//} else if (i > t.key) {
|
|
28762
28826
|
} else if (cmp > 0) {
|
|
28763
|
-
if (t.right === null) break;
|
|
28764
|
-
|
|
28827
|
+
if (t.right === null) break;
|
|
28828
|
+
//if (i > t.right.key) {
|
|
28765
28829
|
if (comparator(i, t.right.key) > 0) {
|
|
28766
|
-
var y = t.right;
|
|
28767
|
-
/* rotate left */
|
|
28768
|
-
|
|
28830
|
+
var y = t.right; /* rotate left */
|
|
28769
28831
|
t.right = y.left;
|
|
28770
28832
|
y.left = t;
|
|
28771
28833
|
t = y;
|
|
28772
28834
|
if (t.right === null) break;
|
|
28773
28835
|
}
|
|
28774
|
-
l.right = t;
|
|
28775
|
-
/* link left */
|
|
28776
|
-
|
|
28836
|
+
l.right = t; /* link left */
|
|
28777
28837
|
l = t;
|
|
28778
28838
|
t = t.right;
|
|
28779
28839
|
} else break;
|
|
28780
28840
|
}
|
|
28781
28841
|
/* assemble */
|
|
28782
|
-
|
|
28783
28842
|
l.right = t.left;
|
|
28784
28843
|
r.left = t.right;
|
|
28785
28844
|
t.left = N.right;
|
|
@@ -28839,7 +28898,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28839
28898
|
/**
|
|
28840
28899
|
* Prints level of the tree
|
|
28841
28900
|
*/
|
|
28842
|
-
|
|
28843
28901
|
function printRow(root, prefix, isTail, out, printNode) {
|
|
28844
28902
|
if (root) {
|
|
28845
28903
|
out("" + prefix + (isTail ? '└── ' : '├── ') + printNode(root) + "\n");
|
|
@@ -28848,8 +28906,7 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28848
28906
|
if (root.right) printRow(root.right, indent, true, out, printNode);
|
|
28849
28907
|
}
|
|
28850
28908
|
}
|
|
28851
|
-
var Tree = /** @class */
|
|
28852
|
-
function () {
|
|
28909
|
+
var Tree = /** @class */function () {
|
|
28853
28910
|
function Tree(comparator) {
|
|
28854
28911
|
if (comparator === void 0) {
|
|
28855
28912
|
comparator = DEFAULT_COMPARE;
|
|
@@ -28861,7 +28918,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28861
28918
|
/**
|
|
28862
28919
|
* Inserts a key, allows duplicates
|
|
28863
28920
|
*/
|
|
28864
|
-
|
|
28865
28921
|
Tree.prototype.insert = function (key, data) {
|
|
28866
28922
|
this._size++;
|
|
28867
28923
|
return this._root = insert(key, data, this._root, this._comparator);
|
|
@@ -28869,7 +28925,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28869
28925
|
/**
|
|
28870
28926
|
* Adds a key, if it is not present in the tree
|
|
28871
28927
|
*/
|
|
28872
|
-
|
|
28873
28928
|
Tree.prototype.add = function (key, data) {
|
|
28874
28929
|
var node = new Node(key, data);
|
|
28875
28930
|
if (this._root === null) {
|
|
@@ -28899,14 +28954,12 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28899
28954
|
* @param {Key} key
|
|
28900
28955
|
* @return {Node|null}
|
|
28901
28956
|
*/
|
|
28902
|
-
|
|
28903
28957
|
Tree.prototype.remove = function (key) {
|
|
28904
28958
|
this._root = this._remove(key, this._root, this._comparator);
|
|
28905
28959
|
};
|
|
28906
28960
|
/**
|
|
28907
28961
|
* Deletes i from the tree if it's there
|
|
28908
28962
|
*/
|
|
28909
|
-
|
|
28910
28963
|
Tree.prototype._remove = function (i, t, comparator) {
|
|
28911
28964
|
var x;
|
|
28912
28965
|
if (t === null) return null;
|
|
@@ -28923,19 +28976,15 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28923
28976
|
this._size--;
|
|
28924
28977
|
return x;
|
|
28925
28978
|
}
|
|
28926
|
-
return t;
|
|
28927
|
-
/* It wasn't there */
|
|
28979
|
+
return t; /* It wasn't there */
|
|
28928
28980
|
};
|
|
28929
28981
|
/**
|
|
28930
28982
|
* Removes and returns the node with smallest key
|
|
28931
28983
|
*/
|
|
28932
|
-
|
|
28933
28984
|
Tree.prototype.pop = function () {
|
|
28934
28985
|
var node = this._root;
|
|
28935
28986
|
if (node) {
|
|
28936
|
-
while (node.left)
|
|
28937
|
-
node = node.left;
|
|
28938
|
-
}
|
|
28987
|
+
while (node.left) node = node.left;
|
|
28939
28988
|
this._root = splay(node.key, this._root, this._comparator);
|
|
28940
28989
|
this._root = this._remove(node.key, this._root, this._comparator);
|
|
28941
28990
|
return {
|
|
@@ -28948,7 +28997,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28948
28997
|
/**
|
|
28949
28998
|
* Find without splaying
|
|
28950
28999
|
*/
|
|
28951
|
-
|
|
28952
29000
|
Tree.prototype.findStatic = function (key) {
|
|
28953
29001
|
var current = this._root;
|
|
28954
29002
|
var compare = this._comparator;
|
|
@@ -28976,9 +29024,7 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28976
29024
|
};
|
|
28977
29025
|
Tree.prototype.forEach = function (visitor, ctx) {
|
|
28978
29026
|
var current = this._root;
|
|
28979
|
-
var Q = [];
|
|
28980
|
-
/* Initialize stack s */
|
|
28981
|
-
|
|
29027
|
+
var Q = []; /* Initialize stack s */
|
|
28982
29028
|
var done = false;
|
|
28983
29029
|
while (!done) {
|
|
28984
29030
|
if (current !== null) {
|
|
@@ -28997,7 +29043,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
28997
29043
|
/**
|
|
28998
29044
|
* Walk key range from `low` to `high`. Stops if `fn` returns a value.
|
|
28999
29045
|
*/
|
|
29000
|
-
|
|
29001
29046
|
Tree.prototype.range = function (low, high, fn, ctx) {
|
|
29002
29047
|
var Q = [];
|
|
29003
29048
|
var compare = this._comparator;
|
|
@@ -29024,7 +29069,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29024
29069
|
/**
|
|
29025
29070
|
* Returns array of keys
|
|
29026
29071
|
*/
|
|
29027
|
-
|
|
29028
29072
|
Tree.prototype.keys = function () {
|
|
29029
29073
|
var keys = [];
|
|
29030
29074
|
this.forEach(function (_a) {
|
|
@@ -29036,7 +29080,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29036
29080
|
/**
|
|
29037
29081
|
* Returns array of all the data in the nodes
|
|
29038
29082
|
*/
|
|
29039
|
-
|
|
29040
29083
|
Tree.prototype.values = function () {
|
|
29041
29084
|
var values = [];
|
|
29042
29085
|
this.forEach(function (_a) {
|
|
@@ -29057,24 +29100,19 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29057
29100
|
if (t === void 0) {
|
|
29058
29101
|
t = this._root;
|
|
29059
29102
|
}
|
|
29060
|
-
if (t) while (t.left)
|
|
29061
|
-
t = t.left;
|
|
29062
|
-
}
|
|
29103
|
+
if (t) while (t.left) t = t.left;
|
|
29063
29104
|
return t;
|
|
29064
29105
|
};
|
|
29065
29106
|
Tree.prototype.maxNode = function (t) {
|
|
29066
29107
|
if (t === void 0) {
|
|
29067
29108
|
t = this._root;
|
|
29068
29109
|
}
|
|
29069
|
-
if (t) while (t.right)
|
|
29070
|
-
t = t.right;
|
|
29071
|
-
}
|
|
29110
|
+
if (t) while (t.right) t = t.right;
|
|
29072
29111
|
return t;
|
|
29073
29112
|
};
|
|
29074
29113
|
/**
|
|
29075
29114
|
* Returns node at given index
|
|
29076
29115
|
*/
|
|
29077
|
-
|
|
29078
29116
|
Tree.prototype.at = function (index) {
|
|
29079
29117
|
var current = this._root;
|
|
29080
29118
|
var done = false;
|
|
@@ -29100,9 +29138,7 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29100
29138
|
var successor = null;
|
|
29101
29139
|
if (d.right) {
|
|
29102
29140
|
successor = d.right;
|
|
29103
|
-
while (successor.left)
|
|
29104
|
-
successor = successor.left;
|
|
29105
|
-
}
|
|
29141
|
+
while (successor.left) successor = successor.left;
|
|
29106
29142
|
return successor;
|
|
29107
29143
|
}
|
|
29108
29144
|
var comparator = this._comparator;
|
|
@@ -29120,9 +29156,7 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29120
29156
|
var predecessor = null;
|
|
29121
29157
|
if (d.left !== null) {
|
|
29122
29158
|
predecessor = d.left;
|
|
29123
|
-
while (predecessor.right)
|
|
29124
|
-
predecessor = predecessor.right;
|
|
29125
|
-
}
|
|
29159
|
+
while (predecessor.right) predecessor = predecessor.right;
|
|
29126
29160
|
return predecessor;
|
|
29127
29161
|
}
|
|
29128
29162
|
var comparator = this._comparator;
|
|
@@ -29146,7 +29180,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29146
29180
|
/**
|
|
29147
29181
|
* Bulk-load items. Both array have to be same size
|
|
29148
29182
|
*/
|
|
29149
|
-
|
|
29150
29183
|
Tree.prototype.load = function (keys, values, presort) {
|
|
29151
29184
|
if (values === void 0) {
|
|
29152
29185
|
values = [];
|
|
@@ -29155,8 +29188,8 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29155
29188
|
presort = false;
|
|
29156
29189
|
}
|
|
29157
29190
|
var size = keys.length;
|
|
29158
|
-
var comparator = this._comparator;
|
|
29159
|
-
|
|
29191
|
+
var comparator = this._comparator;
|
|
29192
|
+
// sort if needed
|
|
29160
29193
|
if (presort) sort(keys, values, 0, size - 1, comparator);
|
|
29161
29194
|
if (this._root === null) {
|
|
29162
29195
|
// empty tree
|
|
@@ -29176,14 +29209,14 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29176
29209
|
return this._root === null;
|
|
29177
29210
|
};
|
|
29178
29211
|
Object.defineProperty(Tree.prototype, "size", {
|
|
29179
|
-
get: function
|
|
29212
|
+
get: function () {
|
|
29180
29213
|
return this._size;
|
|
29181
29214
|
},
|
|
29182
29215
|
enumerable: true,
|
|
29183
29216
|
configurable: true
|
|
29184
29217
|
});
|
|
29185
29218
|
Object.defineProperty(Tree.prototype, "root", {
|
|
29186
|
-
get: function
|
|
29219
|
+
get: function () {
|
|
29187
29220
|
return this._root;
|
|
29188
29221
|
},
|
|
29189
29222
|
enumerable: true,
|
|
@@ -29191,7 +29224,7 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29191
29224
|
});
|
|
29192
29225
|
Tree.prototype.toString = function (printNode) {
|
|
29193
29226
|
if (printNode === void 0) {
|
|
29194
|
-
printNode = function
|
|
29227
|
+
printNode = function (n) {
|
|
29195
29228
|
return String(n.key);
|
|
29196
29229
|
};
|
|
29197
29230
|
}
|
|
@@ -29216,6 +29249,40 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29216
29249
|
Tree.prototype.split = function (key) {
|
|
29217
29250
|
return split(key, this._root, this._comparator);
|
|
29218
29251
|
};
|
|
29252
|
+
Tree.prototype[Symbol.iterator] = function () {
|
|
29253
|
+
var current, Q, done;
|
|
29254
|
+
return __generator(this, function (_a) {
|
|
29255
|
+
switch (_a.label) {
|
|
29256
|
+
case 0:
|
|
29257
|
+
current = this._root;
|
|
29258
|
+
Q = [];
|
|
29259
|
+
done = false;
|
|
29260
|
+
_a.label = 1;
|
|
29261
|
+
case 1:
|
|
29262
|
+
if (!!done) return [3 /*break*/, 6];
|
|
29263
|
+
if (!(current !== null)) return [3 /*break*/, 2];
|
|
29264
|
+
Q.push(current);
|
|
29265
|
+
current = current.left;
|
|
29266
|
+
return [3 /*break*/, 5];
|
|
29267
|
+
case 2:
|
|
29268
|
+
if (!(Q.length !== 0)) return [3 /*break*/, 4];
|
|
29269
|
+
current = Q.pop();
|
|
29270
|
+
return [4 /*yield*/, current];
|
|
29271
|
+
case 3:
|
|
29272
|
+
_a.sent();
|
|
29273
|
+
current = current.right;
|
|
29274
|
+
return [3 /*break*/, 5];
|
|
29275
|
+
case 4:
|
|
29276
|
+
done = true;
|
|
29277
|
+
_a.label = 5;
|
|
29278
|
+
case 5:
|
|
29279
|
+
return [3 /*break*/, 1];
|
|
29280
|
+
case 6:
|
|
29281
|
+
return [2 /*return*/];
|
|
29282
|
+
}
|
|
29283
|
+
});
|
|
29284
|
+
};
|
|
29285
|
+
|
|
29219
29286
|
return Tree;
|
|
29220
29287
|
}();
|
|
29221
29288
|
function loadRecursive(keys, values, start, end) {
|
|
@@ -29258,7 +29325,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29258
29325
|
}
|
|
29259
29326
|
}
|
|
29260
29327
|
p.next = null; // that'll work even if the tree was empty
|
|
29261
|
-
|
|
29262
29328
|
return head.next;
|
|
29263
29329
|
}
|
|
29264
29330
|
function sortedListToBST(list, start, end) {
|
|
@@ -29276,7 +29342,6 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29276
29342
|
}
|
|
29277
29343
|
function mergeLists(l1, l2, compare) {
|
|
29278
29344
|
var head = new Node(null, null); // dummy
|
|
29279
|
-
|
|
29280
29345
|
var p = head;
|
|
29281
29346
|
var p1 = l1;
|
|
29282
29347
|
var p2 = l2;
|
|
@@ -29303,12 +29368,8 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29303
29368
|
var i = left - 1;
|
|
29304
29369
|
var j = right + 1;
|
|
29305
29370
|
while (true) {
|
|
29306
|
-
do
|
|
29307
|
-
|
|
29308
|
-
} while (compare(keys[i], pivot) < 0);
|
|
29309
|
-
do {
|
|
29310
|
-
j--;
|
|
29311
|
-
} while (compare(keys[j], pivot) > 0);
|
|
29371
|
+
do i++; while (compare(keys[i], pivot) < 0);
|
|
29372
|
+
do j--; while (compare(keys[j], pivot) > 0);
|
|
29312
29373
|
if (i >= j) break;
|
|
29313
29374
|
var tmp = keys[i];
|
|
29314
29375
|
keys[i] = keys[j];
|
|
@@ -29327,23 +29388,27 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29327
29388
|
* { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }
|
|
29328
29389
|
*
|
|
29329
29390
|
*/
|
|
29330
|
-
|
|
29391
|
+
|
|
29392
|
+
const isInBbox = (bbox, point) => {
|
|
29331
29393
|
return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;
|
|
29332
29394
|
};
|
|
29395
|
+
|
|
29333
29396
|
/* Returns either null, or a bbox (aka an ordered pair of points)
|
|
29334
29397
|
* If there is only one point of overlap, a bbox with identical points
|
|
29335
29398
|
* will be returned */
|
|
29336
|
-
|
|
29337
|
-
var getBboxOverlap = function getBboxOverlap(b1, b2) {
|
|
29399
|
+
const getBboxOverlap = (b1, b2) => {
|
|
29338
29400
|
// check if the bboxes overlap at all
|
|
29339
|
-
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;
|
|
29401
|
+
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;
|
|
29340
29402
|
|
|
29341
|
-
|
|
29342
|
-
|
|
29403
|
+
// find the middle two X values
|
|
29404
|
+
const lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;
|
|
29405
|
+
const upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x;
|
|
29343
29406
|
|
|
29344
|
-
|
|
29345
|
-
|
|
29407
|
+
// find the middle two Y values
|
|
29408
|
+
const lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;
|
|
29409
|
+
const upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y;
|
|
29346
29410
|
|
|
29411
|
+
// put those middle values together to get the overlap
|
|
29347
29412
|
return {
|
|
29348
29413
|
ll: {
|
|
29349
29414
|
x: lowerX,
|
|
@@ -29361,25 +29426,29 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29361
29426
|
*
|
|
29362
29427
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
|
|
29363
29428
|
*/
|
|
29364
|
-
var epsilon = Number.EPSILON; // IE Polyfill
|
|
29365
29429
|
|
|
29366
|
-
|
|
29367
|
-
|
|
29368
|
-
|
|
29430
|
+
let epsilon$1 = Number.EPSILON;
|
|
29431
|
+
|
|
29432
|
+
// IE Polyfill
|
|
29433
|
+
if (epsilon$1 === undefined) epsilon$1 = Math.pow(2, -52);
|
|
29434
|
+
const EPSILON_SQ = epsilon$1 * epsilon$1;
|
|
29369
29435
|
|
|
29370
|
-
|
|
29436
|
+
/* FLP comparator */
|
|
29437
|
+
const cmp = (a, b) => {
|
|
29371
29438
|
// check if they're both 0
|
|
29372
|
-
if (-epsilon < a && a < epsilon) {
|
|
29373
|
-
if (-epsilon < b && b < epsilon) {
|
|
29439
|
+
if (-epsilon$1 < a && a < epsilon$1) {
|
|
29440
|
+
if (-epsilon$1 < b && b < epsilon$1) {
|
|
29374
29441
|
return 0;
|
|
29375
29442
|
}
|
|
29376
|
-
}
|
|
29443
|
+
}
|
|
29377
29444
|
|
|
29378
|
-
|
|
29445
|
+
// check if they're flp equal
|
|
29446
|
+
const ab = a - b;
|
|
29379
29447
|
if (ab * ab < EPSILON_SQ * a * b) {
|
|
29380
29448
|
return 0;
|
|
29381
|
-
}
|
|
29449
|
+
}
|
|
29382
29450
|
|
|
29451
|
+
// normal comparison
|
|
29383
29452
|
return a < b ? -1 : 1;
|
|
29384
29453
|
};
|
|
29385
29454
|
|
|
@@ -29396,421 +29465,661 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29396
29465
|
* stored in any data structures in the rest of this algorithm.
|
|
29397
29466
|
*/
|
|
29398
29467
|
|
|
29399
|
-
|
|
29400
|
-
|
|
29401
|
-
_classCallCheck(this, PtRounder);
|
|
29468
|
+
class PtRounder {
|
|
29469
|
+
constructor() {
|
|
29402
29470
|
this.reset();
|
|
29403
29471
|
}
|
|
29404
|
-
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
|
|
29408
|
-
|
|
29409
|
-
|
|
29410
|
-
|
|
29411
|
-
|
|
29412
|
-
|
|
29413
|
-
|
|
29414
|
-
|
|
29415
|
-
|
|
29416
|
-
|
|
29417
|
-
|
|
29418
|
-
|
|
29419
|
-
return PtRounder;
|
|
29420
|
-
}();
|
|
29421
|
-
var CoordRounder = /*#__PURE__*/function () {
|
|
29422
|
-
function CoordRounder() {
|
|
29423
|
-
_classCallCheck(this, CoordRounder);
|
|
29424
|
-
this.tree = new Tree(); // preseed with 0 so we don't end up with values < Number.EPSILON
|
|
29425
|
-
|
|
29472
|
+
reset() {
|
|
29473
|
+
this.xRounder = new CoordRounder();
|
|
29474
|
+
this.yRounder = new CoordRounder();
|
|
29475
|
+
}
|
|
29476
|
+
round(x, y) {
|
|
29477
|
+
return {
|
|
29478
|
+
x: this.xRounder.round(x),
|
|
29479
|
+
y: this.yRounder.round(y)
|
|
29480
|
+
};
|
|
29481
|
+
}
|
|
29482
|
+
}
|
|
29483
|
+
class CoordRounder {
|
|
29484
|
+
constructor() {
|
|
29485
|
+
this.tree = new Tree();
|
|
29486
|
+
// preseed with 0 so we don't end up with values < Number.EPSILON
|
|
29426
29487
|
this.round(0);
|
|
29427
|
-
}
|
|
29488
|
+
}
|
|
29489
|
+
|
|
29490
|
+
// Note: this can rounds input values backwards or forwards.
|
|
29428
29491
|
// You might ask, why not restrict this to just rounding
|
|
29429
29492
|
// forwards? Wouldn't that allow left endpoints to always
|
|
29430
29493
|
// remain left endpoints during splitting (never change to
|
|
29431
29494
|
// right). No - it wouldn't, because we snap intersections
|
|
29432
29495
|
// to endpoints (to establish independence from the segment
|
|
29433
29496
|
// angle for t-intersections).
|
|
29434
|
-
|
|
29435
|
-
|
|
29436
|
-
|
|
29437
|
-
|
|
29438
|
-
|
|
29439
|
-
|
|
29440
|
-
|
|
29441
|
-
|
|
29442
|
-
|
|
29443
|
-
|
|
29444
|
-
|
|
29445
|
-
|
|
29446
|
-
|
|
29447
|
-
|
|
29448
|
-
|
|
29449
|
-
|
|
29450
|
-
|
|
29451
|
-
|
|
29452
|
-
|
|
29453
|
-
|
|
29454
|
-
|
|
29455
|
-
|
|
29497
|
+
round(coord) {
|
|
29498
|
+
const node = this.tree.add(coord);
|
|
29499
|
+
const prevNode = this.tree.prev(node);
|
|
29500
|
+
if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {
|
|
29501
|
+
this.tree.remove(coord);
|
|
29502
|
+
return prevNode.key;
|
|
29503
|
+
}
|
|
29504
|
+
const nextNode = this.tree.next(node);
|
|
29505
|
+
if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {
|
|
29506
|
+
this.tree.remove(coord);
|
|
29507
|
+
return nextNode.key;
|
|
29508
|
+
}
|
|
29509
|
+
return coord;
|
|
29510
|
+
}
|
|
29511
|
+
}
|
|
29512
|
+
|
|
29513
|
+
// singleton available by import
|
|
29514
|
+
const rounder = new PtRounder();
|
|
29515
|
+
const epsilon = 1.1102230246251565e-16;
|
|
29516
|
+
const splitter = 134217729;
|
|
29517
|
+
const resulterrbound = (3 + 8 * epsilon) * epsilon;
|
|
29518
|
+
|
|
29519
|
+
// fast_expansion_sum_zeroelim routine from oritinal code
|
|
29520
|
+
function sum(elen, e, flen, f, h) {
|
|
29521
|
+
let Q, Qnew, hh, bvirt;
|
|
29522
|
+
let enow = e[0];
|
|
29523
|
+
let fnow = f[0];
|
|
29524
|
+
let eindex = 0;
|
|
29525
|
+
let findex = 0;
|
|
29526
|
+
if (fnow > enow === fnow > -enow) {
|
|
29527
|
+
Q = enow;
|
|
29528
|
+
enow = e[++eindex];
|
|
29529
|
+
} else {
|
|
29530
|
+
Q = fnow;
|
|
29531
|
+
fnow = f[++findex];
|
|
29532
|
+
}
|
|
29533
|
+
let hindex = 0;
|
|
29534
|
+
if (eindex < elen && findex < flen) {
|
|
29535
|
+
if (fnow > enow === fnow > -enow) {
|
|
29536
|
+
Qnew = enow + Q;
|
|
29537
|
+
hh = Q - (Qnew - enow);
|
|
29538
|
+
enow = e[++eindex];
|
|
29539
|
+
} else {
|
|
29540
|
+
Qnew = fnow + Q;
|
|
29541
|
+
hh = Q - (Qnew - fnow);
|
|
29542
|
+
fnow = f[++findex];
|
|
29543
|
+
}
|
|
29544
|
+
Q = Qnew;
|
|
29545
|
+
if (hh !== 0) {
|
|
29546
|
+
h[hindex++] = hh;
|
|
29547
|
+
}
|
|
29548
|
+
while (eindex < elen && findex < flen) {
|
|
29549
|
+
if (fnow > enow === fnow > -enow) {
|
|
29550
|
+
Qnew = Q + enow;
|
|
29551
|
+
bvirt = Qnew - Q;
|
|
29552
|
+
hh = Q - (Qnew - bvirt) + (enow - bvirt);
|
|
29553
|
+
enow = e[++eindex];
|
|
29554
|
+
} else {
|
|
29555
|
+
Qnew = Q + fnow;
|
|
29556
|
+
bvirt = Qnew - Q;
|
|
29557
|
+
hh = Q - (Qnew - bvirt) + (fnow - bvirt);
|
|
29558
|
+
fnow = f[++findex];
|
|
29559
|
+
}
|
|
29560
|
+
Q = Qnew;
|
|
29561
|
+
if (hh !== 0) {
|
|
29562
|
+
h[hindex++] = hh;
|
|
29563
|
+
}
|
|
29564
|
+
}
|
|
29565
|
+
}
|
|
29566
|
+
while (eindex < elen) {
|
|
29567
|
+
Qnew = Q + enow;
|
|
29568
|
+
bvirt = Qnew - Q;
|
|
29569
|
+
hh = Q - (Qnew - bvirt) + (enow - bvirt);
|
|
29570
|
+
enow = e[++eindex];
|
|
29571
|
+
Q = Qnew;
|
|
29572
|
+
if (hh !== 0) {
|
|
29573
|
+
h[hindex++] = hh;
|
|
29574
|
+
}
|
|
29575
|
+
}
|
|
29576
|
+
while (findex < flen) {
|
|
29577
|
+
Qnew = Q + fnow;
|
|
29578
|
+
bvirt = Qnew - Q;
|
|
29579
|
+
hh = Q - (Qnew - bvirt) + (fnow - bvirt);
|
|
29580
|
+
fnow = f[++findex];
|
|
29581
|
+
Q = Qnew;
|
|
29582
|
+
if (hh !== 0) {
|
|
29583
|
+
h[hindex++] = hh;
|
|
29584
|
+
}
|
|
29585
|
+
}
|
|
29586
|
+
if (Q !== 0 || hindex === 0) {
|
|
29587
|
+
h[hindex++] = Q;
|
|
29588
|
+
}
|
|
29589
|
+
return hindex;
|
|
29590
|
+
}
|
|
29591
|
+
function estimate(elen, e) {
|
|
29592
|
+
let Q = e[0];
|
|
29593
|
+
for (let i = 1; i < elen; i++) Q += e[i];
|
|
29594
|
+
return Q;
|
|
29595
|
+
}
|
|
29596
|
+
function vec(n) {
|
|
29597
|
+
return new Float64Array(n);
|
|
29598
|
+
}
|
|
29599
|
+
const ccwerrboundA = (3 + 16 * epsilon) * epsilon;
|
|
29600
|
+
const ccwerrboundB = (2 + 12 * epsilon) * epsilon;
|
|
29601
|
+
const ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;
|
|
29602
|
+
const B = vec(4);
|
|
29603
|
+
const C1 = vec(8);
|
|
29604
|
+
const C2 = vec(12);
|
|
29605
|
+
const D = vec(16);
|
|
29606
|
+
const u = vec(4);
|
|
29607
|
+
function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
|
|
29608
|
+
let acxtail, acytail, bcxtail, bcytail;
|
|
29609
|
+
let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;
|
|
29610
|
+
const acx = ax - cx;
|
|
29611
|
+
const bcx = bx - cx;
|
|
29612
|
+
const acy = ay - cy;
|
|
29613
|
+
const bcy = by - cy;
|
|
29614
|
+
s1 = acx * bcy;
|
|
29615
|
+
c = splitter * acx;
|
|
29616
|
+
ahi = c - (c - acx);
|
|
29617
|
+
alo = acx - ahi;
|
|
29618
|
+
c = splitter * bcy;
|
|
29619
|
+
bhi = c - (c - bcy);
|
|
29620
|
+
blo = bcy - bhi;
|
|
29621
|
+
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29622
|
+
t1 = acy * bcx;
|
|
29623
|
+
c = splitter * acy;
|
|
29624
|
+
ahi = c - (c - acy);
|
|
29625
|
+
alo = acy - ahi;
|
|
29626
|
+
c = splitter * bcx;
|
|
29627
|
+
bhi = c - (c - bcx);
|
|
29628
|
+
blo = bcx - bhi;
|
|
29629
|
+
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29630
|
+
_i = s0 - t0;
|
|
29631
|
+
bvirt = s0 - _i;
|
|
29632
|
+
B[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
29633
|
+
_j = s1 + _i;
|
|
29634
|
+
bvirt = _j - s1;
|
|
29635
|
+
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
29636
|
+
_i = _0 - t1;
|
|
29637
|
+
bvirt = _0 - _i;
|
|
29638
|
+
B[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
29639
|
+
u3 = _j + _i;
|
|
29640
|
+
bvirt = u3 - _j;
|
|
29641
|
+
B[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
29642
|
+
B[3] = u3;
|
|
29643
|
+
let det = estimate(4, B);
|
|
29644
|
+
let errbound = ccwerrboundB * detsum;
|
|
29645
|
+
if (det >= errbound || -det >= errbound) {
|
|
29646
|
+
return det;
|
|
29647
|
+
}
|
|
29648
|
+
bvirt = ax - acx;
|
|
29649
|
+
acxtail = ax - (acx + bvirt) + (bvirt - cx);
|
|
29650
|
+
bvirt = bx - bcx;
|
|
29651
|
+
bcxtail = bx - (bcx + bvirt) + (bvirt - cx);
|
|
29652
|
+
bvirt = ay - acy;
|
|
29653
|
+
acytail = ay - (acy + bvirt) + (bvirt - cy);
|
|
29654
|
+
bvirt = by - bcy;
|
|
29655
|
+
bcytail = by - (bcy + bvirt) + (bvirt - cy);
|
|
29656
|
+
if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {
|
|
29657
|
+
return det;
|
|
29658
|
+
}
|
|
29659
|
+
errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);
|
|
29660
|
+
det += acx * bcytail + bcy * acxtail - (acy * bcxtail + bcx * acytail);
|
|
29661
|
+
if (det >= errbound || -det >= errbound) return det;
|
|
29662
|
+
s1 = acxtail * bcy;
|
|
29663
|
+
c = splitter * acxtail;
|
|
29664
|
+
ahi = c - (c - acxtail);
|
|
29665
|
+
alo = acxtail - ahi;
|
|
29666
|
+
c = splitter * bcy;
|
|
29667
|
+
bhi = c - (c - bcy);
|
|
29668
|
+
blo = bcy - bhi;
|
|
29669
|
+
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29670
|
+
t1 = acytail * bcx;
|
|
29671
|
+
c = splitter * acytail;
|
|
29672
|
+
ahi = c - (c - acytail);
|
|
29673
|
+
alo = acytail - ahi;
|
|
29674
|
+
c = splitter * bcx;
|
|
29675
|
+
bhi = c - (c - bcx);
|
|
29676
|
+
blo = bcx - bhi;
|
|
29677
|
+
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29678
|
+
_i = s0 - t0;
|
|
29679
|
+
bvirt = s0 - _i;
|
|
29680
|
+
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
29681
|
+
_j = s1 + _i;
|
|
29682
|
+
bvirt = _j - s1;
|
|
29683
|
+
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
29684
|
+
_i = _0 - t1;
|
|
29685
|
+
bvirt = _0 - _i;
|
|
29686
|
+
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
29687
|
+
u3 = _j + _i;
|
|
29688
|
+
bvirt = u3 - _j;
|
|
29689
|
+
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
29690
|
+
u[3] = u3;
|
|
29691
|
+
const C1len = sum(4, B, 4, u, C1);
|
|
29692
|
+
s1 = acx * bcytail;
|
|
29693
|
+
c = splitter * acx;
|
|
29694
|
+
ahi = c - (c - acx);
|
|
29695
|
+
alo = acx - ahi;
|
|
29696
|
+
c = splitter * bcytail;
|
|
29697
|
+
bhi = c - (c - bcytail);
|
|
29698
|
+
blo = bcytail - bhi;
|
|
29699
|
+
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29700
|
+
t1 = acy * bcxtail;
|
|
29701
|
+
c = splitter * acy;
|
|
29702
|
+
ahi = c - (c - acy);
|
|
29703
|
+
alo = acy - ahi;
|
|
29704
|
+
c = splitter * bcxtail;
|
|
29705
|
+
bhi = c - (c - bcxtail);
|
|
29706
|
+
blo = bcxtail - bhi;
|
|
29707
|
+
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29708
|
+
_i = s0 - t0;
|
|
29709
|
+
bvirt = s0 - _i;
|
|
29710
|
+
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
29711
|
+
_j = s1 + _i;
|
|
29712
|
+
bvirt = _j - s1;
|
|
29713
|
+
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
29714
|
+
_i = _0 - t1;
|
|
29715
|
+
bvirt = _0 - _i;
|
|
29716
|
+
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
29717
|
+
u3 = _j + _i;
|
|
29718
|
+
bvirt = u3 - _j;
|
|
29719
|
+
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
29720
|
+
u[3] = u3;
|
|
29721
|
+
const C2len = sum(C1len, C1, 4, u, C2);
|
|
29722
|
+
s1 = acxtail * bcytail;
|
|
29723
|
+
c = splitter * acxtail;
|
|
29724
|
+
ahi = c - (c - acxtail);
|
|
29725
|
+
alo = acxtail - ahi;
|
|
29726
|
+
c = splitter * bcytail;
|
|
29727
|
+
bhi = c - (c - bcytail);
|
|
29728
|
+
blo = bcytail - bhi;
|
|
29729
|
+
s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29730
|
+
t1 = acytail * bcxtail;
|
|
29731
|
+
c = splitter * acytail;
|
|
29732
|
+
ahi = c - (c - acytail);
|
|
29733
|
+
alo = acytail - ahi;
|
|
29734
|
+
c = splitter * bcxtail;
|
|
29735
|
+
bhi = c - (c - bcxtail);
|
|
29736
|
+
blo = bcxtail - bhi;
|
|
29737
|
+
t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);
|
|
29738
|
+
_i = s0 - t0;
|
|
29739
|
+
bvirt = s0 - _i;
|
|
29740
|
+
u[0] = s0 - (_i + bvirt) + (bvirt - t0);
|
|
29741
|
+
_j = s1 + _i;
|
|
29742
|
+
bvirt = _j - s1;
|
|
29743
|
+
_0 = s1 - (_j - bvirt) + (_i - bvirt);
|
|
29744
|
+
_i = _0 - t1;
|
|
29745
|
+
bvirt = _0 - _i;
|
|
29746
|
+
u[1] = _0 - (_i + bvirt) + (bvirt - t1);
|
|
29747
|
+
u3 = _j + _i;
|
|
29748
|
+
bvirt = u3 - _j;
|
|
29749
|
+
u[2] = _j - (u3 - bvirt) + (_i - bvirt);
|
|
29750
|
+
u[3] = u3;
|
|
29751
|
+
const Dlen = sum(C2len, C2, 4, u, D);
|
|
29752
|
+
return D[Dlen - 1];
|
|
29753
|
+
}
|
|
29754
|
+
function orient2d(ax, ay, bx, by, cx, cy) {
|
|
29755
|
+
const detleft = (ay - cy) * (bx - cx);
|
|
29756
|
+
const detright = (ax - cx) * (by - cy);
|
|
29757
|
+
const det = detleft - detright;
|
|
29758
|
+
const detsum = Math.abs(detleft + detright);
|
|
29759
|
+
if (Math.abs(det) >= ccwerrboundA * detsum) return det;
|
|
29760
|
+
return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);
|
|
29761
|
+
}
|
|
29456
29762
|
|
|
29457
29763
|
/* Cross Product of two vectors with first point at origin */
|
|
29764
|
+
const crossProduct = (a, b) => a.x * b.y - a.y * b.x;
|
|
29458
29765
|
|
|
29459
|
-
var crossProduct = function crossProduct(a, b) {
|
|
29460
|
-
return a.x * b.y - a.y * b.x;
|
|
29461
|
-
};
|
|
29462
29766
|
/* Dot Product of two vectors with first point at origin */
|
|
29767
|
+
const dotProduct = (a, b) => a.x * b.x + a.y * b.y;
|
|
29463
29768
|
|
|
29464
|
-
var dotProduct = function dotProduct(a, b) {
|
|
29465
|
-
return a.x * b.x + a.y * b.y;
|
|
29466
|
-
};
|
|
29467
29769
|
/* Comparator for two vectors with same starting point */
|
|
29468
|
-
|
|
29469
|
-
|
|
29470
|
-
|
|
29471
|
-
|
|
29472
|
-
|
|
29473
|
-
};
|
|
29474
|
-
var v2 = {
|
|
29475
|
-
x: endPt2.x - basePt.x,
|
|
29476
|
-
y: endPt2.y - basePt.y
|
|
29477
|
-
};
|
|
29478
|
-
var kross = crossProduct(v1, v2);
|
|
29479
|
-
return cmp(kross, 0);
|
|
29480
|
-
};
|
|
29481
|
-
var length = function length(v) {
|
|
29482
|
-
return Math.sqrt(dotProduct(v, v));
|
|
29770
|
+
const compareVectorAngles = (basePt, endPt1, endPt2) => {
|
|
29771
|
+
const res = orient2d(basePt.x, basePt.y, endPt1.x, endPt1.y, endPt2.x, endPt2.y);
|
|
29772
|
+
if (res > 0) return -1;
|
|
29773
|
+
if (res < 0) return 1;
|
|
29774
|
+
return 0;
|
|
29483
29775
|
};
|
|
29484
|
-
|
|
29776
|
+
const length = v => Math.sqrt(dotProduct(v, v));
|
|
29485
29777
|
|
|
29486
|
-
|
|
29487
|
-
|
|
29778
|
+
/* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */
|
|
29779
|
+
const sineOfAngle = (pShared, pBase, pAngle) => {
|
|
29780
|
+
const vBase = {
|
|
29488
29781
|
x: pBase.x - pShared.x,
|
|
29489
29782
|
y: pBase.y - pShared.y
|
|
29490
29783
|
};
|
|
29491
|
-
|
|
29784
|
+
const vAngle = {
|
|
29492
29785
|
x: pAngle.x - pShared.x,
|
|
29493
29786
|
y: pAngle.y - pShared.y
|
|
29494
29787
|
};
|
|
29495
29788
|
return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);
|
|
29496
29789
|
};
|
|
29497
|
-
/* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
|
|
29498
29790
|
|
|
29499
|
-
|
|
29500
|
-
|
|
29791
|
+
/* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
|
|
29792
|
+
const cosineOfAngle = (pShared, pBase, pAngle) => {
|
|
29793
|
+
const vBase = {
|
|
29501
29794
|
x: pBase.x - pShared.x,
|
|
29502
29795
|
y: pBase.y - pShared.y
|
|
29503
29796
|
};
|
|
29504
|
-
|
|
29797
|
+
const vAngle = {
|
|
29505
29798
|
x: pAngle.x - pShared.x,
|
|
29506
29799
|
y: pAngle.y - pShared.y
|
|
29507
29800
|
};
|
|
29508
29801
|
return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);
|
|
29509
29802
|
};
|
|
29803
|
+
|
|
29510
29804
|
/* Get the x coordinate where the given line (defined by a point and vector)
|
|
29511
29805
|
* crosses the horizontal line with the given y coordiante.
|
|
29512
29806
|
* In the case of parrallel lines (including overlapping ones) returns null. */
|
|
29513
|
-
|
|
29514
|
-
var horizontalIntersection = function horizontalIntersection(pt, v, y) {
|
|
29807
|
+
const horizontalIntersection = (pt, v, y) => {
|
|
29515
29808
|
if (v.y === 0) return null;
|
|
29516
29809
|
return {
|
|
29517
29810
|
x: pt.x + v.x / v.y * (y - pt.y),
|
|
29518
29811
|
y: y
|
|
29519
29812
|
};
|
|
29520
29813
|
};
|
|
29814
|
+
|
|
29521
29815
|
/* Get the y coordinate where the given line (defined by a point and vector)
|
|
29522
29816
|
* crosses the vertical line with the given x coordiante.
|
|
29523
29817
|
* In the case of parrallel lines (including overlapping ones) returns null. */
|
|
29524
|
-
|
|
29525
|
-
var verticalIntersection = function verticalIntersection(pt, v, x) {
|
|
29818
|
+
const verticalIntersection = (pt, v, x) => {
|
|
29526
29819
|
if (v.x === 0) return null;
|
|
29527
29820
|
return {
|
|
29528
29821
|
x: x,
|
|
29529
29822
|
y: pt.y + v.y / v.x * (x - pt.x)
|
|
29530
29823
|
};
|
|
29531
29824
|
};
|
|
29825
|
+
|
|
29532
29826
|
/* Get the intersection of two lines, each defined by a base point and a vector.
|
|
29533
29827
|
* In the case of parrallel lines (including overlapping ones) returns null. */
|
|
29534
|
-
|
|
29535
|
-
var intersection = function intersection(pt1, v1, pt2, v2) {
|
|
29828
|
+
const intersection$1 = (pt1, v1, pt2, v2) => {
|
|
29536
29829
|
// take some shortcuts for vertical and horizontal lines
|
|
29537
29830
|
// this also ensures we don't calculate an intersection and then discover
|
|
29538
29831
|
// it's actually outside the bounding box of the line
|
|
29539
29832
|
if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);
|
|
29540
29833
|
if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);
|
|
29541
29834
|
if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);
|
|
29542
|
-
if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y);
|
|
29835
|
+
if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y);
|
|
29836
|
+
|
|
29837
|
+
// General case for non-overlapping segments.
|
|
29543
29838
|
// This algorithm is based on Schneider and Eberly.
|
|
29544
29839
|
// http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244
|
|
29545
29840
|
|
|
29546
|
-
|
|
29841
|
+
const kross = crossProduct(v1, v2);
|
|
29547
29842
|
if (kross == 0) return null;
|
|
29548
|
-
|
|
29843
|
+
const ve = {
|
|
29549
29844
|
x: pt2.x - pt1.x,
|
|
29550
29845
|
y: pt2.y - pt1.y
|
|
29551
29846
|
};
|
|
29552
|
-
|
|
29553
|
-
|
|
29847
|
+
const d1 = crossProduct(ve, v1) / kross;
|
|
29848
|
+
const d2 = crossProduct(ve, v2) / kross;
|
|
29554
29849
|
|
|
29555
|
-
|
|
29850
|
+
// take the average of the two calculations to minimize rounding error
|
|
29851
|
+
const x1 = pt1.x + d2 * v1.x,
|
|
29556
29852
|
x2 = pt2.x + d1 * v2.x;
|
|
29557
|
-
|
|
29853
|
+
const y1 = pt1.y + d2 * v1.y,
|
|
29558
29854
|
y2 = pt2.y + d1 * v2.y;
|
|
29559
|
-
|
|
29560
|
-
|
|
29855
|
+
const x = (x1 + x2) / 2;
|
|
29856
|
+
const y = (y1 + y2) / 2;
|
|
29561
29857
|
return {
|
|
29562
29858
|
x: x,
|
|
29563
29859
|
y: y
|
|
29564
29860
|
};
|
|
29565
29861
|
};
|
|
29566
|
-
|
|
29567
|
-
|
|
29568
|
-
|
|
29569
|
-
//
|
|
29570
|
-
|
|
29571
|
-
|
|
29572
|
-
var ptCmp = SweepEvent.comparePoints(a.point, b.point);
|
|
29573
|
-
if (ptCmp !== 0) return ptCmp; // the points are the same, so link them if needed
|
|
29862
|
+
class SweepEvent {
|
|
29863
|
+
// for ordering sweep events in the sweep event queue
|
|
29864
|
+
static compare(a, b) {
|
|
29865
|
+
// favor event with a point that the sweep line hits first
|
|
29866
|
+
const ptCmp = SweepEvent.comparePoints(a.point, b.point);
|
|
29867
|
+
if (ptCmp !== 0) return ptCmp;
|
|
29574
29868
|
|
|
29575
|
-
|
|
29869
|
+
// the points are the same, so link them if needed
|
|
29870
|
+
if (a.point !== b.point) a.link(b);
|
|
29576
29871
|
|
|
29577
|
-
|
|
29578
|
-
|
|
29872
|
+
// favor right events over left
|
|
29873
|
+
if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1;
|
|
29579
29874
|
|
|
29580
|
-
|
|
29581
|
-
|
|
29582
|
-
|
|
29583
|
-
|
|
29584
|
-
|
|
29585
|
-
|
|
29586
|
-
|
|
29587
|
-
|
|
29588
|
-
|
|
29589
|
-
|
|
29590
|
-
|
|
29591
|
-
|
|
29875
|
+
// we have two matching left or right endpoints
|
|
29876
|
+
// ordering of this case is the same as for their segments
|
|
29877
|
+
return Segment.compare(a.segment, b.segment);
|
|
29878
|
+
}
|
|
29879
|
+
|
|
29880
|
+
// for ordering points in sweep line order
|
|
29881
|
+
static comparePoints(aPt, bPt) {
|
|
29882
|
+
if (aPt.x < bPt.x) return -1;
|
|
29883
|
+
if (aPt.x > bPt.x) return 1;
|
|
29884
|
+
if (aPt.y < bPt.y) return -1;
|
|
29885
|
+
if (aPt.y > bPt.y) return 1;
|
|
29886
|
+
return 0;
|
|
29887
|
+
}
|
|
29592
29888
|
|
|
29593
|
-
|
|
29594
|
-
|
|
29889
|
+
// Warning: 'point' input will be modified and re-used (for performance)
|
|
29890
|
+
constructor(point, isLeft) {
|
|
29595
29891
|
if (point.events === undefined) point.events = [this];else point.events.push(this);
|
|
29596
29892
|
this.point = point;
|
|
29597
|
-
this.isLeft = isLeft;
|
|
29893
|
+
this.isLeft = isLeft;
|
|
29894
|
+
// this.segment, this.otherSE set by factory
|
|
29598
29895
|
}
|
|
29599
29896
|
|
|
29600
|
-
|
|
29601
|
-
|
|
29602
|
-
|
|
29603
|
-
if (other.point === this.point) {
|
|
29604
|
-
throw new Error('Tried to link already linked events');
|
|
29605
|
-
}
|
|
29606
|
-
var otherEvents = other.point.events;
|
|
29607
|
-
for (var i = 0, iMax = otherEvents.length; i < iMax; i++) {
|
|
29608
|
-
var evt = otherEvents[i];
|
|
29609
|
-
this.point.events.push(evt);
|
|
29610
|
-
evt.point = this.point;
|
|
29611
|
-
}
|
|
29612
|
-
this.checkForConsuming();
|
|
29897
|
+
link(other) {
|
|
29898
|
+
if (other.point === this.point) {
|
|
29899
|
+
throw new Error("Tried to link already linked events");
|
|
29613
29900
|
}
|
|
29614
|
-
|
|
29615
|
-
|
|
29616
|
-
|
|
29617
|
-
|
|
29618
|
-
|
|
29619
|
-
|
|
29620
|
-
|
|
29621
|
-
|
|
29622
|
-
|
|
29623
|
-
|
|
29624
|
-
|
|
29625
|
-
|
|
29626
|
-
|
|
29627
|
-
|
|
29628
|
-
|
|
29629
|
-
|
|
29630
|
-
|
|
29631
|
-
|
|
29632
|
-
|
|
29633
|
-
|
|
29901
|
+
const otherEvents = other.point.events;
|
|
29902
|
+
for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {
|
|
29903
|
+
const evt = otherEvents[i];
|
|
29904
|
+
this.point.events.push(evt);
|
|
29905
|
+
evt.point = this.point;
|
|
29906
|
+
}
|
|
29907
|
+
this.checkForConsuming();
|
|
29908
|
+
}
|
|
29909
|
+
|
|
29910
|
+
/* Do a pass over our linked events and check to see if any pair
|
|
29911
|
+
* of segments match, and should be consumed. */
|
|
29912
|
+
checkForConsuming() {
|
|
29913
|
+
// FIXME: The loops in this method run O(n^2) => no good.
|
|
29914
|
+
// Maintain little ordered sweep event trees?
|
|
29915
|
+
// Can we maintaining an ordering that avoids the need
|
|
29916
|
+
// for the re-sorting with getLeftmostComparator in geom-out?
|
|
29917
|
+
|
|
29918
|
+
// Compare each pair of events to see if other events also match
|
|
29919
|
+
const numEvents = this.point.events.length;
|
|
29920
|
+
for (let i = 0; i < numEvents; i++) {
|
|
29921
|
+
const evt1 = this.point.events[i];
|
|
29922
|
+
if (evt1.segment.consumedBy !== undefined) continue;
|
|
29923
|
+
for (let j = i + 1; j < numEvents; j++) {
|
|
29924
|
+
const evt2 = this.point.events[j];
|
|
29925
|
+
if (evt2.consumedBy !== undefined) continue;
|
|
29926
|
+
if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
|
|
29927
|
+
evt1.segment.consume(evt2.segment);
|
|
29634
29928
|
}
|
|
29635
29929
|
}
|
|
29636
|
-
}
|
|
29637
|
-
|
|
29638
|
-
|
|
29639
|
-
|
|
29640
|
-
|
|
29641
|
-
|
|
29642
|
-
|
|
29643
|
-
|
|
29644
|
-
events.push(evt);
|
|
29645
|
-
}
|
|
29930
|
+
}
|
|
29931
|
+
getAvailableLinkedEvents() {
|
|
29932
|
+
// point.events is always of length 2 or greater
|
|
29933
|
+
const events = [];
|
|
29934
|
+
for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {
|
|
29935
|
+
const evt = this.point.events[i];
|
|
29936
|
+
if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
|
|
29937
|
+
events.push(evt);
|
|
29646
29938
|
}
|
|
29647
|
-
return events;
|
|
29648
29939
|
}
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
* favor the event that will give us the smallest left-side angle.
|
|
29652
|
-
* All ring construction starts as low as possible heading to the right,
|
|
29653
|
-
* so by always turning left as sharp as possible we'll get polygons
|
|
29654
|
-
* without uncessary loops & holes.
|
|
29655
|
-
*
|
|
29656
|
-
* The comparator function has a compute cache such that it avoids
|
|
29657
|
-
* re-computing already-computed values.
|
|
29658
|
-
*/
|
|
29659
|
-
}, {
|
|
29660
|
-
key: "getLeftmostComparator",
|
|
29661
|
-
value: function getLeftmostComparator(baseEvent) {
|
|
29662
|
-
var _this = this;
|
|
29663
|
-
var cache = new Map();
|
|
29664
|
-
var fillCache = function fillCache(linkedEvent) {
|
|
29665
|
-
var nextEvent = linkedEvent.otherSE;
|
|
29666
|
-
cache.set(linkedEvent, {
|
|
29667
|
-
sine: sineOfAngle(_this.point, baseEvent.point, nextEvent.point),
|
|
29668
|
-
cosine: cosineOfAngle(_this.point, baseEvent.point, nextEvent.point)
|
|
29669
|
-
});
|
|
29670
|
-
};
|
|
29671
|
-
return function (a, b) {
|
|
29672
|
-
if (!cache.has(a)) fillCache(a);
|
|
29673
|
-
if (!cache.has(b)) fillCache(b);
|
|
29674
|
-
var _cache$get = cache.get(a),
|
|
29675
|
-
asine = _cache$get.sine,
|
|
29676
|
-
acosine = _cache$get.cosine;
|
|
29677
|
-
var _cache$get2 = cache.get(b),
|
|
29678
|
-
bsine = _cache$get2.sine,
|
|
29679
|
-
bcosine = _cache$get2.cosine; // both on or above x-axis
|
|
29680
|
-
|
|
29681
|
-
if (asine >= 0 && bsine >= 0) {
|
|
29682
|
-
if (acosine < bcosine) return 1;
|
|
29683
|
-
if (acosine > bcosine) return -1;
|
|
29684
|
-
return 0;
|
|
29685
|
-
} // both below x-axis
|
|
29940
|
+
return events;
|
|
29941
|
+
}
|
|
29686
29942
|
|
|
29687
|
-
|
|
29688
|
-
|
|
29689
|
-
|
|
29690
|
-
|
|
29691
|
-
|
|
29943
|
+
/**
|
|
29944
|
+
* Returns a comparator function for sorting linked events that will
|
|
29945
|
+
* favor the event that will give us the smallest left-side angle.
|
|
29946
|
+
* All ring construction starts as low as possible heading to the right,
|
|
29947
|
+
* so by always turning left as sharp as possible we'll get polygons
|
|
29948
|
+
* without uncessary loops & holes.
|
|
29949
|
+
*
|
|
29950
|
+
* The comparator function has a compute cache such that it avoids
|
|
29951
|
+
* re-computing already-computed values.
|
|
29952
|
+
*/
|
|
29953
|
+
getLeftmostComparator(baseEvent) {
|
|
29954
|
+
const cache = new Map();
|
|
29955
|
+
const fillCache = linkedEvent => {
|
|
29956
|
+
const nextEvent = linkedEvent.otherSE;
|
|
29957
|
+
cache.set(linkedEvent, {
|
|
29958
|
+
sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),
|
|
29959
|
+
cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point)
|
|
29960
|
+
});
|
|
29961
|
+
};
|
|
29962
|
+
return (a, b) => {
|
|
29963
|
+
if (!cache.has(a)) fillCache(a);
|
|
29964
|
+
if (!cache.has(b)) fillCache(b);
|
|
29965
|
+
const {
|
|
29966
|
+
sine: asine,
|
|
29967
|
+
cosine: acosine
|
|
29968
|
+
} = cache.get(a);
|
|
29969
|
+
const {
|
|
29970
|
+
sine: bsine,
|
|
29971
|
+
cosine: bcosine
|
|
29972
|
+
} = cache.get(b);
|
|
29973
|
+
|
|
29974
|
+
// both on or above x-axis
|
|
29975
|
+
if (asine >= 0 && bsine >= 0) {
|
|
29976
|
+
if (acosine < bcosine) return 1;
|
|
29977
|
+
if (acosine > bcosine) return -1;
|
|
29978
|
+
return 0;
|
|
29979
|
+
}
|
|
29692
29980
|
|
|
29693
|
-
|
|
29694
|
-
|
|
29981
|
+
// both below x-axis
|
|
29982
|
+
if (asine < 0 && bsine < 0) {
|
|
29983
|
+
if (acosine < bcosine) return -1;
|
|
29984
|
+
if (acosine > bcosine) return 1;
|
|
29695
29985
|
return 0;
|
|
29696
|
-
}
|
|
29697
|
-
}
|
|
29698
|
-
}]);
|
|
29699
|
-
return SweepEvent;
|
|
29700
|
-
}();
|
|
29986
|
+
}
|
|
29701
29987
|
|
|
29988
|
+
// one above x-axis, one below
|
|
29989
|
+
if (bsine < asine) return -1;
|
|
29990
|
+
if (bsine > asine) return 1;
|
|
29991
|
+
return 0;
|
|
29992
|
+
};
|
|
29993
|
+
}
|
|
29994
|
+
}
|
|
29995
|
+
|
|
29996
|
+
// Give segments unique ID's to get consistent sorting of
|
|
29702
29997
|
// segments and sweep events when all else is identical
|
|
29998
|
+
let segmentId = 0;
|
|
29999
|
+
class Segment {
|
|
30000
|
+
/* This compare() function is for ordering segments in the sweep
|
|
30001
|
+
* line tree, and does so according to the following criteria:
|
|
30002
|
+
*
|
|
30003
|
+
* Consider the vertical line that lies an infinestimal step to the
|
|
30004
|
+
* right of the right-more of the two left endpoints of the input
|
|
30005
|
+
* segments. Imagine slowly moving a point up from negative infinity
|
|
30006
|
+
* in the increasing y direction. Which of the two segments will that
|
|
30007
|
+
* point intersect first? That segment comes 'before' the other one.
|
|
30008
|
+
*
|
|
30009
|
+
* If neither segment would be intersected by such a line, (if one
|
|
30010
|
+
* or more of the segments are vertical) then the line to be considered
|
|
30011
|
+
* is directly on the right-more of the two left inputs.
|
|
30012
|
+
*/
|
|
30013
|
+
static compare(a, b) {
|
|
30014
|
+
const alx = a.leftSE.point.x;
|
|
30015
|
+
const blx = b.leftSE.point.x;
|
|
30016
|
+
const arx = a.rightSE.point.x;
|
|
30017
|
+
const brx = b.rightSE.point.x;
|
|
30018
|
+
|
|
30019
|
+
// check if they're even in the same vertical plane
|
|
30020
|
+
if (brx < alx) return 1;
|
|
30021
|
+
if (arx < blx) return -1;
|
|
30022
|
+
const aly = a.leftSE.point.y;
|
|
30023
|
+
const bly = b.leftSE.point.y;
|
|
30024
|
+
const ary = a.rightSE.point.y;
|
|
30025
|
+
const bry = b.rightSE.point.y;
|
|
30026
|
+
|
|
30027
|
+
// is left endpoint of segment B the right-more?
|
|
30028
|
+
if (alx < blx) {
|
|
30029
|
+
// are the two segments in the same horizontal plane?
|
|
30030
|
+
if (bly < aly && bly < ary) return 1;
|
|
30031
|
+
if (bly > aly && bly > ary) return -1;
|
|
30032
|
+
|
|
30033
|
+
// is the B left endpoint colinear to segment A?
|
|
30034
|
+
const aCmpBLeft = a.comparePoint(b.leftSE.point);
|
|
30035
|
+
if (aCmpBLeft < 0) return 1;
|
|
30036
|
+
if (aCmpBLeft > 0) return -1;
|
|
30037
|
+
|
|
30038
|
+
// is the A right endpoint colinear to segment B ?
|
|
30039
|
+
const bCmpARight = b.comparePoint(a.rightSE.point);
|
|
30040
|
+
if (bCmpARight !== 0) return bCmpARight;
|
|
30041
|
+
|
|
30042
|
+
// colinear segments, consider the one with left-more
|
|
30043
|
+
// left endpoint to be first (arbitrary?)
|
|
30044
|
+
return -1;
|
|
30045
|
+
}
|
|
29703
30046
|
|
|
29704
|
-
|
|
29705
|
-
|
|
29706
|
-
|
|
29707
|
-
|
|
29708
|
-
/* This compare() function is for ordering segments in the sweep
|
|
29709
|
-
* line tree, and does so according to the following criteria:
|
|
29710
|
-
*
|
|
29711
|
-
* Consider the vertical line that lies an infinestimal step to the
|
|
29712
|
-
* right of the right-more of the two left endpoints of the input
|
|
29713
|
-
* segments. Imagine slowly moving a point up from negative infinity
|
|
29714
|
-
* in the increasing y direction. Which of the two segments will that
|
|
29715
|
-
* point intersect first? That segment comes 'before' the other one.
|
|
29716
|
-
*
|
|
29717
|
-
* If neither segment would be intersected by such a line, (if one
|
|
29718
|
-
* or more of the segments are vertical) then the line to be considered
|
|
29719
|
-
* is directly on the right-more of the two left inputs.
|
|
29720
|
-
*/
|
|
29721
|
-
value: function compare(a, b) {
|
|
29722
|
-
var alx = a.leftSE.point.x;
|
|
29723
|
-
var blx = b.leftSE.point.x;
|
|
29724
|
-
var arx = a.rightSE.point.x;
|
|
29725
|
-
var brx = b.rightSE.point.x; // check if they're even in the same vertical plane
|
|
29726
|
-
|
|
29727
|
-
if (brx < alx) return 1;
|
|
29728
|
-
if (arx < blx) return -1;
|
|
29729
|
-
var aly = a.leftSE.point.y;
|
|
29730
|
-
var bly = b.leftSE.point.y;
|
|
29731
|
-
var ary = a.rightSE.point.y;
|
|
29732
|
-
var bry = b.rightSE.point.y; // is left endpoint of segment B the right-more?
|
|
29733
|
-
|
|
29734
|
-
if (alx < blx) {
|
|
29735
|
-
// are the two segments in the same horizontal plane?
|
|
29736
|
-
if (bly < aly && bly < ary) return 1;
|
|
29737
|
-
if (bly > aly && bly > ary) return -1; // is the B left endpoint colinear to segment A?
|
|
29738
|
-
|
|
29739
|
-
var aCmpBLeft = a.comparePoint(b.leftSE.point);
|
|
29740
|
-
if (aCmpBLeft < 0) return 1;
|
|
29741
|
-
if (aCmpBLeft > 0) return -1; // is the A right endpoint colinear to segment B ?
|
|
29742
|
-
|
|
29743
|
-
var bCmpARight = b.comparePoint(a.rightSE.point);
|
|
29744
|
-
if (bCmpARight !== 0) return bCmpARight; // colinear segments, consider the one with left-more
|
|
29745
|
-
// left endpoint to be first (arbitrary?)
|
|
29746
|
-
|
|
29747
|
-
return -1;
|
|
29748
|
-
} // is left endpoint of segment A the right-more?
|
|
29749
|
-
|
|
29750
|
-
if (alx > blx) {
|
|
29751
|
-
if (aly < bly && aly < bry) return -1;
|
|
29752
|
-
if (aly > bly && aly > bry) return 1; // is the A left endpoint colinear to segment B?
|
|
29753
|
-
|
|
29754
|
-
var bCmpALeft = b.comparePoint(a.leftSE.point);
|
|
29755
|
-
if (bCmpALeft !== 0) return bCmpALeft; // is the B right endpoint colinear to segment A?
|
|
29756
|
-
|
|
29757
|
-
var aCmpBRight = a.comparePoint(b.rightSE.point);
|
|
29758
|
-
if (aCmpBRight < 0) return 1;
|
|
29759
|
-
if (aCmpBRight > 0) return -1; // colinear segments, consider the one with left-more
|
|
29760
|
-
// left endpoint to be first (arbitrary?)
|
|
29761
|
-
|
|
29762
|
-
return 1;
|
|
29763
|
-
} // if we get here, the two left endpoints are in the same
|
|
29764
|
-
// vertical plane, ie alx === blx
|
|
29765
|
-
// consider the lower left-endpoint to come first
|
|
29766
|
-
|
|
29767
|
-
if (aly < bly) return -1;
|
|
29768
|
-
if (aly > bly) return 1; // left endpoints are identical
|
|
29769
|
-
// check for colinearity by using the left-more right endpoint
|
|
29770
|
-
// is the A right endpoint more left-more?
|
|
29771
|
-
|
|
29772
|
-
if (arx < brx) {
|
|
29773
|
-
var _bCmpARight = b.comparePoint(a.rightSE.point);
|
|
29774
|
-
if (_bCmpARight !== 0) return _bCmpARight;
|
|
29775
|
-
} // is the B right endpoint more left-more?
|
|
29776
|
-
|
|
29777
|
-
if (arx > brx) {
|
|
29778
|
-
var _aCmpBRight = a.comparePoint(b.rightSE.point);
|
|
29779
|
-
if (_aCmpBRight < 0) return 1;
|
|
29780
|
-
if (_aCmpBRight > 0) return -1;
|
|
29781
|
-
}
|
|
29782
|
-
if (arx !== brx) {
|
|
29783
|
-
// are these two [almost] vertical segments with opposite orientation?
|
|
29784
|
-
// if so, the one with the lower right endpoint comes first
|
|
29785
|
-
var ay = ary - aly;
|
|
29786
|
-
var ax = arx - alx;
|
|
29787
|
-
var by = bry - bly;
|
|
29788
|
-
var bx = brx - blx;
|
|
29789
|
-
if (ay > ax && by < bx) return 1;
|
|
29790
|
-
if (ay < ax && by > bx) return -1;
|
|
29791
|
-
} // we have colinear segments with matching orientation
|
|
29792
|
-
// consider the one with more left-more right endpoint to be first
|
|
29793
|
-
|
|
29794
|
-
if (arx > brx) return 1;
|
|
29795
|
-
if (arx < brx) return -1; // if we get here, two two right endpoints are in the same
|
|
29796
|
-
// vertical plane, ie arx === brx
|
|
29797
|
-
// consider the lower right-endpoint to come first
|
|
29798
|
-
|
|
29799
|
-
if (ary < bry) return -1;
|
|
29800
|
-
if (ary > bry) return 1; // right endpoints identical as well, so the segments are idential
|
|
29801
|
-
// fall back on creation order as consistent tie-breaker
|
|
29802
|
-
|
|
29803
|
-
if (a.id < b.id) return -1;
|
|
29804
|
-
if (a.id > b.id) return 1; // identical segment, ie a === b
|
|
30047
|
+
// is left endpoint of segment A the right-more?
|
|
30048
|
+
if (alx > blx) {
|
|
30049
|
+
if (aly < bly && aly < bry) return -1;
|
|
30050
|
+
if (aly > bly && aly > bry) return 1;
|
|
29805
30051
|
|
|
29806
|
-
|
|
30052
|
+
// is the A left endpoint colinear to segment B?
|
|
30053
|
+
const bCmpALeft = b.comparePoint(a.leftSE.point);
|
|
30054
|
+
if (bCmpALeft !== 0) return bCmpALeft;
|
|
30055
|
+
|
|
30056
|
+
// is the B right endpoint colinear to segment A?
|
|
30057
|
+
const aCmpBRight = a.comparePoint(b.rightSE.point);
|
|
30058
|
+
if (aCmpBRight < 0) return 1;
|
|
30059
|
+
if (aCmpBRight > 0) return -1;
|
|
30060
|
+
|
|
30061
|
+
// colinear segments, consider the one with left-more
|
|
30062
|
+
// left endpoint to be first (arbitrary?)
|
|
30063
|
+
return 1;
|
|
29807
30064
|
}
|
|
29808
|
-
/* Warning: a reference to ringWindings input will be stored,
|
|
29809
|
-
* and possibly will be later modified */
|
|
29810
|
-
}]);
|
|
29811
30065
|
|
|
29812
|
-
|
|
29813
|
-
|
|
30066
|
+
// if we get here, the two left endpoints are in the same
|
|
30067
|
+
// vertical plane, ie alx === blx
|
|
30068
|
+
|
|
30069
|
+
// consider the lower left-endpoint to come first
|
|
30070
|
+
if (aly < bly) return -1;
|
|
30071
|
+
if (aly > bly) return 1;
|
|
30072
|
+
|
|
30073
|
+
// left endpoints are identical
|
|
30074
|
+
// check for colinearity by using the left-more right endpoint
|
|
30075
|
+
|
|
30076
|
+
// is the A right endpoint more left-more?
|
|
30077
|
+
if (arx < brx) {
|
|
30078
|
+
const bCmpARight = b.comparePoint(a.rightSE.point);
|
|
30079
|
+
if (bCmpARight !== 0) return bCmpARight;
|
|
30080
|
+
}
|
|
30081
|
+
|
|
30082
|
+
// is the B right endpoint more left-more?
|
|
30083
|
+
if (arx > brx) {
|
|
30084
|
+
const aCmpBRight = a.comparePoint(b.rightSE.point);
|
|
30085
|
+
if (aCmpBRight < 0) return 1;
|
|
30086
|
+
if (aCmpBRight > 0) return -1;
|
|
30087
|
+
}
|
|
30088
|
+
if (arx !== brx) {
|
|
30089
|
+
// are these two [almost] vertical segments with opposite orientation?
|
|
30090
|
+
// if so, the one with the lower right endpoint comes first
|
|
30091
|
+
const ay = ary - aly;
|
|
30092
|
+
const ax = arx - alx;
|
|
30093
|
+
const by = bry - bly;
|
|
30094
|
+
const bx = brx - blx;
|
|
30095
|
+
if (ay > ax && by < bx) return 1;
|
|
30096
|
+
if (ay < ax && by > bx) return -1;
|
|
30097
|
+
}
|
|
30098
|
+
|
|
30099
|
+
// we have colinear segments with matching orientation
|
|
30100
|
+
// consider the one with more left-more right endpoint to be first
|
|
30101
|
+
if (arx > brx) return 1;
|
|
30102
|
+
if (arx < brx) return -1;
|
|
30103
|
+
|
|
30104
|
+
// if we get here, two two right endpoints are in the same
|
|
30105
|
+
// vertical plane, ie arx === brx
|
|
30106
|
+
|
|
30107
|
+
// consider the lower right-endpoint to come first
|
|
30108
|
+
if (ary < bry) return -1;
|
|
30109
|
+
if (ary > bry) return 1;
|
|
30110
|
+
|
|
30111
|
+
// right endpoints identical as well, so the segments are idential
|
|
30112
|
+
// fall back on creation order as consistent tie-breaker
|
|
30113
|
+
if (a.id < b.id) return -1;
|
|
30114
|
+
if (a.id > b.id) return 1;
|
|
30115
|
+
|
|
30116
|
+
// identical segment, ie a === b
|
|
30117
|
+
return 0;
|
|
30118
|
+
}
|
|
30119
|
+
|
|
30120
|
+
/* Warning: a reference to ringWindings input will be stored,
|
|
30121
|
+
* and possibly will be later modified */
|
|
30122
|
+
constructor(leftSE, rightSE, rings, windings) {
|
|
29814
30123
|
this.id = ++segmentId;
|
|
29815
30124
|
this.leftSE = leftSE;
|
|
29816
30125
|
leftSE.segment = this;
|
|
@@ -29819,431 +30128,425 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
29819
30128
|
rightSE.segment = this;
|
|
29820
30129
|
rightSE.otherSE = leftSE;
|
|
29821
30130
|
this.rings = rings;
|
|
29822
|
-
this.windings = windings;
|
|
30131
|
+
this.windings = windings;
|
|
30132
|
+
// left unset for performance, set later in algorithm
|
|
29823
30133
|
// this.ringOut, this.consumedBy, this.prev
|
|
29824
30134
|
}
|
|
29825
30135
|
|
|
29826
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
|
|
29830
|
-
|
|
29831
|
-
|
|
29832
|
-
|
|
29833
|
-
|
|
29834
|
-
|
|
29835
|
-
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
|
|
29839
|
-
|
|
29840
|
-
|
|
29841
|
-
|
|
29842
|
-
|
|
29843
|
-
|
|
29844
|
-
|
|
29845
|
-
|
|
29846
|
-
|
|
29847
|
-
|
|
29848
|
-
|
|
29849
|
-
|
|
29850
|
-
|
|
29851
|
-
|
|
29852
|
-
|
|
29853
|
-
|
|
29854
|
-
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
|
|
29858
|
-
|
|
29859
|
-
|
|
29860
|
-
|
|
29861
|
-
|
|
29862
|
-
|
|
29863
|
-
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;
|
|
29864
|
-
}
|
|
29865
|
-
/* Compare this segment with a point.
|
|
29866
|
-
*
|
|
29867
|
-
* A point P is considered to be colinear to a segment if there
|
|
29868
|
-
* exists a distance D such that if we travel along the segment
|
|
29869
|
-
* from one * endpoint towards the other a distance D, we find
|
|
29870
|
-
* ourselves at point P.
|
|
29871
|
-
*
|
|
29872
|
-
* Return value indicates:
|
|
29873
|
-
*
|
|
29874
|
-
* 1: point lies above the segment (to the left of vertical)
|
|
29875
|
-
* 0: point is colinear to segment
|
|
29876
|
-
* -1: point lies below the segment (to the right of vertical)
|
|
29877
|
-
*/
|
|
29878
|
-
}, {
|
|
29879
|
-
key: "comparePoint",
|
|
29880
|
-
value: function comparePoint(point) {
|
|
29881
|
-
if (this.isAnEndpoint(point)) return 0;
|
|
29882
|
-
var lPt = this.leftSE.point;
|
|
29883
|
-
var rPt = this.rightSE.point;
|
|
29884
|
-
var v = this.vector(); // Exactly vertical segments.
|
|
29885
|
-
|
|
29886
|
-
if (lPt.x === rPt.x) {
|
|
29887
|
-
if (point.x === lPt.x) return 0;
|
|
29888
|
-
return point.x < lPt.x ? 1 : -1;
|
|
29889
|
-
} // Nearly vertical segments with an intersection.
|
|
29890
|
-
// Check to see where a point on the line with matching Y coordinate is.
|
|
29891
|
-
|
|
29892
|
-
var yDist = (point.y - lPt.y) / v.y;
|
|
29893
|
-
var xFromYDist = lPt.x + yDist * v.x;
|
|
29894
|
-
if (point.x === xFromYDist) return 0; // General case.
|
|
29895
|
-
// Check to see where a point on the line with matching X coordinate is.
|
|
29896
|
-
|
|
29897
|
-
var xDist = (point.x - lPt.x) / v.x;
|
|
29898
|
-
var yFromXDist = lPt.y + xDist * v.y;
|
|
29899
|
-
if (point.y === yFromXDist) return 0;
|
|
29900
|
-
return point.y < yFromXDist ? -1 : 1;
|
|
29901
|
-
}
|
|
29902
|
-
/**
|
|
29903
|
-
* Given another segment, returns the first non-trivial intersection
|
|
29904
|
-
* between the two segments (in terms of sweep line ordering), if it exists.
|
|
29905
|
-
*
|
|
29906
|
-
* A 'non-trivial' intersection is one that will cause one or both of the
|
|
29907
|
-
* segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
|
|
29908
|
-
*
|
|
29909
|
-
* * endpoint of segA with endpoint of segB --> trivial
|
|
29910
|
-
* * endpoint of segA with point along segB --> non-trivial
|
|
29911
|
-
* * endpoint of segB with point along segA --> non-trivial
|
|
29912
|
-
* * point along segA with point along segB --> non-trivial
|
|
29913
|
-
*
|
|
29914
|
-
* If no non-trivial intersection exists, return null
|
|
29915
|
-
* Else, return null.
|
|
29916
|
-
*/
|
|
29917
|
-
}, {
|
|
29918
|
-
key: "getIntersection",
|
|
29919
|
-
value: function getIntersection(other) {
|
|
29920
|
-
// If bboxes don't overlap, there can't be any intersections
|
|
29921
|
-
var tBbox = this.bbox();
|
|
29922
|
-
var oBbox = other.bbox();
|
|
29923
|
-
var bboxOverlap = getBboxOverlap(tBbox, oBbox);
|
|
29924
|
-
if (bboxOverlap === null) return null; // We first check to see if the endpoints can be considered intersections.
|
|
29925
|
-
// This will 'snap' intersections to endpoints if possible, and will
|
|
29926
|
-
// handle cases of colinearity.
|
|
29927
|
-
|
|
29928
|
-
var tlp = this.leftSE.point;
|
|
29929
|
-
var trp = this.rightSE.point;
|
|
29930
|
-
var olp = other.leftSE.point;
|
|
29931
|
-
var orp = other.rightSE.point; // does each endpoint touch the other segment?
|
|
29932
|
-
// note that we restrict the 'touching' definition to only allow segments
|
|
29933
|
-
// to touch endpoints that lie forward from where we are in the sweep line pass
|
|
29934
|
-
|
|
29935
|
-
var touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
|
|
29936
|
-
var touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
|
|
29937
|
-
var touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
|
|
29938
|
-
var touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0; // do left endpoints match?
|
|
29939
|
-
|
|
29940
|
-
if (touchesThisLSE && touchesOtherLSE) {
|
|
29941
|
-
// these two cases are for colinear segments with matching left
|
|
29942
|
-
// endpoints, and one segment being longer than the other
|
|
29943
|
-
if (touchesThisRSE && !touchesOtherRSE) return trp;
|
|
29944
|
-
if (!touchesThisRSE && touchesOtherRSE) return orp; // either the two segments match exactly (two trival intersections)
|
|
29945
|
-
// or just on their left endpoint (one trivial intersection
|
|
29946
|
-
|
|
29947
|
-
return null;
|
|
29948
|
-
} // does this left endpoint matches (other doesn't)
|
|
29949
|
-
|
|
29950
|
-
if (touchesThisLSE) {
|
|
29951
|
-
// check for segments that just intersect on opposing endpoints
|
|
29952
|
-
if (touchesOtherRSE) {
|
|
29953
|
-
if (tlp.x === orp.x && tlp.y === orp.y) return null;
|
|
29954
|
-
} // t-intersection on left endpoint
|
|
29955
|
-
|
|
29956
|
-
return tlp;
|
|
29957
|
-
} // does other left endpoint matches (this doesn't)
|
|
29958
|
-
|
|
29959
|
-
if (touchesOtherLSE) {
|
|
29960
|
-
// check for segments that just intersect on opposing endpoints
|
|
29961
|
-
if (touchesThisRSE) {
|
|
29962
|
-
if (trp.x === olp.x && trp.y === olp.y) return null;
|
|
29963
|
-
} // t-intersection on left endpoint
|
|
29964
|
-
|
|
29965
|
-
return olp;
|
|
29966
|
-
} // trivial intersection on right endpoints
|
|
29967
|
-
|
|
29968
|
-
if (touchesThisRSE && touchesOtherRSE) return null; // t-intersections on just one right endpoint
|
|
29969
|
-
|
|
29970
|
-
if (touchesThisRSE) return trp;
|
|
29971
|
-
if (touchesOtherRSE) return orp; // None of our endpoints intersect. Look for a general intersection between
|
|
29972
|
-
// infinite lines laid over the segments
|
|
29973
|
-
|
|
29974
|
-
var pt = intersection(tlp, this.vector(), olp, other.vector()); // are the segments parrallel? Note that if they were colinear with overlap,
|
|
29975
|
-
// they would have an endpoint intersection and that case was already handled above
|
|
29976
|
-
|
|
29977
|
-
if (pt === null) return null; // is the intersection found between the lines not on the segments?
|
|
29978
|
-
|
|
29979
|
-
if (!isInBbox(bboxOverlap, pt)) return null; // round the the computed point if needed
|
|
29980
|
-
|
|
29981
|
-
return rounder.round(pt.x, pt.y);
|
|
29982
|
-
}
|
|
29983
|
-
/**
|
|
29984
|
-
* Split the given segment into multiple segments on the given points.
|
|
29985
|
-
* * Each existing segment will retain its leftSE and a new rightSE will be
|
|
29986
|
-
* generated for it.
|
|
29987
|
-
* * A new segment will be generated which will adopt the original segment's
|
|
29988
|
-
* rightSE, and a new leftSE will be generated for it.
|
|
29989
|
-
* * If there are more than two points given to split on, new segments
|
|
29990
|
-
* in the middle will be generated with new leftSE and rightSE's.
|
|
29991
|
-
* * An array of the newly generated SweepEvents will be returned.
|
|
29992
|
-
*
|
|
29993
|
-
* Warning: input array of points is modified
|
|
29994
|
-
*/
|
|
29995
|
-
}, {
|
|
29996
|
-
key: "split",
|
|
29997
|
-
value: function split(point) {
|
|
29998
|
-
var newEvents = [];
|
|
29999
|
-
var alreadyLinked = point.events !== undefined;
|
|
30000
|
-
var newLeftSE = new SweepEvent(point, true);
|
|
30001
|
-
var newRightSE = new SweepEvent(point, false);
|
|
30002
|
-
var oldRightSE = this.rightSE;
|
|
30003
|
-
this.replaceRightSE(newRightSE);
|
|
30004
|
-
newEvents.push(newRightSE);
|
|
30005
|
-
newEvents.push(newLeftSE);
|
|
30006
|
-
var newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice()); // when splitting a nearly vertical downward-facing segment,
|
|
30007
|
-
// sometimes one of the resulting new segments is vertical, in which
|
|
30008
|
-
// case its left and right events may need to be swapped
|
|
30009
|
-
|
|
30010
|
-
if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
|
|
30011
|
-
newSeg.swapEvents();
|
|
30012
|
-
}
|
|
30013
|
-
if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
|
|
30014
|
-
this.swapEvents();
|
|
30015
|
-
} // in the point we just used to create new sweep events with was already
|
|
30016
|
-
// linked to other events, we need to check if either of the affected
|
|
30017
|
-
// segments should be consumed
|
|
30018
|
-
|
|
30019
|
-
if (alreadyLinked) {
|
|
30020
|
-
newLeftSE.checkForConsuming();
|
|
30021
|
-
newRightSE.checkForConsuming();
|
|
30136
|
+
static fromRing(pt1, pt2, ring) {
|
|
30137
|
+
let leftPt, rightPt, winding;
|
|
30138
|
+
|
|
30139
|
+
// ordering the two points according to sweep line ordering
|
|
30140
|
+
const cmpPts = SweepEvent.comparePoints(pt1, pt2);
|
|
30141
|
+
if (cmpPts < 0) {
|
|
30142
|
+
leftPt = pt1;
|
|
30143
|
+
rightPt = pt2;
|
|
30144
|
+
winding = 1;
|
|
30145
|
+
} else if (cmpPts > 0) {
|
|
30146
|
+
leftPt = pt2;
|
|
30147
|
+
rightPt = pt1;
|
|
30148
|
+
winding = -1;
|
|
30149
|
+
} else throw new Error(`Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`);
|
|
30150
|
+
const leftSE = new SweepEvent(leftPt, true);
|
|
30151
|
+
const rightSE = new SweepEvent(rightPt, false);
|
|
30152
|
+
return new Segment(leftSE, rightSE, [ring], [winding]);
|
|
30153
|
+
}
|
|
30154
|
+
|
|
30155
|
+
/* When a segment is split, the rightSE is replaced with a new sweep event */
|
|
30156
|
+
replaceRightSE(newRightSE) {
|
|
30157
|
+
this.rightSE = newRightSE;
|
|
30158
|
+
this.rightSE.segment = this;
|
|
30159
|
+
this.rightSE.otherSE = this.leftSE;
|
|
30160
|
+
this.leftSE.otherSE = this.rightSE;
|
|
30161
|
+
}
|
|
30162
|
+
bbox() {
|
|
30163
|
+
const y1 = this.leftSE.point.y;
|
|
30164
|
+
const y2 = this.rightSE.point.y;
|
|
30165
|
+
return {
|
|
30166
|
+
ll: {
|
|
30167
|
+
x: this.leftSE.point.x,
|
|
30168
|
+
y: y1 < y2 ? y1 : y2
|
|
30169
|
+
},
|
|
30170
|
+
ur: {
|
|
30171
|
+
x: this.rightSE.point.x,
|
|
30172
|
+
y: y1 > y2 ? y1 : y2
|
|
30022
30173
|
}
|
|
30023
|
-
|
|
30174
|
+
};
|
|
30175
|
+
}
|
|
30176
|
+
|
|
30177
|
+
/* A vector from the left point to the right */
|
|
30178
|
+
vector() {
|
|
30179
|
+
return {
|
|
30180
|
+
x: this.rightSE.point.x - this.leftSE.point.x,
|
|
30181
|
+
y: this.rightSE.point.y - this.leftSE.point.y
|
|
30182
|
+
};
|
|
30183
|
+
}
|
|
30184
|
+
isAnEndpoint(pt) {
|
|
30185
|
+
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;
|
|
30186
|
+
}
|
|
30187
|
+
|
|
30188
|
+
/* Compare this segment with a point.
|
|
30189
|
+
*
|
|
30190
|
+
* A point P is considered to be colinear to a segment if there
|
|
30191
|
+
* exists a distance D such that if we travel along the segment
|
|
30192
|
+
* from one * endpoint towards the other a distance D, we find
|
|
30193
|
+
* ourselves at point P.
|
|
30194
|
+
*
|
|
30195
|
+
* Return value indicates:
|
|
30196
|
+
*
|
|
30197
|
+
* 1: point lies above the segment (to the left of vertical)
|
|
30198
|
+
* 0: point is colinear to segment
|
|
30199
|
+
* -1: point lies below the segment (to the right of vertical)
|
|
30200
|
+
*/
|
|
30201
|
+
comparePoint(point) {
|
|
30202
|
+
if (this.isAnEndpoint(point)) return 0;
|
|
30203
|
+
const lPt = this.leftSE.point;
|
|
30204
|
+
const rPt = this.rightSE.point;
|
|
30205
|
+
const v = this.vector();
|
|
30206
|
+
|
|
30207
|
+
// Exactly vertical segments.
|
|
30208
|
+
if (lPt.x === rPt.x) {
|
|
30209
|
+
if (point.x === lPt.x) return 0;
|
|
30210
|
+
return point.x < lPt.x ? 1 : -1;
|
|
30024
30211
|
}
|
|
30025
|
-
|
|
30026
|
-
|
|
30027
|
-
|
|
30028
|
-
|
|
30029
|
-
|
|
30030
|
-
|
|
30031
|
-
|
|
30032
|
-
|
|
30033
|
-
|
|
30034
|
-
|
|
30035
|
-
|
|
30036
|
-
|
|
30037
|
-
|
|
30038
|
-
|
|
30039
|
-
|
|
30040
|
-
|
|
30041
|
-
|
|
30042
|
-
|
|
30043
|
-
|
|
30044
|
-
|
|
30045
|
-
|
|
30046
|
-
|
|
30047
|
-
|
|
30048
|
-
|
|
30049
|
-
|
|
30050
|
-
|
|
30051
|
-
|
|
30052
|
-
|
|
30053
|
-
|
|
30054
|
-
|
|
30055
|
-
|
|
30056
|
-
|
|
30057
|
-
|
|
30058
|
-
|
|
30059
|
-
|
|
30060
|
-
|
|
30061
|
-
|
|
30062
|
-
|
|
30063
|
-
|
|
30064
|
-
|
|
30065
|
-
|
|
30066
|
-
|
|
30067
|
-
|
|
30068
|
-
|
|
30069
|
-
|
|
30070
|
-
|
|
30071
|
-
|
|
30072
|
-
|
|
30073
|
-
|
|
30074
|
-
|
|
30075
|
-
|
|
30076
|
-
|
|
30077
|
-
|
|
30078
|
-
|
|
30079
|
-
|
|
30080
|
-
|
|
30081
|
-
|
|
30082
|
-
|
|
30083
|
-
|
|
30084
|
-
|
|
30085
|
-
|
|
30086
|
-
|
|
30087
|
-
|
|
30088
|
-
if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
|
|
30089
|
-
return this._prevInResult;
|
|
30212
|
+
|
|
30213
|
+
// Nearly vertical segments with an intersection.
|
|
30214
|
+
// Check to see where a point on the line with matching Y coordinate is.
|
|
30215
|
+
const yDist = (point.y - lPt.y) / v.y;
|
|
30216
|
+
const xFromYDist = lPt.x + yDist * v.x;
|
|
30217
|
+
if (point.x === xFromYDist) return 0;
|
|
30218
|
+
|
|
30219
|
+
// General case.
|
|
30220
|
+
// Check to see where a point on the line with matching X coordinate is.
|
|
30221
|
+
const xDist = (point.x - lPt.x) / v.x;
|
|
30222
|
+
const yFromXDist = lPt.y + xDist * v.y;
|
|
30223
|
+
if (point.y === yFromXDist) return 0;
|
|
30224
|
+
return point.y < yFromXDist ? -1 : 1;
|
|
30225
|
+
}
|
|
30226
|
+
|
|
30227
|
+
/**
|
|
30228
|
+
* Given another segment, returns the first non-trivial intersection
|
|
30229
|
+
* between the two segments (in terms of sweep line ordering), if it exists.
|
|
30230
|
+
*
|
|
30231
|
+
* A 'non-trivial' intersection is one that will cause one or both of the
|
|
30232
|
+
* segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
|
|
30233
|
+
*
|
|
30234
|
+
* * endpoint of segA with endpoint of segB --> trivial
|
|
30235
|
+
* * endpoint of segA with point along segB --> non-trivial
|
|
30236
|
+
* * endpoint of segB with point along segA --> non-trivial
|
|
30237
|
+
* * point along segA with point along segB --> non-trivial
|
|
30238
|
+
*
|
|
30239
|
+
* If no non-trivial intersection exists, return null
|
|
30240
|
+
* Else, return null.
|
|
30241
|
+
*/
|
|
30242
|
+
getIntersection(other) {
|
|
30243
|
+
// If bboxes don't overlap, there can't be any intersections
|
|
30244
|
+
const tBbox = this.bbox();
|
|
30245
|
+
const oBbox = other.bbox();
|
|
30246
|
+
const bboxOverlap = getBboxOverlap(tBbox, oBbox);
|
|
30247
|
+
if (bboxOverlap === null) return null;
|
|
30248
|
+
|
|
30249
|
+
// We first check to see if the endpoints can be considered intersections.
|
|
30250
|
+
// This will 'snap' intersections to endpoints if possible, and will
|
|
30251
|
+
// handle cases of colinearity.
|
|
30252
|
+
|
|
30253
|
+
const tlp = this.leftSE.point;
|
|
30254
|
+
const trp = this.rightSE.point;
|
|
30255
|
+
const olp = other.leftSE.point;
|
|
30256
|
+
const orp = other.rightSE.point;
|
|
30257
|
+
|
|
30258
|
+
// does each endpoint touch the other segment?
|
|
30259
|
+
// note that we restrict the 'touching' definition to only allow segments
|
|
30260
|
+
// to touch endpoints that lie forward from where we are in the sweep line pass
|
|
30261
|
+
const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
|
|
30262
|
+
const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
|
|
30263
|
+
const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
|
|
30264
|
+
const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;
|
|
30265
|
+
|
|
30266
|
+
// do left endpoints match?
|
|
30267
|
+
if (touchesThisLSE && touchesOtherLSE) {
|
|
30268
|
+
// these two cases are for colinear segments with matching left
|
|
30269
|
+
// endpoints, and one segment being longer than the other
|
|
30270
|
+
if (touchesThisRSE && !touchesOtherRSE) return trp;
|
|
30271
|
+
if (!touchesThisRSE && touchesOtherRSE) return orp;
|
|
30272
|
+
// either the two segments match exactly (two trival intersections)
|
|
30273
|
+
// or just on their left endpoint (one trivial intersection
|
|
30274
|
+
return null;
|
|
30090
30275
|
}
|
|
30091
|
-
|
|
30092
|
-
|
|
30093
|
-
|
|
30094
|
-
|
|
30095
|
-
if (
|
|
30096
|
-
|
|
30097
|
-
|
|
30098
|
-
|
|
30099
|
-
|
|
30100
|
-
var seg = this.prev.consumedBy || this.prev;
|
|
30101
|
-
this._beforeState = seg.afterState();
|
|
30102
|
-
}
|
|
30103
|
-
return this._beforeState;
|
|
30276
|
+
|
|
30277
|
+
// does this left endpoint matches (other doesn't)
|
|
30278
|
+
if (touchesThisLSE) {
|
|
30279
|
+
// check for segments that just intersect on opposing endpoints
|
|
30280
|
+
if (touchesOtherRSE) {
|
|
30281
|
+
if (tlp.x === orp.x && tlp.y === orp.y) return null;
|
|
30282
|
+
}
|
|
30283
|
+
// t-intersection on left endpoint
|
|
30284
|
+
return tlp;
|
|
30104
30285
|
}
|
|
30105
|
-
}, {
|
|
30106
|
-
key: "afterState",
|
|
30107
|
-
value: function afterState() {
|
|
30108
|
-
if (this._afterState !== undefined) return this._afterState;
|
|
30109
|
-
var beforeState = this.beforeState();
|
|
30110
|
-
this._afterState = {
|
|
30111
|
-
rings: beforeState.rings.slice(0),
|
|
30112
|
-
windings: beforeState.windings.slice(0),
|
|
30113
|
-
multiPolys: []
|
|
30114
|
-
};
|
|
30115
|
-
var ringsAfter = this._afterState.rings;
|
|
30116
|
-
var windingsAfter = this._afterState.windings;
|
|
30117
|
-
var mpsAfter = this._afterState.multiPolys; // calculate ringsAfter, windingsAfter
|
|
30118
|
-
|
|
30119
|
-
for (var i = 0, iMax = this.rings.length; i < iMax; i++) {
|
|
30120
|
-
var ring = this.rings[i];
|
|
30121
|
-
var winding = this.windings[i];
|
|
30122
|
-
var index = ringsAfter.indexOf(ring);
|
|
30123
|
-
if (index === -1) {
|
|
30124
|
-
ringsAfter.push(ring);
|
|
30125
|
-
windingsAfter.push(winding);
|
|
30126
|
-
} else windingsAfter[index] += winding;
|
|
30127
|
-
} // calcualte polysAfter
|
|
30128
|
-
|
|
30129
|
-
var polysAfter = [];
|
|
30130
|
-
var polysExclude = [];
|
|
30131
|
-
for (var _i = 0, _iMax = ringsAfter.length; _i < _iMax; _i++) {
|
|
30132
|
-
if (windingsAfter[_i] === 0) continue; // non-zero rule
|
|
30133
|
-
|
|
30134
|
-
var _ring = ringsAfter[_i];
|
|
30135
|
-
var poly = _ring.poly;
|
|
30136
|
-
if (polysExclude.indexOf(poly) !== -1) continue;
|
|
30137
|
-
if (_ring.isExterior) polysAfter.push(poly);else {
|
|
30138
|
-
if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
|
|
30139
|
-
var _index = polysAfter.indexOf(_ring.poly);
|
|
30140
|
-
if (_index !== -1) polysAfter.splice(_index, 1);
|
|
30141
|
-
}
|
|
30142
|
-
} // calculate multiPolysAfter
|
|
30143
30286
|
|
|
30144
|
-
|
|
30145
|
-
|
|
30146
|
-
|
|
30287
|
+
// does other left endpoint matches (this doesn't)
|
|
30288
|
+
if (touchesOtherLSE) {
|
|
30289
|
+
// check for segments that just intersect on opposing endpoints
|
|
30290
|
+
if (touchesThisRSE) {
|
|
30291
|
+
if (trp.x === olp.x && trp.y === olp.y) return null;
|
|
30147
30292
|
}
|
|
30148
|
-
|
|
30293
|
+
// t-intersection on left endpoint
|
|
30294
|
+
return olp;
|
|
30149
30295
|
}
|
|
30150
|
-
|
|
30151
|
-
|
|
30152
|
-
|
|
30153
|
-
|
|
30154
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
|
|
30160
|
-
|
|
30161
|
-
|
|
30162
|
-
|
|
30163
|
-
|
|
30164
|
-
|
|
30165
|
-
|
|
30166
|
-
|
|
30167
|
-
|
|
30168
|
-
|
|
30169
|
-
|
|
30170
|
-
|
|
30171
|
-
|
|
30172
|
-
|
|
30173
|
-
|
|
30174
|
-
|
|
30175
|
-
|
|
30176
|
-
|
|
30177
|
-
|
|
30178
|
-
|
|
30179
|
-
|
|
30180
|
-
|
|
30181
|
-
|
|
30182
|
-
|
|
30183
|
-
|
|
30184
|
-
|
|
30185
|
-
|
|
30186
|
-
|
|
30187
|
-
|
|
30188
|
-
|
|
30189
|
-
|
|
30190
|
-
|
|
30191
|
-
|
|
30192
|
-
|
|
30193
|
-
|
|
30194
|
-
|
|
30195
|
-
|
|
30196
|
-
|
|
30197
|
-
|
|
30198
|
-
|
|
30199
|
-
|
|
30200
|
-
|
|
30201
|
-
|
|
30202
|
-
|
|
30203
|
-
|
|
30204
|
-
|
|
30205
|
-
|
|
30296
|
+
|
|
30297
|
+
// trivial intersection on right endpoints
|
|
30298
|
+
if (touchesThisRSE && touchesOtherRSE) return null;
|
|
30299
|
+
|
|
30300
|
+
// t-intersections on just one right endpoint
|
|
30301
|
+
if (touchesThisRSE) return trp;
|
|
30302
|
+
if (touchesOtherRSE) return orp;
|
|
30303
|
+
|
|
30304
|
+
// None of our endpoints intersect. Look for a general intersection between
|
|
30305
|
+
// infinite lines laid over the segments
|
|
30306
|
+
const pt = intersection$1(tlp, this.vector(), olp, other.vector());
|
|
30307
|
+
|
|
30308
|
+
// are the segments parrallel? Note that if they were colinear with overlap,
|
|
30309
|
+
// they would have an endpoint intersection and that case was already handled above
|
|
30310
|
+
if (pt === null) return null;
|
|
30311
|
+
|
|
30312
|
+
// is the intersection found between the lines not on the segments?
|
|
30313
|
+
if (!isInBbox(bboxOverlap, pt)) return null;
|
|
30314
|
+
|
|
30315
|
+
// round the the computed point if needed
|
|
30316
|
+
return rounder.round(pt.x, pt.y);
|
|
30317
|
+
}
|
|
30318
|
+
|
|
30319
|
+
/**
|
|
30320
|
+
* Split the given segment into multiple segments on the given points.
|
|
30321
|
+
* * Each existing segment will retain its leftSE and a new rightSE will be
|
|
30322
|
+
* generated for it.
|
|
30323
|
+
* * A new segment will be generated which will adopt the original segment's
|
|
30324
|
+
* rightSE, and a new leftSE will be generated for it.
|
|
30325
|
+
* * If there are more than two points given to split on, new segments
|
|
30326
|
+
* in the middle will be generated with new leftSE and rightSE's.
|
|
30327
|
+
* * An array of the newly generated SweepEvents will be returned.
|
|
30328
|
+
*
|
|
30329
|
+
* Warning: input array of points is modified
|
|
30330
|
+
*/
|
|
30331
|
+
split(point) {
|
|
30332
|
+
const newEvents = [];
|
|
30333
|
+
const alreadyLinked = point.events !== undefined;
|
|
30334
|
+
const newLeftSE = new SweepEvent(point, true);
|
|
30335
|
+
const newRightSE = new SweepEvent(point, false);
|
|
30336
|
+
const oldRightSE = this.rightSE;
|
|
30337
|
+
this.replaceRightSE(newRightSE);
|
|
30338
|
+
newEvents.push(newRightSE);
|
|
30339
|
+
newEvents.push(newLeftSE);
|
|
30340
|
+
const newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice());
|
|
30341
|
+
|
|
30342
|
+
// when splitting a nearly vertical downward-facing segment,
|
|
30343
|
+
// sometimes one of the resulting new segments is vertical, in which
|
|
30344
|
+
// case its left and right events may need to be swapped
|
|
30345
|
+
if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
|
|
30346
|
+
newSeg.swapEvents();
|
|
30347
|
+
}
|
|
30348
|
+
if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
|
|
30349
|
+
this.swapEvents();
|
|
30350
|
+
}
|
|
30351
|
+
|
|
30352
|
+
// in the point we just used to create new sweep events with was already
|
|
30353
|
+
// linked to other events, we need to check if either of the affected
|
|
30354
|
+
// segments should be consumed
|
|
30355
|
+
if (alreadyLinked) {
|
|
30356
|
+
newLeftSE.checkForConsuming();
|
|
30357
|
+
newRightSE.checkForConsuming();
|
|
30358
|
+
}
|
|
30359
|
+
return newEvents;
|
|
30360
|
+
}
|
|
30361
|
+
|
|
30362
|
+
/* Swap which event is left and right */
|
|
30363
|
+
swapEvents() {
|
|
30364
|
+
const tmpEvt = this.rightSE;
|
|
30365
|
+
this.rightSE = this.leftSE;
|
|
30366
|
+
this.leftSE = tmpEvt;
|
|
30367
|
+
this.leftSE.isLeft = true;
|
|
30368
|
+
this.rightSE.isLeft = false;
|
|
30369
|
+
for (let i = 0, iMax = this.windings.length; i < iMax; i++) {
|
|
30370
|
+
this.windings[i] *= -1;
|
|
30371
|
+
}
|
|
30372
|
+
}
|
|
30373
|
+
|
|
30374
|
+
/* Consume another segment. We take their rings under our wing
|
|
30375
|
+
* and mark them as consumed. Use for perfectly overlapping segments */
|
|
30376
|
+
consume(other) {
|
|
30377
|
+
let consumer = this;
|
|
30378
|
+
let consumee = other;
|
|
30379
|
+
while (consumer.consumedBy) consumer = consumer.consumedBy;
|
|
30380
|
+
while (consumee.consumedBy) consumee = consumee.consumedBy;
|
|
30381
|
+
const cmp = Segment.compare(consumer, consumee);
|
|
30382
|
+
if (cmp === 0) return; // already consumed
|
|
30383
|
+
// the winner of the consumption is the earlier segment
|
|
30384
|
+
// according to sweep line ordering
|
|
30385
|
+
if (cmp > 0) {
|
|
30386
|
+
const tmp = consumer;
|
|
30387
|
+
consumer = consumee;
|
|
30388
|
+
consumee = tmp;
|
|
30389
|
+
}
|
|
30390
|
+
|
|
30391
|
+
// make sure a segment doesn't consume it's prev
|
|
30392
|
+
if (consumer.prev === consumee) {
|
|
30393
|
+
const tmp = consumer;
|
|
30394
|
+
consumer = consumee;
|
|
30395
|
+
consumee = tmp;
|
|
30396
|
+
}
|
|
30397
|
+
for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {
|
|
30398
|
+
const ring = consumee.rings[i];
|
|
30399
|
+
const winding = consumee.windings[i];
|
|
30400
|
+
const index = consumer.rings.indexOf(ring);
|
|
30401
|
+
if (index === -1) {
|
|
30402
|
+
consumer.rings.push(ring);
|
|
30403
|
+
consumer.windings.push(winding);
|
|
30404
|
+
} else consumer.windings[index] += winding;
|
|
30405
|
+
}
|
|
30406
|
+
consumee.rings = null;
|
|
30407
|
+
consumee.windings = null;
|
|
30408
|
+
consumee.consumedBy = consumer;
|
|
30409
|
+
|
|
30410
|
+
// mark sweep events consumed as to maintain ordering in sweep event queue
|
|
30411
|
+
consumee.leftSE.consumedBy = consumer.leftSE;
|
|
30412
|
+
consumee.rightSE.consumedBy = consumer.rightSE;
|
|
30413
|
+
}
|
|
30414
|
+
|
|
30415
|
+
/* The first segment previous segment chain that is in the result */
|
|
30416
|
+
prevInResult() {
|
|
30417
|
+
if (this._prevInResult !== undefined) return this._prevInResult;
|
|
30418
|
+
if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
|
|
30419
|
+
return this._prevInResult;
|
|
30420
|
+
}
|
|
30421
|
+
beforeState() {
|
|
30422
|
+
if (this._beforeState !== undefined) return this._beforeState;
|
|
30423
|
+
if (!this.prev) this._beforeState = {
|
|
30424
|
+
rings: [],
|
|
30425
|
+
windings: [],
|
|
30426
|
+
multiPolys: []
|
|
30427
|
+
};else {
|
|
30428
|
+
const seg = this.prev.consumedBy || this.prev;
|
|
30429
|
+
this._beforeState = seg.afterState();
|
|
30430
|
+
}
|
|
30431
|
+
return this._beforeState;
|
|
30432
|
+
}
|
|
30433
|
+
afterState() {
|
|
30434
|
+
if (this._afterState !== undefined) return this._afterState;
|
|
30435
|
+
const beforeState = this.beforeState();
|
|
30436
|
+
this._afterState = {
|
|
30437
|
+
rings: beforeState.rings.slice(0),
|
|
30438
|
+
windings: beforeState.windings.slice(0),
|
|
30439
|
+
multiPolys: []
|
|
30440
|
+
};
|
|
30441
|
+
const ringsAfter = this._afterState.rings;
|
|
30442
|
+
const windingsAfter = this._afterState.windings;
|
|
30443
|
+
const mpsAfter = this._afterState.multiPolys;
|
|
30444
|
+
|
|
30445
|
+
// calculate ringsAfter, windingsAfter
|
|
30446
|
+
for (let i = 0, iMax = this.rings.length; i < iMax; i++) {
|
|
30447
|
+
const ring = this.rings[i];
|
|
30448
|
+
const winding = this.windings[i];
|
|
30449
|
+
const index = ringsAfter.indexOf(ring);
|
|
30450
|
+
if (index === -1) {
|
|
30451
|
+
ringsAfter.push(ring);
|
|
30452
|
+
windingsAfter.push(winding);
|
|
30453
|
+
} else windingsAfter[index] += winding;
|
|
30454
|
+
}
|
|
30455
|
+
|
|
30456
|
+
// calcualte polysAfter
|
|
30457
|
+
const polysAfter = [];
|
|
30458
|
+
const polysExclude = [];
|
|
30459
|
+
for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {
|
|
30460
|
+
if (windingsAfter[i] === 0) continue; // non-zero rule
|
|
30461
|
+
const ring = ringsAfter[i];
|
|
30462
|
+
const poly = ring.poly;
|
|
30463
|
+
if (polysExclude.indexOf(poly) !== -1) continue;
|
|
30464
|
+
if (ring.isExterior) polysAfter.push(poly);else {
|
|
30465
|
+
if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
|
|
30466
|
+
const index = polysAfter.indexOf(ring.poly);
|
|
30467
|
+
if (index !== -1) polysAfter.splice(index, 1);
|
|
30468
|
+
}
|
|
30469
|
+
}
|
|
30470
|
+
|
|
30471
|
+
// calculate multiPolysAfter
|
|
30472
|
+
for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {
|
|
30473
|
+
const mp = polysAfter[i].multiPoly;
|
|
30474
|
+
if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
|
|
30475
|
+
}
|
|
30476
|
+
return this._afterState;
|
|
30477
|
+
}
|
|
30478
|
+
|
|
30479
|
+
/* Is this segment part of the final result? */
|
|
30480
|
+
isInResult() {
|
|
30481
|
+
// if we've been consumed, we're not in the result
|
|
30482
|
+
if (this.consumedBy) return false;
|
|
30483
|
+
if (this._isInResult !== undefined) return this._isInResult;
|
|
30484
|
+
const mpsBefore = this.beforeState().multiPolys;
|
|
30485
|
+
const mpsAfter = this.afterState().multiPolys;
|
|
30486
|
+
switch (operation.type) {
|
|
30487
|
+
case "union":
|
|
30488
|
+
{
|
|
30489
|
+
// UNION - included iff:
|
|
30490
|
+
// * On one side of us there is 0 poly interiors AND
|
|
30491
|
+
// * On the other side there is 1 or more.
|
|
30492
|
+
const noBefores = mpsBefore.length === 0;
|
|
30493
|
+
const noAfters = mpsAfter.length === 0;
|
|
30494
|
+
this._isInResult = noBefores !== noAfters;
|
|
30495
|
+
break;
|
|
30496
|
+
}
|
|
30497
|
+
case "intersection":
|
|
30498
|
+
{
|
|
30499
|
+
// INTERSECTION - included iff:
|
|
30500
|
+
// * on one side of us all multipolys are rep. with poly interiors AND
|
|
30501
|
+
// * on the other side of us, not all multipolys are repsented
|
|
30502
|
+
// with poly interiors
|
|
30503
|
+
let least;
|
|
30504
|
+
let most;
|
|
30505
|
+
if (mpsBefore.length < mpsAfter.length) {
|
|
30506
|
+
least = mpsBefore.length;
|
|
30507
|
+
most = mpsAfter.length;
|
|
30508
|
+
} else {
|
|
30509
|
+
least = mpsAfter.length;
|
|
30510
|
+
most = mpsBefore.length;
|
|
30206
30511
|
}
|
|
30207
|
-
|
|
30208
|
-
|
|
30209
|
-
|
|
30210
|
-
|
|
30512
|
+
this._isInResult = most === operation.numMultiPolys && least < most;
|
|
30513
|
+
break;
|
|
30514
|
+
}
|
|
30515
|
+
case "xor":
|
|
30516
|
+
{
|
|
30517
|
+
// XOR - included iff:
|
|
30518
|
+
// * the difference between the number of multipolys represented
|
|
30519
|
+
// with poly interiors on our two sides is an odd number
|
|
30520
|
+
const diff = Math.abs(mpsBefore.length - mpsAfter.length);
|
|
30521
|
+
this._isInResult = diff % 2 === 1;
|
|
30522
|
+
break;
|
|
30523
|
+
}
|
|
30524
|
+
case "difference":
|
|
30525
|
+
{
|
|
30526
|
+
// DIFFERENCE included iff:
|
|
30527
|
+
// * on exactly one side, we have just the subject
|
|
30528
|
+
const isJustSubject = mps => mps.length === 1 && mps[0].isSubject;
|
|
30529
|
+
this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
|
|
30530
|
+
break;
|
|
30531
|
+
}
|
|
30532
|
+
default:
|
|
30533
|
+
throw new Error(`Unrecognized operation type found ${operation.type}`);
|
|
30211
30534
|
}
|
|
30212
|
-
|
|
30213
|
-
|
|
30214
|
-
|
|
30215
|
-
|
|
30216
|
-
|
|
30217
|
-
var cmpPts = SweepEvent.comparePoints(pt1, pt2);
|
|
30218
|
-
if (cmpPts < 0) {
|
|
30219
|
-
leftPt = pt1;
|
|
30220
|
-
rightPt = pt2;
|
|
30221
|
-
winding = 1;
|
|
30222
|
-
} else if (cmpPts > 0) {
|
|
30223
|
-
leftPt = pt2;
|
|
30224
|
-
rightPt = pt1;
|
|
30225
|
-
winding = -1;
|
|
30226
|
-
} else throw new Error("Tried to create degenerate segment at [".concat(pt1.x, ", ").concat(pt1.y, "]"));
|
|
30227
|
-
var leftSE = new SweepEvent(leftPt, true);
|
|
30228
|
-
var rightSE = new SweepEvent(rightPt, false);
|
|
30229
|
-
return new Segment(leftSE, rightSE, [ring], [winding]);
|
|
30230
|
-
}
|
|
30231
|
-
}]);
|
|
30232
|
-
return Segment;
|
|
30233
|
-
}();
|
|
30234
|
-
var RingIn = /*#__PURE__*/function () {
|
|
30235
|
-
function RingIn(geomRing, poly, isExterior) {
|
|
30236
|
-
_classCallCheck(this, RingIn);
|
|
30535
|
+
return this._isInResult;
|
|
30536
|
+
}
|
|
30537
|
+
}
|
|
30538
|
+
class RingIn {
|
|
30539
|
+
constructor(geomRing, poly, isExterior) {
|
|
30237
30540
|
if (!Array.isArray(geomRing) || geomRing.length === 0) {
|
|
30238
|
-
throw new Error(
|
|
30541
|
+
throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
|
|
30239
30542
|
}
|
|
30240
30543
|
this.poly = poly;
|
|
30241
30544
|
this.isExterior = isExterior;
|
|
30242
30545
|
this.segments = [];
|
|
30243
|
-
if (typeof geomRing[0][0] !==
|
|
30244
|
-
throw new Error(
|
|
30546
|
+
if (typeof geomRing[0][0] !== "number" || typeof geomRing[0][1] !== "number") {
|
|
30547
|
+
throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
|
|
30245
30548
|
}
|
|
30246
|
-
|
|
30549
|
+
const firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);
|
|
30247
30550
|
this.bbox = {
|
|
30248
30551
|
ll: {
|
|
30249
30552
|
x: firstPoint.x,
|
|
@@ -30254,13 +30557,13 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30254
30557
|
y: firstPoint.y
|
|
30255
30558
|
}
|
|
30256
30559
|
};
|
|
30257
|
-
|
|
30258
|
-
for (
|
|
30259
|
-
if (typeof geomRing[i][0] !==
|
|
30260
|
-
throw new Error(
|
|
30560
|
+
let prevPoint = firstPoint;
|
|
30561
|
+
for (let i = 1, iMax = geomRing.length; i < iMax; i++) {
|
|
30562
|
+
if (typeof geomRing[i][0] !== "number" || typeof geomRing[i][1] !== "number") {
|
|
30563
|
+
throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
|
|
30261
30564
|
}
|
|
30262
|
-
|
|
30263
|
-
|
|
30565
|
+
let point = rounder.round(geomRing[i][0], geomRing[i][1]);
|
|
30566
|
+
// skip repeated points
|
|
30264
30567
|
if (point.x === prevPoint.x && point.y === prevPoint.y) continue;
|
|
30265
30568
|
this.segments.push(Segment.fromRing(prevPoint, point, this));
|
|
30266
30569
|
if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;
|
|
@@ -30268,34 +30571,29 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30268
30571
|
if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;
|
|
30269
30572
|
if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;
|
|
30270
30573
|
prevPoint = point;
|
|
30271
|
-
}
|
|
30272
|
-
|
|
30574
|
+
}
|
|
30575
|
+
// add segment from last to first if last is not the same as first
|
|
30273
30576
|
if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {
|
|
30274
30577
|
this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));
|
|
30275
30578
|
}
|
|
30276
30579
|
}
|
|
30277
|
-
|
|
30278
|
-
|
|
30279
|
-
|
|
30280
|
-
|
|
30281
|
-
|
|
30282
|
-
|
|
30283
|
-
sweepEvents.push(segment.leftSE);
|
|
30284
|
-
sweepEvents.push(segment.rightSE);
|
|
30285
|
-
}
|
|
30286
|
-
return sweepEvents;
|
|
30580
|
+
getSweepEvents() {
|
|
30581
|
+
const sweepEvents = [];
|
|
30582
|
+
for (let i = 0, iMax = this.segments.length; i < iMax; i++) {
|
|
30583
|
+
const segment = this.segments[i];
|
|
30584
|
+
sweepEvents.push(segment.leftSE);
|
|
30585
|
+
sweepEvents.push(segment.rightSE);
|
|
30287
30586
|
}
|
|
30288
|
-
|
|
30289
|
-
|
|
30290
|
-
}
|
|
30291
|
-
|
|
30292
|
-
|
|
30293
|
-
_classCallCheck(this, PolyIn);
|
|
30587
|
+
return sweepEvents;
|
|
30588
|
+
}
|
|
30589
|
+
}
|
|
30590
|
+
class PolyIn {
|
|
30591
|
+
constructor(geomPoly, multiPoly) {
|
|
30294
30592
|
if (!Array.isArray(geomPoly)) {
|
|
30295
|
-
throw new Error(
|
|
30593
|
+
throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
|
|
30296
30594
|
}
|
|
30297
|
-
this.exteriorRing = new RingIn(geomPoly[0], this, true);
|
|
30298
|
-
|
|
30595
|
+
this.exteriorRing = new RingIn(geomPoly[0], this, true);
|
|
30596
|
+
// copy by value
|
|
30299
30597
|
this.bbox = {
|
|
30300
30598
|
ll: {
|
|
30301
30599
|
x: this.exteriorRing.bbox.ll.x,
|
|
@@ -30307,8 +30605,8 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30307
30605
|
}
|
|
30308
30606
|
};
|
|
30309
30607
|
this.interiorRings = [];
|
|
30310
|
-
for (
|
|
30311
|
-
|
|
30608
|
+
for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {
|
|
30609
|
+
const ring = new RingIn(geomPoly[i], this, false);
|
|
30312
30610
|
if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;
|
|
30313
30611
|
if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;
|
|
30314
30612
|
if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;
|
|
@@ -30317,31 +30615,27 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30317
30615
|
}
|
|
30318
30616
|
this.multiPoly = multiPoly;
|
|
30319
30617
|
}
|
|
30320
|
-
|
|
30321
|
-
|
|
30322
|
-
|
|
30323
|
-
|
|
30324
|
-
for (
|
|
30325
|
-
|
|
30326
|
-
for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
|
|
30327
|
-
sweepEvents.push(ringSweepEvents[j]);
|
|
30328
|
-
}
|
|
30618
|
+
getSweepEvents() {
|
|
30619
|
+
const sweepEvents = this.exteriorRing.getSweepEvents();
|
|
30620
|
+
for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
|
|
30621
|
+
const ringSweepEvents = this.interiorRings[i].getSweepEvents();
|
|
30622
|
+
for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
|
|
30623
|
+
sweepEvents.push(ringSweepEvents[j]);
|
|
30329
30624
|
}
|
|
30330
|
-
return sweepEvents;
|
|
30331
30625
|
}
|
|
30332
|
-
|
|
30333
|
-
|
|
30334
|
-
}
|
|
30335
|
-
|
|
30336
|
-
|
|
30337
|
-
_classCallCheck(this, MultiPolyIn);
|
|
30626
|
+
return sweepEvents;
|
|
30627
|
+
}
|
|
30628
|
+
}
|
|
30629
|
+
class MultiPolyIn {
|
|
30630
|
+
constructor(geom, isSubject) {
|
|
30338
30631
|
if (!Array.isArray(geom)) {
|
|
30339
|
-
throw new Error(
|
|
30632
|
+
throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
|
|
30340
30633
|
}
|
|
30341
30634
|
try {
|
|
30342
30635
|
// if the input looks like a polygon, convert it to a multipolygon
|
|
30343
|
-
if (typeof geom[0][0][0] ===
|
|
30344
|
-
} catch (ex) {
|
|
30636
|
+
if (typeof geom[0][0][0] === "number") geom = [geom];
|
|
30637
|
+
} catch (ex) {
|
|
30638
|
+
// The input is either malformed or has empty arrays.
|
|
30345
30639
|
// In either case, it will be handled later on.
|
|
30346
30640
|
}
|
|
30347
30641
|
this.polys = [];
|
|
@@ -30355,8 +30649,8 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30355
30649
|
y: Number.NEGATIVE_INFINITY
|
|
30356
30650
|
}
|
|
30357
30651
|
};
|
|
30358
|
-
for (
|
|
30359
|
-
|
|
30652
|
+
for (let i = 0, iMax = geom.length; i < iMax; i++) {
|
|
30653
|
+
const poly = new PolyIn(geom[i], this);
|
|
30360
30654
|
if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;
|
|
30361
30655
|
if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;
|
|
30362
30656
|
if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;
|
|
@@ -30365,254 +30659,223 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30365
30659
|
}
|
|
30366
30660
|
this.isSubject = isSubject;
|
|
30367
30661
|
}
|
|
30368
|
-
|
|
30369
|
-
|
|
30370
|
-
|
|
30371
|
-
|
|
30372
|
-
for (
|
|
30373
|
-
|
|
30374
|
-
|
|
30375
|
-
|
|
30376
|
-
|
|
30377
|
-
|
|
30378
|
-
|
|
30379
|
-
|
|
30380
|
-
|
|
30381
|
-
|
|
30382
|
-
|
|
30383
|
-
|
|
30384
|
-
|
|
30385
|
-
|
|
30386
|
-
|
|
30387
|
-
|
|
30388
|
-
|
|
30389
|
-
|
|
30390
|
-
|
|
30391
|
-
|
|
30392
|
-
|
|
30393
|
-
|
|
30394
|
-
|
|
30395
|
-
|
|
30396
|
-
|
|
30397
|
-
|
|
30398
|
-
|
|
30399
|
-
/* Walk the chain of linked events to form a closed ring */
|
|
30662
|
+
getSweepEvents() {
|
|
30663
|
+
const sweepEvents = [];
|
|
30664
|
+
for (let i = 0, iMax = this.polys.length; i < iMax; i++) {
|
|
30665
|
+
const polySweepEvents = this.polys[i].getSweepEvents();
|
|
30666
|
+
for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
|
|
30667
|
+
sweepEvents.push(polySweepEvents[j]);
|
|
30668
|
+
}
|
|
30669
|
+
}
|
|
30670
|
+
return sweepEvents;
|
|
30671
|
+
}
|
|
30672
|
+
}
|
|
30673
|
+
class RingOut {
|
|
30674
|
+
/* Given the segments from the sweep line pass, compute & return a series
|
|
30675
|
+
* of closed rings from all the segments marked to be part of the result */
|
|
30676
|
+
static factory(allSegments) {
|
|
30677
|
+
const ringsOut = [];
|
|
30678
|
+
for (let i = 0, iMax = allSegments.length; i < iMax; i++) {
|
|
30679
|
+
const segment = allSegments[i];
|
|
30680
|
+
if (!segment.isInResult() || segment.ringOut) continue;
|
|
30681
|
+
let prevEvent = null;
|
|
30682
|
+
let event = segment.leftSE;
|
|
30683
|
+
let nextEvent = segment.rightSE;
|
|
30684
|
+
const events = [event];
|
|
30685
|
+
const startingPoint = event.point;
|
|
30686
|
+
const intersectionLEs = [];
|
|
30687
|
+
|
|
30688
|
+
/* Walk the chain of linked events to form a closed ring */
|
|
30689
|
+
while (true) {
|
|
30690
|
+
prevEvent = event;
|
|
30691
|
+
event = nextEvent;
|
|
30692
|
+
events.push(event);
|
|
30400
30693
|
|
|
30694
|
+
/* Is the ring complete? */
|
|
30695
|
+
if (event.point === startingPoint) break;
|
|
30401
30696
|
while (true) {
|
|
30402
|
-
|
|
30403
|
-
|
|
30404
|
-
|
|
30405
|
-
|
|
30697
|
+
const availableLEs = event.getAvailableLinkedEvents();
|
|
30698
|
+
|
|
30699
|
+
/* Did we hit a dead end? This shouldn't happen.
|
|
30700
|
+
* Indicates some earlier part of the algorithm malfunctioned. */
|
|
30701
|
+
if (availableLEs.length === 0) {
|
|
30702
|
+
const firstPt = events[0].point;
|
|
30703
|
+
const lastPt = events[events.length - 1].point;
|
|
30704
|
+
throw new Error(`Unable to complete output ring starting at [${firstPt.x},` + ` ${firstPt.y}]. Last matching segment found ends at` + ` [${lastPt.x}, ${lastPt.y}].`);
|
|
30705
|
+
}
|
|
30406
30706
|
|
|
30407
|
-
|
|
30408
|
-
|
|
30409
|
-
|
|
30410
|
-
|
|
30411
|
-
|
|
30412
|
-
|
|
30413
|
-
if (availableLEs.length === 0) {
|
|
30414
|
-
var firstPt = events[0].point;
|
|
30415
|
-
var lastPt = events[events.length - 1].point;
|
|
30416
|
-
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, "]."));
|
|
30417
|
-
}
|
|
30418
|
-
/* Only one way to go, so cotinue on the path */
|
|
30707
|
+
/* Only one way to go, so cotinue on the path */
|
|
30708
|
+
if (availableLEs.length === 1) {
|
|
30709
|
+
nextEvent = availableLEs[0].otherSE;
|
|
30710
|
+
break;
|
|
30711
|
+
}
|
|
30419
30712
|
|
|
30420
|
-
|
|
30421
|
-
|
|
30713
|
+
/* We must have an intersection. Check for a completed loop */
|
|
30714
|
+
let indexLE = null;
|
|
30715
|
+
for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
|
|
30716
|
+
if (intersectionLEs[j].point === event.point) {
|
|
30717
|
+
indexLE = j;
|
|
30422
30718
|
break;
|
|
30423
30719
|
}
|
|
30424
|
-
/* We must have an intersection. Check for a completed loop */
|
|
30425
|
-
|
|
30426
|
-
var indexLE = null;
|
|
30427
|
-
for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
|
|
30428
|
-
if (intersectionLEs[j].point === event.point) {
|
|
30429
|
-
indexLE = j;
|
|
30430
|
-
break;
|
|
30431
|
-
}
|
|
30432
|
-
}
|
|
30433
|
-
/* Found a completed loop. Cut that off and make a ring */
|
|
30434
|
-
|
|
30435
|
-
if (indexLE !== null) {
|
|
30436
|
-
var intersectionLE = intersectionLEs.splice(indexLE)[0];
|
|
30437
|
-
var ringEvents = events.splice(intersectionLE.index);
|
|
30438
|
-
ringEvents.unshift(ringEvents[0].otherSE);
|
|
30439
|
-
ringsOut.push(new RingOut(ringEvents.reverse()));
|
|
30440
|
-
continue;
|
|
30441
|
-
}
|
|
30442
|
-
/* register the intersection */
|
|
30443
|
-
|
|
30444
|
-
intersectionLEs.push({
|
|
30445
|
-
index: events.length,
|
|
30446
|
-
point: event.point
|
|
30447
|
-
});
|
|
30448
|
-
/* Choose the left-most option to continue the walk */
|
|
30449
|
-
|
|
30450
|
-
var comparator = event.getLeftmostComparator(prevEvent);
|
|
30451
|
-
nextEvent = availableLEs.sort(comparator)[0].otherSE;
|
|
30452
|
-
break;
|
|
30453
30720
|
}
|
|
30721
|
+
/* Found a completed loop. Cut that off and make a ring */
|
|
30722
|
+
if (indexLE !== null) {
|
|
30723
|
+
const intersectionLE = intersectionLEs.splice(indexLE)[0];
|
|
30724
|
+
const ringEvents = events.splice(intersectionLE.index);
|
|
30725
|
+
ringEvents.unshift(ringEvents[0].otherSE);
|
|
30726
|
+
ringsOut.push(new RingOut(ringEvents.reverse()));
|
|
30727
|
+
continue;
|
|
30728
|
+
}
|
|
30729
|
+
/* register the intersection */
|
|
30730
|
+
intersectionLEs.push({
|
|
30731
|
+
index: events.length,
|
|
30732
|
+
point: event.point
|
|
30733
|
+
});
|
|
30734
|
+
/* Choose the left-most option to continue the walk */
|
|
30735
|
+
const comparator = event.getLeftmostComparator(prevEvent);
|
|
30736
|
+
nextEvent = availableLEs.sort(comparator)[0].otherSE;
|
|
30737
|
+
break;
|
|
30454
30738
|
}
|
|
30455
|
-
ringsOut.push(new RingOut(events));
|
|
30456
30739
|
}
|
|
30457
|
-
|
|
30740
|
+
ringsOut.push(new RingOut(events));
|
|
30458
30741
|
}
|
|
30459
|
-
|
|
30460
|
-
|
|
30461
|
-
|
|
30742
|
+
return ringsOut;
|
|
30743
|
+
}
|
|
30744
|
+
constructor(events) {
|
|
30462
30745
|
this.events = events;
|
|
30463
|
-
for (
|
|
30746
|
+
for (let i = 0, iMax = events.length; i < iMax; i++) {
|
|
30464
30747
|
events[i].segment.ringOut = this;
|
|
30465
30748
|
}
|
|
30466
30749
|
this.poly = null;
|
|
30467
30750
|
}
|
|
30468
|
-
|
|
30469
|
-
|
|
30470
|
-
|
|
30471
|
-
|
|
30472
|
-
|
|
30473
|
-
|
|
30474
|
-
|
|
30475
|
-
|
|
30476
|
-
|
|
30477
|
-
|
|
30478
|
-
|
|
30479
|
-
|
|
30480
|
-
|
|
30481
|
-
|
|
30482
|
-
|
|
30483
|
-
|
|
30484
|
-
|
|
30485
|
-
|
|
30486
|
-
|
|
30487
|
-
|
|
30488
|
-
|
|
30489
|
-
|
|
30490
|
-
|
|
30491
|
-
|
|
30492
|
-
|
|
30493
|
-
|
|
30494
|
-
|
|
30495
|
-
|
|
30496
|
-
|
|
30497
|
-
|
|
30498
|
-
|
|
30499
|
-
|
|
30500
|
-
|
|
30501
|
-
|
|
30502
|
-
|
|
30503
|
-
|
|
30504
|
-
|
|
30505
|
-
}
|
|
30506
|
-
|
|
30507
|
-
|
|
30508
|
-
|
|
30509
|
-
|
|
30510
|
-
|
|
30511
|
-
|
|
30512
|
-
|
|
30513
|
-
|
|
30514
|
-
|
|
30515
|
-
|
|
30516
|
-
|
|
30517
|
-
|
|
30518
|
-
|
|
30519
|
-
|
|
30520
|
-
|
|
30521
|
-
|
|
30522
|
-
|
|
30523
|
-
if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
|
|
30524
|
-
}
|
|
30525
|
-
var prevSeg = leftMostEvt.segment.prevInResult();
|
|
30526
|
-
var prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
|
|
30527
|
-
while (true) {
|
|
30528
|
-
// no segment found, thus no ring can enclose us
|
|
30529
|
-
if (!prevSeg) return null; // no segments below prev segment found, thus the ring of the prev
|
|
30530
|
-
// segment must loop back around and enclose us
|
|
30531
|
-
|
|
30532
|
-
if (!prevPrevSeg) return prevSeg.ringOut; // if the two segments are of different rings, the ring of the prev
|
|
30533
|
-
// segment must either loop around us or the ring of the prev prev
|
|
30534
|
-
// seg, which would make us and the ring of the prev peers
|
|
30751
|
+
getGeom() {
|
|
30752
|
+
// Remove superfluous points (ie extra points along a straight line),
|
|
30753
|
+
let prevPt = this.events[0].point;
|
|
30754
|
+
const points = [prevPt];
|
|
30755
|
+
for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {
|
|
30756
|
+
const pt = this.events[i].point;
|
|
30757
|
+
const nextPt = this.events[i + 1].point;
|
|
30758
|
+
if (compareVectorAngles(pt, prevPt, nextPt) === 0) continue;
|
|
30759
|
+
points.push(pt);
|
|
30760
|
+
prevPt = pt;
|
|
30761
|
+
}
|
|
30762
|
+
|
|
30763
|
+
// ring was all (within rounding error of angle calc) colinear points
|
|
30764
|
+
if (points.length === 1) return null;
|
|
30765
|
+
|
|
30766
|
+
// check if the starting point is necessary
|
|
30767
|
+
const pt = points[0];
|
|
30768
|
+
const nextPt = points[1];
|
|
30769
|
+
if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();
|
|
30770
|
+
points.push(points[0]);
|
|
30771
|
+
const step = this.isExteriorRing() ? 1 : -1;
|
|
30772
|
+
const iStart = this.isExteriorRing() ? 0 : points.length - 1;
|
|
30773
|
+
const iEnd = this.isExteriorRing() ? points.length : -1;
|
|
30774
|
+
const orderedPoints = [];
|
|
30775
|
+
for (let i = iStart; i != iEnd; i += step) orderedPoints.push([points[i].x, points[i].y]);
|
|
30776
|
+
return orderedPoints;
|
|
30777
|
+
}
|
|
30778
|
+
isExteriorRing() {
|
|
30779
|
+
if (this._isExteriorRing === undefined) {
|
|
30780
|
+
const enclosing = this.enclosingRing();
|
|
30781
|
+
this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
|
|
30782
|
+
}
|
|
30783
|
+
return this._isExteriorRing;
|
|
30784
|
+
}
|
|
30785
|
+
enclosingRing() {
|
|
30786
|
+
if (this._enclosingRing === undefined) {
|
|
30787
|
+
this._enclosingRing = this._calcEnclosingRing();
|
|
30788
|
+
}
|
|
30789
|
+
return this._enclosingRing;
|
|
30790
|
+
}
|
|
30791
|
+
|
|
30792
|
+
/* Returns the ring that encloses this one, if any */
|
|
30793
|
+
_calcEnclosingRing() {
|
|
30794
|
+
// start with the ealier sweep line event so that the prevSeg
|
|
30795
|
+
// chain doesn't lead us inside of a loop of ours
|
|
30796
|
+
let leftMostEvt = this.events[0];
|
|
30797
|
+
for (let i = 1, iMax = this.events.length; i < iMax; i++) {
|
|
30798
|
+
const evt = this.events[i];
|
|
30799
|
+
if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
|
|
30800
|
+
}
|
|
30801
|
+
let prevSeg = leftMostEvt.segment.prevInResult();
|
|
30802
|
+
let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
|
|
30803
|
+
while (true) {
|
|
30804
|
+
// no segment found, thus no ring can enclose us
|
|
30805
|
+
if (!prevSeg) return null;
|
|
30535
30806
|
|
|
30536
|
-
|
|
30537
|
-
|
|
30538
|
-
|
|
30539
|
-
} else return prevSeg.ringOut.enclosingRing();
|
|
30540
|
-
} // two segments are from the same ring, so this was a penisula
|
|
30541
|
-
// of that ring. iterate downward, keep searching
|
|
30807
|
+
// no segments below prev segment found, thus the ring of the prev
|
|
30808
|
+
// segment must loop back around and enclose us
|
|
30809
|
+
if (!prevPrevSeg) return prevSeg.ringOut;
|
|
30542
30810
|
|
|
30543
|
-
|
|
30544
|
-
|
|
30811
|
+
// if the two segments are of different rings, the ring of the prev
|
|
30812
|
+
// segment must either loop around us or the ring of the prev prev
|
|
30813
|
+
// seg, which would make us and the ring of the prev peers
|
|
30814
|
+
if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
|
|
30815
|
+
if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {
|
|
30816
|
+
return prevSeg.ringOut;
|
|
30817
|
+
} else return prevSeg.ringOut.enclosingRing();
|
|
30545
30818
|
}
|
|
30819
|
+
|
|
30820
|
+
// two segments are from the same ring, so this was a penisula
|
|
30821
|
+
// of that ring. iterate downward, keep searching
|
|
30822
|
+
prevSeg = prevPrevSeg.prevInResult();
|
|
30823
|
+
prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
|
|
30546
30824
|
}
|
|
30547
|
-
}
|
|
30548
|
-
|
|
30549
|
-
|
|
30550
|
-
|
|
30551
|
-
function PolyOut(exteriorRing) {
|
|
30552
|
-
_classCallCheck(this, PolyOut);
|
|
30825
|
+
}
|
|
30826
|
+
}
|
|
30827
|
+
class PolyOut {
|
|
30828
|
+
constructor(exteriorRing) {
|
|
30553
30829
|
this.exteriorRing = exteriorRing;
|
|
30554
30830
|
exteriorRing.poly = this;
|
|
30555
30831
|
this.interiorRings = [];
|
|
30556
30832
|
}
|
|
30557
|
-
|
|
30558
|
-
|
|
30559
|
-
|
|
30560
|
-
|
|
30561
|
-
|
|
30562
|
-
|
|
30563
|
-
|
|
30564
|
-
|
|
30565
|
-
|
|
30566
|
-
|
|
30567
|
-
|
|
30568
|
-
if (
|
|
30569
|
-
|
|
30570
|
-
var ringGeom = this.interiorRings[i].getGeom(); // interior ring was all (within rounding error of angle calc) colinear points
|
|
30571
|
-
|
|
30572
|
-
if (ringGeom === null) continue;
|
|
30573
|
-
geom.push(ringGeom);
|
|
30574
|
-
}
|
|
30575
|
-
return geom;
|
|
30833
|
+
addInterior(ring) {
|
|
30834
|
+
this.interiorRings.push(ring);
|
|
30835
|
+
ring.poly = this;
|
|
30836
|
+
}
|
|
30837
|
+
getGeom() {
|
|
30838
|
+
const geom = [this.exteriorRing.getGeom()];
|
|
30839
|
+
// exterior ring was all (within rounding error of angle calc) colinear points
|
|
30840
|
+
if (geom[0] === null) return null;
|
|
30841
|
+
for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
|
|
30842
|
+
const ringGeom = this.interiorRings[i].getGeom();
|
|
30843
|
+
// interior ring was all (within rounding error of angle calc) colinear points
|
|
30844
|
+
if (ringGeom === null) continue;
|
|
30845
|
+
geom.push(ringGeom);
|
|
30576
30846
|
}
|
|
30577
|
-
|
|
30578
|
-
|
|
30579
|
-
}
|
|
30580
|
-
|
|
30581
|
-
|
|
30582
|
-
_classCallCheck(this, MultiPolyOut);
|
|
30847
|
+
return geom;
|
|
30848
|
+
}
|
|
30849
|
+
}
|
|
30850
|
+
class MultiPolyOut {
|
|
30851
|
+
constructor(rings) {
|
|
30583
30852
|
this.rings = rings;
|
|
30584
30853
|
this.polys = this._composePolys(rings);
|
|
30585
30854
|
}
|
|
30586
|
-
|
|
30587
|
-
|
|
30588
|
-
|
|
30589
|
-
|
|
30590
|
-
|
|
30591
|
-
|
|
30592
|
-
|
|
30593
|
-
if (polyGeom === null) continue;
|
|
30594
|
-
geom.push(polyGeom);
|
|
30595
|
-
}
|
|
30596
|
-
return geom;
|
|
30855
|
+
getGeom() {
|
|
30856
|
+
const geom = [];
|
|
30857
|
+
for (let i = 0, iMax = this.polys.length; i < iMax; i++) {
|
|
30858
|
+
const polyGeom = this.polys[i].getGeom();
|
|
30859
|
+
// exterior ring was all (within rounding error of angle calc) colinear points
|
|
30860
|
+
if (polyGeom === null) continue;
|
|
30861
|
+
geom.push(polyGeom);
|
|
30597
30862
|
}
|
|
30598
|
-
|
|
30599
|
-
|
|
30600
|
-
|
|
30601
|
-
|
|
30602
|
-
|
|
30603
|
-
|
|
30604
|
-
|
|
30605
|
-
|
|
30606
|
-
|
|
30607
|
-
|
|
30608
|
-
|
|
30609
|
-
}
|
|
30863
|
+
return geom;
|
|
30864
|
+
}
|
|
30865
|
+
_composePolys(rings) {
|
|
30866
|
+
const polys = [];
|
|
30867
|
+
for (let i = 0, iMax = rings.length; i < iMax; i++) {
|
|
30868
|
+
const ring = rings[i];
|
|
30869
|
+
if (ring.poly) continue;
|
|
30870
|
+
if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {
|
|
30871
|
+
const enclosingRing = ring.enclosingRing();
|
|
30872
|
+
if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));
|
|
30873
|
+
enclosingRing.poly.addInterior(ring);
|
|
30610
30874
|
}
|
|
30611
|
-
return polys;
|
|
30612
30875
|
}
|
|
30613
|
-
|
|
30614
|
-
|
|
30615
|
-
}
|
|
30876
|
+
return polys;
|
|
30877
|
+
}
|
|
30878
|
+
}
|
|
30616
30879
|
|
|
30617
30880
|
/**
|
|
30618
30881
|
* NOTE: We must be careful not to change any segments while
|
|
@@ -30625,271 +30888,269 @@ module.exports = function pointInPolygonNested(point, vs, start, end) {
|
|
|
30625
30888
|
* it sometimes does.)
|
|
30626
30889
|
*/
|
|
30627
30890
|
|
|
30628
|
-
|
|
30629
|
-
|
|
30630
|
-
|
|
30631
|
-
_classCallCheck(this, SweepLine);
|
|
30891
|
+
class SweepLine {
|
|
30892
|
+
constructor(queue) {
|
|
30893
|
+
let comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;
|
|
30632
30894
|
this.queue = queue;
|
|
30633
30895
|
this.tree = new Tree(comparator);
|
|
30634
30896
|
this.segments = [];
|
|
30635
30897
|
}
|
|
30636
|
-
|
|
30637
|
-
|
|
30638
|
-
|
|
30639
|
-
|
|
30640
|
-
|
|
30641
|
-
|
|
30642
|
-
|
|
30643
|
-
if (event.
|
|
30644
|
-
|
|
30645
|
-
|
|
30646
|
-
|
|
30647
|
-
|
|
30648
|
-
|
|
30649
|
-
|
|
30650
|
-
|
|
30651
|
-
|
|
30652
|
-
|
|
30653
|
-
|
|
30654
|
-
|
|
30655
|
-
|
|
30656
|
-
|
|
30657
|
-
|
|
30658
|
-
|
|
30659
|
-
|
|
30660
|
-
|
|
30661
|
-
|
|
30662
|
-
|
|
30663
|
-
|
|
30664
|
-
|
|
30665
|
-
|
|
30666
|
-
|
|
30667
|
-
|
|
30668
|
-
|
|
30669
|
-
|
|
30670
|
-
|
|
30671
|
-
|
|
30672
|
-
|
|
30673
|
-
|
|
30674
|
-
|
|
30675
|
-
}
|
|
30676
|
-
}
|
|
30677
|
-
} // Check for intersections against the next segment in the sweep line
|
|
30678
|
-
|
|
30679
|
-
var nextMySplitter = null;
|
|
30680
|
-
if (nextSeg) {
|
|
30681
|
-
var nextInter = nextSeg.getIntersection(segment);
|
|
30682
|
-
if (nextInter !== null) {
|
|
30683
|
-
if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
|
|
30684
|
-
if (!nextSeg.isAnEndpoint(nextInter)) {
|
|
30685
|
-
var _newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
|
|
30686
|
-
for (var _i = 0, _iMax = _newEventsFromSplit.length; _i < _iMax; _i++) {
|
|
30687
|
-
newEvents.push(_newEventsFromSplit[_i]);
|
|
30688
|
-
}
|
|
30898
|
+
process(event) {
|
|
30899
|
+
const segment = event.segment;
|
|
30900
|
+
const newEvents = [];
|
|
30901
|
+
|
|
30902
|
+
// if we've already been consumed by another segment,
|
|
30903
|
+
// clean up our body parts and get out
|
|
30904
|
+
if (event.consumedBy) {
|
|
30905
|
+
if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);
|
|
30906
|
+
return newEvents;
|
|
30907
|
+
}
|
|
30908
|
+
const node = event.isLeft ? this.tree.add(segment) : this.tree.find(segment);
|
|
30909
|
+
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.");
|
|
30910
|
+
let prevNode = node;
|
|
30911
|
+
let nextNode = node;
|
|
30912
|
+
let prevSeg = undefined;
|
|
30913
|
+
let nextSeg = undefined;
|
|
30914
|
+
|
|
30915
|
+
// skip consumed segments still in tree
|
|
30916
|
+
while (prevSeg === undefined) {
|
|
30917
|
+
prevNode = this.tree.prev(prevNode);
|
|
30918
|
+
if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;
|
|
30919
|
+
}
|
|
30920
|
+
|
|
30921
|
+
// skip consumed segments still in tree
|
|
30922
|
+
while (nextSeg === undefined) {
|
|
30923
|
+
nextNode = this.tree.next(nextNode);
|
|
30924
|
+
if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;
|
|
30925
|
+
}
|
|
30926
|
+
if (event.isLeft) {
|
|
30927
|
+
// Check for intersections against the previous segment in the sweep line
|
|
30928
|
+
let prevMySplitter = null;
|
|
30929
|
+
if (prevSeg) {
|
|
30930
|
+
const prevInter = prevSeg.getIntersection(segment);
|
|
30931
|
+
if (prevInter !== null) {
|
|
30932
|
+
if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
|
|
30933
|
+
if (!prevSeg.isAnEndpoint(prevInter)) {
|
|
30934
|
+
const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
|
|
30935
|
+
for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
|
|
30936
|
+
newEvents.push(newEventsFromSplit[i]);
|
|
30689
30937
|
}
|
|
30690
30938
|
}
|
|
30691
|
-
} // For simplicity, even if we find more than one intersection we only
|
|
30692
|
-
// spilt on the 'earliest' (sweep-line style) of the intersections.
|
|
30693
|
-
// The other intersection will be handled in a future process().
|
|
30694
|
-
|
|
30695
|
-
if (prevMySplitter !== null || nextMySplitter !== null) {
|
|
30696
|
-
var mySplitter = null;
|
|
30697
|
-
if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
|
|
30698
|
-
var cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
|
|
30699
|
-
mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
|
|
30700
|
-
} // Rounding errors can cause changes in ordering,
|
|
30701
|
-
// so remove afected segments and right sweep events before splitting
|
|
30702
|
-
|
|
30703
|
-
this.queue.remove(segment.rightSE);
|
|
30704
|
-
newEvents.push(segment.rightSE);
|
|
30705
|
-
var _newEventsFromSplit2 = segment.split(mySplitter);
|
|
30706
|
-
for (var _i2 = 0, _iMax2 = _newEventsFromSplit2.length; _i2 < _iMax2; _i2++) {
|
|
30707
|
-
newEvents.push(_newEventsFromSplit2[_i2]);
|
|
30708
|
-
}
|
|
30709
|
-
}
|
|
30710
|
-
if (newEvents.length > 0) {
|
|
30711
|
-
// We found some intersections, so re-do the current event to
|
|
30712
|
-
// make sure sweep line ordering is totally consistent for later
|
|
30713
|
-
// use with the segment 'prev' pointers
|
|
30714
|
-
this.tree.remove(segment);
|
|
30715
|
-
newEvents.push(event);
|
|
30716
|
-
} else {
|
|
30717
|
-
// done with left event
|
|
30718
|
-
this.segments.push(segment);
|
|
30719
|
-
segment.prev = prevSeg;
|
|
30720
30939
|
}
|
|
30721
|
-
}
|
|
30722
|
-
|
|
30723
|
-
|
|
30724
|
-
|
|
30725
|
-
|
|
30726
|
-
|
|
30727
|
-
|
|
30728
|
-
|
|
30729
|
-
|
|
30730
|
-
|
|
30731
|
-
|
|
30732
|
-
|
|
30733
|
-
}
|
|
30734
|
-
if (!nextSeg.isAnEndpoint(inter)) {
|
|
30735
|
-
var _newEventsFromSplit4 = this._splitSafely(nextSeg, inter);
|
|
30736
|
-
for (var _i4 = 0, _iMax4 = _newEventsFromSplit4.length; _i4 < _iMax4; _i4++) {
|
|
30737
|
-
newEvents.push(_newEventsFromSplit4[_i4]);
|
|
30738
|
-
}
|
|
30940
|
+
}
|
|
30941
|
+
|
|
30942
|
+
// Check for intersections against the next segment in the sweep line
|
|
30943
|
+
let nextMySplitter = null;
|
|
30944
|
+
if (nextSeg) {
|
|
30945
|
+
const nextInter = nextSeg.getIntersection(segment);
|
|
30946
|
+
if (nextInter !== null) {
|
|
30947
|
+
if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
|
|
30948
|
+
if (!nextSeg.isAnEndpoint(nextInter)) {
|
|
30949
|
+
const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
|
|
30950
|
+
for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
|
|
30951
|
+
newEvents.push(newEventsFromSplit[i]);
|
|
30739
30952
|
}
|
|
30740
30953
|
}
|
|
30741
30954
|
}
|
|
30742
|
-
this.tree.remove(segment);
|
|
30743
30955
|
}
|
|
30744
|
-
|
|
30745
|
-
|
|
30746
|
-
|
|
30747
|
-
|
|
30748
|
-
|
|
30749
|
-
|
|
30750
|
-
|
|
30751
|
-
|
|
30752
|
-
|
|
30753
|
-
|
|
30754
|
-
|
|
30755
|
-
|
|
30756
|
-
|
|
30757
|
-
|
|
30758
|
-
|
|
30759
|
-
|
|
30760
|
-
|
|
30761
|
-
|
|
30762
|
-
return newEvents;
|
|
30763
|
-
}
|
|
30764
|
-
}]);
|
|
30765
|
-
return SweepLine;
|
|
30766
|
-
}();
|
|
30767
|
-
var POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== 'undefined' && ({"NODE_ENV":"production","BASE_URL":"/"}).POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
|
|
30768
|
-
var POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== 'undefined' && ({"NODE_ENV":"production","BASE_URL":"/"}).POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
|
|
30769
|
-
var Operation = /*#__PURE__*/function () {
|
|
30770
|
-
function Operation() {
|
|
30771
|
-
_classCallCheck(this, Operation);
|
|
30772
|
-
}
|
|
30773
|
-
_createClass(Operation, [{
|
|
30774
|
-
key: "run",
|
|
30775
|
-
value: function run(type, geom, moreGeoms) {
|
|
30776
|
-
operation.type = type;
|
|
30777
|
-
rounder.reset();
|
|
30778
|
-
/* Convert inputs to MultiPoly objects */
|
|
30779
|
-
|
|
30780
|
-
var multipolys = [new MultiPolyIn(geom, true)];
|
|
30781
|
-
for (var i = 0, iMax = moreGeoms.length; i < iMax; i++) {
|
|
30782
|
-
multipolys.push(new MultiPolyIn(moreGeoms[i], false));
|
|
30783
|
-
}
|
|
30784
|
-
operation.numMultiPolys = multipolys.length;
|
|
30785
|
-
/* BBox optimization for difference operation
|
|
30786
|
-
* If the bbox of a multipolygon that's part of the clipping doesn't
|
|
30787
|
-
* intersect the bbox of the subject at all, we can just drop that
|
|
30788
|
-
* multiploygon. */
|
|
30789
|
-
|
|
30790
|
-
if (operation.type === 'difference') {
|
|
30791
|
-
// in place removal
|
|
30792
|
-
var subject = multipolys[0];
|
|
30793
|
-
var _i = 1;
|
|
30794
|
-
while (_i < multipolys.length) {
|
|
30795
|
-
if (getBboxOverlap(multipolys[_i].bbox, subject.bbox) !== null) _i++;else multipolys.splice(_i, 1);
|
|
30956
|
+
|
|
30957
|
+
// For simplicity, even if we find more than one intersection we only
|
|
30958
|
+
// spilt on the 'earliest' (sweep-line style) of the intersections.
|
|
30959
|
+
// The other intersection will be handled in a future process().
|
|
30960
|
+
if (prevMySplitter !== null || nextMySplitter !== null) {
|
|
30961
|
+
let mySplitter = null;
|
|
30962
|
+
if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
|
|
30963
|
+
const cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
|
|
30964
|
+
mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
|
|
30965
|
+
}
|
|
30966
|
+
|
|
30967
|
+
// Rounding errors can cause changes in ordering,
|
|
30968
|
+
// so remove afected segments and right sweep events before splitting
|
|
30969
|
+
this.queue.remove(segment.rightSE);
|
|
30970
|
+
newEvents.push(segment.rightSE);
|
|
30971
|
+
const newEventsFromSplit = segment.split(mySplitter);
|
|
30972
|
+
for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
|
|
30973
|
+
newEvents.push(newEventsFromSplit[i]);
|
|
30796
30974
|
}
|
|
30797
30975
|
}
|
|
30798
|
-
|
|
30799
|
-
|
|
30800
|
-
|
|
30801
|
-
|
|
30802
|
-
|
|
30803
|
-
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
|
|
30808
|
-
|
|
30976
|
+
if (newEvents.length > 0) {
|
|
30977
|
+
// We found some intersections, so re-do the current event to
|
|
30978
|
+
// make sure sweep line ordering is totally consistent for later
|
|
30979
|
+
// use with the segment 'prev' pointers
|
|
30980
|
+
this.tree.remove(segment);
|
|
30981
|
+
newEvents.push(event);
|
|
30982
|
+
} else {
|
|
30983
|
+
// done with left event
|
|
30984
|
+
this.segments.push(segment);
|
|
30985
|
+
segment.prev = prevSeg;
|
|
30986
|
+
}
|
|
30987
|
+
} else {
|
|
30988
|
+
// event.isRight
|
|
30989
|
+
|
|
30990
|
+
// since we're about to be removed from the sweep line, check for
|
|
30991
|
+
// intersections between our previous and next segments
|
|
30992
|
+
if (prevSeg && nextSeg) {
|
|
30993
|
+
const inter = prevSeg.getIntersection(nextSeg);
|
|
30994
|
+
if (inter !== null) {
|
|
30995
|
+
if (!prevSeg.isAnEndpoint(inter)) {
|
|
30996
|
+
const newEventsFromSplit = this._splitSafely(prevSeg, inter);
|
|
30997
|
+
for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
|
|
30998
|
+
newEvents.push(newEventsFromSplit[i]);
|
|
30999
|
+
}
|
|
31000
|
+
}
|
|
31001
|
+
if (!nextSeg.isAnEndpoint(inter)) {
|
|
31002
|
+
const newEventsFromSplit = this._splitSafely(nextSeg, inter);
|
|
31003
|
+
for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
|
|
31004
|
+
newEvents.push(newEventsFromSplit[i]);
|
|
31005
|
+
}
|
|
30809
31006
|
}
|
|
30810
31007
|
}
|
|
30811
31008
|
}
|
|
30812
|
-
|
|
30813
|
-
|
|
30814
|
-
|
|
30815
|
-
|
|
30816
|
-
|
|
30817
|
-
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
|
|
30821
|
-
|
|
30822
|
-
|
|
31009
|
+
this.tree.remove(segment);
|
|
31010
|
+
}
|
|
31011
|
+
return newEvents;
|
|
31012
|
+
}
|
|
31013
|
+
|
|
31014
|
+
/* Safely split a segment that is currently in the datastructures
|
|
31015
|
+
* IE - a segment other than the one that is currently being processed. */
|
|
31016
|
+
_splitSafely(seg, pt) {
|
|
31017
|
+
// Rounding errors can cause changes in ordering,
|
|
31018
|
+
// so remove afected segments and right sweep events before splitting
|
|
31019
|
+
// removeNode() doesn't work, so have re-find the seg
|
|
31020
|
+
// https://github.com/w8r/splay-tree/pull/5
|
|
31021
|
+
this.tree.remove(seg);
|
|
31022
|
+
const rightSE = seg.rightSE;
|
|
31023
|
+
this.queue.remove(rightSE);
|
|
31024
|
+
const newEvents = seg.split(pt);
|
|
31025
|
+
newEvents.push(rightSE);
|
|
31026
|
+
// splitting can trigger consumption
|
|
31027
|
+
if (seg.consumedBy === undefined) this.tree.add(seg);
|
|
31028
|
+
return newEvents;
|
|
31029
|
+
}
|
|
31030
|
+
}
|
|
31031
|
+
|
|
31032
|
+
// Limits on iterative processes to prevent infinite loops - usually caused by floating-point math round-off errors.
|
|
31033
|
+
const POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== "undefined" && ({"NODE_ENV":"production","BASE_URL":"/"}).POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
|
|
31034
|
+
const POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== "undefined" && ({"NODE_ENV":"production","BASE_URL":"/"}).POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
|
|
31035
|
+
class Operation {
|
|
31036
|
+
run(type, geom, moreGeoms) {
|
|
31037
|
+
operation.type = type;
|
|
31038
|
+
rounder.reset();
|
|
31039
|
+
|
|
31040
|
+
/* Convert inputs to MultiPoly objects */
|
|
31041
|
+
const multipolys = [new MultiPolyIn(geom, true)];
|
|
31042
|
+
for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {
|
|
31043
|
+
multipolys.push(new MultiPolyIn(moreGeoms[i], false));
|
|
31044
|
+
}
|
|
31045
|
+
operation.numMultiPolys = multipolys.length;
|
|
31046
|
+
|
|
31047
|
+
/* BBox optimization for difference operation
|
|
31048
|
+
* If the bbox of a multipolygon that's part of the clipping doesn't
|
|
31049
|
+
* intersect the bbox of the subject at all, we can just drop that
|
|
31050
|
+
* multiploygon. */
|
|
31051
|
+
if (operation.type === "difference") {
|
|
31052
|
+
// in place removal
|
|
31053
|
+
const subject = multipolys[0];
|
|
31054
|
+
let i = 1;
|
|
31055
|
+
while (i < multipolys.length) {
|
|
31056
|
+
if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null) i++;else multipolys.splice(i, 1);
|
|
31057
|
+
}
|
|
31058
|
+
}
|
|
31059
|
+
|
|
31060
|
+
/* BBox optimization for intersection operation
|
|
31061
|
+
* If we can find any pair of multipolygons whose bbox does not overlap,
|
|
31062
|
+
* then the result will be empty. */
|
|
31063
|
+
if (operation.type === "intersection") {
|
|
31064
|
+
// TODO: this is O(n^2) in number of polygons. By sorting the bboxes,
|
|
31065
|
+
// it could be optimized to O(n * ln(n))
|
|
31066
|
+
for (let i = 0, iMax = multipolys.length; i < iMax; i++) {
|
|
31067
|
+
const mpA = multipolys[i];
|
|
31068
|
+
for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {
|
|
31069
|
+
if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
|
|
30823
31070
|
}
|
|
30824
31071
|
}
|
|
30825
|
-
|
|
31072
|
+
}
|
|
30826
31073
|
|
|
30827
|
-
|
|
30828
|
-
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
30832
|
-
|
|
30833
|
-
// prevents an infinite loop, an otherwise common manifestation of bugs
|
|
30834
|
-
var seg = evt.segment;
|
|
30835
|
-
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.');
|
|
30836
|
-
}
|
|
31074
|
+
/* Put segment endpoints in a priority queue */
|
|
31075
|
+
const queue = new Tree(SweepEvent.compare);
|
|
31076
|
+
for (let i = 0, iMax = multipolys.length; i < iMax; i++) {
|
|
31077
|
+
const sweepEvents = multipolys[i].getSweepEvents();
|
|
31078
|
+
for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {
|
|
31079
|
+
queue.insert(sweepEvents[j]);
|
|
30837
31080
|
if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
|
|
30838
31081
|
// prevents an infinite loop, an otherwise common manifestation of bugs
|
|
30839
|
-
throw new Error(
|
|
30840
|
-
}
|
|
30841
|
-
if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
|
|
30842
|
-
// prevents an infinite loop, an otherwise common manifestation of bugs
|
|
30843
|
-
throw new Error('Infinite loop when passing sweep line over endpoints ' + '(too many sweep line segments). Please file a bug report.');
|
|
31082
|
+
throw new Error("Infinite loop when putting segment endpoints in a priority queue " + "(queue size too big).");
|
|
30844
31083
|
}
|
|
30845
|
-
|
|
30846
|
-
|
|
30847
|
-
var _evt = newEvents[_i4];
|
|
30848
|
-
if (_evt.consumedBy === undefined) queue.insert(_evt);
|
|
30849
|
-
}
|
|
30850
|
-
prevQueueSize = queue.size;
|
|
30851
|
-
node = queue.pop();
|
|
30852
|
-
} // free some memory we don't need anymore
|
|
30853
|
-
|
|
30854
|
-
rounder.reset();
|
|
30855
|
-
/* Collect and compile segments we're keeping into a multipolygon */
|
|
31084
|
+
}
|
|
31085
|
+
}
|
|
30856
31086
|
|
|
30857
|
-
|
|
30858
|
-
|
|
30859
|
-
|
|
31087
|
+
/* Pass the sweep line over those endpoints */
|
|
31088
|
+
const sweepLine = new SweepLine(queue);
|
|
31089
|
+
let prevQueueSize = queue.size;
|
|
31090
|
+
let node = queue.pop();
|
|
31091
|
+
while (node) {
|
|
31092
|
+
const evt = node.key;
|
|
31093
|
+
if (queue.size === prevQueueSize) {
|
|
31094
|
+
// prevents an infinite loop, an otherwise common manifestation of bugs
|
|
31095
|
+
const seg = evt.segment;
|
|
31096
|
+
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.`);
|
|
31097
|
+
}
|
|
31098
|
+
if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
|
|
31099
|
+
// prevents an infinite loop, an otherwise common manifestation of bugs
|
|
31100
|
+
throw new Error("Infinite loop when passing sweep line over endpoints " + "(queue size too big).");
|
|
31101
|
+
}
|
|
31102
|
+
if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
|
|
31103
|
+
// prevents an infinite loop, an otherwise common manifestation of bugs
|
|
31104
|
+
throw new Error("Infinite loop when passing sweep line over endpoints " + "(too many sweep line segments).");
|
|
31105
|
+
}
|
|
31106
|
+
const newEvents = sweepLine.process(evt);
|
|
31107
|
+
for (let i = 0, iMax = newEvents.length; i < iMax; i++) {
|
|
31108
|
+
const evt = newEvents[i];
|
|
31109
|
+
if (evt.consumedBy === undefined) queue.insert(evt);
|
|
31110
|
+
}
|
|
31111
|
+
prevQueueSize = queue.size;
|
|
31112
|
+
node = queue.pop();
|
|
30860
31113
|
}
|
|
30861
|
-
}]);
|
|
30862
|
-
return Operation;
|
|
30863
|
-
}(); // singleton available by import
|
|
30864
31114
|
|
|
30865
|
-
|
|
30866
|
-
|
|
31115
|
+
// free some memory we don't need anymore
|
|
31116
|
+
rounder.reset();
|
|
31117
|
+
|
|
31118
|
+
/* Collect and compile segments we're keeping into a multipolygon */
|
|
31119
|
+
const ringsOut = RingOut.factory(sweepLine.segments);
|
|
31120
|
+
const result = new MultiPolyOut(ringsOut);
|
|
31121
|
+
return result.getGeom();
|
|
31122
|
+
}
|
|
31123
|
+
}
|
|
31124
|
+
|
|
31125
|
+
// singleton available by import
|
|
31126
|
+
const operation = new Operation();
|
|
31127
|
+
const union = function (geom) {
|
|
30867
31128
|
for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
30868
31129
|
moreGeoms[_key - 1] = arguments[_key];
|
|
30869
31130
|
}
|
|
30870
|
-
return operation.run(
|
|
31131
|
+
return operation.run("union", geom, moreGeoms);
|
|
30871
31132
|
};
|
|
30872
|
-
|
|
31133
|
+
const intersection = function (geom) {
|
|
30873
31134
|
for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
30874
31135
|
moreGeoms[_key2 - 1] = arguments[_key2];
|
|
30875
31136
|
}
|
|
30876
|
-
return operation.run(
|
|
31137
|
+
return operation.run("intersection", geom, moreGeoms);
|
|
30877
31138
|
};
|
|
30878
|
-
|
|
31139
|
+
const xor = function (geom) {
|
|
30879
31140
|
for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
|
30880
31141
|
moreGeoms[_key3 - 1] = arguments[_key3];
|
|
30881
31142
|
}
|
|
30882
|
-
return operation.run(
|
|
31143
|
+
return operation.run("xor", geom, moreGeoms);
|
|
30883
31144
|
};
|
|
30884
|
-
|
|
31145
|
+
const difference = function (subjectGeom) {
|
|
30885
31146
|
for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
|
|
30886
31147
|
clippingGeoms[_key4 - 1] = arguments[_key4];
|
|
30887
31148
|
}
|
|
30888
|
-
return operation.run(
|
|
31149
|
+
return operation.run("difference", subjectGeom, clippingGeoms);
|
|
30889
31150
|
};
|
|
30890
31151
|
var index = {
|
|
30891
31152
|
union: union,
|
|
30892
|
-
intersection: intersection
|
|
31153
|
+
intersection: intersection,
|
|
30893
31154
|
xor: xor,
|
|
30894
31155
|
difference: difference
|
|
30895
31156
|
};
|
|
@@ -43515,19 +43776,19 @@ var update = add("33a2ac54", content, true, {"sourceMap":false,"shadowMode":fals
|
|
|
43515
43776
|
|
|
43516
43777
|
/***/ }),
|
|
43517
43778
|
|
|
43518
|
-
/***/
|
|
43779
|
+
/***/ 8082:
|
|
43519
43780
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
43520
43781
|
|
|
43521
43782
|
// style-loader: Adds some css to the DOM by adding a <style> tag
|
|
43522
43783
|
|
|
43523
43784
|
// load the styles
|
|
43524
|
-
var content = __webpack_require__(
|
|
43785
|
+
var content = __webpack_require__(313);
|
|
43525
43786
|
if(content.__esModule) content = content.default;
|
|
43526
43787
|
if(typeof content === 'string') content = [[module.id, content, '']];
|
|
43527
43788
|
if(content.locals) module.exports = content.locals;
|
|
43528
43789
|
// add the styles to the DOM
|
|
43529
43790
|
var add = (__webpack_require__(208)/* ["default"] */ .Z)
|
|
43530
|
-
var update = add("
|
|
43791
|
+
var update = add("4c9211ec", content, true, {"sourceMap":false,"shadowMode":false});
|
|
43531
43792
|
|
|
43532
43793
|
/***/ }),
|
|
43533
43794
|
|
|
@@ -121206,15 +121467,15 @@ var mapStyle_component = normalizeComponent(
|
|
|
121206
121467
|
)
|
|
121207
121468
|
|
|
121208
121469
|
/* harmony default export */ var mapStyle = (mapStyle_component.exports);
|
|
121209
|
-
;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-82.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/package/draw/index.vue?vue&type=template&id=
|
|
121210
|
-
var
|
|
121470
|
+
;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-82.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/package/draw/index.vue?vue&type=template&id=45cab0e4&scoped=true&
|
|
121471
|
+
var drawvue_type_template_id_45cab0e4_scoped_true_render = function render() {
|
|
121211
121472
|
var _vm = this,
|
|
121212
121473
|
_c = _vm._self._c;
|
|
121213
121474
|
return _c('div', [_c('div', {
|
|
121214
121475
|
staticClass: "tools"
|
|
121215
121476
|
}, [_c('div', {
|
|
121216
121477
|
staticClass: "tools-bar flex flex-align-center"
|
|
121217
|
-
}, [_c('div', {
|
|
121478
|
+
}, [_vm._t("top-left-tools"), _c('div', {
|
|
121218
121479
|
class: {
|
|
121219
121480
|
'main-color': _vm.type === 'move'
|
|
121220
121481
|
},
|
|
@@ -121288,7 +121549,7 @@ var drawvue_type_template_id_782e8856_scoped_true_render = function render() {
|
|
|
121288
121549
|
}
|
|
121289
121550
|
}, [_c('i', {
|
|
121290
121551
|
staticClass: "el-icon-delete mr-5"
|
|
121291
|
-
}), _vm._v("清空")]) : _vm._e(), _vm.showFullBtn ? _c('map-full-screen', {
|
|
121552
|
+
}), _vm._v("清空")]) : _vm._e(), _vm._t("top-right-tools"), _vm.showFullBtn ? _c('map-full-screen', {
|
|
121292
121553
|
staticClass: "ml-20",
|
|
121293
121554
|
attrs: {
|
|
121294
121555
|
"dom": _vm.fullDom
|
|
@@ -121373,7 +121634,7 @@ var drawvue_type_template_id_782e8856_scoped_true_render = function render() {
|
|
|
121373
121634
|
style: _vm.tooltip.style
|
|
121374
121635
|
}, [_vm._v(_vm._s(_vm.tooltip.text))]) : _vm._e()]);
|
|
121375
121636
|
};
|
|
121376
|
-
var
|
|
121637
|
+
var drawvue_type_template_id_45cab0e4_scoped_true_staticRenderFns = [];
|
|
121377
121638
|
|
|
121378
121639
|
// EXTERNAL MODULE: ./node_modules/@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css
|
|
121379
121640
|
var dist_mapbox_gl_draw = __webpack_require__(5620);
|
|
@@ -122229,50 +122490,26 @@ var shpFile_component = normalizeComponent(
|
|
|
122229
122490
|
lines = polygonFeature.geometry.coordinates.map(coords => es_polygon(coords));
|
|
122230
122491
|
}
|
|
122231
122492
|
const splitter = lineString(splitLine.geometry.coordinates);
|
|
122232
|
-
let splitResults = [];
|
|
122233
|
-
let noSplitResults = []; //未拆分线段
|
|
122234
|
-
let isSucess = false; // 是否有效分割
|
|
122235
|
-
console.log('拆分线', lines);
|
|
122493
|
+
let splitResults = [];
|
|
122236
122494
|
// 对每条线进行分割
|
|
122237
122495
|
lines.forEach(line => {
|
|
122238
122496
|
const split = line_split_dist_es(line, splitter);
|
|
122239
|
-
if (split.features.length == 0)
|
|
122240
|
-
|
|
122241
|
-
noSplitResults.push(line);
|
|
122242
|
-
} else {
|
|
122243
|
-
splitResults = splitResults.concat(split.features);
|
|
122244
|
-
isSucess = true;
|
|
122245
|
-
}
|
|
122497
|
+
if (split.features.length == 0) splitResults.push(line); //当线段无法拆分时,返回本身对象
|
|
122498
|
+
else splitResults = splitResults.concat(split.features);
|
|
122246
122499
|
});
|
|
122247
|
-
console.log('拆分线结果', splitResults, noSplitResults);
|
|
122248
122500
|
|
|
122249
|
-
//
|
|
122250
|
-
|
|
122501
|
+
// 转换为 Mapbox Draw 格式
|
|
122502
|
+
const newLines = splitResults.map((feature, index) => ({
|
|
122251
122503
|
type: 'Feature',
|
|
122252
122504
|
id: `${oldFeature.id}_${index}`,
|
|
122253
122505
|
geometry: feature.geometry,
|
|
122254
122506
|
properties: Object.assign({}, oldFeature.properties)
|
|
122255
122507
|
}));
|
|
122256
122508
|
|
|
122257
|
-
//未被成功拆分的线段 多线、多面应该自动合并回多线面模式
|
|
122258
|
-
if (noSplitResults.length > 0) {
|
|
122259
|
-
newLines.push({
|
|
122260
|
-
type: 'Feature',
|
|
122261
|
-
id: `${oldFeature.id}_${newLines.length}`,
|
|
122262
|
-
geometry: {
|
|
122263
|
-
coordinates: noSplitResults.length === 1 ? noSplitResults[0].geometry.coordinates : noSplitResults.map(item => item.geometry.coordinates),
|
|
122264
|
-
type: oldFeature.geometry.type
|
|
122265
|
-
},
|
|
122266
|
-
properties: Object.assign({}, oldFeature.properties)
|
|
122267
|
-
});
|
|
122268
|
-
}
|
|
122269
|
-
console.log('拆分线结果', newLines);
|
|
122270
|
-
|
|
122271
122509
|
// 删除拆分线
|
|
122272
122510
|
this.draw.delete(splitLine.id);
|
|
122273
|
-
if (
|
|
122274
|
-
this.$
|
|
122275
|
-
this.$message.warning('拆分失败,拆分线之间无交集!');
|
|
122511
|
+
if (newLines.length == 1) {
|
|
122512
|
+
this.$message.error('拆分失败,拆分线之间无交集!');
|
|
122276
122513
|
return;
|
|
122277
122514
|
}
|
|
122278
122515
|
|
|
@@ -122378,9 +122615,9 @@ var shpFile_component = normalizeComponent(
|
|
|
122378
122615
|
});
|
|
122379
122616
|
;// CONCATENATED MODULE: ./src/package/draw/index.vue?vue&type=script&lang=js&
|
|
122380
122617
|
/* harmony default export */ var package_drawvue_type_script_lang_js_ = (drawvue_type_script_lang_js_);
|
|
122381
|
-
// EXTERNAL MODULE: ./node_modules/vue-style-loader/index.js??clonedRuleSet-64.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-64.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-64.use[2]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-64.use[3]!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-64.use[4]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/package/draw/index.vue?vue&type=style&index=0&id=
|
|
122382
|
-
var
|
|
122383
|
-
;// CONCATENATED MODULE: ./src/package/draw/index.vue?vue&type=style&index=0&id=
|
|
122618
|
+
// EXTERNAL MODULE: ./node_modules/vue-style-loader/index.js??clonedRuleSet-64.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-64.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-64.use[2]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-64.use[3]!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-64.use[4]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/package/draw/index.vue?vue&type=style&index=0&id=45cab0e4&prod&lang=scss&scoped=true&
|
|
122619
|
+
var drawvue_type_style_index_0_id_45cab0e4_prod_lang_scss_scoped_true_ = __webpack_require__(8082);
|
|
122620
|
+
;// CONCATENATED MODULE: ./src/package/draw/index.vue?vue&type=style&index=0&id=45cab0e4&prod&lang=scss&scoped=true&
|
|
122384
122621
|
|
|
122385
122622
|
;// CONCATENATED MODULE: ./src/package/draw/index.vue
|
|
122386
122623
|
|
|
@@ -122393,11 +122630,11 @@ var drawvue_type_style_index_0_id_782e8856_prod_lang_scss_scoped_true_ = __webpa
|
|
|
122393
122630
|
|
|
122394
122631
|
var draw_component = normalizeComponent(
|
|
122395
122632
|
package_drawvue_type_script_lang_js_,
|
|
122396
|
-
|
|
122397
|
-
|
|
122633
|
+
drawvue_type_template_id_45cab0e4_scoped_true_render,
|
|
122634
|
+
drawvue_type_template_id_45cab0e4_scoped_true_staticRenderFns,
|
|
122398
122635
|
false,
|
|
122399
122636
|
null,
|
|
122400
|
-
"
|
|
122637
|
+
"45cab0e4",
|
|
122401
122638
|
null
|
|
122402
122639
|
|
|
122403
122640
|
)
|