index.cjs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  21. // If the importer is in node compatibility mode or this is not an ESM
  22. // file that has been converted to a CommonJS file using a Babel-
  23. // compatible transform (i.e. "__esModule" has not been set), then set
  24. // "default" to the CommonJS "module.exports" for node compatibility.
  25. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  26. mod
  27. ));
  28. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  29. // src/index.ts
  30. var src_exports = {};
  31. __export(src_exports, {
  32. difference: () => difference,
  33. intersection: () => intersection2,
  34. setPrecision: () => setPrecision,
  35. union: () => union,
  36. xor: () => xor
  37. });
  38. module.exports = __toCommonJS(src_exports);
  39. // src/geom-in.ts
  40. var import_bignumber2 = __toESM(require("bignumber.js"), 1);
  41. // src/constant.ts
  42. var constant_default = (x) => {
  43. return () => {
  44. return x;
  45. };
  46. };
  47. // src/compare.ts
  48. var compare_default = (eps) => {
  49. const almostEqual = eps ? (a, b) => b.minus(a).abs().isLessThanOrEqualTo(eps) : constant_default(false);
  50. return (a, b) => {
  51. if (almostEqual(a, b)) return 0;
  52. return a.comparedTo(b);
  53. };
  54. };
  55. // src/orient.ts
  56. function orient_default(eps) {
  57. const almostCollinear = eps ? (area2, ax, ay, cx, cy) => area2.exponentiatedBy(2).isLessThanOrEqualTo(
  58. cx.minus(ax).exponentiatedBy(2).plus(cy.minus(ay).exponentiatedBy(2)).times(eps)
  59. ) : constant_default(false);
  60. return (a, b, c) => {
  61. const ax = a.x, ay = a.y, cx = c.x, cy = c.y;
  62. const area2 = ay.minus(cy).times(b.x.minus(cx)).minus(ax.minus(cx).times(b.y.minus(cy)));
  63. if (almostCollinear(area2, ax, ay, cx, cy)) return 0;
  64. return area2.comparedTo(0);
  65. };
  66. }
  67. // src/snap.ts
  68. var import_bignumber = __toESM(require("bignumber.js"), 1);
  69. var import_splaytree_ts = require("splaytree-ts");
  70. // src/identity.ts
  71. var identity_default = (x) => {
  72. return x;
  73. };
  74. // src/snap.ts
  75. var snap_default = (eps) => {
  76. if (eps) {
  77. const xTree = new import_splaytree_ts.SplayTreeSet(compare_default(eps));
  78. const yTree = new import_splaytree_ts.SplayTreeSet(compare_default(eps));
  79. const snapCoord = (coord, tree) => {
  80. return tree.addAndReturn(coord);
  81. };
  82. const snap = (v) => {
  83. return {
  84. x: snapCoord(v.x, xTree),
  85. y: snapCoord(v.y, yTree)
  86. };
  87. };
  88. snap({ x: new import_bignumber.default(0), y: new import_bignumber.default(0) });
  89. return snap;
  90. }
  91. return identity_default;
  92. };
  93. // src/precision.ts
  94. var set = (eps) => {
  95. return {
  96. set: (eps2) => {
  97. precision = set(eps2);
  98. },
  99. reset: () => set(eps),
  100. compare: compare_default(eps),
  101. snap: snap_default(eps),
  102. orient: orient_default(eps)
  103. };
  104. };
  105. var precision = set();
  106. // src/bbox.ts
  107. var isInBbox = (bbox, point) => {
  108. return bbox.ll.x.isLessThanOrEqualTo(point.x) && point.x.isLessThanOrEqualTo(bbox.ur.x) && bbox.ll.y.isLessThanOrEqualTo(point.y) && point.y.isLessThanOrEqualTo(bbox.ur.y);
  109. };
  110. var getBboxOverlap = (b1, b2) => {
  111. if (b2.ur.x.isLessThan(b1.ll.x) || b1.ur.x.isLessThan(b2.ll.x) || b2.ur.y.isLessThan(b1.ll.y) || b1.ur.y.isLessThan(b2.ll.y))
  112. return null;
  113. const lowerX = b1.ll.x.isLessThan(b2.ll.x) ? b2.ll.x : b1.ll.x;
  114. const upperX = b1.ur.x.isLessThan(b2.ur.x) ? b1.ur.x : b2.ur.x;
  115. const lowerY = b1.ll.y.isLessThan(b2.ll.y) ? b2.ll.y : b1.ll.y;
  116. const upperY = b1.ur.y.isLessThan(b2.ur.y) ? b1.ur.y : b2.ur.y;
  117. return { ll: { x: lowerX, y: lowerY }, ur: { x: upperX, y: upperY } };
  118. };
  119. // src/operation.ts
  120. var import_splaytree_ts3 = require("splaytree-ts");
  121. // src/vector.ts
  122. var crossProduct = (a, b) => a.x.times(b.y).minus(a.y.times(b.x));
  123. var dotProduct = (a, b) => a.x.times(b.x).plus(a.y.times(b.y));
  124. var length = (v) => dotProduct(v, v).sqrt();
  125. var sineOfAngle = (pShared, pBase, pAngle) => {
  126. const vBase = { x: pBase.x.minus(pShared.x), y: pBase.y.minus(pShared.y) };
  127. const vAngle = { x: pAngle.x.minus(pShared.x), y: pAngle.y.minus(pShared.y) };
  128. return crossProduct(vAngle, vBase).div(length(vAngle)).div(length(vBase));
  129. };
  130. var cosineOfAngle = (pShared, pBase, pAngle) => {
  131. const vBase = { x: pBase.x.minus(pShared.x), y: pBase.y.minus(pShared.y) };
  132. const vAngle = { x: pAngle.x.minus(pShared.x), y: pAngle.y.minus(pShared.y) };
  133. return dotProduct(vAngle, vBase).div(length(vAngle)).div(length(vBase));
  134. };
  135. var horizontalIntersection = (pt, v, y) => {
  136. if (v.y.isZero()) return null;
  137. return { x: pt.x.plus(v.x.div(v.y).times(y.minus(pt.y))), y };
  138. };
  139. var verticalIntersection = (pt, v, x) => {
  140. if (v.x.isZero()) return null;
  141. return { x, y: pt.y.plus(v.y.div(v.x).times(x.minus(pt.x))) };
  142. };
  143. var intersection = (pt1, v1, pt2, v2) => {
  144. if (v1.x.isZero()) return verticalIntersection(pt2, v2, pt1.x);
  145. if (v2.x.isZero()) return verticalIntersection(pt1, v1, pt2.x);
  146. if (v1.y.isZero()) return horizontalIntersection(pt2, v2, pt1.y);
  147. if (v2.y.isZero()) return horizontalIntersection(pt1, v1, pt2.y);
  148. const kross = crossProduct(v1, v2);
  149. if (kross.isZero()) return null;
  150. const ve = { x: pt2.x.minus(pt1.x), y: pt2.y.minus(pt1.y) };
  151. const d1 = crossProduct(ve, v1).div(kross);
  152. const d2 = crossProduct(ve, v2).div(kross);
  153. const x1 = pt1.x.plus(d2.times(v1.x)), x2 = pt2.x.plus(d1.times(v2.x));
  154. const y1 = pt1.y.plus(d2.times(v1.y)), y2 = pt2.y.plus(d1.times(v2.y));
  155. const x = x1.plus(x2).div(2);
  156. const y = y1.plus(y2).div(2);
  157. return { x, y };
  158. };
  159. // src/sweep-event.ts
  160. var SweepEvent = class _SweepEvent {
  161. point;
  162. isLeft;
  163. segment;
  164. otherSE;
  165. consumedBy;
  166. // for ordering sweep events in the sweep event queue
  167. static compare(a, b) {
  168. const ptCmp = _SweepEvent.comparePoints(a.point, b.point);
  169. if (ptCmp !== 0) return ptCmp;
  170. if (a.point !== b.point) a.link(b);
  171. if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1;
  172. return Segment.compare(a.segment, b.segment);
  173. }
  174. // for ordering points in sweep line order
  175. static comparePoints(aPt, bPt) {
  176. if (aPt.x.isLessThan(bPt.x)) return -1;
  177. if (aPt.x.isGreaterThan(bPt.x)) return 1;
  178. if (aPt.y.isLessThan(bPt.y)) return -1;
  179. if (aPt.y.isGreaterThan(bPt.y)) return 1;
  180. return 0;
  181. }
  182. // Warning: 'point' input will be modified and re-used (for performance)
  183. constructor(point, isLeft) {
  184. if (point.events === void 0) point.events = [this];
  185. else point.events.push(this);
  186. this.point = point;
  187. this.isLeft = isLeft;
  188. }
  189. link(other) {
  190. if (other.point === this.point) {
  191. throw new Error("Tried to link already linked events");
  192. }
  193. const otherEvents = other.point.events;
  194. for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {
  195. const evt = otherEvents[i];
  196. this.point.events.push(evt);
  197. evt.point = this.point;
  198. }
  199. this.checkForConsuming();
  200. }
  201. /* Do a pass over our linked events and check to see if any pair
  202. * of segments match, and should be consumed. */
  203. checkForConsuming() {
  204. const numEvents = this.point.events.length;
  205. for (let i = 0; i < numEvents; i++) {
  206. const evt1 = this.point.events[i];
  207. if (evt1.segment.consumedBy !== void 0) continue;
  208. for (let j = i + 1; j < numEvents; j++) {
  209. const evt2 = this.point.events[j];
  210. if (evt2.consumedBy !== void 0) continue;
  211. if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
  212. evt1.segment.consume(evt2.segment);
  213. }
  214. }
  215. }
  216. getAvailableLinkedEvents() {
  217. const events = [];
  218. for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {
  219. const evt = this.point.events[i];
  220. if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
  221. events.push(evt);
  222. }
  223. }
  224. return events;
  225. }
  226. /**
  227. * Returns a comparator function for sorting linked events that will
  228. * favor the event that will give us the smallest left-side angle.
  229. * All ring construction starts as low as possible heading to the right,
  230. * so by always turning left as sharp as possible we'll get polygons
  231. * without uncessary loops & holes.
  232. *
  233. * The comparator function has a compute cache such that it avoids
  234. * re-computing already-computed values.
  235. */
  236. getLeftmostComparator(baseEvent) {
  237. const cache = /* @__PURE__ */ new Map();
  238. const fillCache = (linkedEvent) => {
  239. const nextEvent = linkedEvent.otherSE;
  240. cache.set(linkedEvent, {
  241. sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),
  242. cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point)
  243. });
  244. };
  245. return (a, b) => {
  246. if (!cache.has(a)) fillCache(a);
  247. if (!cache.has(b)) fillCache(b);
  248. const { sine: asine, cosine: acosine } = cache.get(a);
  249. const { sine: bsine, cosine: bcosine } = cache.get(b);
  250. if (asine.isGreaterThanOrEqualTo(0) && bsine.isGreaterThanOrEqualTo(0)) {
  251. if (acosine.isLessThan(bcosine)) return 1;
  252. if (acosine.isGreaterThan(bcosine)) return -1;
  253. return 0;
  254. }
  255. if (asine.isLessThan(0) && bsine.isLessThan(0)) {
  256. if (acosine.isLessThan(bcosine)) return -1;
  257. if (acosine.isGreaterThan(bcosine)) return 1;
  258. return 0;
  259. }
  260. if (bsine.isLessThan(asine)) return -1;
  261. if (bsine.isGreaterThan(asine)) return 1;
  262. return 0;
  263. };
  264. }
  265. };
  266. // src/geom-out.ts
  267. var RingOut = class _RingOut {
  268. events;
  269. poly;
  270. _isExteriorRing;
  271. _enclosingRing;
  272. /* Given the segments from the sweep line pass, compute & return a series
  273. * of closed rings from all the segments marked to be part of the result */
  274. static factory(allSegments) {
  275. const ringsOut = [];
  276. for (let i = 0, iMax = allSegments.length; i < iMax; i++) {
  277. const segment = allSegments[i];
  278. if (!segment.isInResult() || segment.ringOut) continue;
  279. let prevEvent = null;
  280. let event = segment.leftSE;
  281. let nextEvent = segment.rightSE;
  282. const events = [event];
  283. const startingPoint = event.point;
  284. const intersectionLEs = [];
  285. while (true) {
  286. prevEvent = event;
  287. event = nextEvent;
  288. events.push(event);
  289. if (event.point === startingPoint) break;
  290. while (true) {
  291. const availableLEs = event.getAvailableLinkedEvents();
  292. if (availableLEs.length === 0) {
  293. const firstPt = events[0].point;
  294. const lastPt = events[events.length - 1].point;
  295. throw new Error(
  296. `Unable to complete output ring starting at [${firstPt.x}, ${firstPt.y}]. Last matching segment found ends at [${lastPt.x}, ${lastPt.y}].`
  297. );
  298. }
  299. if (availableLEs.length === 1) {
  300. nextEvent = availableLEs[0].otherSE;
  301. break;
  302. }
  303. let indexLE = null;
  304. for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
  305. if (intersectionLEs[j].point === event.point) {
  306. indexLE = j;
  307. break;
  308. }
  309. }
  310. if (indexLE !== null) {
  311. const intersectionLE = intersectionLEs.splice(indexLE)[0];
  312. const ringEvents = events.splice(intersectionLE.index);
  313. ringEvents.unshift(ringEvents[0].otherSE);
  314. ringsOut.push(new _RingOut(ringEvents.reverse()));
  315. continue;
  316. }
  317. intersectionLEs.push({
  318. index: events.length,
  319. point: event.point
  320. });
  321. const comparator = event.getLeftmostComparator(prevEvent);
  322. nextEvent = availableLEs.sort(comparator)[0].otherSE;
  323. break;
  324. }
  325. }
  326. ringsOut.push(new _RingOut(events));
  327. }
  328. return ringsOut;
  329. }
  330. constructor(events) {
  331. this.events = events;
  332. for (let i = 0, iMax = events.length; i < iMax; i++) {
  333. events[i].segment.ringOut = this;
  334. }
  335. this.poly = null;
  336. }
  337. getGeom() {
  338. let prevPt = this.events[0].point;
  339. const points = [prevPt];
  340. for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {
  341. const pt2 = this.events[i].point;
  342. const nextPt2 = this.events[i + 1].point;
  343. if (precision.orient(pt2, prevPt, nextPt2) === 0) continue;
  344. points.push(pt2);
  345. prevPt = pt2;
  346. }
  347. if (points.length === 1) return null;
  348. const pt = points[0];
  349. const nextPt = points[1];
  350. if (precision.orient(pt, prevPt, nextPt) === 0) points.shift();
  351. points.push(points[0]);
  352. const step = this.isExteriorRing() ? 1 : -1;
  353. const iStart = this.isExteriorRing() ? 0 : points.length - 1;
  354. const iEnd = this.isExteriorRing() ? points.length : -1;
  355. const orderedPoints = [];
  356. for (let i = iStart; i != iEnd; i += step)
  357. orderedPoints.push([points[i].x.toNumber(), points[i].y.toNumber()]);
  358. return orderedPoints;
  359. }
  360. isExteriorRing() {
  361. if (this._isExteriorRing === void 0) {
  362. const enclosing = this.enclosingRing();
  363. this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
  364. }
  365. return this._isExteriorRing;
  366. }
  367. enclosingRing() {
  368. if (this._enclosingRing === void 0) {
  369. this._enclosingRing = this._calcEnclosingRing();
  370. }
  371. return this._enclosingRing;
  372. }
  373. /* Returns the ring that encloses this one, if any */
  374. _calcEnclosingRing() {
  375. let leftMostEvt = this.events[0];
  376. for (let i = 1, iMax = this.events.length; i < iMax; i++) {
  377. const evt = this.events[i];
  378. if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
  379. }
  380. let prevSeg = leftMostEvt.segment.prevInResult();
  381. let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
  382. while (true) {
  383. if (!prevSeg) return null;
  384. if (!prevPrevSeg) return prevSeg.ringOut;
  385. if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
  386. if (prevPrevSeg.ringOut?.enclosingRing() !== prevSeg.ringOut) {
  387. return prevSeg.ringOut;
  388. } else return prevSeg.ringOut?.enclosingRing();
  389. }
  390. prevSeg = prevPrevSeg.prevInResult();
  391. prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
  392. }
  393. }
  394. };
  395. var PolyOut = class {
  396. exteriorRing;
  397. interiorRings;
  398. constructor(exteriorRing) {
  399. this.exteriorRing = exteriorRing;
  400. exteriorRing.poly = this;
  401. this.interiorRings = [];
  402. }
  403. addInterior(ring) {
  404. this.interiorRings.push(ring);
  405. ring.poly = this;
  406. }
  407. getGeom() {
  408. const geom0 = this.exteriorRing.getGeom();
  409. if (geom0 === null) return null;
  410. const geom = [geom0];
  411. for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
  412. const ringGeom = this.interiorRings[i].getGeom();
  413. if (ringGeom === null) continue;
  414. geom.push(ringGeom);
  415. }
  416. return geom;
  417. }
  418. };
  419. var MultiPolyOut = class {
  420. rings;
  421. polys;
  422. constructor(rings) {
  423. this.rings = rings;
  424. this.polys = this._composePolys(rings);
  425. }
  426. getGeom() {
  427. const geom = [];
  428. for (let i = 0, iMax = this.polys.length; i < iMax; i++) {
  429. const polyGeom = this.polys[i].getGeom();
  430. if (polyGeom === null) continue;
  431. geom.push(polyGeom);
  432. }
  433. return geom;
  434. }
  435. _composePolys(rings) {
  436. const polys = [];
  437. for (let i = 0, iMax = rings.length; i < iMax; i++) {
  438. const ring = rings[i];
  439. if (ring.poly) continue;
  440. if (ring.isExteriorRing()) polys.push(new PolyOut(ring));
  441. else {
  442. const enclosingRing = ring.enclosingRing();
  443. if (!enclosingRing?.poly) polys.push(new PolyOut(enclosingRing));
  444. enclosingRing?.poly?.addInterior(ring);
  445. }
  446. }
  447. return polys;
  448. }
  449. };
  450. // src/sweep-line.ts
  451. var import_splaytree_ts2 = require("splaytree-ts");
  452. var SweepLine = class {
  453. queue;
  454. tree;
  455. segments;
  456. constructor(queue, comparator = Segment.compare) {
  457. this.queue = queue;
  458. this.tree = new import_splaytree_ts2.SplayTreeSet(comparator);
  459. this.segments = [];
  460. }
  461. process(event) {
  462. const segment = event.segment;
  463. const newEvents = [];
  464. if (event.consumedBy) {
  465. if (event.isLeft) this.queue.delete(event.otherSE);
  466. else this.tree.delete(segment);
  467. return newEvents;
  468. }
  469. if (event.isLeft) this.tree.add(segment);
  470. let prevSeg = segment;
  471. let nextSeg = segment;
  472. do {
  473. prevSeg = this.tree.lastBefore(prevSeg);
  474. } while (prevSeg != null && prevSeg.consumedBy != void 0);
  475. do {
  476. nextSeg = this.tree.firstAfter(nextSeg);
  477. } while (nextSeg != null && nextSeg.consumedBy != void 0);
  478. if (event.isLeft) {
  479. let prevMySplitter = null;
  480. if (prevSeg) {
  481. const prevInter = prevSeg.getIntersection(segment);
  482. if (prevInter !== null) {
  483. if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
  484. if (!prevSeg.isAnEndpoint(prevInter)) {
  485. const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
  486. for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
  487. newEvents.push(newEventsFromSplit[i]);
  488. }
  489. }
  490. }
  491. }
  492. let nextMySplitter = null;
  493. if (nextSeg) {
  494. const nextInter = nextSeg.getIntersection(segment);
  495. if (nextInter !== null) {
  496. if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
  497. if (!nextSeg.isAnEndpoint(nextInter)) {
  498. const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
  499. for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
  500. newEvents.push(newEventsFromSplit[i]);
  501. }
  502. }
  503. }
  504. }
  505. if (prevMySplitter !== null || nextMySplitter !== null) {
  506. let mySplitter = null;
  507. if (prevMySplitter === null) mySplitter = nextMySplitter;
  508. else if (nextMySplitter === null) mySplitter = prevMySplitter;
  509. else {
  510. const cmpSplitters = SweepEvent.comparePoints(
  511. prevMySplitter,
  512. nextMySplitter
  513. );
  514. mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
  515. }
  516. this.queue.delete(segment.rightSE);
  517. newEvents.push(segment.rightSE);
  518. const newEventsFromSplit = segment.split(mySplitter);
  519. for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
  520. newEvents.push(newEventsFromSplit[i]);
  521. }
  522. }
  523. if (newEvents.length > 0) {
  524. this.tree.delete(segment);
  525. newEvents.push(event);
  526. } else {
  527. this.segments.push(segment);
  528. segment.prev = prevSeg;
  529. }
  530. } else {
  531. if (prevSeg && nextSeg) {
  532. const inter = prevSeg.getIntersection(nextSeg);
  533. if (inter !== null) {
  534. if (!prevSeg.isAnEndpoint(inter)) {
  535. const newEventsFromSplit = this._splitSafely(prevSeg, inter);
  536. for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
  537. newEvents.push(newEventsFromSplit[i]);
  538. }
  539. }
  540. if (!nextSeg.isAnEndpoint(inter)) {
  541. const newEventsFromSplit = this._splitSafely(nextSeg, inter);
  542. for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
  543. newEvents.push(newEventsFromSplit[i]);
  544. }
  545. }
  546. }
  547. }
  548. this.tree.delete(segment);
  549. }
  550. return newEvents;
  551. }
  552. /* Safely split a segment that is currently in the datastructures
  553. * IE - a segment other than the one that is currently being processed. */
  554. _splitSafely(seg, pt) {
  555. this.tree.delete(seg);
  556. const rightSE = seg.rightSE;
  557. this.queue.delete(rightSE);
  558. const newEvents = seg.split(pt);
  559. newEvents.push(rightSE);
  560. if (seg.consumedBy === void 0) this.tree.add(seg);
  561. return newEvents;
  562. }
  563. };
  564. // src/operation.ts
  565. var Operation = class {
  566. type;
  567. numMultiPolys;
  568. run(type, geom, moreGeoms) {
  569. operation.type = type;
  570. const multipolys = [new MultiPolyIn(geom, true)];
  571. for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {
  572. multipolys.push(new MultiPolyIn(moreGeoms[i], false));
  573. }
  574. operation.numMultiPolys = multipolys.length;
  575. if (operation.type === "difference") {
  576. const subject = multipolys[0];
  577. let i = 1;
  578. while (i < multipolys.length) {
  579. if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null) i++;
  580. else multipolys.splice(i, 1);
  581. }
  582. }
  583. if (operation.type === "intersection") {
  584. for (let i = 0, iMax = multipolys.length; i < iMax; i++) {
  585. const mpA = multipolys[i];
  586. for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {
  587. if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
  588. }
  589. }
  590. }
  591. const queue = new import_splaytree_ts3.SplayTreeSet(SweepEvent.compare);
  592. for (let i = 0, iMax = multipolys.length; i < iMax; i++) {
  593. const sweepEvents = multipolys[i].getSweepEvents();
  594. for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {
  595. queue.add(sweepEvents[j]);
  596. }
  597. }
  598. const sweepLine = new SweepLine(queue);
  599. let evt = null;
  600. if (queue.size != 0) {
  601. evt = queue.first();
  602. queue.delete(evt);
  603. }
  604. while (evt) {
  605. const newEvents = sweepLine.process(evt);
  606. for (let i = 0, iMax = newEvents.length; i < iMax; i++) {
  607. const evt2 = newEvents[i];
  608. if (evt2.consumedBy === void 0) queue.add(evt2);
  609. }
  610. if (queue.size != 0) {
  611. evt = queue.first();
  612. queue.delete(evt);
  613. } else {
  614. evt = null;
  615. }
  616. }
  617. precision.reset();
  618. const ringsOut = RingOut.factory(sweepLine.segments);
  619. const result = new MultiPolyOut(ringsOut);
  620. return result.getGeom();
  621. }
  622. };
  623. var operation = new Operation();
  624. var operation_default = operation;
  625. // src/segment.ts
  626. var segmentId = 0;
  627. var Segment = class _Segment {
  628. id;
  629. leftSE;
  630. rightSE;
  631. rings;
  632. windings;
  633. ringOut;
  634. consumedBy;
  635. prev;
  636. _prevInResult;
  637. _beforeState;
  638. _afterState;
  639. _isInResult;
  640. /* This compare() function is for ordering segments in the sweep
  641. * line tree, and does so according to the following criteria:
  642. *
  643. * Consider the vertical line that lies an infinestimal step to the
  644. * right of the right-more of the two left endpoints of the input
  645. * segments. Imagine slowly moving a point up from negative infinity
  646. * in the increasing y direction. Which of the two segments will that
  647. * point intersect first? That segment comes 'before' the other one.
  648. *
  649. * If neither segment would be intersected by such a line, (if one
  650. * or more of the segments are vertical) then the line to be considered
  651. * is directly on the right-more of the two left inputs.
  652. */
  653. static compare(a, b) {
  654. const alx = a.leftSE.point.x;
  655. const blx = b.leftSE.point.x;
  656. const arx = a.rightSE.point.x;
  657. const brx = b.rightSE.point.x;
  658. if (brx.isLessThan(alx)) return 1;
  659. if (arx.isLessThan(blx)) return -1;
  660. const aly = a.leftSE.point.y;
  661. const bly = b.leftSE.point.y;
  662. const ary = a.rightSE.point.y;
  663. const bry = b.rightSE.point.y;
  664. if (alx.isLessThan(blx)) {
  665. if (bly.isLessThan(aly) && bly.isLessThan(ary)) return 1;
  666. if (bly.isGreaterThan(aly) && bly.isGreaterThan(ary)) return -1;
  667. const aCmpBLeft = a.comparePoint(b.leftSE.point);
  668. if (aCmpBLeft < 0) return 1;
  669. if (aCmpBLeft > 0) return -1;
  670. const bCmpARight = b.comparePoint(a.rightSE.point);
  671. if (bCmpARight !== 0) return bCmpARight;
  672. return -1;
  673. }
  674. if (alx.isGreaterThan(blx)) {
  675. if (aly.isLessThan(bly) && aly.isLessThan(bry)) return -1;
  676. if (aly.isGreaterThan(bly) && aly.isGreaterThan(bry)) return 1;
  677. const bCmpALeft = b.comparePoint(a.leftSE.point);
  678. if (bCmpALeft !== 0) return bCmpALeft;
  679. const aCmpBRight = a.comparePoint(b.rightSE.point);
  680. if (aCmpBRight < 0) return 1;
  681. if (aCmpBRight > 0) return -1;
  682. return 1;
  683. }
  684. if (aly.isLessThan(bly)) return -1;
  685. if (aly.isGreaterThan(bly)) return 1;
  686. if (arx.isLessThan(brx)) {
  687. const bCmpARight = b.comparePoint(a.rightSE.point);
  688. if (bCmpARight !== 0) return bCmpARight;
  689. }
  690. if (arx.isGreaterThan(brx)) {
  691. const aCmpBRight = a.comparePoint(b.rightSE.point);
  692. if (aCmpBRight < 0) return 1;
  693. if (aCmpBRight > 0) return -1;
  694. }
  695. if (!arx.eq(brx)) {
  696. const ay = ary.minus(aly);
  697. const ax = arx.minus(alx);
  698. const by = bry.minus(bly);
  699. const bx = brx.minus(blx);
  700. if (ay.isGreaterThan(ax) && by.isLessThan(bx)) return 1;
  701. if (ay.isLessThan(ax) && by.isGreaterThan(bx)) return -1;
  702. }
  703. if (arx.isGreaterThan(brx)) return 1;
  704. if (arx.isLessThan(brx)) return -1;
  705. if (ary.isLessThan(bry)) return -1;
  706. if (ary.isGreaterThan(bry)) return 1;
  707. if (a.id < b.id) return -1;
  708. if (a.id > b.id) return 1;
  709. return 0;
  710. }
  711. /* Warning: a reference to ringWindings input will be stored,
  712. * and possibly will be later modified */
  713. constructor(leftSE, rightSE, rings, windings) {
  714. this.id = ++segmentId;
  715. this.leftSE = leftSE;
  716. leftSE.segment = this;
  717. leftSE.otherSE = rightSE;
  718. this.rightSE = rightSE;
  719. rightSE.segment = this;
  720. rightSE.otherSE = leftSE;
  721. this.rings = rings;
  722. this.windings = windings;
  723. }
  724. static fromRing(pt1, pt2, ring) {
  725. let leftPt, rightPt, winding;
  726. const cmpPts = SweepEvent.comparePoints(pt1, pt2);
  727. if (cmpPts < 0) {
  728. leftPt = pt1;
  729. rightPt = pt2;
  730. winding = 1;
  731. } else if (cmpPts > 0) {
  732. leftPt = pt2;
  733. rightPt = pt1;
  734. winding = -1;
  735. } else
  736. throw new Error(
  737. `Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`
  738. );
  739. const leftSE = new SweepEvent(leftPt, true);
  740. const rightSE = new SweepEvent(rightPt, false);
  741. return new _Segment(leftSE, rightSE, [ring], [winding]);
  742. }
  743. /* When a segment is split, the rightSE is replaced with a new sweep event */
  744. replaceRightSE(newRightSE) {
  745. this.rightSE = newRightSE;
  746. this.rightSE.segment = this;
  747. this.rightSE.otherSE = this.leftSE;
  748. this.leftSE.otherSE = this.rightSE;
  749. }
  750. bbox() {
  751. const y1 = this.leftSE.point.y;
  752. const y2 = this.rightSE.point.y;
  753. return {
  754. ll: { x: this.leftSE.point.x, y: y1.isLessThan(y2) ? y1 : y2 },
  755. ur: { x: this.rightSE.point.x, y: y1.isGreaterThan(y2) ? y1 : y2 }
  756. };
  757. }
  758. /* A vector from the left point to the right */
  759. vector() {
  760. return {
  761. x: this.rightSE.point.x.minus(this.leftSE.point.x),
  762. y: this.rightSE.point.y.minus(this.leftSE.point.y)
  763. };
  764. }
  765. isAnEndpoint(pt) {
  766. return pt.x.eq(this.leftSE.point.x) && pt.y.eq(this.leftSE.point.y) || pt.x.eq(this.rightSE.point.x) && pt.y.eq(this.rightSE.point.y);
  767. }
  768. /* Compare this segment with a point.
  769. *
  770. * A point P is considered to be colinear to a segment if there
  771. * exists a distance D such that if we travel along the segment
  772. * from one * endpoint towards the other a distance D, we find
  773. * ourselves at point P.
  774. *
  775. * Return value indicates:
  776. *
  777. * 1: point lies above the segment (to the left of vertical)
  778. * 0: point is colinear to segment
  779. * -1: point lies below the segment (to the right of vertical)
  780. */
  781. comparePoint(point) {
  782. return precision.orient(this.leftSE.point, point, this.rightSE.point);
  783. }
  784. /**
  785. * Given another segment, returns the first non-trivial intersection
  786. * between the two segments (in terms of sweep line ordering), if it exists.
  787. *
  788. * A 'non-trivial' intersection is one that will cause one or both of the
  789. * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
  790. *
  791. * * endpoint of segA with endpoint of segB --> trivial
  792. * * endpoint of segA with point along segB --> non-trivial
  793. * * endpoint of segB with point along segA --> non-trivial
  794. * * point along segA with point along segB --> non-trivial
  795. *
  796. * If no non-trivial intersection exists, return null
  797. * Else, return null.
  798. */
  799. getIntersection(other) {
  800. const tBbox = this.bbox();
  801. const oBbox = other.bbox();
  802. const bboxOverlap = getBboxOverlap(tBbox, oBbox);
  803. if (bboxOverlap === null) return null;
  804. const tlp = this.leftSE.point;
  805. const trp = this.rightSE.point;
  806. const olp = other.leftSE.point;
  807. const orp = other.rightSE.point;
  808. const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
  809. const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
  810. const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
  811. const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;
  812. if (touchesThisLSE && touchesOtherLSE) {
  813. if (touchesThisRSE && !touchesOtherRSE) return trp;
  814. if (!touchesThisRSE && touchesOtherRSE) return orp;
  815. return null;
  816. }
  817. if (touchesThisLSE) {
  818. if (touchesOtherRSE) {
  819. if (tlp.x.eq(orp.x) && tlp.y.eq(orp.y)) return null;
  820. }
  821. return tlp;
  822. }
  823. if (touchesOtherLSE) {
  824. if (touchesThisRSE) {
  825. if (trp.x.eq(olp.x) && trp.y.eq(olp.y)) return null;
  826. }
  827. return olp;
  828. }
  829. if (touchesThisRSE && touchesOtherRSE) return null;
  830. if (touchesThisRSE) return trp;
  831. if (touchesOtherRSE) return orp;
  832. const pt = intersection(tlp, this.vector(), olp, other.vector());
  833. if (pt === null) return null;
  834. if (!isInBbox(bboxOverlap, pt)) return null;
  835. return precision.snap(pt);
  836. }
  837. /**
  838. * Split the given segment into multiple segments on the given points.
  839. * * Each existing segment will retain its leftSE and a new rightSE will be
  840. * generated for it.
  841. * * A new segment will be generated which will adopt the original segment's
  842. * rightSE, and a new leftSE will be generated for it.
  843. * * If there are more than two points given to split on, new segments
  844. * in the middle will be generated with new leftSE and rightSE's.
  845. * * An array of the newly generated SweepEvents will be returned.
  846. *
  847. * Warning: input array of points is modified
  848. */
  849. split(point) {
  850. const newEvents = [];
  851. const alreadyLinked = point.events !== void 0;
  852. const newLeftSE = new SweepEvent(point, true);
  853. const newRightSE = new SweepEvent(point, false);
  854. const oldRightSE = this.rightSE;
  855. this.replaceRightSE(newRightSE);
  856. newEvents.push(newRightSE);
  857. newEvents.push(newLeftSE);
  858. const newSeg = new _Segment(
  859. newLeftSE,
  860. oldRightSE,
  861. this.rings.slice(),
  862. this.windings.slice()
  863. );
  864. if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
  865. newSeg.swapEvents();
  866. }
  867. if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
  868. this.swapEvents();
  869. }
  870. if (alreadyLinked) {
  871. newLeftSE.checkForConsuming();
  872. newRightSE.checkForConsuming();
  873. }
  874. return newEvents;
  875. }
  876. /* Swap which event is left and right */
  877. swapEvents() {
  878. const tmpEvt = this.rightSE;
  879. this.rightSE = this.leftSE;
  880. this.leftSE = tmpEvt;
  881. this.leftSE.isLeft = true;
  882. this.rightSE.isLeft = false;
  883. for (let i = 0, iMax = this.windings.length; i < iMax; i++) {
  884. this.windings[i] *= -1;
  885. }
  886. }
  887. /* Consume another segment. We take their rings under our wing
  888. * and mark them as consumed. Use for perfectly overlapping segments */
  889. consume(other) {
  890. let consumer = this;
  891. let consumee = other;
  892. while (consumer.consumedBy) consumer = consumer.consumedBy;
  893. while (consumee.consumedBy) consumee = consumee.consumedBy;
  894. const cmp = _Segment.compare(consumer, consumee);
  895. if (cmp === 0) return;
  896. if (cmp > 0) {
  897. const tmp = consumer;
  898. consumer = consumee;
  899. consumee = tmp;
  900. }
  901. if (consumer.prev === consumee) {
  902. const tmp = consumer;
  903. consumer = consumee;
  904. consumee = tmp;
  905. }
  906. for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {
  907. const ring = consumee.rings[i];
  908. const winding = consumee.windings[i];
  909. const index = consumer.rings.indexOf(ring);
  910. if (index === -1) {
  911. consumer.rings.push(ring);
  912. consumer.windings.push(winding);
  913. } else consumer.windings[index] += winding;
  914. }
  915. consumee.rings = null;
  916. consumee.windings = null;
  917. consumee.consumedBy = consumer;
  918. consumee.leftSE.consumedBy = consumer.leftSE;
  919. consumee.rightSE.consumedBy = consumer.rightSE;
  920. }
  921. /* The first segment previous segment chain that is in the result */
  922. prevInResult() {
  923. if (this._prevInResult !== void 0) return this._prevInResult;
  924. if (!this.prev) this._prevInResult = null;
  925. else if (this.prev.isInResult()) this._prevInResult = this.prev;
  926. else this._prevInResult = this.prev.prevInResult();
  927. return this._prevInResult;
  928. }
  929. beforeState() {
  930. if (this._beforeState !== void 0) return this._beforeState;
  931. if (!this.prev)
  932. this._beforeState = {
  933. rings: [],
  934. windings: [],
  935. multiPolys: []
  936. };
  937. else {
  938. const seg = this.prev.consumedBy || this.prev;
  939. this._beforeState = seg.afterState();
  940. }
  941. return this._beforeState;
  942. }
  943. afterState() {
  944. if (this._afterState !== void 0) return this._afterState;
  945. const beforeState = this.beforeState();
  946. this._afterState = {
  947. rings: beforeState.rings.slice(0),
  948. windings: beforeState.windings.slice(0),
  949. multiPolys: []
  950. };
  951. const ringsAfter = this._afterState.rings;
  952. const windingsAfter = this._afterState.windings;
  953. const mpsAfter = this._afterState.multiPolys;
  954. for (let i = 0, iMax = this.rings.length; i < iMax; i++) {
  955. const ring = this.rings[i];
  956. const winding = this.windings[i];
  957. const index = ringsAfter.indexOf(ring);
  958. if (index === -1) {
  959. ringsAfter.push(ring);
  960. windingsAfter.push(winding);
  961. } else windingsAfter[index] += winding;
  962. }
  963. const polysAfter = [];
  964. const polysExclude = [];
  965. for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {
  966. if (windingsAfter[i] === 0) continue;
  967. const ring = ringsAfter[i];
  968. const poly = ring.poly;
  969. if (polysExclude.indexOf(poly) !== -1) continue;
  970. if (ring.isExterior) polysAfter.push(poly);
  971. else {
  972. if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
  973. const index = polysAfter.indexOf(ring.poly);
  974. if (index !== -1) polysAfter.splice(index, 1);
  975. }
  976. }
  977. for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {
  978. const mp = polysAfter[i].multiPoly;
  979. if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
  980. }
  981. return this._afterState;
  982. }
  983. /* Is this segment part of the final result? */
  984. isInResult() {
  985. if (this.consumedBy) return false;
  986. if (this._isInResult !== void 0) return this._isInResult;
  987. const mpsBefore = this.beforeState().multiPolys;
  988. const mpsAfter = this.afterState().multiPolys;
  989. switch (operation_default.type) {
  990. case "union": {
  991. const noBefores = mpsBefore.length === 0;
  992. const noAfters = mpsAfter.length === 0;
  993. this._isInResult = noBefores !== noAfters;
  994. break;
  995. }
  996. case "intersection": {
  997. let least;
  998. let most;
  999. if (mpsBefore.length < mpsAfter.length) {
  1000. least = mpsBefore.length;
  1001. most = mpsAfter.length;
  1002. } else {
  1003. least = mpsAfter.length;
  1004. most = mpsBefore.length;
  1005. }
  1006. this._isInResult = most === operation_default.numMultiPolys && least < most;
  1007. break;
  1008. }
  1009. case "xor": {
  1010. const diff = Math.abs(mpsBefore.length - mpsAfter.length);
  1011. this._isInResult = diff % 2 === 1;
  1012. break;
  1013. }
  1014. case "difference": {
  1015. const isJustSubject = (mps) => mps.length === 1 && mps[0].isSubject;
  1016. this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
  1017. break;
  1018. }
  1019. }
  1020. return this._isInResult;
  1021. }
  1022. };
  1023. // src/geom-in.ts
  1024. var RingIn = class {
  1025. poly;
  1026. isExterior;
  1027. segments;
  1028. bbox;
  1029. constructor(geomRing, poly, isExterior) {
  1030. if (!Array.isArray(geomRing) || geomRing.length === 0) {
  1031. throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
  1032. }
  1033. this.poly = poly;
  1034. this.isExterior = isExterior;
  1035. this.segments = [];
  1036. if (typeof geomRing[0][0] !== "number" || typeof geomRing[0][1] !== "number") {
  1037. throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
  1038. }
  1039. const firstPoint = precision.snap({ x: new import_bignumber2.default(geomRing[0][0]), y: new import_bignumber2.default(geomRing[0][1]) });
  1040. this.bbox = {
  1041. ll: { x: firstPoint.x, y: firstPoint.y },
  1042. ur: { x: firstPoint.x, y: firstPoint.y }
  1043. };
  1044. let prevPoint = firstPoint;
  1045. for (let i = 1, iMax = geomRing.length; i < iMax; i++) {
  1046. if (typeof geomRing[i][0] !== "number" || typeof geomRing[i][1] !== "number") {
  1047. throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
  1048. }
  1049. const point = precision.snap({ x: new import_bignumber2.default(geomRing[i][0]), y: new import_bignumber2.default(geomRing[i][1]) });
  1050. if (point.x.eq(prevPoint.x) && point.y.eq(prevPoint.y)) continue;
  1051. this.segments.push(Segment.fromRing(prevPoint, point, this));
  1052. if (point.x.isLessThan(this.bbox.ll.x)) this.bbox.ll.x = point.x;
  1053. if (point.y.isLessThan(this.bbox.ll.y)) this.bbox.ll.y = point.y;
  1054. if (point.x.isGreaterThan(this.bbox.ur.x)) this.bbox.ur.x = point.x;
  1055. if (point.y.isGreaterThan(this.bbox.ur.y)) this.bbox.ur.y = point.y;
  1056. prevPoint = point;
  1057. }
  1058. if (!firstPoint.x.eq(prevPoint.x) || !firstPoint.y.eq(prevPoint.y)) {
  1059. this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));
  1060. }
  1061. }
  1062. getSweepEvents() {
  1063. const sweepEvents = [];
  1064. for (let i = 0, iMax = this.segments.length; i < iMax; i++) {
  1065. const segment = this.segments[i];
  1066. sweepEvents.push(segment.leftSE);
  1067. sweepEvents.push(segment.rightSE);
  1068. }
  1069. return sweepEvents;
  1070. }
  1071. };
  1072. var PolyIn = class {
  1073. multiPoly;
  1074. exteriorRing;
  1075. interiorRings;
  1076. bbox;
  1077. constructor(geomPoly, multiPoly) {
  1078. if (!Array.isArray(geomPoly)) {
  1079. throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
  1080. }
  1081. this.exteriorRing = new RingIn(geomPoly[0], this, true);
  1082. this.bbox = {
  1083. ll: { x: this.exteriorRing.bbox.ll.x, y: this.exteriorRing.bbox.ll.y },
  1084. ur: { x: this.exteriorRing.bbox.ur.x, y: this.exteriorRing.bbox.ur.y }
  1085. };
  1086. this.interiorRings = [];
  1087. for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {
  1088. const ring = new RingIn(geomPoly[i], this, false);
  1089. if (ring.bbox.ll.x.isLessThan(this.bbox.ll.x)) this.bbox.ll.x = ring.bbox.ll.x;
  1090. if (ring.bbox.ll.y.isLessThan(this.bbox.ll.y)) this.bbox.ll.y = ring.bbox.ll.y;
  1091. if (ring.bbox.ur.x.isGreaterThan(this.bbox.ur.x)) this.bbox.ur.x = ring.bbox.ur.x;
  1092. if (ring.bbox.ur.y.isGreaterThan(this.bbox.ur.y)) this.bbox.ur.y = ring.bbox.ur.y;
  1093. this.interiorRings.push(ring);
  1094. }
  1095. this.multiPoly = multiPoly;
  1096. }
  1097. getSweepEvents() {
  1098. const sweepEvents = this.exteriorRing.getSweepEvents();
  1099. for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
  1100. const ringSweepEvents = this.interiorRings[i].getSweepEvents();
  1101. for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
  1102. sweepEvents.push(ringSweepEvents[j]);
  1103. }
  1104. }
  1105. return sweepEvents;
  1106. }
  1107. };
  1108. var MultiPolyIn = class {
  1109. isSubject;
  1110. polys;
  1111. bbox;
  1112. constructor(geom, isSubject) {
  1113. if (!Array.isArray(geom)) {
  1114. throw new Error("Input geometry is not a valid Polygon or MultiPolygon");
  1115. }
  1116. try {
  1117. if (typeof geom[0][0][0] === "number") geom = [geom];
  1118. } catch (ex) {
  1119. }
  1120. this.polys = [];
  1121. this.bbox = {
  1122. ll: { x: new import_bignumber2.default(Number.POSITIVE_INFINITY), y: new import_bignumber2.default(Number.POSITIVE_INFINITY) },
  1123. ur: { x: new import_bignumber2.default(Number.NEGATIVE_INFINITY), y: new import_bignumber2.default(Number.NEGATIVE_INFINITY) }
  1124. };
  1125. for (let i = 0, iMax = geom.length; i < iMax; i++) {
  1126. const poly = new PolyIn(geom[i], this);
  1127. if (poly.bbox.ll.x.isLessThan(this.bbox.ll.x)) this.bbox.ll.x = poly.bbox.ll.x;
  1128. if (poly.bbox.ll.y.isLessThan(this.bbox.ll.y)) this.bbox.ll.y = poly.bbox.ll.y;
  1129. if (poly.bbox.ur.x.isGreaterThan(this.bbox.ur.x)) this.bbox.ur.x = poly.bbox.ur.x;
  1130. if (poly.bbox.ur.y.isGreaterThan(this.bbox.ur.y)) this.bbox.ur.y = poly.bbox.ur.y;
  1131. this.polys.push(poly);
  1132. }
  1133. this.isSubject = isSubject;
  1134. }
  1135. getSweepEvents() {
  1136. const sweepEvents = [];
  1137. for (let i = 0, iMax = this.polys.length; i < iMax; i++) {
  1138. const polySweepEvents = this.polys[i].getSweepEvents();
  1139. for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
  1140. sweepEvents.push(polySweepEvents[j]);
  1141. }
  1142. }
  1143. return sweepEvents;
  1144. }
  1145. };
  1146. // src/index.ts
  1147. var union = (geom, ...moreGeoms) => operation_default.run("union", geom, moreGeoms);
  1148. var intersection2 = (geom, ...moreGeoms) => operation_default.run("intersection", geom, moreGeoms);
  1149. var xor = (geom, ...moreGeoms) => operation_default.run("xor", geom, moreGeoms);
  1150. var difference = (geom, ...moreGeoms) => operation_default.run("difference", geom, moreGeoms);
  1151. var setPrecision = precision.set;
  1152. // Annotate the CommonJS export names for ESM import in node:
  1153. 0 && (module.exports = {
  1154. difference,
  1155. intersection,
  1156. setPrecision,
  1157. union,
  1158. xor
  1159. });
  1160. //# sourceMappingURL=index.cjs.map