pattapatta 0.2.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +98 -0
  4. package/dist/circle-BDbKfrdR.d.ts +12 -0
  5. package/dist/circlePacking/index.d.ts +78 -0
  6. package/dist/circlePacking/index.js +381 -0
  7. package/dist/circlePacking/index.js.map +1 -0
  8. package/dist/cli.js +365 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/construction/index.d.ts +26 -0
  11. package/dist/construction/index.js +102 -0
  12. package/dist/construction/index.js.map +1 -0
  13. package/dist/contour/index.d.ts +20 -0
  14. package/dist/contour/index.js +118 -0
  15. package/dist/contour/index.js.map +1 -0
  16. package/dist/conversion/index.d.ts +31 -0
  17. package/dist/conversion/index.js +99 -0
  18. package/dist/conversion/index.js.map +1 -0
  19. package/dist/group-BNjVVYSQ.d.ts +13 -0
  20. package/dist/hatch/index.d.ts +41 -0
  21. package/dist/hatch/index.js +253 -0
  22. package/dist/hatch/index.js.map +1 -0
  23. package/dist/hull/index.d.ts +16 -0
  24. package/dist/hull/index.js +97 -0
  25. package/dist/hull/index.js.map +1 -0
  26. package/dist/index.d.ts +67 -0
  27. package/dist/index.js +3933 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/meshing/index.d.ts +125 -0
  30. package/dist/meshing/index.js +1333 -0
  31. package/dist/meshing/index.js.map +1 -0
  32. package/dist/morphology/index.d.ts +58 -0
  33. package/dist/morphology/index.js +268 -0
  34. package/dist/morphology/index.js.map +1 -0
  35. package/dist/optimisation/index.d.ts +43 -0
  36. package/dist/optimisation/index.js +400 -0
  37. package/dist/optimisation/index.js.map +1 -0
  38. package/dist/path-0RjhYjJs.d.ts +21 -0
  39. package/dist/pointSet/index.d.ts +24 -0
  40. package/dist/pointSet/index.js +139 -0
  41. package/dist/pointSet/index.js.map +1 -0
  42. package/dist/polygonisation/index.d.ts +44 -0
  43. package/dist/polygonisation/index.js +310 -0
  44. package/dist/polygonisation/index.js.map +1 -0
  45. package/dist/predicates/index.d.ts +35 -0
  46. package/dist/predicates/index.js +159 -0
  47. package/dist/predicates/index.js.map +1 -0
  48. package/dist/processing/index.d.ts +54 -0
  49. package/dist/processing/index.js +457 -0
  50. package/dist/processing/index.js.map +1 -0
  51. package/dist/segment-BKuIFMKD.d.ts +10 -0
  52. package/dist/segmentSet/index.d.ts +25 -0
  53. package/dist/segmentSet/index.js +109 -0
  54. package/dist/segmentSet/index.js.map +1 -0
  55. package/dist/shapeBoolean/index.d.ts +41 -0
  56. package/dist/shapeBoolean/index.js +211 -0
  57. package/dist/shapeBoolean/index.js.map +1 -0
  58. package/dist/svg/index.d.ts +38 -0
  59. package/dist/svg/index.js +317 -0
  60. package/dist/svg/index.js.map +1 -0
  61. package/dist/tiling/index.d.ts +32 -0
  62. package/dist/tiling/index.js +344 -0
  63. package/dist/tiling/index.js.map +1 -0
  64. package/dist/transformation/index.d.ts +37 -0
  65. package/dist/transformation/index.js +184 -0
  66. package/dist/transformation/index.js.map +1 -0
  67. package/dist/triangulation/index.d.ts +48 -0
  68. package/dist/triangulation/index.js +334 -0
  69. package/dist/triangulation/index.js.map +1 -0
  70. package/dist/vec2-CWyXN1Wj.d.ts +10 -0
  71. package/dist/voronoi/index.d.ts +31 -0
  72. package/dist/voronoi/index.js +211 -0
  73. package/dist/voronoi/index.js.map +1 -0
  74. package/package.json +165 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/vec2.ts","../../src/types/path.ts","../../src/predicates/index.ts","../../src/transformation/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/** 2D point / vector. */\nexport type Vec2 = {\n x: number\n y: number\n}\n\nexport function vec2(x: number, y: number): Vec2 {\n return { x, y }\n}\n\nexport function cloneVec2(v: Vec2): Vec2 {\n return { x: v.x, y: v.y }\n}\n\nexport function equalsVec2(a: Vec2, b: Vec2, eps = 1e-9): boolean {\n return Math.abs(a.x - b.x) <= eps && Math.abs(a.y - b.y) <= eps\n}\n","import type { Vec2 } from './vec2.js'\nimport { cloneVec2, equalsVec2 } from './vec2.js'\n\n/** Ordered ring of vertices (typically without repeating the closing vertex). */\nexport type Ring = Vec2[]\n\n/**\n * A path: one exterior ring plus optional holes, or an open polyline.\n * `rings[0]` is the exterior (or the open polyline when `closed` is false).\n * Additional rings are holes (only meaningful when `closed` is true).\n */\nexport type Path = {\n rings: Ring[]\n closed: boolean\n}\n\nexport function path(rings: Ring[], closed = true): Path {\n return {\n rings: rings.map((ring) => ring.map(cloneVec2)),\n closed,\n }\n}\n\nexport function polyline(points: Ring): Path {\n return path([points], false)\n}\n\nexport function polygon(exterior: Ring, holes: Ring[] = []): Path {\n return path([exterior, ...holes], true)\n}\n\n/** Drop a trailing vertex that duplicates the first (SVG often closes this way). */\nexport function normalizeRing(ring: Ring, eps = 1e-9): Ring {\n if (ring.length < 2) return ring.map(cloneVec2)\n const first = ring[0]\n const last = ring[ring.length - 1]\n if (first && last && equalsVec2(first, last, eps)) {\n return ring.slice(0, -1).map(cloneVec2)\n }\n return ring.map(cloneVec2)\n}\n\nexport function clonePath(p: Path): Path {\n return {\n closed: p.closed,\n rings: p.rings.map((ring) => ring.map(cloneVec2)),\n }\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { vec2 } from '../types/index.js'\nimport {\n pathToPathsD,\n pathsArea,\n pointInRing,\n} from '../clipper/convert.js'\n\n/** Signed area of a closed ring (shoelace). */\nexport function ringArea(ring: Vec2[]): number {\n if (ring.length < 3) return 0\n let sum = 0\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % ring.length]!\n sum += a.x * b.y - b.x * a.y\n }\n return sum / 2\n}\n\n/** Absolute area of a closed path (exterior minus holes). */\nexport function area(p: Path): number {\n if (!p.closed || p.rings.length === 0) return 0\n try {\n return pathsArea(pathToPathsD(p))\n } catch {\n let total = 0\n for (let i = 0; i < p.rings.length; i++) {\n const a = Math.abs(ringArea(p.rings[i]!))\n total += i === 0 ? a : -a\n }\n return Math.max(0, total)\n }\n}\n\nexport function areaGroup(g: Group): number {\n return g.paths.reduce((sum, p) => sum + area(p), 0)\n}\n\n/** Centroid of a closed exterior ring (ignores holes for Phase 2). */\nexport function centroid(p: Path): Vec2 {\n const ring = p.rings[0]\n if (!ring || ring.length === 0) return vec2(0, 0)\n const a = ringArea(ring)\n if (Math.abs(a) < 1e-12) {\n let sx = 0\n let sy = 0\n for (const v of ring) {\n sx += v.x\n sy += v.y\n }\n return vec2(sx / ring.length, sy / ring.length)\n }\n let cx = 0\n let cy = 0\n for (let i = 0; i < ring.length; i++) {\n const p0 = ring[i]!\n const p1 = ring[(i + 1) % ring.length]!\n const cross = p0.x * p1.y - p1.x * p0.y\n cx += (p0.x + p1.x) * cross\n cy += (p0.y + p1.y) * cross\n }\n return vec2(cx / (6 * a), cy / (6 * a))\n}\n\nexport function containsPoint(p: Path, point: Vec2): boolean {\n if (!p.closed || !p.rings[0]) return false\n if (!pointInRing(point, p.rings[0])) return false\n for (let i = 1; i < p.rings.length; i++) {\n const hole = p.rings[i]\n if (hole && pointInRing(point, hole)) return false\n }\n return true\n}\n\nexport function bounds(p: Path): {\n minX: number\n minY: number\n maxX: number\n maxY: number\n} {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const ring of p.rings) {\n for (const v of ring) {\n minX = Math.min(minX, v.x)\n minY = Math.min(minY, v.y)\n maxX = Math.max(maxX, v.x)\n maxY = Math.max(maxY, v.y)\n }\n }\n if (!Number.isFinite(minX)) {\n return { minX: 0, minY: 0, maxX: 0, maxY: 0 }\n }\n return { minX, minY, maxX, maxY }\n}\n\nexport function width(p: Path): number {\n const b = bounds(p)\n return b.maxX - b.minX\n}\n\nexport function height(p: Path): number {\n const b = bounds(p)\n return b.maxY - b.minY\n}\n\n/** Rough polygon similarity via absolute area difference relative to max area. */\nexport function areaSimilarity(a: Path, b: Path): number {\n const aa = area(a)\n const bb = area(b)\n const denom = Math.max(aa, bb, 1e-12)\n return 1 - Math.abs(aa - bb) / denom\n}\n\nexport const predicates = {\n area,\n areaGroup,\n ringArea,\n centroid,\n containsPoint,\n bounds,\n width,\n height,\n areaSimilarity,\n}\n","import type { Path, Vec2 } from '../types/index.js'\nimport { path, normalizeRing, clonePath } from '../types/index.js'\nimport { bounds, centroid } from '../predicates/index.js'\n\nfunction mapPath(p: Path, fn: (v: Vec2) => Vec2): Path {\n return path(\n p.rings.map((ring) => normalizeRing(ring.map(fn))),\n p.closed,\n )\n}\n\nexport function translate(p: Path, dx: number, dy: number): Path {\n return mapPath(p, (v) => ({ x: v.x + dx, y: v.y + dy }))\n}\n\nexport function translateToOrigin(p: Path): Path {\n const c = centroid(p)\n return translate(p, -c.x, -c.y)\n}\n\nexport function translateCentroidTo(p: Path, target: Vec2): Path {\n const c = centroid(p)\n return translate(p, target.x - c.x, target.y - c.y)\n}\n\nexport function rotate(p: Path, angleRad: number, pivot?: Vec2): Path {\n const o = pivot ?? { x: 0, y: 0 }\n const cos = Math.cos(angleRad)\n const sin = Math.sin(angleRad)\n return mapPath(p, (v) => {\n const x = v.x - o.x\n const y = v.y - o.y\n return {\n x: o.x + x * cos - y * sin,\n y: o.y + x * sin + y * cos,\n }\n })\n}\n\nexport function rotateAroundCenter(p: Path, angleRad: number): Path {\n return rotate(p, angleRad, centroid(p))\n}\n\nexport function scale(p: Path, sx: number, sy = sx, pivot?: Vec2): Path {\n const o = pivot ?? { x: 0, y: 0 }\n return mapPath(p, (v) => ({\n x: o.x + (v.x - o.x) * sx,\n y: o.y + (v.y - o.y) * sy,\n }))\n}\n\nexport function originScale(p: Path, s: number): Path {\n return scale(p, s, s, { x: 0, y: 0 })\n}\n\nexport function flipHorizontal(p: Path, x = 0): Path {\n return mapPath(p, (v) => ({ x: 2 * x - v.x, y: v.y }))\n}\n\nexport function flipVertical(p: Path, y = 0): Path {\n return mapPath(p, (v) => ({ x: v.x, y: 2 * y - v.y }))\n}\n\n/** Uniform resize so bounding-box width equals `width`. */\nexport function resizeByWidth(p: Path, width: number): Path {\n const b = bounds(p)\n const w = b.maxX - b.minX\n if (w < 1e-12) return clonePath(p)\n return scale(p, width / w, width / w, { x: b.minX, y: b.minY })\n}\n\n/** Uniform resize so bounding-box height equals `height`. */\nexport function resizeByHeight(p: Path, height: number): Path {\n const b = bounds(p)\n const h = b.maxY - b.minY\n if (h < 1e-12) return clonePath(p)\n return scale(p, height / h, height / h, { x: b.minX, y: b.minY })\n}\n\n/** Move the AABB min corner to `target`. */\nexport function translateCornerTo(p: Path, target: Vec2): Path {\n const b = bounds(p)\n return translate(p, target.x - b.minX, target.y - b.minY)\n}\n\n/** Shear: x' = x + shx * y, y' = y + shy * x (about origin or pivot). */\nexport function shear(\n p: Path,\n shx: number,\n shy = 0,\n pivot?: Vec2,\n): Path {\n const o = pivot ?? { x: 0, y: 0 }\n return mapPath(p, (v) => {\n const x = v.x - o.x\n const y = v.y - o.y\n return {\n x: o.x + x + shx * y,\n y: o.y + y + shy * x,\n }\n })\n}\n\nexport const transformation = {\n translate,\n translateToOrigin,\n translateCentroidTo,\n translateCornerTo,\n rotate,\n rotateAroundCenter,\n scale,\n originScale,\n flipHorizontal,\n flipVertical,\n resizeByWidth,\n resizeByHeight,\n shear,\n}\n"]}
@@ -0,0 +1,48 @@
1
+ import { V as Vec2 } from '../vec2-CWyXN1Wj.js';
2
+ import { P as Path } from '../path-0RjhYjJs.js';
3
+
4
+ /**
5
+ * Triangulate a closed path into triangle polygons (Clipper2).
6
+ * Holes are supported when present on the path. `useDelaunay` prefers
7
+ * better-shaped triangles when Clipper can apply it.
8
+ */
9
+ declare function earCutTriangulation(p: Path, options?: {
10
+ useDelaunay?: boolean;
11
+ precision?: number;
12
+ }): Path[];
13
+ /** Alias matching PGS naming for Clipper/Delaunay triangulation of a polygon. */
14
+ declare function delaunayTriangulation(p: Path): Path[];
15
+ /** Delaunay triangulation of a point set (d3-delaunay). */
16
+ declare function delaunayTriangulationPoints(points: Vec2[]): Path[];
17
+ /**
18
+ * Boundary vertices plus Poisson-disk Steiner points inside `path`.
19
+ */
20
+ declare function poissonTriangulationPoints(path: Path, minDistance: number, seed?: number): Vec2[];
21
+ /**
22
+ * Delaunay triangulation of a path with Poisson Steiner points inserted.
23
+ * Triangles whose centroid falls outside the path (or in a hole) are dropped.
24
+ */
25
+ declare function poissonTriangulation(path: Path, minDistance: number, seed?: number): Path[];
26
+ type RefineOptions = {
27
+ /** Minimum allowed interior angle (radians). Default ≈ 20°. */
28
+ minAngle?: number;
29
+ /** Safety cap on Steiner insertions. Default `200`. */
30
+ maxIterations?: number;
31
+ };
32
+ /**
33
+ * Ruppert-inspired angle refinement for plotter meshes.
34
+ * Clean-room approximation (not a full constrained CDT): insert circumcenters
35
+ * of skinny triangles when they lie inside the path; otherwise split the
36
+ * longest edge of that triangle (simple encroachment stand-in).
37
+ */
38
+ declare function refine(path: Path, options?: RefineOptions): Path[];
39
+ declare const triangulation: {
40
+ earCutTriangulation: typeof earCutTriangulation;
41
+ delaunayTriangulation: typeof delaunayTriangulation;
42
+ delaunayTriangulationPoints: typeof delaunayTriangulationPoints;
43
+ poissonTriangulation: typeof poissonTriangulation;
44
+ poissonTriangulationPoints: typeof poissonTriangulationPoints;
45
+ refine: typeof refine;
46
+ };
47
+
48
+ export { type RefineOptions, delaunayTriangulation, delaunayTriangulationPoints, earCutTriangulation, poissonTriangulation, poissonTriangulationPoints, refine, triangulation };
@@ -0,0 +1,334 @@
1
+ import { FillRule, triangulateD, pointInPolygonD, PointInPolygonResult } from 'clipper2-ts';
2
+ import { Delaunay } from 'd3-delaunay';
3
+
4
+ // src/triangulation/index.ts
5
+
6
+ // src/types/vec2.ts
7
+ function vec2(x, y) {
8
+ return { x, y };
9
+ }
10
+ function cloneVec2(v) {
11
+ return { x: v.x, y: v.y };
12
+ }
13
+ function equalsVec2(a, b, eps = 1e-9) {
14
+ return Math.abs(a.x - b.x) <= eps && Math.abs(a.y - b.y) <= eps;
15
+ }
16
+
17
+ // src/types/path.ts
18
+ function path(rings, closed = true) {
19
+ return {
20
+ rings: rings.map((ring) => ring.map(cloneVec2)),
21
+ closed
22
+ };
23
+ }
24
+ function polygon(exterior, holes = []) {
25
+ return path([exterior, ...holes], true);
26
+ }
27
+ function normalizeRing(ring, eps = 1e-9) {
28
+ if (ring.length < 2) return ring.map(cloneVec2);
29
+ const first = ring[0];
30
+ const last = ring[ring.length - 1];
31
+ if (first && last && equalsVec2(first, last, eps)) {
32
+ return ring.slice(0, -1).map(cloneVec2);
33
+ }
34
+ return ring.map(cloneVec2);
35
+ }
36
+ FillRule.NonZero;
37
+ function ringToPathD(ring) {
38
+ const pts = [];
39
+ for (const v of normalizeRing(ring)) {
40
+ pts.push({ x: v.x, y: v.y, z: 0 });
41
+ }
42
+ return pts;
43
+ }
44
+ function pathToPathsD(p) {
45
+ if (!p.closed || p.rings.length === 0) {
46
+ throw new Error("Boolean ops require a closed path with at least one ring");
47
+ }
48
+ return p.rings.map((ring) => ringToPathD(ring));
49
+ }
50
+ function pathDToRing(pd) {
51
+ return normalizeRing(pd.map((p) => vec2(p.x, p.y)));
52
+ }
53
+ function pointInRing(point, ring) {
54
+ const result = pointInPolygonD(
55
+ { x: point.x, y: point.y, z: 0 },
56
+ ringToPathD(ring)
57
+ );
58
+ return result === PointInPolygonResult.IsInside || result === PointInPolygonResult.IsOn;
59
+ }
60
+
61
+ // src/predicates/index.ts
62
+ function containsPoint(p, point) {
63
+ if (!p.closed || !p.rings[0]) return false;
64
+ if (!pointInRing(point, p.rings[0])) return false;
65
+ for (let i = 1; i < p.rings.length; i++) {
66
+ const hole = p.rings[i];
67
+ if (hole && pointInRing(point, hole)) return false;
68
+ }
69
+ return true;
70
+ }
71
+ function bounds(p) {
72
+ let minX = Infinity;
73
+ let minY = Infinity;
74
+ let maxX = -Infinity;
75
+ let maxY = -Infinity;
76
+ for (const ring of p.rings) {
77
+ for (const v of ring) {
78
+ minX = Math.min(minX, v.x);
79
+ minY = Math.min(minY, v.y);
80
+ maxX = Math.max(maxX, v.x);
81
+ maxY = Math.max(maxY, v.y);
82
+ }
83
+ }
84
+ if (!Number.isFinite(minX)) {
85
+ return { minX: 0, minY: 0, maxX: 0, maxY: 0 };
86
+ }
87
+ return { minX, minY, maxX, maxY };
88
+ }
89
+
90
+ // src/pointSet/index.ts
91
+ function mulberry32(a) {
92
+ return function() {
93
+ let t = a += 1831565813;
94
+ t = Math.imul(t ^ t >>> 15, t | 1);
95
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
96
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
97
+ };
98
+ }
99
+ function poisson(minDistance, minX, minY, maxX, maxY, seed = 1, maxAttempts = 30) {
100
+ const rng = mulberry32(seed >>> 0);
101
+ const r = Math.max(minDistance, 1e-9);
102
+ const cell = r / Math.SQRT2;
103
+ const w = maxX - minX;
104
+ const h = maxY - minY;
105
+ const gw = Math.max(1, Math.ceil(w / cell));
106
+ const gh = Math.max(1, Math.ceil(h / cell));
107
+ const grid = Array(gw * gh).fill(null);
108
+ const points = [];
109
+ const active = [];
110
+ const gx = (p) => Math.min(gw - 1, Math.floor((p.x - minX) / cell));
111
+ const gy = (p) => Math.min(gh - 1, Math.floor((p.y - minY) / cell));
112
+ const emit = (p) => {
113
+ const i = points.length;
114
+ points.push(p);
115
+ active.push(i);
116
+ grid[gy(p) * gw + gx(p)] = i;
117
+ };
118
+ emit({
119
+ x: minX + rng() * w,
120
+ y: minY + rng() * h
121
+ });
122
+ while (active.length > 0) {
123
+ const ai = Math.floor(rng() * active.length);
124
+ const i = active[ai];
125
+ const src = points[i];
126
+ let found = false;
127
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
128
+ const ang = rng() * Math.PI * 2;
129
+ const rad = r * (1 + rng());
130
+ const cand = {
131
+ x: src.x + Math.cos(ang) * rad,
132
+ y: src.y + Math.sin(ang) * rad
133
+ };
134
+ if (cand.x < minX || cand.x > maxX || cand.y < minY || cand.y > maxY) {
135
+ continue;
136
+ }
137
+ const cx = gx(cand);
138
+ const cy = gy(cand);
139
+ let ok = true;
140
+ for (let yy = Math.max(0, cy - 2); yy <= Math.min(gh - 1, cy + 2) && ok; yy++) {
141
+ for (let xx = Math.max(0, cx - 2); xx <= Math.min(gw - 1, cx + 2); xx++) {
142
+ const j = grid[yy * gw + xx];
143
+ if (j == null) continue;
144
+ const q = points[j];
145
+ if (Math.hypot(cand.x - q.x, cand.y - q.y) < r) {
146
+ ok = false;
147
+ break;
148
+ }
149
+ }
150
+ }
151
+ if (ok) {
152
+ emit(cand);
153
+ found = true;
154
+ break;
155
+ }
156
+ }
157
+ if (!found) active.splice(ai, 1);
158
+ }
159
+ return points;
160
+ }
161
+
162
+ // src/triangulation/index.ts
163
+ function earCutTriangulation(p, options = {}) {
164
+ if (!p.closed || p.rings.length === 0) return [];
165
+ const { solution } = triangulateD(
166
+ pathToPathsD(p),
167
+ options.precision ?? 8,
168
+ options.useDelaunay ?? false
169
+ );
170
+ const tris = [];
171
+ for (const pd of solution) {
172
+ const ring = pathDToRing(pd);
173
+ if (ring.length >= 3) tris.push(polygon(ring.slice(0, 3)));
174
+ }
175
+ return tris;
176
+ }
177
+ function delaunayTriangulation(p) {
178
+ return earCutTriangulation(p, { useDelaunay: true });
179
+ }
180
+ function delaunayTriangulationPoints(points) {
181
+ if (points.length < 3) return [];
182
+ const delaunay = Delaunay.from(
183
+ points,
184
+ (d) => d.x,
185
+ (d) => d.y
186
+ );
187
+ const tris = [];
188
+ const { triangles } = delaunay;
189
+ for (let i = 0; i < triangles.length; i += 3) {
190
+ const a = points[triangles[i]];
191
+ const b = points[triangles[i + 1]];
192
+ const c = points[triangles[i + 2]];
193
+ tris.push(polygon([a, b, c]));
194
+ }
195
+ return tris;
196
+ }
197
+ function poissonTriangulationPoints(path2, minDistance, seed = 1) {
198
+ if (!path2.closed || path2.rings.length === 0) return [];
199
+ const b = bounds(path2);
200
+ const samples = poisson(
201
+ minDistance,
202
+ b.minX,
203
+ b.minY,
204
+ b.maxX,
205
+ b.maxY,
206
+ seed
207
+ ).filter((pt) => containsPoint(path2, pt));
208
+ return dedupePoints([...pathVertices(path2), ...samples]);
209
+ }
210
+ function poissonTriangulation(path2, minDistance, seed = 1) {
211
+ const pts = poissonTriangulationPoints(path2, minDistance, seed);
212
+ return trianglesInsidePath(delaunayTriangulationPoints(pts), path2);
213
+ }
214
+ function refine(path2, options = {}) {
215
+ if (!path2.closed || path2.rings.length === 0) return [];
216
+ const minAngle = options.minAngle ?? 20 * Math.PI / 180;
217
+ const maxIterations = Math.max(1, options.maxIterations ?? 200);
218
+ const points = dedupePoints(pathVertices(path2));
219
+ if (points.length < 3) return [];
220
+ for (let iter = 0; iter < maxIterations; iter++) {
221
+ const tris = trianglesInsidePath(
222
+ delaunayTriangulationPoints(points),
223
+ path2
224
+ );
225
+ if (tris.length === 0) break;
226
+ let skinny = null;
227
+ let worst = minAngle;
228
+ for (const t of tris) {
229
+ const a = minTriangleAngle(t);
230
+ if (a < worst) {
231
+ worst = a;
232
+ skinny = t;
233
+ }
234
+ }
235
+ if (!skinny) break;
236
+ const ring = skinny.rings[0];
237
+ const cc = circumcenter(ring[0], ring[1], ring[2]);
238
+ if (!cc) break;
239
+ const insert = containsPoint(path2, cc) ? cc : longestEdgeMidpoint(ring[0], ring[1], ring[2]);
240
+ if (points.some((p) => Math.hypot(p.x - insert.x, p.y - insert.y) < 1e-9)) {
241
+ break;
242
+ }
243
+ points.push(insert);
244
+ }
245
+ return trianglesInsidePath(delaunayTriangulationPoints(points), path2);
246
+ }
247
+ function pathVertices(path2) {
248
+ const out = [];
249
+ for (const ring of path2.rings) {
250
+ for (const v of ring) out.push({ x: v.x, y: v.y });
251
+ }
252
+ return out;
253
+ }
254
+ function dedupePoints(points, eps = 1e-9) {
255
+ const out = [];
256
+ for (const p of points) {
257
+ if (out.some((q) => Math.hypot(q.x - p.x, q.y - p.y) < eps)) continue;
258
+ out.push(p);
259
+ }
260
+ return out;
261
+ }
262
+ function triangleCentroid(t) {
263
+ const r = t.rings[0];
264
+ if (!r || r.length < 3) return null;
265
+ return {
266
+ x: (r[0].x + r[1].x + r[2].x) / 3,
267
+ y: (r[0].y + r[1].y + r[2].y) / 3
268
+ };
269
+ }
270
+ function trianglesInsidePath(tris, path2) {
271
+ return tris.filter((t) => {
272
+ const c = triangleCentroid(t);
273
+ return c != null && containsPoint(path2, c);
274
+ });
275
+ }
276
+ function minTriangleAngle(t) {
277
+ const r = t.rings[0];
278
+ if (!r || r.length < 3) return 0;
279
+ const a = r[0];
280
+ const b = r[1];
281
+ const c = r[2];
282
+ return Math.min(angleAt(a, b, c), angleAt(b, c, a), angleAt(c, a, b));
283
+ }
284
+ function angleAt(vertex, p, q) {
285
+ const ux = p.x - vertex.x;
286
+ const uy = p.y - vertex.y;
287
+ const vx = q.x - vertex.x;
288
+ const vy = q.y - vertex.y;
289
+ const lu = Math.hypot(ux, uy);
290
+ const lv = Math.hypot(vx, vy);
291
+ if (lu < 1e-18 || lv < 1e-18) return 0;
292
+ const cos = Math.max(-1, Math.min(1, (ux * vx + uy * vy) / (lu * lv)));
293
+ return Math.acos(cos);
294
+ }
295
+ function circumcenter(a, b, c) {
296
+ const d = 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y));
297
+ if (Math.abs(d) < 1e-18) return null;
298
+ const a2 = a.x * a.x + a.y * a.y;
299
+ const b2 = b.x * b.x + b.y * b.y;
300
+ const c2 = c.x * c.x + c.y * c.y;
301
+ return {
302
+ x: (a2 * (b.y - c.y) + b2 * (c.y - a.y) + c2 * (a.y - b.y)) / d,
303
+ y: (a2 * (c.x - b.x) + b2 * (a.x - c.x) + c2 * (b.x - a.x)) / d
304
+ };
305
+ }
306
+ function longestEdgeMidpoint(a, b, c) {
307
+ const edges = [
308
+ [a, b],
309
+ [b, c],
310
+ [c, a]
311
+ ];
312
+ let best = edges[0];
313
+ let bestLen = -1;
314
+ for (const e of edges) {
315
+ const len = Math.hypot(e[0].x - e[1].x, e[0].y - e[1].y);
316
+ if (len > bestLen) {
317
+ bestLen = len;
318
+ best = e;
319
+ }
320
+ }
321
+ return { x: (best[0].x + best[1].x) / 2, y: (best[0].y + best[1].y) / 2 };
322
+ }
323
+ var triangulation = {
324
+ earCutTriangulation,
325
+ delaunayTriangulation,
326
+ delaunayTriangulationPoints,
327
+ poissonTriangulation,
328
+ poissonTriangulationPoints,
329
+ refine
330
+ };
331
+
332
+ export { delaunayTriangulation, delaunayTriangulationPoints, earCutTriangulation, poissonTriangulation, poissonTriangulationPoints, refine, triangulation };
333
+ //# sourceMappingURL=index.js.map
334
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/vec2.ts","../../src/types/path.ts","../../src/clipper/convert.ts","../../src/predicates/index.ts","../../src/pointSet/index.ts","../../src/triangulation/index.ts"],"names":["path"],"mappings":"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","file":"index.js","sourcesContent":["/** 2D point / vector. */\nexport type Vec2 = {\n x: number\n y: number\n}\n\nexport function vec2(x: number, y: number): Vec2 {\n return { x, y }\n}\n\nexport function cloneVec2(v: Vec2): Vec2 {\n return { x: v.x, y: v.y }\n}\n\nexport function equalsVec2(a: Vec2, b: Vec2, eps = 1e-9): boolean {\n return Math.abs(a.x - b.x) <= eps && Math.abs(a.y - b.y) <= eps\n}\n","import type { Vec2 } from './vec2.js'\nimport { cloneVec2, equalsVec2 } from './vec2.js'\n\n/** Ordered ring of vertices (typically without repeating the closing vertex). */\nexport type Ring = Vec2[]\n\n/**\n * A path: one exterior ring plus optional holes, or an open polyline.\n * `rings[0]` is the exterior (or the open polyline when `closed` is false).\n * Additional rings are holes (only meaningful when `closed` is true).\n */\nexport type Path = {\n rings: Ring[]\n closed: boolean\n}\n\nexport function path(rings: Ring[], closed = true): Path {\n return {\n rings: rings.map((ring) => ring.map(cloneVec2)),\n closed,\n }\n}\n\nexport function polyline(points: Ring): Path {\n return path([points], false)\n}\n\nexport function polygon(exterior: Ring, holes: Ring[] = []): Path {\n return path([exterior, ...holes], true)\n}\n\n/** Drop a trailing vertex that duplicates the first (SVG often closes this way). */\nexport function normalizeRing(ring: Ring, eps = 1e-9): Ring {\n if (ring.length < 2) return ring.map(cloneVec2)\n const first = ring[0]\n const last = ring[ring.length - 1]\n if (first && last && equalsVec2(first, last, eps)) {\n return ring.slice(0, -1).map(cloneVec2)\n }\n return ring.map(cloneVec2)\n}\n\nexport function clonePath(p: Path): Path {\n return {\n closed: p.closed,\n rings: p.rings.map((ring) => ring.map(cloneVec2)),\n }\n}\n","import {\n FillRule,\n areaD,\n differenceD,\n intersectD,\n isPositiveD,\n pointInPolygonD,\n PointInPolygonResult,\n unionD,\n xorD,\n type PathD,\n type PathsD,\n type PointD,\n} from 'clipper2-ts'\nimport type { Group, Path, Ring, Vec2 } from '../types/index.js'\nimport { group, normalizeRing, path, vec2 } from '../types/index.js'\n\nexport const DEFAULT_FILL_RULE = FillRule.NonZero\n\nexport function ringToPathD(ring: Ring): PathD {\n const pts: PointD[] = []\n for (const v of normalizeRing(ring)) {\n pts.push({ x: v.x, y: v.y, z: 0 })\n }\n return pts\n}\n\n/** Closed path → Clipper subject/clip paths (exterior + holes). */\nexport function pathToPathsD(p: Path): PathsD {\n if (!p.closed || p.rings.length === 0) {\n throw new Error('Boolean ops require a closed path with at least one ring')\n }\n return p.rings.map((ring) => ringToPathD(ring))\n}\n\nexport function pathsDToGroup(paths: PathsD): Group {\n if (paths.length === 0) return group([])\n\n const outers: { ring: Ring; holes: Ring[] }[] = []\n const holes: Ring[] = []\n\n for (const pd of paths) {\n const ring = pathDToRing(pd)\n if (ring.length < 3) continue\n if (isPositiveD(pd)) {\n outers.push({ ring, holes: [] })\n } else {\n holes.push(ring)\n }\n }\n\n for (const hole of holes) {\n const sample = hole[0]\n if (!sample) continue\n let assigned = false\n for (const outer of outers) {\n if (pointInRing(sample, outer.ring)) {\n outer.holes.push(hole)\n assigned = true\n break\n }\n }\n if (!assigned) {\n // Treat unmatched negative rings as their own outers (orientation flip).\n outers.push({ ring: [...hole].reverse(), holes: [] })\n }\n }\n\n return group(outers.map((o) => path([o.ring, ...o.holes], true)))\n}\n\nexport function pathDToRing(pd: PathD): Ring {\n return normalizeRing(pd.map((p) => vec2(p.x, p.y)))\n}\n\nexport function pointInRing(point: Vec2, ring: Ring): boolean {\n const result = pointInPolygonD(\n { x: point.x, y: point.y, z: 0 },\n ringToPathD(ring),\n )\n return (\n result === PointInPolygonResult.IsInside ||\n result === PointInPolygonResult.IsOn\n )\n}\n\nexport function clipUnion(a: PathsD, b: PathsD): PathsD {\n return unionD(a, b, DEFAULT_FILL_RULE)\n}\n\nexport function clipIntersect(a: PathsD, b: PathsD): PathsD {\n return intersectD(a, b, DEFAULT_FILL_RULE)\n}\n\nexport function clipDifference(a: PathsD, b: PathsD): PathsD {\n return differenceD(a, b, DEFAULT_FILL_RULE)\n}\n\nexport function clipXor(a: PathsD, b: PathsD): PathsD {\n return xorD(a, b, DEFAULT_FILL_RULE)\n}\n\nexport function pathsArea(paths: PathsD): number {\n let sum = 0\n for (const p of paths) {\n sum += Math.abs(areaD(p))\n }\n return sum\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { vec2 } from '../types/index.js'\nimport {\n pathToPathsD,\n pathsArea,\n pointInRing,\n} from '../clipper/convert.js'\n\n/** Signed area of a closed ring (shoelace). */\nexport function ringArea(ring: Vec2[]): number {\n if (ring.length < 3) return 0\n let sum = 0\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % ring.length]!\n sum += a.x * b.y - b.x * a.y\n }\n return sum / 2\n}\n\n/** Absolute area of a closed path (exterior minus holes). */\nexport function area(p: Path): number {\n if (!p.closed || p.rings.length === 0) return 0\n try {\n return pathsArea(pathToPathsD(p))\n } catch {\n let total = 0\n for (let i = 0; i < p.rings.length; i++) {\n const a = Math.abs(ringArea(p.rings[i]!))\n total += i === 0 ? a : -a\n }\n return Math.max(0, total)\n }\n}\n\nexport function areaGroup(g: Group): number {\n return g.paths.reduce((sum, p) => sum + area(p), 0)\n}\n\n/** Centroid of a closed exterior ring (ignores holes for Phase 2). */\nexport function centroid(p: Path): Vec2 {\n const ring = p.rings[0]\n if (!ring || ring.length === 0) return vec2(0, 0)\n const a = ringArea(ring)\n if (Math.abs(a) < 1e-12) {\n let sx = 0\n let sy = 0\n for (const v of ring) {\n sx += v.x\n sy += v.y\n }\n return vec2(sx / ring.length, sy / ring.length)\n }\n let cx = 0\n let cy = 0\n for (let i = 0; i < ring.length; i++) {\n const p0 = ring[i]!\n const p1 = ring[(i + 1) % ring.length]!\n const cross = p0.x * p1.y - p1.x * p0.y\n cx += (p0.x + p1.x) * cross\n cy += (p0.y + p1.y) * cross\n }\n return vec2(cx / (6 * a), cy / (6 * a))\n}\n\nexport function containsPoint(p: Path, point: Vec2): boolean {\n if (!p.closed || !p.rings[0]) return false\n if (!pointInRing(point, p.rings[0])) return false\n for (let i = 1; i < p.rings.length; i++) {\n const hole = p.rings[i]\n if (hole && pointInRing(point, hole)) return false\n }\n return true\n}\n\nexport function bounds(p: Path): {\n minX: number\n minY: number\n maxX: number\n maxY: number\n} {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const ring of p.rings) {\n for (const v of ring) {\n minX = Math.min(minX, v.x)\n minY = Math.min(minY, v.y)\n maxX = Math.max(maxX, v.x)\n maxY = Math.max(maxY, v.y)\n }\n }\n if (!Number.isFinite(minX)) {\n return { minX: 0, minY: 0, maxX: 0, maxY: 0 }\n }\n return { minX, minY, maxX, maxY }\n}\n\nexport function width(p: Path): number {\n const b = bounds(p)\n return b.maxX - b.minX\n}\n\nexport function height(p: Path): number {\n const b = bounds(p)\n return b.maxY - b.minY\n}\n\n/** Rough polygon similarity via absolute area difference relative to max area. */\nexport function areaSimilarity(a: Path, b: Path): number {\n const aa = area(a)\n const bb = area(b)\n const denom = Math.max(aa, bb, 1e-12)\n return 1 - Math.abs(aa - bb) / denom\n}\n\nexport const predicates = {\n area,\n areaGroup,\n ringArea,\n centroid,\n containsPoint,\n bounds,\n width,\n height,\n areaSimilarity,\n}\n","import type { Vec2 } from '../types/index.js'\n\n/** Seeded uniform random points in an axis-aligned box. */\nexport function random(\n count: number,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n seed = 1,\n): Vec2[] {\n const rng = mulberry32(seed >>> 0)\n const out: Vec2[] = []\n for (let i = 0; i < count; i++) {\n out.push({\n x: minX + rng() * (maxX - minX),\n y: minY + rng() * (maxY - minY),\n })\n }\n return out\n}\n\n/** Square lattice points covering [minX,maxX] × [minY,maxY]. */\nexport function squareGrid(\n spacing: number,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): Vec2[] {\n const s = Math.max(spacing, 1e-9)\n const out: Vec2[] = []\n for (let x = minX; x <= maxX + 1e-12; x += s) {\n for (let y = minY; y <= maxY + 1e-12; y += s) {\n out.push({ x, y })\n }\n }\n return out\n}\n\n/** Hexagonal lattice points covering the box. */\nexport function hexGrid(\n spacing: number,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): Vec2[] {\n const s = Math.max(spacing, 1e-9)\n const dx = s\n const dy = s * Math.sqrt(3) * 0.5\n const out: Vec2[] = []\n let row = 0\n for (let y = minY; y <= maxY + 1e-12; y += dy, row++) {\n const x0 = minX + (row % 2 === 0 ? 0 : s * 0.5)\n for (let x = x0; x <= maxX + 1e-12; x += dx) {\n out.push({ x, y })\n }\n }\n return out\n}\n\n/** Ring of `count` points around `center` with `radius`. */\nexport function ring(\n count: number,\n center: Vec2,\n radius: number,\n): Vec2[] {\n const out: Vec2[] = []\n for (let i = 0; i < count; i++) {\n const t = (i / count) * Math.PI * 2\n out.push({\n x: center.x + Math.cos(t) * radius,\n y: center.y + Math.sin(t) * radius,\n })\n }\n return out\n}\n\nfunction mulberry32(a: number): () => number {\n return function () {\n let t = (a += 0x6d2b79f5)\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** Bridson-ish Poisson disk sample in a box (seeded). */\nexport function poisson(\n minDistance: number,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n seed = 1,\n maxAttempts = 30,\n): Vec2[] {\n const rng = mulberry32(seed >>> 0)\n const r = Math.max(minDistance, 1e-9)\n const cell = r / Math.SQRT2\n const w = maxX - minX\n const h = maxY - minY\n const gw = Math.max(1, Math.ceil(w / cell))\n const gh = Math.max(1, Math.ceil(h / cell))\n const grid: (number | null)[] = Array(gw * gh).fill(null)\n const points: Vec2[] = []\n const active: number[] = []\n\n const gx = (p: Vec2) => Math.min(gw - 1, Math.floor((p.x - minX) / cell))\n const gy = (p: Vec2) => Math.min(gh - 1, Math.floor((p.y - minY) / cell))\n\n const emit = (p: Vec2) => {\n const i = points.length\n points.push(p)\n active.push(i)\n grid[gy(p) * gw + gx(p)] = i\n }\n\n emit({\n x: minX + rng() * w,\n y: minY + rng() * h,\n })\n\n while (active.length > 0) {\n const ai = Math.floor(rng() * active.length)\n const i = active[ai]!\n const src = points[i]!\n let found = false\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const ang = rng() * Math.PI * 2\n const rad = r * (1 + rng())\n const cand = {\n x: src.x + Math.cos(ang) * rad,\n y: src.y + Math.sin(ang) * rad,\n }\n if (\n cand.x < minX ||\n cand.x > maxX ||\n cand.y < minY ||\n cand.y > maxY\n ) {\n continue\n }\n const cx = gx(cand)\n const cy = gy(cand)\n let ok = true\n for (let yy = Math.max(0, cy - 2); yy <= Math.min(gh - 1, cy + 2) && ok; yy++) {\n for (let xx = Math.max(0, cx - 2); xx <= Math.min(gw - 1, cx + 2); xx++) {\n const j = grid[yy * gw + xx]\n if (j == null) continue\n const q = points[j]!\n if (Math.hypot(cand.x - q.x, cand.y - q.y) < r) {\n ok = false\n break\n }\n }\n }\n if (ok) {\n emit(cand)\n found = true\n break\n }\n }\n if (!found) active.splice(ai, 1)\n }\n return points\n}\n\n/** Drop points closer than `minDistance` (greedy keep-first). */\nexport function prunePointsWithinDistance(\n points: Vec2[],\n minDistance: number,\n): Vec2[] {\n const r = Math.max(minDistance, 0)\n const out: Vec2[] = []\n for (const p of points) {\n if (out.every((q) => Math.hypot(p.x - q.x, p.y - q.y) >= r)) {\n out.push(p)\n }\n }\n return out\n}\n\nexport const pointSet = {\n random,\n squareGrid,\n hexGrid,\n ring,\n poisson,\n prunePointsWithinDistance,\n}\n","import { triangulateD } from 'clipper2-ts'\nimport { Delaunay } from 'd3-delaunay'\nimport type { Path, Vec2 } from '../types/index.js'\nimport { polygon } from '../types/index.js'\nimport { pathToPathsD, pathDToRing } from '../clipper/convert.js'\nimport { bounds, containsPoint } from '../predicates/index.js'\nimport { poisson } from '../pointSet/index.js'\n\n/**\n * Triangulate a closed path into triangle polygons (Clipper2).\n * Holes are supported when present on the path. `useDelaunay` prefers\n * better-shaped triangles when Clipper can apply it.\n */\nexport function earCutTriangulation(\n p: Path,\n options: { useDelaunay?: boolean; precision?: number } = {},\n): Path[] {\n if (!p.closed || p.rings.length === 0) return []\n const { solution } = triangulateD(\n pathToPathsD(p),\n options.precision ?? 8,\n options.useDelaunay ?? false,\n )\n const tris: Path[] = []\n for (const pd of solution) {\n const ring = pathDToRing(pd)\n if (ring.length >= 3) tris.push(polygon(ring.slice(0, 3)))\n }\n return tris\n}\n\n/** Alias matching PGS naming for Clipper/Delaunay triangulation of a polygon. */\nexport function delaunayTriangulation(p: Path): Path[] {\n return earCutTriangulation(p, { useDelaunay: true })\n}\n\n/** Delaunay triangulation of a point set (d3-delaunay). */\nexport function delaunayTriangulationPoints(points: Vec2[]): Path[] {\n if (points.length < 3) return []\n const delaunay = Delaunay.from(\n points,\n (d) => d.x,\n (d) => d.y,\n )\n const tris: Path[] = []\n const { triangles } = delaunay\n for (let i = 0; i < triangles.length; i += 3) {\n const a = points[triangles[i]!]!\n const b = points[triangles[i + 1]!]!\n const c = points[triangles[i + 2]!]!\n tris.push(polygon([a, b, c]))\n }\n return tris\n}\n\n/**\n * Boundary vertices plus Poisson-disk Steiner points inside `path`.\n */\nexport function poissonTriangulationPoints(\n path: Path,\n minDistance: number,\n seed = 1,\n): Vec2[] {\n if (!path.closed || path.rings.length === 0) return []\n const b = bounds(path)\n const samples = poisson(\n minDistance,\n b.minX,\n b.minY,\n b.maxX,\n b.maxY,\n seed,\n ).filter((pt) => containsPoint(path, pt))\n return dedupePoints([...pathVertices(path), ...samples])\n}\n\n/**\n * Delaunay triangulation of a path with Poisson Steiner points inserted.\n * Triangles whose centroid falls outside the path (or in a hole) are dropped.\n */\nexport function poissonTriangulation(\n path: Path,\n minDistance: number,\n seed = 1,\n): Path[] {\n const pts = poissonTriangulationPoints(path, minDistance, seed)\n return trianglesInsidePath(delaunayTriangulationPoints(pts), path)\n}\n\nexport type RefineOptions = {\n /** Minimum allowed interior angle (radians). Default ≈ 20°. */\n minAngle?: number\n /** Safety cap on Steiner insertions. Default `200`. */\n maxIterations?: number\n}\n\n/**\n * Ruppert-inspired angle refinement for plotter meshes.\n * Clean-room approximation (not a full constrained CDT): insert circumcenters\n * of skinny triangles when they lie inside the path; otherwise split the\n * longest edge of that triangle (simple encroachment stand-in).\n */\nexport function refine(path: Path, options: RefineOptions = {}): Path[] {\n if (!path.closed || path.rings.length === 0) return []\n const minAngle = options.minAngle ?? (20 * Math.PI) / 180\n const maxIterations = Math.max(1, options.maxIterations ?? 200)\n const points = dedupePoints(pathVertices(path))\n if (points.length < 3) return []\n\n for (let iter = 0; iter < maxIterations; iter++) {\n const tris = trianglesInsidePath(\n delaunayTriangulationPoints(points),\n path,\n )\n if (tris.length === 0) break\n\n let skinny: Path | null = null\n let worst = minAngle\n for (const t of tris) {\n const a = minTriangleAngle(t)\n if (a < worst) {\n worst = a\n skinny = t\n }\n }\n if (!skinny) break\n\n const ring = skinny.rings[0]!\n const cc = circumcenter(ring[0]!, ring[1]!, ring[2]!)\n if (!cc) break\n\n const insert = containsPoint(path, cc)\n ? cc\n : longestEdgeMidpoint(ring[0]!, ring[1]!, ring[2]!)\n if (\n points.some((p) => Math.hypot(p.x - insert.x, p.y - insert.y) < 1e-9)\n ) {\n break\n }\n points.push(insert)\n }\n\n return trianglesInsidePath(delaunayTriangulationPoints(points), path)\n}\n\nfunction pathVertices(path: Path): Vec2[] {\n const out: Vec2[] = []\n for (const ring of path.rings) {\n for (const v of ring) out.push({ x: v.x, y: v.y })\n }\n return out\n}\n\nfunction dedupePoints(points: Vec2[], eps = 1e-9): Vec2[] {\n const out: Vec2[] = []\n for (const p of points) {\n if (out.some((q) => Math.hypot(q.x - p.x, q.y - p.y) < eps)) continue\n out.push(p)\n }\n return out\n}\n\nfunction triangleCentroid(t: Path): Vec2 | null {\n const r = t.rings[0]\n if (!r || r.length < 3) return null\n return {\n x: (r[0]!.x + r[1]!.x + r[2]!.x) / 3,\n y: (r[0]!.y + r[1]!.y + r[2]!.y) / 3,\n }\n}\n\nfunction trianglesInsidePath(tris: Path[], path: Path): Path[] {\n return tris.filter((t) => {\n const c = triangleCentroid(t)\n return c != null && containsPoint(path, c)\n })\n}\n\nfunction minTriangleAngle(t: Path): number {\n const r = t.rings[0]\n if (!r || r.length < 3) return 0\n const a = r[0]!\n const b = r[1]!\n const c = r[2]!\n return Math.min(angleAt(a, b, c), angleAt(b, c, a), angleAt(c, a, b))\n}\n\nfunction angleAt(vertex: Vec2, p: Vec2, q: Vec2): number {\n const ux = p.x - vertex.x\n const uy = p.y - vertex.y\n const vx = q.x - vertex.x\n const vy = q.y - vertex.y\n const lu = Math.hypot(ux, uy)\n const lv = Math.hypot(vx, vy)\n if (lu < 1e-18 || lv < 1e-18) return 0\n const cos = Math.max(-1, Math.min(1, (ux * vx + uy * vy) / (lu * lv)))\n return Math.acos(cos)\n}\n\nfunction circumcenter(a: Vec2, b: Vec2, c: Vec2): Vec2 | null {\n const d =\n 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y))\n if (Math.abs(d) < 1e-18) return null\n const a2 = a.x * a.x + a.y * a.y\n const b2 = b.x * b.x + b.y * b.y\n const c2 = c.x * c.x + c.y * c.y\n return {\n x: (a2 * (b.y - c.y) + b2 * (c.y - a.y) + c2 * (a.y - b.y)) / d,\n y: (a2 * (c.x - b.x) + b2 * (a.x - c.x) + c2 * (b.x - a.x)) / d,\n }\n}\n\nfunction longestEdgeMidpoint(a: Vec2, b: Vec2, c: Vec2): Vec2 {\n const edges: [Vec2, Vec2][] = [\n [a, b],\n [b, c],\n [c, a],\n ]\n let best = edges[0]!\n let bestLen = -1\n for (const e of edges) {\n const len = Math.hypot(e[0].x - e[1].x, e[0].y - e[1].y)\n if (len > bestLen) {\n bestLen = len\n best = e\n }\n }\n return { x: (best[0].x + best[1].x) / 2, y: (best[0].y + best[1].y) / 2 }\n}\n\nexport const triangulation = {\n earCutTriangulation,\n delaunayTriangulation,\n delaunayTriangulationPoints,\n poissonTriangulation,\n poissonTriangulationPoints,\n refine,\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /** 2D point / vector. */
2
+ type Vec2 = {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ declare function vec2(x: number, y: number): Vec2;
7
+ declare function cloneVec2(v: Vec2): Vec2;
8
+ declare function equalsVec2(a: Vec2, b: Vec2, eps?: number): boolean;
9
+
10
+ export { type Vec2 as V, cloneVec2 as c, equalsVec2 as e, vec2 as v };
@@ -0,0 +1,31 @@
1
+ import { V as Vec2 } from '../vec2-CWyXN1Wj.js';
2
+ import { P as Path } from '../path-0RjhYjJs.js';
3
+ import { G as Group } from '../group-BNjVVYSQ.js';
4
+
5
+ type VoronoiOptions = {
6
+ /** Clip cells to this bbox; default padded bounds of the sites. */
7
+ bounds?: {
8
+ minX: number;
9
+ minY: number;
10
+ maxX: number;
11
+ maxY: number;
12
+ };
13
+ };
14
+ /**
15
+ * Voronoi cells for a point set as closed polygons (clipped to a bbox).
16
+ * PGS `compoundVoronoi` analogue — one path per site.
17
+ */
18
+ declare function compoundVoronoi(sites: Vec2[], options?: VoronoiOptions): Group;
19
+ /**
20
+ * Voronoi clipped to the interior of `container` (intersect each cell).
21
+ */
22
+ declare function innerVoronoi(sites: Vec2[], container: Path, options?: VoronoiOptions): Group;
23
+ /** Raw cell polygons without container clip (same as compoundVoronoi). */
24
+ declare function innerVoronoiRaw(sites: Vec2[], options?: VoronoiOptions): Group;
25
+ declare const voronoi: {
26
+ compoundVoronoi: typeof compoundVoronoi;
27
+ innerVoronoi: typeof innerVoronoi;
28
+ innerVoronoiRaw: typeof innerVoronoiRaw;
29
+ };
30
+
31
+ export { type VoronoiOptions, compoundVoronoi, innerVoronoi, innerVoronoiRaw, voronoi };