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