clipper2-ts 1.5.4-3.9a869ba

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/dist/Core.js ADDED
@@ -0,0 +1,645 @@
1
+ "use strict";
2
+ /*******************************************************************************
3
+ * Author : Angus Johnson *
4
+ * Date : 12 October 2025 *
5
+ * Website : https://www.angusj.com *
6
+ * Copyright : Angus Johnson 2010-2025 *
7
+ * Purpose : Core structures and functions for the Clipper Library *
8
+ * License : https://www.boost.org/LICENSE_1_0.txt *
9
+ *******************************************************************************/
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.InvalidRectD = exports.InvalidRect64 = exports.PathsUtils = exports.PathUtils = exports.RectDUtils = exports.Rect64Utils = exports.PointDUtils = exports.Point64Utils = exports.InternalClipper = exports.PointInPolygonResult = exports.FillRule = exports.PathType = exports.ClipType = void 0;
12
+ // Note: all clipping operations except for Difference are commutative.
13
+ var ClipType;
14
+ (function (ClipType) {
15
+ ClipType[ClipType["NoClip"] = 0] = "NoClip";
16
+ ClipType[ClipType["Intersection"] = 1] = "Intersection";
17
+ ClipType[ClipType["Union"] = 2] = "Union";
18
+ ClipType[ClipType["Difference"] = 3] = "Difference";
19
+ ClipType[ClipType["Xor"] = 4] = "Xor";
20
+ })(ClipType || (exports.ClipType = ClipType = {}));
21
+ var PathType;
22
+ (function (PathType) {
23
+ PathType[PathType["Subject"] = 0] = "Subject";
24
+ PathType[PathType["Clip"] = 1] = "Clip";
25
+ })(PathType || (exports.PathType = PathType = {}));
26
+ // By far the most widely used filling rules for polygons are EvenOdd
27
+ // and NonZero, sometimes called Alternate and Winding respectively.
28
+ // https://en.wikipedia.org/wiki/Nonzero-rule
29
+ var FillRule;
30
+ (function (FillRule) {
31
+ FillRule[FillRule["EvenOdd"] = 0] = "EvenOdd";
32
+ FillRule[FillRule["NonZero"] = 1] = "NonZero";
33
+ FillRule[FillRule["Positive"] = 2] = "Positive";
34
+ FillRule[FillRule["Negative"] = 3] = "Negative";
35
+ })(FillRule || (exports.FillRule = FillRule = {}));
36
+ // PointInPolygon
37
+ var PointInPolygonResult;
38
+ (function (PointInPolygonResult) {
39
+ PointInPolygonResult[PointInPolygonResult["IsOn"] = 0] = "IsOn";
40
+ PointInPolygonResult[PointInPolygonResult["IsInside"] = 1] = "IsInside";
41
+ PointInPolygonResult[PointInPolygonResult["IsOutside"] = 2] = "IsOutside";
42
+ })(PointInPolygonResult || (exports.PointInPolygonResult = PointInPolygonResult = {}));
43
+ var InternalClipper;
44
+ (function (InternalClipper) {
45
+ InternalClipper.MaxInt64 = 9223372036854775807n;
46
+ InternalClipper.MaxCoord = Number(InternalClipper.MaxInt64 / 4n);
47
+ InternalClipper.max_coord = InternalClipper.MaxCoord;
48
+ InternalClipper.min_coord = -InternalClipper.MaxCoord;
49
+ InternalClipper.Invalid64 = Number(InternalClipper.MaxInt64);
50
+ InternalClipper.floatingPointTolerance = 1E-12;
51
+ InternalClipper.defaultMinimumEdgeLength = 0.1;
52
+ function crossProduct(pt1, pt2, pt3) {
53
+ // typecast to avoid potential int overflow
54
+ return ((pt2.x - pt1.x) * (pt3.y - pt2.y) -
55
+ (pt2.y - pt1.y) * (pt3.x - pt2.x));
56
+ }
57
+ InternalClipper.crossProduct = crossProduct;
58
+ function crossProductSign(pt1, pt2, pt3) {
59
+ const a = pt2.x - pt1.x;
60
+ const b = pt3.y - pt2.y;
61
+ const c = pt2.y - pt1.y;
62
+ const d = pt3.x - pt2.x;
63
+ const ab = multiplyUInt64(Math.abs(a), Math.abs(b));
64
+ const cd = multiplyUInt64(Math.abs(c), Math.abs(d));
65
+ const signAB = triSign(a) * triSign(b);
66
+ const signCD = triSign(c) * triSign(d);
67
+ if (signAB === signCD) {
68
+ let result;
69
+ if (ab.hi64 === cd.hi64) {
70
+ if (ab.lo64 === cd.lo64)
71
+ return 0;
72
+ result = (ab.lo64 > cd.lo64) ? 1 : -1;
73
+ }
74
+ else {
75
+ result = (ab.hi64 > cd.hi64) ? 1 : -1;
76
+ }
77
+ return (signAB > 0) ? result : -result;
78
+ }
79
+ return (signAB > signCD) ? 1 : -1;
80
+ }
81
+ InternalClipper.crossProductSign = crossProductSign;
82
+ function checkPrecision(precision) {
83
+ if (precision < -8 || precision > 8) {
84
+ throw new Error("Error: Precision is out of range.");
85
+ }
86
+ }
87
+ InternalClipper.checkPrecision = checkPrecision;
88
+ function isAlmostZero(value) {
89
+ return Math.abs(value) <= InternalClipper.floatingPointTolerance;
90
+ }
91
+ InternalClipper.isAlmostZero = isAlmostZero;
92
+ function triSign(x) {
93
+ return (x < 0) ? -1 : (x > 0) ? 1 : 0;
94
+ }
95
+ InternalClipper.triSign = triSign;
96
+ function multiplyUInt64(a, b) {
97
+ // Convert to BigInt for accurate 64-bit multiplication
98
+ const aBig = BigInt(a >>> 0); // Ensure unsigned
99
+ const bBig = BigInt(b >>> 0);
100
+ const x1 = (aBig & 0xffffffffn) * (bBig & 0xffffffffn);
101
+ const x2 = (aBig >> 32n) * (bBig & 0xffffffffn) + (x1 >> 32n);
102
+ const x3 = (aBig & 0xffffffffn) * (bBig >> 32n) + (x2 & 0xffffffffn);
103
+ const lobits = (x3 & 0xffffffffn) << 32n | (x1 & 0xffffffffn);
104
+ const hibits = (aBig >> 32n) * (bBig >> 32n) + (x2 >> 32n) + (x3 >> 32n);
105
+ return {
106
+ lo64: Number(lobits & 0xffffffffffffffffn),
107
+ hi64: Number(hibits & 0xffffffffffffffffn)
108
+ };
109
+ }
110
+ InternalClipper.multiplyUInt64 = multiplyUInt64;
111
+ // returns true if (and only if) a * b == c * d
112
+ function productsAreEqual(a, b, c, d) {
113
+ // nb: unsigned values will be needed for CalcOverflowCarry()
114
+ const absA = Math.abs(a);
115
+ const absB = Math.abs(b);
116
+ const absC = Math.abs(c);
117
+ const absD = Math.abs(d);
118
+ // fast path for typical coordinates: 46341^2 < 2^31 (safe for JS number multiplication)
119
+ if (absA < 46341 && absB < 46341 && absC < 46341 && absD < 46341) {
120
+ return a * b === c * d;
121
+ }
122
+ const mulAb = multiplyUInt64(absA, absB);
123
+ const mulCd = multiplyUInt64(absC, absD);
124
+ // nb: it's important to differentiate 0 values here from other values
125
+ const signAb = triSign(a) * triSign(b);
126
+ const signCd = triSign(c) * triSign(d);
127
+ return mulAb.lo64 === mulCd.lo64 && mulAb.hi64 === mulCd.hi64 && signAb === signCd;
128
+ }
129
+ InternalClipper.productsAreEqual = productsAreEqual;
130
+ function isCollinear(pt1, sharedPt, pt2) {
131
+ const a = sharedPt.x - pt1.x;
132
+ const b = pt2.y - sharedPt.y;
133
+ const c = sharedPt.y - pt1.y;
134
+ const d = pt2.x - sharedPt.x;
135
+ // When checking for collinearity with very large coordinate values
136
+ // then ProductsAreEqual is more accurate than using CrossProduct.
137
+ return productsAreEqual(a, b, c, d);
138
+ }
139
+ InternalClipper.isCollinear = isCollinear;
140
+ function dotProduct(pt1, pt2, pt3) {
141
+ // typecast to avoid potential int overflow
142
+ return ((pt2.x - pt1.x) * (pt3.x - pt2.x) +
143
+ (pt2.y - pt1.y) * (pt3.y - pt2.y));
144
+ }
145
+ InternalClipper.dotProduct = dotProduct;
146
+ function crossProductD(vec1, vec2) {
147
+ return (vec1.y * vec2.x - vec2.y * vec1.x);
148
+ }
149
+ InternalClipper.crossProductD = crossProductD;
150
+ function dotProductD(vec1, vec2) {
151
+ return (vec1.x * vec2.x + vec1.y * vec2.y);
152
+ }
153
+ InternalClipper.dotProductD = dotProductD;
154
+ // Banker's rounding (round half to even) to match C# MidpointRounding.ToEven
155
+ function roundToEven(value) {
156
+ // Use the built-in behavior that's closer to C# MidpointRounding.ToEven
157
+ // JavaScript's Math.round actually implements "round half away from zero"
158
+ // but for most practical cases, the difference is minimal
159
+ const floor = Math.floor(value);
160
+ const diff = value - floor;
161
+ if (Math.abs(diff - 0.5) < 1e-10) {
162
+ // Exactly halfway - round to even
163
+ return floor % 2 === 0 ? floor : floor + 1;
164
+ }
165
+ return Math.round(value);
166
+ }
167
+ InternalClipper.roundToEven = roundToEven;
168
+ function checkCastInt64(val) {
169
+ if ((val >= InternalClipper.max_coord) || (val <= InternalClipper.min_coord))
170
+ return InternalClipper.Invalid64;
171
+ return Math.round(val);
172
+ }
173
+ InternalClipper.checkCastInt64 = checkCastInt64;
174
+ // GetLineIntersectPt - a 'true' result is non-parallel. The 'ip' will also
175
+ // be constrained to seg1. However, it's possible that 'ip' won't be inside
176
+ // seg2, even when 'ip' hasn't been constrained (ie 'ip' is inside seg1).
177
+ function getLineIntersectPt(ln1a, ln1b, ln2a, ln2b) {
178
+ const dy1 = (ln1b.y - ln1a.y);
179
+ const dx1 = (ln1b.x - ln1a.x);
180
+ const dy2 = (ln2b.y - ln2a.y);
181
+ const dx2 = (ln2b.x - ln2a.x);
182
+ const det = dy1 * dx2 - dy2 * dx1;
183
+ if (det === 0.0) {
184
+ return { intersects: false, point: { x: 0, y: 0 } };
185
+ }
186
+ const t = ((ln1a.x - ln2a.x) * dy2 - (ln1a.y - ln2a.y) * dx2) / det;
187
+ let ip;
188
+ if (t <= 0.0) {
189
+ ip = { x: ln1a.x, y: ln1a.y }; // Create a copy to avoid mutating original
190
+ }
191
+ else if (t >= 1.0) {
192
+ ip = { x: ln1b.x, y: ln1b.y }; // Create a copy to avoid mutating original
193
+ }
194
+ else {
195
+ // avoid using constructor (and rounding too) as they affect performance
196
+ // Use Math.trunc to match C# (long) cast behavior which truncates towards zero
197
+ const rawX = ln1a.x + t * dx1;
198
+ const rawY = ln1a.y + t * dy1;
199
+ ip = {
200
+ x: Math.trunc(rawX),
201
+ y: Math.trunc(rawY)
202
+ };
203
+ }
204
+ return { intersects: true, point: ip };
205
+ }
206
+ InternalClipper.getLineIntersectPt = getLineIntersectPt;
207
+ function getLineIntersectPtD(ln1a, ln1b, ln2a, ln2b) {
208
+ const dy1 = ln1b.y - ln1a.y;
209
+ const dx1 = ln1b.x - ln1a.x;
210
+ const dy2 = ln2b.y - ln2a.y;
211
+ const dx2 = ln2b.x - ln2a.x;
212
+ const det = dy1 * dx2 - dy2 * dx1;
213
+ if (det === 0.0) {
214
+ return { success: false, ip: { x: 0, y: 0 } };
215
+ }
216
+ const t = ((ln1a.x - ln2a.x) * dy2 - (ln1a.y - ln2a.y) * dx2) / det;
217
+ let ip;
218
+ if (t <= 0.0) {
219
+ ip = { ...ln1a };
220
+ }
221
+ else if (t >= 1.0) {
222
+ ip = { ...ln1b };
223
+ }
224
+ else {
225
+ ip = {
226
+ x: ln1a.x + t * dx1,
227
+ y: ln1a.y + t * dy1
228
+ };
229
+ }
230
+ return { success: true, ip };
231
+ }
232
+ InternalClipper.getLineIntersectPtD = getLineIntersectPtD;
233
+ function segsIntersect(seg1a, seg1b, seg2a, seg2b, inclusive = false) {
234
+ if (!inclusive) {
235
+ // Match C# fast path - use cross product multiplication
236
+ // This avoids floating point equality checks (safer than === 0)
237
+ return (crossProduct(seg1a, seg2a, seg2b) *
238
+ crossProduct(seg1b, seg2a, seg2b) < 0) &&
239
+ (crossProduct(seg2a, seg1a, seg1b) *
240
+ crossProduct(seg2b, seg1a, seg1b) < 0);
241
+ }
242
+ // Inclusive case - match C# implementation
243
+ const res1 = crossProduct(seg1a, seg2a, seg2b);
244
+ const res2 = crossProduct(seg1b, seg2a, seg2b);
245
+ if (res1 * res2 > 0)
246
+ return false;
247
+ const res3 = crossProduct(seg2a, seg1a, seg1b);
248
+ const res4 = crossProduct(seg2b, seg1a, seg1b);
249
+ if (res3 * res4 > 0)
250
+ return false;
251
+ // ensure NOT collinear
252
+ return (res1 !== 0 || res2 !== 0 || res3 !== 0 || res4 !== 0);
253
+ }
254
+ InternalClipper.segsIntersect = segsIntersect;
255
+ function getBounds(path) {
256
+ if (path.length === 0)
257
+ return { left: 0, top: 0, right: 0, bottom: 0 };
258
+ const result = {
259
+ left: Number.MAX_SAFE_INTEGER,
260
+ top: Number.MAX_SAFE_INTEGER,
261
+ right: Number.MIN_SAFE_INTEGER,
262
+ bottom: Number.MIN_SAFE_INTEGER
263
+ };
264
+ for (const pt of path) {
265
+ if (pt.x < result.left)
266
+ result.left = pt.x;
267
+ if (pt.x > result.right)
268
+ result.right = pt.x;
269
+ if (pt.y < result.top)
270
+ result.top = pt.y;
271
+ if (pt.y > result.bottom)
272
+ result.bottom = pt.y;
273
+ }
274
+ return result.left === Number.MAX_SAFE_INTEGER ?
275
+ { left: 0, top: 0, right: 0, bottom: 0 } : result;
276
+ }
277
+ InternalClipper.getBounds = getBounds;
278
+ function getClosestPtOnSegment(offPt, seg1, seg2) {
279
+ if (seg1.x === seg2.x && seg1.y === seg2.y)
280
+ return { x: seg1.x, y: seg1.y }; // Return copy, not reference
281
+ const dx = (seg2.x - seg1.x);
282
+ const dy = (seg2.y - seg1.y);
283
+ const q = ((offPt.x - seg1.x) * dx + (offPt.y - seg1.y) * dy) / ((dx * dx) + (dy * dy));
284
+ const qClamped = q < 0 ? 0 : (q > 1 ? 1 : q);
285
+ return {
286
+ // use Math.round to match the C# MidpointRounding.ToEven behavior
287
+ x: Math.round(seg1.x + qClamped * dx),
288
+ y: Math.round(seg1.y + qClamped * dy)
289
+ };
290
+ }
291
+ InternalClipper.getClosestPtOnSegment = getClosestPtOnSegment;
292
+ function pointInPolygon(pt, polygon) {
293
+ const len = polygon.length;
294
+ let start = 0;
295
+ if (len < 3)
296
+ return PointInPolygonResult.IsOutside;
297
+ while (start < len && polygon[start].y === pt.y)
298
+ start++;
299
+ if (start === len)
300
+ return PointInPolygonResult.IsOutside;
301
+ let isAbove = polygon[start].y < pt.y;
302
+ const startingAbove = isAbove;
303
+ let val = 0;
304
+ let i = start + 1;
305
+ let end = len;
306
+ while (true) {
307
+ if (i === end) {
308
+ if (end === 0 || start === 0)
309
+ break;
310
+ end = start;
311
+ i = 0;
312
+ }
313
+ if (isAbove) {
314
+ while (i < end && polygon[i].y < pt.y)
315
+ i++;
316
+ }
317
+ else {
318
+ while (i < end && polygon[i].y > pt.y)
319
+ i++;
320
+ }
321
+ if (i === end)
322
+ continue;
323
+ const curr = polygon[i];
324
+ const prev = i > 0 ? polygon[i - 1] : polygon[len - 1];
325
+ if (curr.y === pt.y) {
326
+ if (curr.x === pt.x || (curr.y === prev.y &&
327
+ ((pt.x < prev.x) !== (pt.x < curr.x)))) {
328
+ return PointInPolygonResult.IsOn;
329
+ }
330
+ i++;
331
+ if (i === start)
332
+ break;
333
+ continue;
334
+ }
335
+ if (pt.x < curr.x && pt.x < prev.x) {
336
+ // we're only interested in edges crossing on the left
337
+ }
338
+ else if (pt.x > prev.x && pt.x > curr.x) {
339
+ val = 1 - val; // toggle val
340
+ }
341
+ else {
342
+ const cps = crossProductSign(prev, curr, pt);
343
+ if (cps === 0)
344
+ return PointInPolygonResult.IsOn;
345
+ if ((cps < 0) === isAbove)
346
+ val = 1 - val;
347
+ }
348
+ isAbove = !isAbove;
349
+ i++;
350
+ }
351
+ if (isAbove === startingAbove) {
352
+ return val === 0 ? PointInPolygonResult.IsOutside : PointInPolygonResult.IsInside;
353
+ }
354
+ if (i === len)
355
+ i = 0;
356
+ const cps = i === 0 ?
357
+ crossProductSign(polygon[len - 1], polygon[0], pt) :
358
+ crossProductSign(polygon[i - 1], polygon[i], pt);
359
+ if (cps === 0)
360
+ return PointInPolygonResult.IsOn;
361
+ if ((cps < 0) === isAbove)
362
+ val = 1 - val;
363
+ return val === 0 ? PointInPolygonResult.IsOutside : PointInPolygonResult.IsInside;
364
+ }
365
+ InternalClipper.pointInPolygon = pointInPolygon;
366
+ function path2ContainsPath1(path1, path2) {
367
+ // we need to make some accommodation for rounding errors
368
+ // so we won't jump if the first vertex is found outside
369
+ let pip = PointInPolygonResult.IsOn;
370
+ for (const pt of path1) {
371
+ switch (pointInPolygon(pt, path2)) {
372
+ case PointInPolygonResult.IsOutside:
373
+ if (pip === PointInPolygonResult.IsOutside)
374
+ return false;
375
+ pip = PointInPolygonResult.IsOutside;
376
+ break;
377
+ case PointInPolygonResult.IsInside:
378
+ if (pip === PointInPolygonResult.IsInside)
379
+ return true;
380
+ pip = PointInPolygonResult.IsInside;
381
+ break;
382
+ default:
383
+ break;
384
+ }
385
+ }
386
+ // since path1's location is still equivocal, check its midpoint
387
+ const mp = getBounds(path1);
388
+ const midPt = {
389
+ x: Math.round((mp.left + mp.right) / 2),
390
+ y: Math.round((mp.top + mp.bottom) / 2)
391
+ };
392
+ return pointInPolygon(midPt, path2) !== PointInPolygonResult.IsOutside;
393
+ }
394
+ InternalClipper.path2ContainsPath1 = path2ContainsPath1;
395
+ })(InternalClipper || (exports.InternalClipper = InternalClipper = {}));
396
+ // Point64 utility functions
397
+ var Point64Utils;
398
+ (function (Point64Utils) {
399
+ function create(x = 0, y = 0) {
400
+ return { x: Math.round(x), y: Math.round(y) };
401
+ }
402
+ Point64Utils.create = create;
403
+ function fromPointD(pt) {
404
+ return { x: Math.round(pt.x), y: Math.round(pt.y) };
405
+ }
406
+ Point64Utils.fromPointD = fromPointD;
407
+ function scale(pt, scale) {
408
+ return {
409
+ x: Math.round(pt.x * scale),
410
+ y: Math.round(pt.y * scale)
411
+ };
412
+ }
413
+ Point64Utils.scale = scale;
414
+ function equals(a, b) {
415
+ return a.x === b.x && a.y === b.y;
416
+ }
417
+ Point64Utils.equals = equals;
418
+ function add(a, b) {
419
+ return { x: a.x + b.x, y: a.y + b.y };
420
+ }
421
+ Point64Utils.add = add;
422
+ function subtract(a, b) {
423
+ return { x: a.x - b.x, y: a.y - b.y };
424
+ }
425
+ Point64Utils.subtract = subtract;
426
+ function toString(pt) {
427
+ return `${pt.x},${pt.y} `;
428
+ }
429
+ Point64Utils.toString = toString;
430
+ })(Point64Utils || (exports.Point64Utils = Point64Utils = {}));
431
+ // PointD utility functions
432
+ var PointDUtils;
433
+ (function (PointDUtils) {
434
+ function create(x = 0, y = 0) {
435
+ return { x, y };
436
+ }
437
+ PointDUtils.create = create;
438
+ function fromPoint64(pt) {
439
+ return { x: pt.x, y: pt.y };
440
+ }
441
+ PointDUtils.fromPoint64 = fromPoint64;
442
+ function scale(pt, scale) {
443
+ return { x: pt.x * scale, y: pt.y * scale };
444
+ }
445
+ PointDUtils.scale = scale;
446
+ function equals(a, b) {
447
+ return InternalClipper.isAlmostZero(a.x - b.x) &&
448
+ InternalClipper.isAlmostZero(a.y - b.y);
449
+ }
450
+ PointDUtils.equals = equals;
451
+ function negate(pt) {
452
+ pt.x = -pt.x;
453
+ pt.y = -pt.y;
454
+ }
455
+ PointDUtils.negate = negate;
456
+ function toString(pt, precision = 2) {
457
+ return `${pt.x.toFixed(precision)},${pt.y.toFixed(precision)}`;
458
+ }
459
+ PointDUtils.toString = toString;
460
+ })(PointDUtils || (exports.PointDUtils = PointDUtils = {}));
461
+ // Rect64 utility functions
462
+ var Rect64Utils;
463
+ (function (Rect64Utils) {
464
+ function create(l = 0, t = 0, r = 0, b = 0) {
465
+ return { left: l, top: t, right: r, bottom: b };
466
+ }
467
+ Rect64Utils.create = create;
468
+ function createInvalid() {
469
+ return {
470
+ left: Number.MAX_SAFE_INTEGER,
471
+ top: Number.MAX_SAFE_INTEGER,
472
+ right: Number.MIN_SAFE_INTEGER,
473
+ bottom: Number.MIN_SAFE_INTEGER
474
+ };
475
+ }
476
+ Rect64Utils.createInvalid = createInvalid;
477
+ function width(rect) {
478
+ return rect.right - rect.left;
479
+ }
480
+ Rect64Utils.width = width;
481
+ function height(rect) {
482
+ return rect.bottom - rect.top;
483
+ }
484
+ Rect64Utils.height = height;
485
+ function isEmpty(rect) {
486
+ return rect.bottom <= rect.top || rect.right <= rect.left;
487
+ }
488
+ Rect64Utils.isEmpty = isEmpty;
489
+ function isValid(rect) {
490
+ return rect.left < Number.MAX_SAFE_INTEGER;
491
+ }
492
+ Rect64Utils.isValid = isValid;
493
+ function midPoint(rect) {
494
+ return {
495
+ x: Math.round((rect.left + rect.right) / 2),
496
+ y: Math.round((rect.top + rect.bottom) / 2)
497
+ };
498
+ }
499
+ Rect64Utils.midPoint = midPoint;
500
+ function contains(rect, pt) {
501
+ return pt.x > rect.left && pt.x < rect.right &&
502
+ pt.y > rect.top && pt.y < rect.bottom;
503
+ }
504
+ Rect64Utils.contains = contains;
505
+ function containsRect(rect, rec) {
506
+ return rec.left >= rect.left && rec.right <= rect.right &&
507
+ rec.top >= rect.top && rec.bottom <= rect.bottom;
508
+ }
509
+ Rect64Utils.containsRect = containsRect;
510
+ function intersects(rect, rec) {
511
+ return (Math.max(rect.left, rec.left) <= Math.min(rect.right, rec.right)) &&
512
+ (Math.max(rect.top, rec.top) <= Math.min(rect.bottom, rec.bottom));
513
+ }
514
+ Rect64Utils.intersects = intersects;
515
+ function asPath(rect) {
516
+ return [
517
+ { x: rect.left, y: rect.top },
518
+ { x: rect.right, y: rect.top },
519
+ { x: rect.right, y: rect.bottom },
520
+ { x: rect.left, y: rect.bottom }
521
+ ];
522
+ }
523
+ Rect64Utils.asPath = asPath;
524
+ })(Rect64Utils || (exports.Rect64Utils = Rect64Utils = {}));
525
+ // RectD utility functions
526
+ var RectDUtils;
527
+ (function (RectDUtils) {
528
+ function create(l = 0, t = 0, r = 0, b = 0) {
529
+ return { left: l, top: t, right: r, bottom: b };
530
+ }
531
+ RectDUtils.create = create;
532
+ function createInvalid() {
533
+ return {
534
+ left: Number.MAX_VALUE,
535
+ top: Number.MAX_VALUE,
536
+ right: -Number.MAX_VALUE,
537
+ bottom: -Number.MAX_VALUE
538
+ };
539
+ }
540
+ RectDUtils.createInvalid = createInvalid;
541
+ function width(rect) {
542
+ return rect.right - rect.left;
543
+ }
544
+ RectDUtils.width = width;
545
+ function height(rect) {
546
+ return rect.bottom - rect.top;
547
+ }
548
+ RectDUtils.height = height;
549
+ function isEmpty(rect) {
550
+ return rect.bottom <= rect.top || rect.right <= rect.left;
551
+ }
552
+ RectDUtils.isEmpty = isEmpty;
553
+ function midPoint(rect) {
554
+ return {
555
+ x: (rect.left + rect.right) / 2,
556
+ y: (rect.top + rect.bottom) / 2
557
+ };
558
+ }
559
+ RectDUtils.midPoint = midPoint;
560
+ function contains(rect, pt) {
561
+ return pt.x > rect.left && pt.x < rect.right &&
562
+ pt.y > rect.top && pt.y < rect.bottom;
563
+ }
564
+ RectDUtils.contains = contains;
565
+ function containsRect(rect, rec) {
566
+ return rec.left >= rect.left && rec.right <= rect.right &&
567
+ rec.top >= rect.top && rec.bottom <= rect.bottom;
568
+ }
569
+ RectDUtils.containsRect = containsRect;
570
+ function intersects(rect, rec) {
571
+ return (Math.max(rect.left, rec.left) < Math.min(rect.right, rec.right)) &&
572
+ (Math.max(rect.top, rec.top) < Math.min(rect.bottom, rec.bottom));
573
+ }
574
+ RectDUtils.intersects = intersects;
575
+ function asPath(rect) {
576
+ return [
577
+ { x: rect.left, y: rect.top },
578
+ { x: rect.right, y: rect.top },
579
+ { x: rect.right, y: rect.bottom },
580
+ { x: rect.left, y: rect.bottom }
581
+ ];
582
+ }
583
+ RectDUtils.asPath = asPath;
584
+ })(RectDUtils || (exports.RectDUtils = RectDUtils = {}));
585
+ // Path utility functions
586
+ var PathUtils;
587
+ (function (PathUtils) {
588
+ function toString64(path) {
589
+ let result = "";
590
+ for (const pt of path) {
591
+ result += Point64Utils.toString(pt);
592
+ }
593
+ return result + '\n';
594
+ }
595
+ PathUtils.toString64 = toString64;
596
+ function toStringD(path, precision = 2) {
597
+ let result = "";
598
+ for (const pt of path) {
599
+ result += PointDUtils.toString(pt, precision) + ", ";
600
+ }
601
+ if (result !== "")
602
+ result = result.slice(0, -2);
603
+ return result;
604
+ }
605
+ PathUtils.toStringD = toStringD;
606
+ function reverse64(path) {
607
+ return [...path].reverse();
608
+ }
609
+ PathUtils.reverse64 = reverse64;
610
+ function reverseD(path) {
611
+ return [...path].reverse();
612
+ }
613
+ PathUtils.reverseD = reverseD;
614
+ })(PathUtils || (exports.PathUtils = PathUtils = {}));
615
+ var PathsUtils;
616
+ (function (PathsUtils) {
617
+ function toString64(paths) {
618
+ let result = "";
619
+ for (const path of paths) {
620
+ result += PathUtils.toString64(path);
621
+ }
622
+ return result;
623
+ }
624
+ PathsUtils.toString64 = toString64;
625
+ function toStringD(paths, precision = 2) {
626
+ let result = "";
627
+ for (const path of paths) {
628
+ result += PathUtils.toStringD(path, precision) + "\n";
629
+ }
630
+ return result;
631
+ }
632
+ PathsUtils.toStringD = toStringD;
633
+ function reverse64(paths) {
634
+ return paths.map(path => PathUtils.reverse64(path));
635
+ }
636
+ PathsUtils.reverse64 = reverse64;
637
+ function reverseD(paths) {
638
+ return paths.map(path => PathUtils.reverseD(path));
639
+ }
640
+ PathsUtils.reverseD = reverseD;
641
+ })(PathsUtils || (exports.PathsUtils = PathsUtils = {}));
642
+ // Constants
643
+ exports.InvalidRect64 = Rect64Utils.createInvalid();
644
+ exports.InvalidRectD = RectDUtils.createInvalid();
645
+ //# sourceMappingURL=Core.js.map