leaflet-paintpolygon
Version:
Leaflet plugin to create polygon with circle, for touchscreen
37 lines • 137 kB
JavaScript
!function(n){var e={};function t(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return n[i].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var r in n)t.d(i,r,function(e){return n[e]}.bind(null,r));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=8)}([function(module,exports,__webpack_require__){var factory;"undefined"!=typeof self&&self,factory=function(){return function(n){var e={};function t(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return n[i].call(r.exports,r,r.exports,t),r.l=!0,r.exports}return t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var r in n)t.d(i,r,function(e){return n[e]}.bind(null,r));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s="./main.js")}({"./main.js":
/*!*****************!*\
!*** ./main.js ***!
\*****************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval('\n\nObject.defineProperty(exports, "__esModule", {\n value: true\n});\nexports.difference = exports.xor = exports.intersection = exports.union = undefined;\n\nvar _src = __webpack_require__(/*! ./src */ "./src/index.js");\n\nvar _src2 = _interopRequireDefault(_src);\n\nvar _operation = __webpack_require__(/*! ./src/operation */ "./src/operation.js");\n\nvar _operation2 = _interopRequireDefault(_operation);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar union = exports.union = function union(geom) {\n for (var _len = arguments.length, moreGeoms = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n moreGeoms[_key - 1] = arguments[_key];\n }\n\n return (0, _src2.default)(_operation2.default.types.UNION, geom, moreGeoms);\n};\n\nvar intersection = exports.intersection = function intersection(geom) {\n for (var _len2 = arguments.length, moreGeoms = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n moreGeoms[_key2 - 1] = arguments[_key2];\n }\n\n return (0, _src2.default)(_operation2.default.types.INTERSECTION, geom, moreGeoms);\n};\n\nvar xor = exports.xor = function xor(geom) {\n for (var _len3 = arguments.length, moreGeoms = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n moreGeoms[_key3 - 1] = arguments[_key3];\n }\n\n return (0, _src2.default)(_operation2.default.types.XOR, geom, moreGeoms);\n};\n\nvar difference = exports.difference = function difference(subjectGeom) {\n for (var _len4 = arguments.length, clippingGeoms = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n clippingGeoms[_key4 - 1] = arguments[_key4];\n }\n\n return (0, _src2.default)(_operation2.default.types.DIFFERENCE, subjectGeom, clippingGeoms);\n};\n\n//# sourceURL=webpack://polygon-clipping/./main.js?')},"./node_modules/qheap/index.js":
/*!*************************************!*\
!*** ./node_modules/qheap/index.js ***!
\*************************************/
/*! no static exports found */function(module,exports,__webpack_require__){eval('module.exports = __webpack_require__(/*! ./lib/qheap.js */ "./node_modules/qheap/lib/qheap.js");\n\n\n//# sourceURL=webpack://polygon-clipping/./node_modules/qheap/index.js?')},"./node_modules/qheap/lib/qheap.js":
/*!*****************************************!*\
!*** ./node_modules/qheap/lib/qheap.js ***!
\*****************************************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval("/**\n * nodejs heap, classic array implementation\n *\n * Items are stored in a balanced binary tree packed into an array where\n * node is at [i], left child is at [2*i], right at [2*i+1]. Root is at [1].\n *\n * Copyright (C) 2014-2017 Andras Radics\n * Licensed under the Apache License, Version 2.0\n */\n\n\n\nmodule.exports = Heap;\n\nfunction isBeforeDefault( a, b ) { return a < b; }\n\nfunction Heap( opts ) {\n opts = opts || {};\n if (typeof opts === 'function') opts = {compar: opts};\n\n if (opts.compar) {\n this._isBefore = function(a, b) { return opts.compar(a,b) < 0 };\n } else if (opts.comparBefore) {\n this._isBefore = opts.comparBefore;\n } else {\n this._isBefore = isBeforeDefault;\n }\n this.length = 0;\n this._freeSpace = opts.freeSpace ? this._trimArraySize : false;\n this._list = new Array(opts.size || 100);\n}\n\nHeap.prototype._list = null;\nHeap.prototype._compar = null;\nHeap.prototype._isBefore = null;\nHeap.prototype._freeSpace = null;\nHeap.prototype.length = 0;\n\n/*\n * insert new item at end, and bubble up\n */\nHeap.prototype.insert = function Heap_insert( item ) {\n var idx = ++this.length;\n var list = this._list;\n list[idx] = item;\n\n while (idx > 1) {\n var parentidx = idx >> 1;\n var parentval = list[parentidx];\n if (!(this._isBefore(item, parentval))) break;\n list[idx] = parentval;\n idx = parentidx;\n }\n list[idx] = item;\n};\nHeap.prototype.append = Heap.prototype.insert;\nHeap.prototype.push = Heap.prototype.insert;\nHeap.prototype.unshift = Heap.prototype.insert;\nHeap.prototype.enqueue = Heap.prototype.insert;\n\nHeap.prototype.peek = function Heap_peek( ) {\n return this.length > 0 ? this._list[1] : undefined;\n};\n\nHeap.prototype.size = function Heap_size( ) {\n return this.length;\n};\n\n/*\n * return the root, and bubble down last item from top root position\n * when bubbling down, r: root idx, c: child sub-tree root idx, cv: child root value\n * Note that the child at (c == this.length) does not have to be tested in the loop,\n * since its value is the one being bubbled down, so can loop `while (c < len)`.\n *\n * Note that a redundant (c < len &&) test before the c vs c+1 compar lets node v0.10\n * run 4x faster; v4, v5 and v6 run faster without it if using _isBefore and not\n * raw _compar.\n *\n * Note that this version runs faster than the two-pass pull-up-new-root then\n * bubble-up-last-value-from-hole approach (except when inserting pre-sorted data).\n */\nHeap.prototype.remove = function Heap_remove( ) {\n if (this.length < 1) return undefined;\n var ret = this._list[1];\n var itm = this._list[this.length];\n\n var r = 1, c = 2, cv;\n var len = this.length;\n while (c < len) {\n cv = this._list[c];\n if (this._isBefore(this._list[c+1], cv)) { cv = this._list[c+1] ; c = c+1 }\n if (!(this._isBefore(cv, itm))) break;\n this._list[r] = cv;\n r = c;\n c = c << 1;\n }\n this._list[len] = 0;\n this.length = --len;\n if (len) this._list[r] = itm;\n if (this._freeSpace) this._freeSpace(this._list, len);\n\n return ret;\n};\nHeap.prototype.shift = Heap.prototype.remove;\nHeap.prototype.pop = Heap.prototype.remove;\nHeap.prototype.dequeue = Heap.prototype.remove;\n\n/*\n * Free unused storage slots in the _list.\n * The default is to unconditionally gc, use the options to omit when not useful.\n */\nHeap.prototype.gc = function Heap_gc( options ) {\n if (!options) options = {};\n\n var minListLength = options.minLength; // smallest list that will be gc-d\n if (minListLength === undefined) minListLength = 0;\n\n var minListFull = options.minFull; // list utilization below which to gc\n if (minListFull === undefined) minListFull = 1.00;\n\n if (this._list.length >= minListLength && (this.length < this._list.length * minListFull)) {\n // gc reallocates the array to free the unused storage slots at the end\n // use splice to actually free memory; 7% slower than setting .length\n // note: list.slice makes the array slower to insert to?? splice is better\n this._list.splice(this.length+1, this._list.length);\n }\n}\n\nHeap.prototype._trimArraySize = function Heap__trimArraySize( list, len ) {\n if (len > 10000 && list.length > 4 * len) {\n // use slice to actually free memory; 7% slower than setting .length\n // note: list.slice makes the array slower to insert to?? splice is better\n list.splice(len+1, list.length);\n }\n}\n\nHeap.prototype._check = function Heap__check( ) {\n var isBefore = this._isBefore;\n var _compar = function(a, b) { return isBefore(a, b) ? -1 : 1 };\n\n var i, p, fail = 0;\n for (i=this.length; i>1; i--) {\n // error if parent should go after child, but not if don`t care\n p = i >>> 1;\n // swapping the values must change their ordering, otherwise the\n // comparison is a tie. (Ie, consider the ordering func (a <= b)\n // that for some values reports both that a < b and b < a.)\n if (_compar(this._list[p], this._list[i]) > 0 &&\n _compar(this._list[i], this._list[p]) < 0)\n {\n fail = i;\n }\n }\n if (fail) console.log(\"failed at\", (fail >>> 1), fail);\n return !fail;\n}\n\n// optimize access\nHeap.prototype = Heap.prototype;\n\n\n//# sourceURL=webpack://polygon-clipping/./node_modules/qheap/lib/qheap.js?")},"./node_modules/splaytree/index.js":
/*!*****************************************!*\
!*** ./node_modules/splaytree/index.js ***!
\*****************************************/
/*! exports provided: default */function(module,__webpack_exports__,__webpack_require__){"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Tree; });\n/* follows \"An implementation of top-down splaying\"\n * by D. Sleator <sleator@cs.cmu.edu> March 1992\n */\n\n/**\n * @typedef {*} Key\n */\n\n\n/**\n * @typedef {*} Value\n */\n\n\n/**\n * @typedef {function(node:Node):void} Visitor\n */\n\n\n/**\n * @typedef {function(a:Key, b:Key):number} Comparator\n */\n\n\n/**\n * @param {function(node:Node):string} NodePrinter\n */\n\n\n/**\n * @typedef {Object} Node\n * @property {Key} Key\n * @property {Value=} data\n * @property {Node} left\n * @property {Node} right\n */\n\nclass Node {\n\n constructor (key, data) {\n this.key = key;\n this.data = data;\n this.left = null;\n this.right = null;\n }\n}\n\nfunction DEFAULT_COMPARE (a, b) { return a > b ? 1 : a < b ? -1 : 0; }\n\n\n/**\n * Simple top down splay, not requiring i to be in the tree t.\n * @param {Key} i\n * @param {Node?} t\n * @param {Comparator} comparator\n */\nfunction splay (i, t, comparator) {\n if (t === null) return t;\n let l, r, y;\n const N = new Node();\n l = r = N;\n\n while (true) {\n const cmp = comparator(i, t.key);\n //if (i < t.key) {\n if (cmp < 0) {\n if (t.left === null) break;\n //if (i < t.left.key) {\n if (comparator(i, t.left.key) < 0) {\n y = t.left; /* rotate right */\n t.left = y.right;\n y.right = t;\n t = y;\n if (t.left === null) break;\n }\n r.left = t; /* link right */\n r = t;\n t = t.left;\n //} else if (i > t.key) {\n } else if (cmp > 0) {\n if (t.right === null) break;\n //if (i > t.right.key) {\n if (comparator(i, t.right.key) > 0) {\n y = t.right; /* rotate left */\n t.right = y.left;\n y.left = t;\n t = y;\n if (t.right === null) break;\n }\n l.right = t; /* link left */\n l = t;\n t = t.right;\n } else {\n break;\n }\n }\n /* assemble */\n l.right = t.left;\n r.left = t.right;\n t.left = N.right;\n t.right = N.left;\n return t;\n}\n\n\n/**\n * @param {Key} i\n * @param {Value} data\n * @param {Comparator} comparator\n * @param {Tree} tree\n * @return {Node} root\n */\nfunction insert (i, data, t, comparator, tree) {\n const node = new Node(i, data);\n\n tree._size++;\n\n if (t === null) {\n node.left = node.right = null;\n return node;\n }\n\n t = splay(i, t, comparator);\n const cmp = comparator(i, t.key);\n if (cmp < 0) {\n node.left = t.left;\n node.right = t;\n t.left = null;\n } else if (cmp >= 0) {\n node.right = t.right;\n node.left = t;\n t.right = null;\n }\n return node;\n}\n\n\n/**\n * Insert i into the tree t, unless it's already there.\n * @param {Key} i\n * @param {Value} data\n * @param {Comparator} comparator\n * @param {Tree} tree\n * @return {Node} root\n */\nfunction add (i, data, t, comparator, tree) {\n const node = new Node(i, data);\n\n if (t === null) {\n node.left = node.right = null;\n tree._size++;\n return node;\n }\n\n t = splay(i, t, comparator);\n const cmp = comparator(i, t.key);\n if (cmp === 0) return t;\n else {\n if (cmp < 0) {\n node.left = t.left;\n node.right = t;\n t.left = null;\n } else if (cmp > 0) {\n node.right = t.right;\n node.left = t;\n t.right = null;\n }\n tree._size++;\n return node;\n }\n}\n\n\n/**\n * Deletes i from the tree if it's there\n * @param {Key} i\n * @param {Tree} tree\n * @param {Comparator} comparator\n * @param {Tree} tree\n * @return {Node} new root\n */\nfunction remove (i, t, comparator, tree) {\n let x;\n if (t === null) return null;\n t = splay(i, t, comparator);\n if (i === t.key) { /* found it */\n if (t.left === null) {\n x = t.right;\n } else {\n x = splay(i, t.left, comparator);\n x.right = t.right;\n }\n tree._size--;\n return x;\n }\n return t; /* It wasn't there */\n}\n\n\nfunction split (key, v, comparator) {\n let left, right;\n if (v === null) {\n left = right = null;\n } else {\n v = splay(key, v, comparator);\n\n const cmp = comparator(v.key, key);\n if (cmp === 0) {\n left = v.left;\n right = v.right;\n } else if (cmp < 0) {\n right = v.right;\n v.right = null;\n left = v;\n } else {\n left = v.left;\n v.left = null;\n right = v;\n }\n }\n return { left, right };\n}\n\n\nfunction merge (left, right, comparator) {\n if (right === null) return left;\n if (left === null) return right;\n\n right = splay(left.key, right, comparator);\n right.left = left;\n return right;\n}\n\n\n/**\n * Prints level of the tree\n * @param {Node} root\n * @param {String} prefix\n * @param {Boolean} isTail\n * @param {Array<string>} out\n * @param {Function(node:Node):String} printNode\n */\nfunction printRow (root, prefix, isTail, out, printNode) {\n if (root) {\n out(`${ prefix }${ isTail ? '└── ' : '├── ' }${ printNode(root) }\\n`);\n const indent = prefix + (isTail ? ' ' : '│ ');\n if (root.left) printRow(root.left, indent, false, out, printNode);\n if (root.right) printRow(root.right, indent, true, out, printNode);\n }\n}\n\n\nclass Tree {\n\n constructor (comparator = DEFAULT_COMPARE) {\n this._comparator = comparator;\n this._root = null;\n this._size = 0;\n }\n\n\n /**\n * Inserts a key, allows duplicates\n * @param {Key} key\n * @param {Value=} data\n * @return {Node|null}\n */\n insert (key, data) {\n return this._root = insert(key, data, this._root, this._comparator, this);\n }\n\n\n /**\n * Adds a key, if it is not present in the tree\n * @param {Key} key\n * @param {Value=} data\n * @return {Node|null}\n */\n add (key, data) {\n return this._root = add(key, data, this._root, this._comparator, this);\n }\n\n\n /**\n * @param {Key} key\n * @return {Node|null}\n */\n remove (key) {\n this._root = remove(key, this._root, this._comparator, this);\n }\n\n\n /**\n * Removes and returns the node with smallest key\n * @return {?Node}\n */\n pop () {\n let node = this._root;\n if (node) {\n while (node.left) node = node.left;\n this._root = splay(node.key, this._root, this._comparator);\n this._root = remove(node.key, this._root, this._comparator, this);\n return { key: node.key, data: node.data };\n }\n return null;\n }\n\n\n /**\n * @param {Key} key\n * @return {Node|null}\n */\n findStatic (key) {\n let current = this._root;\n const compare = this._comparator;\n while (current) {\n const cmp = compare(key, current.key);\n if (cmp === 0) return current;\n else if (cmp < 0) current = current.left;\n else current = current.right;\n }\n return null;\n }\n\n\n /**\n * @param {Key} key\n * @return {Node|null}\n */\n find (key) {\n if (this._root) {\n this._root = splay(key, this._root, this._comparator);\n if (this._comparator(key, this._root.key) !== 0) return null;\n }\n return this._root;\n }\n\n\n /**\n * @param {Key} key\n * @return {Boolean}\n */\n contains (key) {\n let current = this._root;\n const compare = this._comparator;\n while (current) {\n const cmp = compare(key, current.key);\n if (cmp === 0) return true;\n else if (cmp < 0) current = current.left;\n else current = current.right;\n }\n return false;\n }\n\n\n /**\n * @param {Visitor} visitor\n * @param {*=} ctx\n * @return {SplayTree}\n */\n forEach (visitor, ctx) {\n let current = this._root;\n const Q = []; /* Initialize stack s */\n let done = false;\n\n while (!done) {\n if (current !== null) {\n Q.push(current);\n current = current.left;\n } else {\n if (Q.length !== 0) {\n current = Q.pop();\n visitor.call(ctx, current);\n\n current = current.right;\n } else done = true;\n }\n }\n return this;\n }\n\n\n /**\n * Walk key range from `low` to `high`. Stops if `fn` returns a value.\n * @param {Key} low\n * @param {Key} high\n * @param {Function} fn\n * @param {*?} ctx\n * @return {SplayTree}\n */\n range (low, high, fn, ctx) {\n const Q = [];\n const compare = this._comparator;\n let node = this._root, cmp;\n\n while (Q.length !== 0 || node) {\n if (node) {\n Q.push(node);\n node = node.left;\n } else {\n node = Q.pop();\n cmp = compare(node.key, high);\n if (cmp > 0) {\n break;\n } else if (compare(node.key, low) >= 0) {\n if (fn.call(ctx, node)) return this; // stop if smth is returned\n }\n node = node.right;\n }\n }\n return this;\n }\n\n\n /**\n * Returns array of keys\n * @return {Array<Key>}\n */\n keys () {\n const keys = [];\n this.forEach(({ key }) => keys.push(key));\n return keys;\n }\n\n\n /**\n * Returns array of all the data in the nodes\n * @return {Array<Value>}\n */\n values () {\n const values = [];\n this.forEach(({ data }) => values.push(data));\n return values;\n }\n\n\n /**\n * @return {Key|null}\n */\n min() {\n if (this._root) return this.minNode(this._root).key;\n return null;\n }\n\n\n /**\n * @return {Key|null}\n */\n max() {\n if (this._root) return this.maxNode(this._root).key;\n return null;\n }\n\n\n /**\n * @return {Node|null}\n */\n minNode(t = this._root) {\n if (t) while (t.left) t = t.left;\n return t;\n }\n\n\n /**\n * @return {Node|null}\n */\n maxNode(t = this._root) {\n if (t) while (t.right) t = t.right;\n return t;\n }\n\n\n /**\n * Returns node at given index\n * @param {number} index\n * @return {?Node}\n */\n at (index) {\n let current = this._root, done = false, i = 0;\n const Q = [];\n\n while (!done) {\n if (current) {\n Q.push(current);\n current = current.left;\n } else {\n if (Q.length > 0) {\n current = Q.pop();\n if (i === index) return current;\n i++;\n current = current.right;\n } else done = true;\n }\n }\n return null;\n }\n\n\n /**\n * @param {Node} d\n * @return {Node|null}\n */\n next (d) {\n let root = this._root;\n let successor = null;\n\n if (d.right) {\n successor = d.right;\n while (successor.left) successor = successor.left;\n return successor;\n }\n\n const comparator = this._comparator;\n while (root) {\n const cmp = comparator(d.key, root.key);\n if (cmp === 0) break;\n else if (cmp < 0) {\n successor = root;\n root = root.left;\n } else root = root.right;\n }\n\n return successor;\n }\n\n\n /**\n * @param {Node} d\n * @return {Node|null}\n */\n prev (d) {\n let root = this._root;\n let predecessor = null;\n\n if (d.left !== null) {\n predecessor = d.left;\n while (predecessor.right) predecessor = predecessor.right;\n return predecessor;\n }\n\n const comparator = this._comparator;\n while (root) {\n const cmp = comparator(d.key, root.key);\n if (cmp === 0) break;\n else if (cmp < 0) root = root.left;\n else {\n predecessor = root;\n root = root.right;\n }\n }\n return predecessor;\n }\n\n\n /**\n * @return {SplayTree}\n */\n clear() {\n this._root = null;\n this._size = 0;\n return this;\n }\n\n\n /**\n * @return {NodeList}\n */\n toList() {\n return toList(this._root);\n }\n\n\n /**\n * Bulk-load items. Both array have to be same size\n * @param {Array<Key>} keys\n * @param {Array<Value>} [values]\n * @param {Boolean} [presort=false] Pre-sort keys and values, using\n * tree's comparator. Sorting is done\n * in-place\n * @return {AVLTree}\n */\n load (keys = [], values = [], presort = false) {\n let size = keys.length;\n const comparator = this._comparator;\n\n // sort if needed\n if (presort) sort(keys, values, 0, size - 1, comparator);\n\n if (this._root === null) { // empty tree\n this._root = loadRecursive(this._root, keys, values, 0, size);\n this._size = size;\n } else { // that re-builds the whole tree from two in-order traversals\n const mergedList = mergeLists(this.toList(), createList(keys, values), comparator);\n size = this._size + size;\n this._root = sortedListToBST({ head: mergedList }, 0, size);\n }\n return this;\n }\n\n\n /**\n * @return {Boolean}\n */\n isEmpty() { return this._root === null; }\n\n get size () { return this._size; }\n\n\n /**\n * @param {NodePrinter=} printNode\n * @return {String}\n */\n toString (printNode = (n) => n.key) {\n const out = [];\n printRow(this._root, '', true, (v) => out.push(v), printNode);\n return out.join('');\n }\n\n\n update (key, newKey, newData) {\n const comparator = this._comparator;\n let { left, right } = split(key, this._root, comparator);\n this._size--;\n if (comparator(key, newKey) < 0) {\n right = insert(newKey, newData, right, comparator, this);\n } else {\n left = insert(newKey, newData, left, comparator, this);\n }\n this._root = merge(left, right, comparator);\n }\n\n\n split(key) {\n return split(key, this._root, this._comparator);\n }\n}\n\n\nfunction loadRecursive (parent, keys, values, start, end) {\n const size = end - start;\n if (size > 0) {\n const middle = start + Math.floor(size / 2);\n const key = keys[middle];\n const data = values[middle];\n const node = { key, data, parent };\n node.left = loadRecursive(node, keys, values, start, middle);\n node.right = loadRecursive(node, keys, values, middle + 1, end);\n return node;\n }\n return null;\n}\n\n\nfunction createList(keys, values) {\n const head = { next: null };\n let p = head;\n for (let i = 0; i < keys.length; i++) {\n p = p.next = { key: keys[i], data: values[i] };\n }\n p.next = null;\n return head.next;\n}\n\n\nfunction toList (root) {\n var current = root;\n var Q = [], done = false;\n\n const head = { next: null };\n let p = head;\n\n while (!done) {\n if (current) {\n Q.push(current);\n current = current.left;\n } else {\n if (Q.length > 0) {\n current = p = p.next = Q.pop();\n current = current.right;\n } else done = true;\n }\n }\n p.next = null; // that'll work even if the tree was empty\n return head.next;\n}\n\n\nfunction sortedListToBST(list, start, end) {\n const size = end - start;\n if (size > 0) {\n const middle = start + Math.floor(size / 2);\n const left = sortedListToBST(list, start, middle);\n\n const root = list.head;\n root.left = left;\n\n list.head = list.head.next;\n\n root.right = sortedListToBST(list, middle + 1, end);\n return root;\n }\n return null;\n}\n\n\nfunction mergeLists (l1, l2, compare = (a, b) => a - b) {\n const head = {}; // dummy\n let p = head;\n\n let p1 = l1;\n let p2 = l2;\n\n while (p1 !== null && p2 !== null) {\n if (compare(p1.key, p2.key) < 0) {\n p.next = p1;\n p1 = p1.next;\n } else {\n p.next = p2;\n p2 = p2.next;\n }\n p = p.next;\n }\n\n if (p1 !== null) p.next = p1;\n else if (p2 !== null) p.next = p2;\n\n return head.next;\n}\n\n\nfunction sort(keys, values, left, right, compare) {\n if (left >= right) return;\n\n const pivot = keys[(left + right) >> 1];\n let i = left - 1;\n let j = right + 1;\n\n while (true) {\n do i++; while (compare(keys[i], pivot) < 0);\n do j--; while (compare(keys[j], pivot) > 0);\n if (i >= j) break;\n\n let tmp = keys[i];\n keys[i] = keys[j];\n keys[j] = tmp;\n\n tmp = values[i];\n values[i] = values[j];\n values[j] = tmp;\n }\n\n sort(keys, values, left, j, compare);\n sort(keys, values, j + 1, right, compare);\n}\n\n\n//# sourceURL=webpack://polygon-clipping/./node_modules/splaytree/index.js?")},"./src/bbox.js":
/*!*********************!*\
!*** ./src/bbox.js ***!
\*********************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval('\n\nObject.defineProperty(exports, "__esModule", {\n value: true\n});\nexports.getUniqueCorners = exports.getBboxOverlap = exports.doBboxesOverlap = exports.isInBbox = undefined;\n\nvar _flp = __webpack_require__(/*! ./flp */ "./src/flp.js");\n\n/**\n * A bounding box has the format:\n *\n * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }\n *\n */\n\nvar isInBbox = exports.isInBbox = function isInBbox(bbox, point) {\n var xmin = bbox.ll.x;\n var ymin = bbox.ll.y;\n var xmax = bbox.ur.x;\n var ymax = bbox.ur.y;\n var xpt = point.x;\n var ypt = point.y;\n return (0, _flp.cmp)(xmin, xpt) <= 0 && (0, _flp.cmp)(xpt, xmax) <= 0 && (0, _flp.cmp)(ymin, ypt) <= 0 && (0, _flp.cmp)(ypt, ymax) <= 0;\n};\n\nvar doBboxesOverlap = exports.doBboxesOverlap = function doBboxesOverlap(b1, b2) {\n return !((0, _flp.cmp)(b2.ur.x, b1.ll.x) < 0 || (0, _flp.cmp)(b1.ur.x, b2.ll.x) < 0 || (0, _flp.cmp)(b2.ur.y, b1.ll.y) < 0 || (0, _flp.cmp)(b1.ur.y, b2.ll.y) < 0);\n};\n\n/* Returns either null, or a bbox (aka an ordered pair of points)\n * If there is only one point of overlap, a bbox with identical points\n * will be returned */\nvar getBboxOverlap = exports.getBboxOverlap = function getBboxOverlap(b1, b2) {\n if (!doBboxesOverlap(b1, b2)) return null;\n\n // find the middle two X values\n var lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;\n var upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x;\n\n // find the middle two Y values\n var lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;\n var upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y;\n\n // put those middle values together to get the overlap\n return { ll: { x: lowerX, y: lowerY }, ur: { x: upperX, y: upperY } };\n};\n\n/* Returns a list of unique corners.\n * Will contain one, two or four points */\nvar getUniqueCorners = exports.getUniqueCorners = function getUniqueCorners(bbox) {\n var xmin = bbox.ll.x;\n var ymin = bbox.ll.y;\n var xmax = bbox.ur.x;\n var ymax = bbox.ur.y;\n var xEq = (0, _flp.cmp)(xmin, xmax) === 0;\n var yEq = (0, _flp.cmp)(ymin, ymax) === 0;\n if (xEq && yEq) return [{ x: xmin, y: ymin }];\n if (xEq) return [{ x: xmin, y: ymin }, { x: xmin, y: ymax }];\n if (yEq) return [{ x: xmin, y: ymin }, { x: xmax, y: ymin }];\n return [{ x: xmin, y: ymin }, { x: xmin, y: ymax }, { x: xmax, y: ymin }, { x: xmax, y: ymax }];\n};\n\n//# sourceURL=webpack://polygon-clipping/./src/bbox.js?')},"./src/clean-input.js":
/*!****************************!*\
!*** ./src/clean-input.js ***!
\****************************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.errorOnSelfIntersectingRings = exports.cleanRing = exports.cleanMultiPoly = exports.forceMultiPoly = exports.pointsAsObjects = undefined;\n\nvar _flp = __webpack_require__(/*! ./flp */ \"./src/flp.js\");\n\nvar _vector = __webpack_require__(/*! ./vector */ \"./src/vector.js\");\n\n/* Given input geometry as a standard array-of-arrays geojson-style\n * geometry, return one that uses objects as points, for better perf */\nvar pointsAsObjects = exports.pointsAsObjects = function pointsAsObjects(geom) {\n // we can handle well-formed multipolys and polys\n var output = [];\n if (!Array.isArray(geom)) {\n throw new Error('Input is not a Polygon or MultiPolygon');\n }\n for (var i = 0, iMax = geom.length; i < iMax; i++) {\n if (!Array.isArray(geom[i])) {\n throw new Error('Input is not a Polygon or MultiPolygon');\n }\n output.push([]);\n for (var j = 0, jMax = geom[i].length; j < jMax; j++) {\n if (!Array.isArray(geom[i][j])) {\n throw new Error('Input is not a Polygon or MultiPolygon');\n }\n if (geom[i][j].length === 2) {\n output[i].push({ x: geom[i][j][0], y: geom[i][j][1] });\n continue;\n }\n output[i].push([]);\n for (var k = 0, kMax = geom[i][j].length; k < kMax; k++) {\n if (!Array.isArray(geom[i][j][k]) || geom[i][j][k].length !== 2) {\n throw new Error('Input is not a Polygon or MultiPolygon');\n }\n output[i][j].push({ x: geom[i][j][k][0], y: geom[i][j][k][1] });\n }\n }\n }\n return output;\n};\n\n/* WARN: input modified directly */\nvar forceMultiPoly = exports.forceMultiPoly = function forceMultiPoly(geom) {\n if (Array.isArray(geom)) {\n if (geom.length === 0) return; // allow empty multipolys\n\n if (Array.isArray(geom[0])) {\n if (Array.isArray(geom[0][0])) {\n if (typeof geom[0][0][0].x === 'number' && typeof geom[0][0][0].y === 'number') {\n // multipolygon\n return;\n }\n }\n if (typeof geom[0][0].x === 'number' && typeof geom[0][0].y === 'number') {\n // polygon\n geom.unshift(geom.splice(0));\n return;\n }\n }\n }\n throw new Error('Unrecognized input - not a polygon nor multipolygon');\n};\n\n/* WARN: input modified directly */\nvar cleanMultiPoly = exports.cleanMultiPoly = function cleanMultiPoly(multipoly) {\n var i = 0;\n while (i < multipoly.length) {\n var poly = multipoly[i];\n if (poly.length === 0) {\n multipoly.splice(i, 1);\n continue;\n }\n\n var exteriorRing = poly[0];\n cleanRing(exteriorRing);\n // poly is dropped if exteriorRing is degenerate\n if (exteriorRing.length === 0) {\n multipoly.splice(i, 1);\n continue;\n }\n\n var j = 1;\n while (j < poly.length) {\n var interiorRing = poly[j];\n cleanRing(interiorRing);\n if (interiorRing.length === 0) poly.splice(j, 1);else j++;\n }\n\n i++;\n }\n};\n\n/* Clean ring:\n * - remove duplicate points\n * - remove colinear points\n * - remove rings with no area (less than 3 distinct points)\n * - close rings (last point should equal first)\n *\n * WARN: input modified directly */\nvar cleanRing = exports.cleanRing = function cleanRing(ring) {\n if (ring.length === 0) return;\n if ((0, _flp.cmpPoints)(ring[0], ring[ring.length - 1]) !== 0) {\n ring.push({ x: ring[0].x, y: ring[0].y }); // copy by value\n }\n\n var isPointUncessary = function isPointUncessary(prevPt, pt, nextPt) {\n return (0, _flp.cmpPoints)(prevPt, pt) === 0 || (0, _flp.cmpPoints)(pt, nextPt) === 0 || (0, _vector.compareVectorAngles)(pt, prevPt, nextPt) === 0;\n };\n\n var i = 1;\n while (i < ring.length - 1) {\n if (isPointUncessary(ring[i - 1], ring[i], ring[i + 1])) ring.splice(i, 1);else i++;\n }\n\n // check the first/last point as well\n while (ring.length > 2) {\n if (!isPointUncessary(ring[ring.length - 2], ring[0], ring[1])) break;\n ring.splice(0, 1);\n ring.splice(ring.length - 1, 1);\n ring.push(ring[0]);\n }\n\n // if our ring has less than 3 distinct points now (so is degenerate)\n // shrink it down to the empty array to communicate to our caller to\n // drop it\n while (ring.length < 4 && ring.length > 0) {\n ring.pop();\n }\n};\n\n/* Scan the already-linked events of the segments for any\n * self-intersecting input rings (which are not supported) */\nvar errorOnSelfIntersectingRings = exports.errorOnSelfIntersectingRings = function errorOnSelfIntersectingRings(segments) {\n var _loop = function _loop(i, iMax) {\n var seg = segments[i];\n\n var evt = seg.flowIntoSE;\n\n if (evt.linkedEvents.length > 2) {\n var evtsThisRing = evt.linkedEvents.filter(function (other) {\n return other.segment.ringIn === seg.ringIn;\n });\n if (evtsThisRing.length > 2) {\n evtsThisRing.sort(evt.getLeftmostComparator(evt.otherSE));\n var leftMostEvt = evtsThisRing[1]; // skip ourself\n var rightMostEvt = evtsThisRing[evtsThisRing.length - 1];\n\n // both the segment on our immediate left and right will flow\n // 'out' in intersection point was a touch and not a crossing\n if (leftMostEvt.segment.flowIntoSE === leftMostEvt || rightMostEvt.segment.flowIntoSE === rightMostEvt) {\n throw new Error('Self-intersecting, crossing input ring found at ' + ('[' + evt.point.x + ', ' + evt.point.y + ']'));\n }\n }\n }\n };\n\n for (var i = 0, iMax = segments.length; i < iMax; i++) {\n _loop(i, iMax);\n }\n};\n\n//# sourceURL=webpack://polygon-clipping/./src/clean-input.js?")},"./src/flp.js":
/*!********************!*\
!*** ./src/flp.js ***!
\********************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/* Javascript doesn't do integer math. Everything is\n * floating point with percision Number.EPSILON.\n *\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON\n */\n\n// IE Polyfill\nif (Number.EPSILON === undefined) Number.EPSILON = Math.pow(2, -52);\n\nvar EPSILON_SQ = Number.EPSILON * Number.EPSILON;\n\n/* FLP comparator */\nvar cmp = exports.cmp = function cmp(a, b) {\n // check if they're both 0\n if (-Number.EPSILON < a && a < Number.EPSILON) {\n if (-Number.EPSILON < b && b < Number.EPSILON) {\n return 0;\n }\n }\n\n // check if they're flp equal\n if ((a - b) * (a - b) < EPSILON_SQ * a * b) {\n return 0;\n }\n\n // normal comparison\n return a < b ? -1 : 1;\n};\n\n/* FLP point comparator, favors point encountered first by sweep line */\nvar cmpPoints = exports.cmpPoints = function cmpPoints(aPt, bPt) {\n // fist compare X, then compare Y\n\n var a = aPt.x;\n var b = bPt.x;\n\n // inlined version of cmp() for performance boost\n if (a <= -Number.EPSILON || Number.EPSILON <= a || b <= -Number.EPSILON || Number.EPSILON <= b) {\n var diff = a - b;\n if (diff * diff >= EPSILON_SQ * a * b) {\n return a < b ? -1 : 1;\n }\n }\n\n a = aPt.y;\n b = bPt.y;\n\n // inlined version of cmp() for performance boost\n if (a <= -Number.EPSILON || Number.EPSILON <= a || b <= -Number.EPSILON || Number.EPSILON <= b) {\n var _diff = a - b;\n if (_diff * _diff >= EPSILON_SQ * a * b) {\n return a < b ? -1 : 1;\n }\n }\n\n // they're the same\n return 0;\n};\n\n//# sourceURL=webpack://polygon-clipping/./src/flp.js?")},"./src/geom-in.js":
/*!************************!*\
!*** ./src/geom-in.js ***!
\************************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.MultiPoly = exports.Poly = exports.Ring = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _segment = __webpack_require__(/*! ./segment */ \"./src/segment.js\");\n\nvar _segment2 = _interopRequireDefault(_segment);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n// Give rings unique ID's to get consistent sorting of segments\n// and sweep events when all else is identical\nvar ringId = 0;\n\nvar Ring = exports.Ring = function () {\n function Ring(geomRing, poly) {\n _classCallCheck(this, Ring);\n\n this.id = ringId++;\n this.poly = poly;\n this.segments = [];\n\n for (var i = 1, iMax = geomRing.length; i < iMax; i++) {\n this.segments.push(new _segment2.default(geomRing[i - 1], geomRing[i], this));\n }\n }\n\n _createClass(Ring, [{\n key: 'getSweepEvents',\n value: function getSweepEvents() {\n var sweepEvents = [];\n for (var i = 0, iMax = this.segments.length; i < iMax; i++) {\n var segment = this.segments[i];\n sweepEvents.push(segment.leftSE);\n sweepEvents.push(segment.rightSE);\n }\n return sweepEvents;\n }\n }, {\n key: 'isValid',\n\n\n /* Given a segment on this rings with these relationships to other rings,\n * is it a valid segment of the ring's poly? */\n value: function isValid(ringsSameSLER, ringsDiffSLER, ringsInsideOf) {\n var exterior = this.poly.exteriorRing;\n var interiors = this.poly.interiorRings;\n\n if (this === exterior) {\n // exterior segments inside or interior, nope\n for (var i = 0, iMax = ringsInsideOf.length; i < iMax; i++) {\n if (interiors.includes(ringsInsideOf[i])) return false;\n }\n\n // overlap with an interior of same SWL orientatio, nope\n for (var _i = 0, _iMax = ringsSameSLER.length; _i < _iMax; _i++) {\n if (interiors.includes(ringsSameSLER[_i])) return false;\n }\n\n return true;\n }\n\n // interior rings that aren't inside the exterior nor\n // overlapping with different SWE\n if (!ringsInsideOf.includes(exterior)) {\n if (!ringsDiffSLER.includes(exterior)) return false;\n }\n\n // interior rings inside another interior, nope\n for (var _i2 = 0, _iMax2 = ringsInsideOf.length; _i2 < _iMax2; _i2++) {\n if (interiors.includes(ringsInsideOf[_i2])) return false;\n }\n\n // overlapping interiors with different sweep line orientation, nope\n for (var _i3 = 0, _iMax3 = ringsDiffSLER.length; _i3 < _iMax3; _i3++) {\n if (interiors.includes(ringsDiffSLER[_i3])) return false;\n }\n\n return true;\n }\n }, {\n key: 'isExterior',\n get: function get() {\n return this.poly.exteriorRing === this;\n }\n }, {\n key: 'isInterior',\n get: function get() {\n return this.poly.exteriorRing !== this;\n }\n }]);\n\n return Ring;\n}();\n\nvar Poly = exports.Poly = function () {\n function Poly(geomPoly, multiPoly) {\n _classCallCheck(this, Poly);\n\n this.exteriorRing = new Ring(geomPoly[0], this);\n this.interiorRings = [];\n for (var i = 1, iMax = geomPoly.length; i < iMax; i++) {\n this.interiorRings.push(new Ring(geomPoly[i], this));\n }\n this.multiPoly = multiPoly;\n }\n\n _createClass(Poly, [{\n key: 'getSweepEvents',\n value: function getSweepEvents() {\n var sweepEvents = this.exteriorRing.getSweepEvents();\n for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n var ringSweepEvents = this.interiorRings[i].getSweepEvents();\n for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {\n sweepEvents.push(ringSweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n\n /* Given a segment with these rings, is that segment inside this polygon? */\n\n }, {\n key: 'isInside',\n value: function isInside(ringsOnEdgeOf, ringsInsideOf) {\n // if we're on an edge, we can't be inside\n for (var i = 0, iMax = ringsOnEdgeOf.length; i < iMax; i++) {\n if (ringsOnEdgeOf[i].poly === this) return false;\n }\n\n // we need to be inside the exterior, and nothing else\n var isInsideExterior = false;\n for (var _i4 = 0, _iMax4 = ringsInsideOf.length; _i4 < _iMax4; _i4++) {\n var ring = ringsInsideOf[_i4];\n if (ring.poly !== this) continue;\n if (ring.isInterior) return false;\n isInsideExterior = true;\n }\n return isInsideExterior;\n }\n }]);\n\n return Poly;\n}();\n\nvar MultiPoly = exports.MultiPoly = function () {\n function MultiPoly(geomMultiPoly) {\n _classCallCheck(this, MultiPoly);\n\n this.polys = [];\n for (var i = 0, iMax = geomMultiPoly.length; i < iMax; i++) {\n this.polys.push(new Poly(geomMultiPoly[i], this));\n }\n this.isSubject = false;\n }\n\n _createClass(MultiPoly, [{\n key: 'markAsSubject',\n value: function markAsSubject() {\n this.isSubject = true;\n }\n }, {\n key: 'getSweepEvents',\n value: function getSweepEvents() {\n var sweepEvents = [];\n for (var i = 0, iMax = this.polys.length; i < iMax; i++) {\n var polySweepEvents = this.polys[i].getSweepEvents();\n for (var j = 0, jMax = polySweepEvents.length; j < jMax; j++) {\n sweepEvents.push(polySweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n }]);\n\n return MultiPoly;\n}();\n\n//# sourceURL=webpack://polygon-clipping/./src/geom-in.js?")},"./src/geom-out.js":
/*!*************************!*\
!*** ./src/geom-out.js ***!
\*************************/
/*! no static exports found */function(module,exports,__webpack_require__){"use strict";eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.MultiPoly = exports.Poly = exports.Ring = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _vector = __webpack_require__(/*! ./vector */ \"./src/vector.js\");\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar Ring = exports.Ring = function () {\n _createClass(Ring, null, [{\n key: 'factory',\n\n /* Given the segments from the sweep line pass, compute & return a series\n * of closed rings from all the segments marked to be part of the result */\n value: function factory(allSegments) {\n var ringsOut = [];\n\n for (var i = 0, iMax = allSegments.length; i < iMax; i++) {\n var segment = allSegments[i];\n if (!segment.isInResult || segment.ringOut) continue;\n\n var prevEvent = null;\n var event = segment.leftSE;\n var nextEvent = segment.rightSE;\n var events = [event];\n\n var startingLE = event.linkedEvents;\n var intersectionLEs = [];\n\n /* Walk the chain of linked events to form a closed ring */\n while (true) {\n prevEvent = event;\n event = nextEvent;\n events.push(event);\n\n /* Is the ring complete? */\n if (event.linkedEvents === startingLE) break;\n\n while (true) {\n var availableLEs = event.getAvailableLinkedEvents();\n\n /* Did we hit a dead end? This shouldn't happen. Indicates some earlier\n * part of the algorithm malfunctioned... please file a bug report. */\n if (availableLEs.length === 0) {\n var firstPt = events[0].point;\n var lastPt = events[events.length - 1].point;\n throw new Error('Unable to complete output ring starting at [' + firstPt.x + ',' + (' ' + firstPt.y + ']. Last matching segment found ends at ') + (' [' + lastPt.x + ', ' + lastPt.y + '].'));\n }\n\n /* Only one way to go, so cotinue on the path */\n if (availableLEs.length === 1) {\n nextEvent = availableLEs[0].otherSE;\n break;\n }\n\n /* We must have an intersection. Check for a completed loop */\n var indexLE = null;\n for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) {\n if (intersectionLEs[j].linkedEvents === event.linkedEvents) {\n indexLE = j;\n break;\n }\n }\n /* Found a completed loop. Cut that off and make a ring */\n if (indexLE !== null) {\n var intersectionLE = intersectionLEs.splice(indexLE)[0];\n var ringEvents = events.splice(intersectionLE.index);\n ringEvents.unshift(ringEvents[0].otherSE);\n ringsOut.push(new Ring(ringEvents.reverse()));\n continue;\n }\n /* register the intersection */\n intersectionLEs.push({\n index: events.length,\n linkedEvents: event.linkedEvents\n });\n /* Choose the left-most option to continue the walk */\n var comparator = event.getLeftmostComparator(prevEvent);\n nextEvent = availableLEs.sort(comparator)[0].otherSE;\n break;\n }\n }\n\n ringsOut.push(new Ring(events));\n }\n return ringsOut;\n }\n }]);\n\n function Ring(events) {\n _classCallCheck(this, Ring);\n\n this.events = events;\n for (var i = 0, iMax = events.length; i < iMax; i++) {\n events[i].segment.registerRingOut(this);\n }\n this.poly = null;\n this._clearCache();\n }\n\n _createClass(Ring, [{\n key: 'registerPoly',\n value: function registerPoly(poly) {\n this.poly = poly;\n }\n }, {\n key: 'getGeom',\n value: function getGeom() {\n // Remove superfluous points (ie extra points along a straight line),\n var points = [[this.events[0].point.x, this.events[0].point.y]];\n for (var i = 1, iMax = this.events.length - 1; i < iMax; i++) {\n var _prevPt = this.events[i - 1].point;\n var _pt = this.events[i].point;\n var _nextPt = this.events[i + 1].point;\n if ((0, _vector.compareVectorAngles)(_pt, _prevPt, _nextPt) === 0) continue;\n points.push([_pt.x, _pt.y]);\n }\n\n // check if the starting point is necessary\n var prevPt = this.events[this.events.length - 2].point;\n var pt = this.events[0].point;\n var nextPt = this.events[1].point;\n if ((0, _vector.compareVectorAngles)(pt, prevPt, nextPt) === 0) points.shift();\n\n // ring was all (within rounding error of angle calc) colinear points\n if (points.length === 0) return null;\n\n points.push(points[0]);\n return this.isExteriorRing ? points : points.reverse();\n }\n }, {\n key: '_clearCache',\n value: function _clearCache() {\n this._cache = {};\n