pattapatta 0.2.0 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/vec2.ts","../../src/types/path.ts","../../src/types/group.ts","../../src/clipper/convert.ts","../../src/morphology/buffer.ts","../../src/contour/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 type { Path } from './path.js'\nimport { clonePath } from './path.js'\n\n/**\n * Ordered collection of paths. Later entries are “on top” for occlusion-style ops.\n */\nexport type Group = {\n paths: Path[]\n}\n\nexport function group(paths: Path[] = []): Group {\n return { paths: paths.map(clonePath) }\n}\n\nexport function groupFromPaths(...paths: Path[]): Group {\n return group(paths)\n}\n\nexport function cloneGroup(g: Group): Group {\n return group(g.paths)\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 } from '../types/index.js'\nimport { group } from '../types/index.js'\nimport { inflatePathsD, JoinType, EndType } from 'clipper2-ts'\nimport { pathToPathsD, pathsDToGroup } from '../clipper/convert.js'\n\nexport type BufferOptions = {\n /** Join style for offset. Default round. */\n join?: 'round' | 'miter' | 'square'\n}\n\n/**\n * Offset / buffer a closed path by `delta` (positive = expand, negative = erode).\n * Returns a group of resulting closed paths (may split or vanish when eroding).\n */\nexport function buffer(\n path: Path,\n delta: number,\n options: BufferOptions = {},\n): Group {\n const subject = pathToPathsD(path)\n const join =\n options.join === 'miter'\n ? JoinType.Miter\n : options.join === 'square'\n ? JoinType.Square\n : JoinType.Round\n const inflated = inflatePathsD(subject, delta, join, EndType.Polygon)\n return pathsDToGroup(inflated)\n}\n\n/**\n * Erode by `|amount|` then dilate by `|amount|` (opening). Useful for cleaning.\n */\nexport function erosionDilation(p: Path, amount: number): Group {\n const a = Math.abs(amount)\n if (a < 1e-12) return group([p])\n const eroded = buffer(p, -a)\n if (eroded.paths.length === 0) return eroded\n const dilated: Path[] = []\n for (const q of eroded.paths) {\n dilated.push(...buffer(q, a).paths)\n }\n return group(dilated)\n}\n\n/**\n * Dilate by `|amount|` then erode by `|amount|` (closing). Fills small gaps.\n */\nexport function dilationErosion(p: Path, amount: number): Group {\n const a = Math.abs(amount)\n if (a < 1e-12) return group([p])\n const dilated = buffer(p, a)\n if (dilated.paths.length === 0) return dilated\n const eroded: Path[] = []\n for (const q of dilated.paths) {\n eroded.push(...buffer(q, -a).paths)\n }\n return group(eroded)\n}\n","import type { Group, Path } from '../types/index.js'\nimport { buffer } from '../morphology/buffer.js'\n\n/**\n * Offset the path outward by `distance` (positive buffer).\n * Returns possibly multiple closed contours.\n */\nexport function offsetCurvesOutward(p: Path, distance: number): Group {\n return buffer(p, Math.abs(distance))\n}\n\n/**\n * Offset the path inward by `distance` (negative buffer / erosion).\n * May return empty group if distance exceeds inradius.\n */\nexport function offsetCurvesInward(p: Path, distance: number): Group {\n return buffer(p, -Math.abs(distance))\n}\n\nexport const contour = {\n offsetCurvesOutward,\n offsetCurvesInward,\n}\n"]}
1
+ {"version":3,"sources":["../../src/types/vec2.ts","../../src/types/circle.ts","../../src/types/segment.ts","../../src/types/path.ts","../../src/types/group.ts","../../src/clipper/convert.ts","../../src/morphology/buffer.ts","../../src/predicates/index.ts","../../src/processing/index.ts","../../src/pointSet/index.ts","../../src/triangulation/index.ts","../../src/contour/dissolve.ts","../../src/contour/chordalAxis.ts","../../src/circlePacking/index.ts","../../src/optimisation/index.ts","../../src/contour/boundaryDistance.ts","../../src/contour/medialAxis.ts","../../src/contour/straightSkeleton.ts","../../src/contour/marchingSquares.ts","../../src/contour/fields.ts","../../src/contour/distanceTree.ts","../../src/contour/index.ts"],"names":["path","distanceToBoundary","len","Delaunay","edgeKey","mid","key","bounds"],"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'\n\n/** Circle with center (x, y) and radius r (PGS often stored radius in PVector.z). */\nexport type Circle = {\n x: number\n y: number\n r: number\n}\n\nexport function circle(x: number, y: number, r: number): Circle {\n return { x, y, r }\n}\n\nexport function circleCenter(c: Circle): Vec2 {\n return { x: c.x, y: c.y }\n}\n","import type { Vec2 } from './vec2.js'\n\n/** Line segment between two points. */\nexport type Segment = {\n a: Vec2\n b: Vec2\n}\n\nexport function segment(a: Vec2, b: Vec2): Segment {\n return { a, b }\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 { Path } from './path.js'\nimport { clonePath } from './path.js'\n\n/**\n * Ordered collection of paths. Later entries are “on top” for occlusion-style ops.\n */\nexport type Group = {\n paths: Path[]\n}\n\nexport function group(paths: Path[] = []): Group {\n return { paths: paths.map(clonePath) }\n}\n\nexport function groupFromPaths(...paths: Path[]): Group {\n return group(paths)\n}\n\nexport function cloneGroup(g: Group): Group {\n return group(g.paths)\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 } from '../types/index.js'\nimport { group } from '../types/index.js'\nimport { inflatePathsD, JoinType, EndType } from 'clipper2-ts'\nimport { pathToPathsD, pathsDToGroup } from '../clipper/convert.js'\n\nexport type BufferOptions = {\n /** Join style for offset. Default round. */\n join?: 'round' | 'miter' | 'square'\n}\n\n/**\n * Offset / buffer a closed path by `delta` (positive = expand, negative = erode).\n * Returns a group of resulting closed paths (may split or vanish when eroding).\n */\nexport function buffer(\n path: Path,\n delta: number,\n options: BufferOptions = {},\n): Group {\n const subject = pathToPathsD(path)\n const join =\n options.join === 'miter'\n ? JoinType.Miter\n : options.join === 'square'\n ? JoinType.Square\n : JoinType.Round\n const inflated = inflatePathsD(subject, delta, join, EndType.Polygon)\n return pathsDToGroup(inflated)\n}\n\n/**\n * Erode by `|amount|` then dilate by `|amount|` (opening). Useful for cleaning.\n */\nexport function erosionDilation(p: Path, amount: number): Group {\n const a = Math.abs(amount)\n if (a < 1e-12) return group([p])\n const eroded = buffer(p, -a)\n if (eroded.paths.length === 0) return eroded\n const dilated: Path[] = []\n for (const q of eroded.paths) {\n dilated.push(...buffer(q, a).paths)\n }\n return group(dilated)\n}\n\n/**\n * Dilate by `|amount|` then erode by `|amount|` (closing). Fills small gaps.\n */\nexport function dilationErosion(p: Path, amount: number): Group {\n const a = Math.abs(amount)\n if (a < 1e-12) return group([p])\n const dilated = buffer(p, a)\n if (dilated.paths.length === 0) return dilated\n const eroded: Path[] = []\n for (const q of dilated.paths) {\n eroded.push(...buffer(q, -a).paths)\n }\n return group(eroded)\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 { Group, Path, Segment, Vec2 } from '../types/index.js'\nimport { path, normalizeRing, polygon, segment, group } from '../types/index.js'\nimport { bounds, containsPoint, centroid } from '../predicates/index.js'\nimport { intersect, unionAll } from '../shapeBoolean/index.js'\n\n/** Exterior ring as its own closed path (holes dropped). */\nexport function extractPerimeter(p: Path): Path {\n const exterior = p.rings[0]\n if (!exterior) return path([], true)\n return polygon(exterior)\n}\n\n/** Alias for extractPerimeter. */\nexport function extractBoundary(p: Path): Path {\n return extractPerimeter(p)\n}\n\n/** Each hole as a separate closed path. */\nexport function extractHoles(p: Path): Path[] {\n const holes: Path[] = []\n for (let i = 1; i < p.rings.length; i++) {\n const hole = p.rings[i]\n if (hole && hole.length >= 3) holes.push(polygon(hole))\n }\n return holes\n}\n\n/**\n * Insert vertices so no edge exceeds `maxSegLen`.\n * Closed rings treat the wrap-around edge.\n */\nexport function densify(p: Path, maxSegLen: number): Path {\n if (maxSegLen <= 0) return p\n return path(\n p.rings.map((ring) => densifyRing(ring, maxSegLen, p.closed)),\n p.closed,\n )\n}\n\nfunction densifyRing(\n ring: Vec2[],\n maxSegLen: number,\n closed: boolean,\n): Vec2[] {\n if (ring.length < 2) return [...ring]\n const out: Vec2[] = []\n const n = ring.length\n const edges = closed ? n : n - 1\n for (let i = 0; i < edges; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % n]!\n out.push(a)\n const dist = Math.hypot(b.x - a.x, b.y - a.y)\n const steps = Math.floor(dist / maxSegLen)\n for (let s = 1; s < steps; s++) {\n const t = s / steps\n out.push({\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n })\n }\n }\n if (!closed) out.push(ring[n - 1]!)\n return closed ? normalizeRing(out) : out\n}\n\n/** Drop holes whose absolute area is below `minArea`. */\nexport function removeSmallHoles(p: Path, minArea: number): Path {\n if (p.rings.length <= 1) return p\n const exterior = p.rings[0]!\n const kept = p.rings.slice(1).filter((hole) => {\n const a = Math.abs(shoelace(hole))\n return a >= minArea\n })\n return path([exterior, ...kept], p.closed)\n}\n\n/** Seeded uniform random points inside a closed path. */\nexport function generateRandomPoints(\n p: Path,\n count: number,\n seed = 1,\n): Vec2[] {\n const rng = mulberry32(seed >>> 0)\n const b = bounds(p)\n const out: Vec2[] = []\n let attempts = 0\n const maxAttempts = Math.max(count * 50, 100)\n while (out.length < count && attempts < maxAttempts) {\n attempts++\n const pt = {\n x: b.minX + rng() * (b.maxX - b.minX),\n y: b.minY + rng() * (b.maxY - b.minY),\n }\n if (containsPoint(p, pt)) out.push(pt)\n }\n return out\n}\n\n/** Axis-aligned grid samples that fall inside the path. */\nexport function generateRandomGridPoints(\n p: Path,\n spacing: number,\n): Vec2[] {\n const step = Math.max(spacing, 1e-9)\n const b = bounds(p)\n const out: Vec2[] = []\n for (let x = b.minX; x <= b.maxX + 1e-12; x += step) {\n for (let y = b.minY; y <= b.maxY + 1e-12; y += step) {\n const pt = { x, y }\n if (containsPoint(p, pt)) out.push(pt)\n }\n }\n return out\n}\n\n/** Evenly spaced samples along the exterior perimeter. */\nexport function pointsOnExterior(p: Path, count: number): Vec2[] {\n const ring = p.rings[0]\n if (!ring || ring.length < 2 || count <= 0) return []\n const lengths = edgeLengths(ring, true)\n const total = lengths.reduce((s, L) => s + L, 0)\n if (total < 1e-12) return []\n const out: Vec2[] = []\n for (let i = 0; i < count; i++) {\n const target = (i / count) * total\n out.push(pointAtArcLength(ring, lengths, target))\n }\n return out\n}\n\n/** Exterior edges as segments. */\nexport function segmentsOnExterior(p: Path): Segment[] {\n const ring = p.rings[0]\n if (!ring || ring.length < 2) return []\n const n = ring.length\n const closed = p.closed\n const edges = closed ? n : n - 1\n const out: Segment[] = []\n for (let i = 0; i < edges; i++) {\n out.push(segment(ring[i]!, ring[(i + 1) % n]!))\n }\n return out\n}\n\n/**\n * Cut `p` with the infinite line through `a`→`b`.\n * Returns pieces on both sides (typically 0–2 paths).\n */\nexport function slice(p: Path, a: Vec2, b: Vec2): Group {\n const dx = b.x - a.x\n const dy = b.y - a.y\n const len = Math.hypot(dx, dy)\n if (len < 1e-12) return group([p])\n const nx = -dy / len\n const ny = dx / len\n const bb = bounds(p)\n const span =\n Math.hypot(bb.maxX - bb.minX, bb.maxY - bb.minY) * 4 + 10\n const left = halfPlanePoly(a, nx, ny, span)\n const right = halfPlanePoly(a, -nx, -ny, span)\n const parts: Path[] = []\n for (const half of [left, right]) {\n parts.push(...intersect(p, half).paths)\n }\n return group(parts)\n}\n\n/** Split through the centroid with a vertical cut (left/right). */\nexport function centroidSplit(p: Path): Group {\n const c = centroid(p)\n const bb = bounds(p)\n const pad = Math.max(bb.maxY - bb.minY, 1) + 1\n return slice(p, { x: c.x, y: c.y - pad }, { x: c.x, y: c.y + pad })\n}\n\n/** Union all closed paths in a group (dissolve overlapping contours). */\nexport function dissolve(paths: Path[]): Group {\n return unionAll(paths)\n}\n\n/** Vertex–edge intersection points between two path boundaries. */\nexport function intersectionPoints(a: Path, b: Path): Vec2[] {\n const segsA = allSegments(a)\n const segsB = allSegments(b)\n const out: Vec2[] = []\n const seen = new Set<string>()\n for (const sa of segsA) {\n for (const sb of segsB) {\n const hit = segmentIntersection(sa.a, sa.b, sb.a, sb.b)\n if (!hit) continue\n const key = `${hit.x.toFixed(9)},${hit.y.toFixed(9)}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(hit)\n }\n }\n return out\n}\n\nfunction halfPlanePoly(\n origin: Vec2,\n nx: number,\n ny: number,\n span: number,\n): Path {\n // Orthonormal tangent\n const tx = -ny\n const ty = nx\n const o = origin\n return polygon([\n {\n x: o.x - tx * span + nx * 1e-9,\n y: o.y - ty * span + ny * 1e-9,\n },\n {\n x: o.x + tx * span + nx * 1e-9,\n y: o.y + ty * span + ny * 1e-9,\n },\n {\n x: o.x + tx * span + nx * span,\n y: o.y + ty * span + ny * span,\n },\n {\n x: o.x - tx * span + nx * span,\n y: o.y - ty * span + ny * span,\n },\n ])\n}\n\nfunction allSegments(p: Path): Segment[] {\n const out: Segment[] = []\n for (const ring of p.rings) {\n const n = ring.length\n const edges = p.closed ? n : Math.max(0, n - 1)\n for (let i = 0; i < edges; i++) {\n out.push(segment(ring[i]!, ring[(i + 1) % n]!))\n }\n }\n return out\n}\n\nfunction segmentIntersection(\n a: Vec2,\n b: Vec2,\n c: Vec2,\n d: Vec2,\n): Vec2 | null {\n const rX = b.x - a.x\n const rY = b.y - a.y\n const sX = d.x - c.x\n const sY = d.y - c.y\n const den = rX * sY - rY * sX\n if (Math.abs(den) < 1e-14) return null\n const t = ((c.x - a.x) * sY - (c.y - a.y) * sX) / den\n const u = ((c.x - a.x) * rY - (c.y - a.y) * rX) / den\n if (t < -1e-9 || t > 1 + 1e-9 || u < -1e-9 || u > 1 + 1e-9) return null\n return { x: a.x + t * rX, y: a.y + t * rY }\n}\n\nfunction edgeLengths(ring: Vec2[], closed: boolean): number[] {\n const n = ring.length\n const edges = closed ? n : n - 1\n const lengths: number[] = []\n for (let i = 0; i < edges; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % n]!\n lengths.push(Math.hypot(b.x - a.x, b.y - a.y))\n }\n return lengths\n}\n\nfunction pointAtArcLength(\n ring: Vec2[],\n lengths: number[],\n target: number,\n): Vec2 {\n let remain = target\n const n = ring.length\n for (let i = 0; i < lengths.length; i++) {\n const L = lengths[i]!\n if (remain <= L || i === lengths.length - 1) {\n const t = L < 1e-12 ? 0 : remain / L\n const a = ring[i]!\n const b = ring[(i + 1) % n]!\n return {\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n }\n }\n remain -= L\n }\n return { ...ring[0]! }\n}\n\nfunction shoelace(ring: Vec2[]): number {\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\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\nexport const processing = {\n extractPerimeter,\n extractBoundary,\n extractHoles,\n densify,\n removeSmallHoles,\n generateRandomPoints,\n generateRandomGridPoints,\n pointsOnExterior,\n segmentsOnExterior,\n slice,\n centroidSplit,\n dissolve,\n intersectionPoints,\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","import type { Group, Path, Segment, Vec2 } from '../types/index.js'\nimport { group, polyline } from '../types/index.js'\n\nfunction key(v: Vec2, digits = 9): string {\n return `${v.x.toFixed(digits)},${v.y.toFixed(digits)}`\n}\n\nfunction same(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\n/**\n * Chain connected segments into maximal-length open polylines.\n */\nexport function dissolveSegments(segments: Segment[]): Group {\n const segs = segments.filter((s) => !same(s.a, s.b))\n if (segs.length === 0) return group([])\n\n // adjacency: endpoint key -> list of {segIdx, otherKey}\n const adj = new Map<string, { segIdx: number; other: string }[]>()\n const pts = new Map<string, Vec2>()\n\n const add = (a: Vec2, b: Vec2, segIdx: number) => {\n const ka = key(a)\n const kb = key(b)\n pts.set(ka, a)\n pts.set(kb, b)\n if (!adj.has(ka)) adj.set(ka, [])\n if (!adj.has(kb)) adj.set(kb, [])\n adj.get(ka)!.push({ segIdx, other: kb })\n adj.get(kb)!.push({ segIdx, other: ka })\n }\n\n for (let i = 0; i < segs.length; i++) {\n add(segs[i]!.a, segs[i]!.b, i)\n }\n\n const used = new Set<number>()\n const paths: Path[] = []\n\n const unusedDegree = (k: string) =>\n (adj.get(k) ?? []).filter((e) => !used.has(e.segIdx)).length\n\n const nextUnused = (k: string) =>\n (adj.get(k) ?? []).find((e) => !used.has(e.segIdx))\n\n const starts = [...adj.keys()].sort(\n (a, b) => unusedDegree(a) - unusedDegree(b),\n )\n\n for (const start of starts) {\n let link = nextUnused(start)\n while (link) {\n const chain: Vec2[] = [pts.get(start)!]\n let curr = start\n used.add(link.segIdx)\n let next = link.other\n chain.push(pts.get(next)!)\n\n while (unusedDegree(next) === 1) {\n const e = nextUnused(next)\n if (!e) break\n used.add(e.segIdx)\n curr = next\n next = e.other\n void curr\n chain.push(pts.get(next)!)\n if (next === start) break\n }\n\n if (chain.length >= 2) paths.push(polyline(chain))\n link = nextUnused(start)\n }\n }\n\n for (let i = 0; i < segs.length; i++) {\n if (used.has(i)) continue\n const s = segs[i]!\n paths.push(polyline([s.a, s.b]))\n }\n\n return group(paths)\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { segment } from '../types/index.js'\nimport { densify } from '../processing/index.js'\nimport { delaunayTriangulation } from '../triangulation/index.js'\nimport { centroid } from '../predicates/index.js'\nimport { dissolveSegments } from './dissolve.js'\n\nfunction mid(a: Vec2, b: Vec2): Vec2 {\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 }\n}\n\nfunction len(a: Vec2, b: Vec2): number {\n return Math.hypot(b.x - a.x, b.y - a.y)\n}\n\nfunction edgeKey(a: Vec2, b: Vec2): string {\n const ka = `${a.x.toFixed(8)},${a.y.toFixed(8)}`\n const kb = `${b.x.toFixed(8)},${b.y.toFixed(8)}`\n return ka < kb ? `${ka}|${kb}` : `${kb}|${ka}`\n}\n\n/**\n * Chordal Axis Transform: join midpoints of interior chords / centroids of\n * terminal & junction triangles from a densified Delaunay triangulation.\n */\nexport function chordalAxis(shape: Path): Group {\n if (!shape.closed || shape.rings.length === 0) return dissolveSegments([])\n\n const b = boundsSpan(shape)\n const densified = densify(shape, Math.max(b / 40, 1e-3))\n const tris = delaunayTriangulation(densified)\n if (tris.length === 0) return dissolveSegments([])\n\n // Count how many triangles share each edge\n const edgeCount = new Map<string, number>()\n const triEdges: [Vec2, Vec2, Vec2][] = []\n\n for (const t of tris) {\n const r = t.rings[0]\n if (!r || r.length < 3) continue\n const a = r[0]!\n const b0 = r[1]!\n const c = r[2]!\n triEdges.push([a, b0, c])\n for (const [u, v] of [\n [a, b0],\n [b0, c],\n [c, a],\n ] as [Vec2, Vec2][]) {\n const k = edgeKey(u, v)\n edgeCount.set(k, (edgeCount.get(k) ?? 0) + 1)\n }\n }\n\n const isBoundary = (u: Vec2, v: Vec2) => (edgeCount.get(edgeKey(u, v)) ?? 0) <= 1\n\n const segs = []\n for (const [a, b0, c] of triEdges) {\n const edges: [Vec2, Vec2][] = [\n [a, b0],\n [b0, c],\n [c, a],\n ]\n const interior = edges.filter(([u, v]) => !isBoundary(u, v))\n const degree = interior.length // number of interior edges (= neighbors)\n\n if (degree === 1) {\n // Terminal: centroid → midpoint of interior edge\n const [u, v] = interior[0]!\n const cen = centroid({ rings: [[a, b0, c]], closed: true })\n segs.push(segment(cen, mid(u, v)))\n } else if (degree === 2) {\n // Sleeve: connect midpoints of two interior edges\n const m0 = mid(interior[0]![0], interior[0]![1])\n const m1 = mid(interior[1]![0], interior[1]![1])\n segs.push(segment(m0, m1))\n } else if (degree === 3) {\n // Junction: midpoints of two shortest → midpoint of longest\n const ranked = edges\n .map(([u, v]) => ({ u, v, l: len(u, v) }))\n .sort((x, y) => y.l - x.l)\n const longest = ranked[0]!\n const shortA = ranked[1]!\n const shortB = ranked[2]!\n const mL = mid(longest.u, longest.v)\n segs.push(segment(mid(shortA.u, shortA.v), mL))\n segs.push(segment(mid(shortB.u, shortB.v), mL))\n }\n }\n\n return dissolveSegments(segs)\n}\n\nfunction boundsSpan(p: Path): number {\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 return Math.max(maxX - minX, maxY - minY, 1)\n}\n","import type { Circle, Path, Vec2 } from '../types/index.js'\nimport { circle } from '../types/index.js'\nimport { bounds, containsPoint } from '../predicates/index.js'\n\n/**\n * Lattice inclusion mode.\n * - `overlap` (default): full-path fill — keep disks that overlap the path;\n * center the lattice so opposite-edge cutoffs match. Clip in SVG to cut at\n * the boundary (including holes).\n * - `contained`: keep only disks fully inside the path (when you must stroke\n * complete circles); lattice centered with equal leftover margins.\n */\nexport type LatticePackMode = 'overlap' | 'contained'\n\n/**\n * Square lattice of equal circles.\n * @see docs/decisions/0003-deferred-circle-packing.md\n */\nexport function squareLatticePack(\n path: Path,\n diameter: number,\n mode: LatticePackMode = 'overlap',\n): Circle[] {\n const d = Math.max(diameter, 0.1)\n const r = d / 2\n const b = bounds(path)\n const out: Circle[] = []\n const accept =\n mode === 'contained' ? circleContainedInPath : circleOverlapsPath\n const inset = mode === 'contained' ? r : 0\n const { ox, oy, nX, nY } = centeredLatticeGrid(b, d, d, inset, d)\n if (nX < 1 || nY < 1) return out\n\n for (let i = 0; i < nX; i++) {\n for (let j = 0; j < nY; j++) {\n const c = circle(ox + i * d, oy + j * d, r)\n if (accept(c, path)) out.push(c)\n }\n }\n return out\n}\n\n/**\n * Hexagonal lattice of equal circles.\n */\nexport function hexLatticePack(\n path: Path,\n diameter: number,\n mode: LatticePackMode = 'overlap',\n): Circle[] {\n const d = Math.max(diameter, 0.1)\n const r = d / 2\n const b = bounds(path)\n const z = r * Math.sqrt(3)\n const out: Circle[] = []\n const accept =\n mode === 'contained' ? circleContainedInPath : circleOverlapsPath\n const inset = mode === 'contained' ? r : 0\n const { ox, nX, nY } = centeredLatticeGrid(b, z, d, inset, d)\n if (nX < 1 || nY < 1) return out\n\n // First column uses offset `r`, so Y centers span [oy - r, oy + (nY-1)*d].\n // Re-center that full extent so top/bottom cutoffs match.\n const innerH = b.maxY - b.minY - 2 * inset\n const extentY = (nY - 1) * d + r\n const oy = b.minY + inset + (innerH - extentY) / 2 + r\n\n let offset = 0\n for (let i = 0; i < nX; i++) {\n offset = offset === r ? 0 : r\n for (let j = 0; j < nY; j++) {\n const c = circle(ox + i * z, oy + j * d - offset, r)\n if (accept(c, path)) out.push(c)\n }\n }\n return out\n}\n\n/**\n * Centered lattice grid. `inset` > 0 (contained) keeps disk edges inside the AABB;\n * `inset` 0 (overlap) matches PGS coverage count, shifted so opposite cutoffs match.\n * `endPad` mirrors the historical loop bound `max + diameter`.\n */\nfunction centeredLatticeGrid(\n b: { minX: number; minY: number; maxX: number; maxY: number },\n stepX: number,\n stepY: number,\n inset: number,\n endPad: number,\n): { ox: number; oy: number; nX: number; nY: number } {\n const innerW = b.maxX - b.minX - 2 * inset\n const innerH = b.maxY - b.minY - 2 * inset\n if (innerW < -1e-9 || innerH < -1e-9) {\n return { ox: 0, oy: 0, nX: 0, nY: 0 }\n }\n\n let nX: number\n let nY: number\n if (inset > 0) {\n nX = Math.floor(innerW / stepX + 1e-9) + 1\n nY = Math.floor(innerH / stepY + 1e-9) + 1\n } else {\n // Same count as `for (x = min; x < max + endPad; x += step)`\n nX = Math.floor((innerW + endPad) / stepX - 1e-12) + 1\n nY = Math.floor((innerH + endPad) / stepY - 1e-12) + 1\n }\n\n const spanX = (nX - 1) * stepX\n const spanY = (nY - 1) * stepY\n const ox = b.minX + inset + (innerW - spanX) / 2\n const oy = b.minY + inset + (innerH - spanY) / 2\n return { ox, oy, nX, nY }\n}\n\n/**\n * Seeded stochastic packing: sample random points, grow max non-overlapping\n * radius (tangent to nearest circle or limited by distance to boundary).\n * Triangulation Steiner mode deferred.\n */\nexport function stochasticPack(\n path: Path,\n points: number,\n minRadius: number,\n seed = 1,\n): Circle[] {\n const rng = mulberry32(seed >>> 0)\n const b = bounds(path)\n const packing: Circle[] = []\n\n for (let attempt = 0; attempt < points; attempt++) {\n const p = vecInBounds(b, rng)\n if (!containsPoint(path, p)) continue\n\n const maxR = clearanceRadius(p, path, packing)\n if (maxR < minRadius) continue\n packing.push(circle(p.x, p.y, maxR))\n }\n\n return packing\n}\n\n/**\n * Pack up to `n` maximum inscribed circles via iterative largest-empty-circle\n * search (grid + local refine). Circles are fully contained and non-overlapping.\n * `tolerance` controls coarse grid step as a fraction of the bbox diagonal\n * (PGS uses a related accuracy knob; values ~0.5–1 are reasonable).\n *\n * Deferred: `tangencyPack`, `trinscribedPack` — see ADR 0003.\n */\nexport function maximumInscribedPack(\n path: Path,\n n: number,\n tolerance = 1,\n): Circle[] {\n return obstaclePack(path, [], n, tolerance)\n}\n\n/**\n * Pack inscribed circles while radius stays ≥ `minRadius`.\n */\nexport function maximumInscribedPackUntil(\n path: Path,\n minRadius: number,\n tolerance = 1,\n): Circle[] {\n const packing: Circle[] = []\n const tol = Math.max(0.01, tolerance)\n const minR = Math.max(0.01, minRadius)\n for (;;) {\n const next = findLargestEmptyCircle(path, packing, tol)\n if (!next || next.r < minR) break\n packing.push(next)\n }\n return packing\n}\n\n/**\n * Successive LECs inside `path`, treating `obstacles` as already-placed disks.\n * Simpler than full PGS obstacle packing; sufficient for “avoid these circles.”\n */\nexport function obstaclePack(\n path: Path,\n obstacles: Circle[],\n n: number,\n tolerance = 1,\n): Circle[] {\n const packing: Circle[] = obstacles.map((c) => ({ ...c }))\n const placed: Circle[] = []\n const tol = Math.max(0.01, tolerance)\n for (let i = 0; i < n; i++) {\n const next = findLargestEmptyCircle(path, packing, tol)\n if (!next || next.r <= 1e-9) break\n packing.push(next)\n placed.push(next)\n }\n return placed\n}\n\n/**\n * Front-chain-inspired packing of (possibly varying) radii in the path envelope,\n * then keep circles that overlap the path. Seeded for determinism.\n * Grows until placement stalls (region effectively full); no fixed circle count.\n * Not a line-by-line port of PGS FrontChainPacker — same role, approximate layout.\n */\nexport function frontChainPack(\n path: Path,\n radiusMin: number,\n radiusMax: number,\n seed = 1,\n): Circle[] {\n let rMin = Math.max(1e-6, Math.min(radiusMin, radiusMax))\n let rMax = Math.max(rMin, Math.max(radiusMin, radiusMax))\n const rng = mulberry32(seed >>> 0)\n const b = bounds(path)\n const packing: Circle[] = []\n const area = Math.max(1e-6, (b.maxX - b.minX) * (b.maxY - b.minY))\n // Safety ceiling only — real stop is consecutive placement failures.\n const capacity = Math.max(\n 4,\n Math.ceil((area / (Math.PI * rMin * rMin)) * 2),\n )\n\n const trySeed = (): boolean => {\n const p = vecInBounds(b, rng)\n const r = rMin + rng() * (rMax - rMin)\n const c = circle(p.x, p.y, r)\n if (!overlapsAny(c, packing) && circleOverlapsPath(c, path)) {\n packing.push(c)\n return true\n }\n return false\n }\n\n // Seed a few circles, then grow a frontier of tangent candidates.\n for (let i = 0; i < 8; i++) trySeed()\n\n let fails = 0\n while (packing.length < capacity) {\n const stallLimit = Math.max(500, packing.length * 12)\n if (fails >= stallLimit) break\n\n if (packing.length === 0) {\n if (trySeed()) fails = 0\n else fails++\n continue\n }\n\n // Reseed empty pockets so growth is not stuck on one cluster.\n if (fails > 0 && fails % 50 === 0) {\n if (trySeed()) {\n fails = 0\n continue\n }\n }\n\n const base = packing[Math.floor(rng() * packing.length)]!\n const ang = rng() * Math.PI * 2\n const r = rMin + rng() * (rMax - rMin)\n const dist = base.r + r\n const c = circle(\n base.x + Math.cos(ang) * dist,\n base.y + Math.sin(ang) * dist,\n r,\n )\n if (\n c.x < b.minX - rMax ||\n c.x > b.maxX + rMax ||\n c.y < b.minY - rMax ||\n c.y > b.maxY + rMax\n ) {\n fails++\n continue\n }\n if (!overlapsAny(c, packing) && circleOverlapsPath(c, path)) {\n packing.push(c)\n fails = 0\n } else {\n fails++\n }\n }\n\n return packing.filter((c) => circleOverlapsPath(c, path))\n}\n\n/**\n * Seed random circles in the envelope, then iteratively repulse overlaps;\n * keep those that overlap the path (PGS repulsionPack role).\n */\nexport function repulsionPack(\n path: Path,\n radiusMin: number,\n radiusMax: number,\n seed = 1,\n iterations = 80,\n): Circle[] {\n const rMin = Math.max(1e-6, Math.min(radiusMin, radiusMax))\n const rMax = Math.max(rMin, Math.max(radiusMin, radiusMax))\n const rng = mulberry32(seed >>> 0)\n const b = bounds(path)\n const area = Math.max(1e-6, (b.maxX - b.minX) * (b.maxY - b.minY))\n const avgR = (rMin + rMax) / 2\n const target = Math.max(\n 4,\n Math.floor(area / (Math.PI * avgR * avgR) * 0.6),\n )\n\n const circles: Circle[] = []\n for (let i = 0; i < target; i++) {\n const p = vecInBounds(b, rng)\n circles.push(circle(p.x, p.y, rMin + rng() * (rMax - rMin)))\n }\n\n for (let iter = 0; iter < iterations; iter++) {\n for (let i = 0; i < circles.length; i++) {\n for (let j = i + 1; j < circles.length; j++) {\n const a = circles[i]!\n const bC = circles[j]!\n const dx = bC.x - a.x\n const dy = bC.y - a.y\n const dist = Math.hypot(dx, dy) || 1e-9\n const minDist = a.r + bC.r\n if (dist >= minDist) continue\n const push = ((minDist - dist) / 2) * 0.5\n const ux = dx / dist\n const uy = dy / dist\n a.x -= ux * push\n a.y -= uy * push\n bC.x += ux * push\n bC.y += uy * push\n }\n }\n // Soft clamp to inflated envelope\n for (const c of circles) {\n c.x = Math.min(b.maxX + c.r, Math.max(b.minX - c.r, c.x))\n c.y = Math.min(b.maxY + c.r, Math.max(b.minY - c.r, c.y))\n }\n }\n\n return circles.filter((c) => circleOverlapsPath(c, path))\n}\n\n/** True if disk overlaps the filled path (including partial exterior overlap). */\nexport function circleOverlapsPath(c: Circle, path: Path): boolean {\n const center = { x: c.x, y: c.y }\n const dist = distanceToPolygon(center, path)\n return dist <= c.r * 0.95\n}\n\n/** True if the disk lies fully inside the path. */\nexport function circleContainedInPath(c: Circle, path: Path): boolean {\n const center = { x: c.x, y: c.y }\n if (!containsPoint(path, center)) return false\n return distanceToBoundary(center, path) + 1e-9 >= c.r\n}\n\n/** Distance from point to polygon: 0 if inside, else distance to boundary. */\nexport function distanceToPolygon(p: Vec2, path: Path): number {\n if (containsPoint(path, p)) return 0\n return distanceToBoundary(p, path)\n}\n\nfunction findLargestEmptyCircle(\n path: Path,\n obstacles: Circle[],\n tolerance: number,\n): Circle | null {\n const b = bounds(path)\n const diag = Math.hypot(b.maxX - b.minX, b.maxY - b.minY) || 1\n // denser grid for smaller tolerance\n const step = Math.max(diag * 0.02 * Math.sqrt(tolerance), diag * 0.01)\n let best: Circle | null = null\n\n for (let x = b.minX; x <= b.maxX; x += step) {\n for (let y = b.minY; y <= b.maxY; y += step) {\n const p = { x, y }\n if (!containsPoint(path, p)) continue\n const r = clearanceRadius(p, path, obstacles)\n if (!best || r > best.r) best = circle(p.x, p.y, r)\n }\n }\n\n if (!best) return null\n\n // Local refine around best\n let cur = best\n let span = step\n for (let iter = 0; iter < 8; iter++) {\n let improved = cur\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue\n const p = { x: cur.x + dx * span, y: cur.y + dy * span }\n if (!containsPoint(path, p)) continue\n const r = clearanceRadius(p, path, obstacles)\n if (r > improved.r) improved = circle(p.x, p.y, r)\n }\n }\n cur = improved\n span *= 0.5\n }\n return cur\n}\n\nfunction clearanceRadius(\n p: Vec2,\n path: Path,\n obstacles: Circle[],\n): number {\n let r = distanceToBoundary(p, path)\n for (const c of obstacles) {\n r = Math.min(r, Math.hypot(p.x - c.x, p.y - c.y) - c.r)\n }\n return Math.max(0, r)\n}\n\nfunction overlapsAny(c: Circle, packing: Circle[]): boolean {\n for (const o of packing) {\n if (Math.hypot(c.x - o.x, c.y - o.y) < c.r + o.r - 1e-9) return true\n }\n return false\n}\n\nfunction distanceToBoundary(p: Vec2, path: Path): number {\n let min = Infinity\n for (const ring of path.rings) {\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % ring.length]!\n min = Math.min(min, pointSegmentDistance(p, a, b))\n }\n }\n return min\n}\n\nfunction pointSegmentDistance(p: Vec2, a: Vec2, b: Vec2): number {\n const abx = b.x - a.x\n const aby = b.y - a.y\n const len2 = abx * abx + aby * aby\n if (len2 < 1e-18) return Math.hypot(p.x - a.x, p.y - a.y)\n let t = ((p.x - a.x) * abx + (p.y - a.y) * aby) / len2\n t = Math.max(0, Math.min(1, t))\n return Math.hypot(p.x - (a.x + t * abx), p.y - (a.y + t * aby))\n}\n\nfunction vecInBounds(\n b: { minX: number; minY: number; maxX: number; maxY: number },\n rng: () => number,\n): Vec2 {\n return {\n x: b.minX + rng() * (b.maxX - b.minX),\n y: b.minY + rng() * (b.maxY - b.minY),\n }\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\nexport const circlePacking = {\n squareLatticePack,\n hexLatticePack,\n stochasticPack,\n maximumInscribedPack,\n maximumInscribedPackUntil,\n obstaclePack,\n frontChainPack,\n repulsionPack,\n circleOverlapsPath,\n circleContainedInPath,\n}\n","import type { Circle, Path, Vec2 } from '../types/index.js'\nimport { circle, polygon } from '../types/index.js'\nimport { bounds, containsPoint } from '../predicates/index.js'\nimport { boundingBox, convexHull } from '../hull/index.js'\nimport {\n maximumInscribedPack,\n maximumInscribedPackUntil,\n} from '../circlePacking/index.js'\n\n/** Axis-aligned envelope (alias of hull.boundingBox). */\nexport function envelope(p: Path): Path {\n return boundingBox(p)\n}\n\n/** Largest inscribed circle (fully contained). */\nexport function maximumInscribedCircle(\n p: Path,\n tolerance = 1,\n): Circle | null {\n return maximumInscribedPack(p, 1, tolerance)[0] ?? null\n}\n\n/** Alias: successive LECs until radius drops below `minRadius`. */\nexport function largestEmptyCircles(\n p: Path,\n minRadius: number,\n tolerance = 1,\n): Circle[] {\n return maximumInscribedPackUntil(p, minRadius, tolerance)\n}\n\n/** Single largest empty circle (no obstacle circles). */\nexport function largestEmptyCircle(\n p: Path,\n tolerance = 1,\n): Circle | null {\n return maximumInscribedCircle(p, tolerance)\n}\n\n/**\n * Heuristic maximum axis-aligned inscribed rectangle: inset the AABB until all\n * four corners lie inside. If the AABB corners are already inside, returns the envelope.\n */\nexport function maximumInscribedAARectangle(p: Path): Path {\n const b = bounds(p)\n const w = b.maxX - b.minX\n const h = b.maxY - b.minY\n if (w < 1e-12 || h < 1e-12) return envelope(p)\n\n const fits = (m: number) => {\n const rect = [\n { x: b.minX + m, y: b.minY + m },\n { x: b.maxX - m, y: b.minY + m },\n { x: b.maxX - m, y: b.maxY - m },\n { x: b.minX + m, y: b.maxY - m },\n ]\n return rect.every((pt) => containsPoint(p, pt))\n }\n\n if (fits(0)) return envelope(p)\n\n let lo = 0\n let hi = Math.min(w, h) / 2\n let best = hi\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2\n if (fits(mid)) {\n best = mid\n hi = mid\n } else {\n lo = mid\n }\n }\n const m = best\n return polygon([\n { x: b.minX + m, y: b.minY + m },\n { x: b.maxX - m, y: b.minY + m },\n { x: b.maxX - m, y: b.maxY - m },\n { x: b.minX + m, y: b.maxY - m },\n ])\n}\n\n/** Closest point on the path boundary to `point`. */\nexport function closestPoint(p: Path, point: Vec2): Vec2 {\n let best = point\n let bestD = Infinity\n for (const ring of p.rings) {\n const n = ring.length\n const edges = p.closed ? n : Math.max(0, n - 1)\n for (let i = 0; i < edges; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % n]!\n const q = projectPointToSegment(point, a, b)\n const d = Math.hypot(q.x - point.x, q.y - point.y)\n if (d < bestD) {\n bestD = d\n best = q\n }\n }\n }\n return best\n}\n\n/** Closest vertex of the path to `point`. */\nexport function closestVertex(p: Path, point: Vec2): Vec2 {\n let best = p.rings[0]?.[0] ?? point\n let bestD = Infinity\n for (const ring of p.rings) {\n for (const v of ring) {\n const d = Math.hypot(v.x - point.x, v.y - point.y)\n if (d < bestD) {\n bestD = d\n best = v\n }\n }\n }\n return { ...best }\n}\n\n/** Closest pair among a point set (O(n²); fine for small sets). */\nexport function closestPointPair(points: Vec2[]): [Vec2, Vec2] | null {\n if (points.length < 2) return null\n let best: [Vec2, Vec2] = [points[0]!, points[1]!]\n let bestD = Infinity\n for (let i = 0; i < points.length; i++) {\n for (let j = i + 1; j < points.length; j++) {\n const d = Math.hypot(\n points[i]!.x - points[j]!.x,\n points[i]!.y - points[j]!.y,\n )\n if (d < bestD) {\n bestD = d\n best = [points[i]!, points[j]!]\n }\n }\n }\n return best\n}\n\n/** Farthest pair among a point set (O(n²)). */\nexport function farthestPointPair(points: Vec2[]): [Vec2, Vec2] | null {\n if (points.length < 2) return null\n let best: [Vec2, Vec2] = [points[0]!, points[1]!]\n let bestD = -1\n for (let i = 0; i < points.length; i++) {\n for (let j = i + 1; j < points.length; j++) {\n const d = Math.hypot(\n points[i]!.x - points[j]!.x,\n points[i]!.y - points[j]!.y,\n )\n if (d > bestD) {\n bestD = d\n best = [points[i]!, points[j]!]\n }\n }\n }\n return best\n}\n\n/**\n * Minimum bounding circle of a path's vertices (Welzl on convex hull).\n */\nexport function minimumBoundingCircle(p: Path): Circle {\n const pts: Vec2[] = []\n for (const ring of p.rings) pts.push(...ring)\n const hull = convexHull(pts).rings[0] ?? pts\n return minDisk(hull)\n}\n\nfunction minDisk(points: Vec2[]): Circle {\n // Deterministic Welzl (no shuffle); fine for typical vertex counts.\n return welzl(points.map((p) => ({ ...p })), [], 0)\n}\n\nfunction welzl(P: Vec2[], R: Vec2[], i: number): Circle {\n if (i === P.length || R.length === 3) return diskFromBoundary(R)\n const d = welzl(P, R, i + 1)\n const p = P[i]!\n if (Math.hypot(p.x - d.x, p.y - d.y) <= d.r + 1e-9) return d\n return welzl(P, [...R, p], i + 1)\n}\n\nfunction diskFromBoundary(R: Vec2[]): Circle {\n if (R.length === 0) return circle(0, 0, 0)\n if (R.length === 1) return circle(R[0]!.x, R[0]!.y, 0)\n if (R.length === 2) {\n const a = R[0]!\n const b = R[1]!\n return circle(\n (a.x + b.x) / 2,\n (a.y + b.y) / 2,\n Math.hypot(a.x - b.x, a.y - b.y) / 2,\n )\n }\n return circumcircle(R[0]!, R[1]!, R[2]!)\n}\n\nfunction circumcircle(a: Vec2, b: Vec2, c: Vec2): Circle {\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-14) {\n // collinear — diameter of farthest pair\n const pair = farthestPointPair([a, b, c])!\n return circle(\n (pair[0].x + pair[1].x) / 2,\n (pair[0].y + pair[1].y) / 2,\n Math.hypot(pair[0].x - pair[1].x, pair[0].y - pair[1].y) / 2,\n )\n }\n const ux =\n ((a.x * a.x + a.y * a.y) * (b.y - c.y) +\n (b.x * b.x + b.y * b.y) * (c.y - a.y) +\n (c.x * c.x + c.y * c.y) * (a.y - b.y)) /\n d\n const uy =\n ((a.x * a.x + a.y * a.y) * (c.x - b.x) +\n (b.x * b.x + b.y * b.y) * (a.x - c.x) +\n (c.x * c.x + c.y * c.y) * (b.x - a.x)) /\n d\n return circle(ux, uy, Math.hypot(ux - a.x, uy - a.y))\n}\n\nfunction projectPointToSegment(p: Vec2, a: Vec2, b: Vec2): Vec2 {\n const abx = b.x - a.x\n const aby = b.y - a.y\n const len2 = abx * abx + aby * aby\n if (len2 < 1e-18) return { ...a }\n let t = ((p.x - a.x) * abx + (p.y - a.y) * aby) / len2\n t = Math.max(0, Math.min(1, t))\n return { x: a.x + t * abx, y: a.y + t * aby }\n}\n\nexport const optimisation = {\n envelope,\n maximumInscribedCircle,\n largestEmptyCircle,\n largestEmptyCircles,\n maximumInscribedAARectangle,\n closestPoint,\n closestVertex,\n closestPointPair,\n farthestPointPair,\n minimumBoundingCircle,\n}\n","import type { Path, Vec2 } from '../types/index.js'\n\n/** Shortest Euclidean distance from a point to the path boundary (all rings). */\nexport function distanceToBoundary(path: Path, p: Vec2): number {\n let best = Infinity\n for (const ring of path.rings) {\n if (ring.length < 2) continue\n const n = ring.length\n const closed = path.closed\n const limit = closed ? n : n - 1\n for (let i = 0; i < limit; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % n]!\n best = Math.min(best, distPointSeg(p, a, b))\n }\n }\n return best\n}\n\n/** Collect all boundary segments as endpoint pairs. */\nexport function boundarySegments(path: Path): { a: Vec2; b: Vec2 }[] {\n const out: { a: Vec2; b: Vec2 }[] = []\n for (const ring of path.rings) {\n if (ring.length < 2) continue\n const n = ring.length\n const limit = path.closed ? n : n - 1\n for (let i = 0; i < limit; i++) {\n out.push({ a: ring[i]!, b: ring[(i + 1) % n]! })\n }\n }\n return out\n}\n\n/** Densified boundary sample points (including holes). */\nexport function sampleBoundary(path: Path, maxSegLen: number): Vec2[] {\n const pts: Vec2[] = []\n const lim = Math.max(maxSegLen, 1e-9)\n for (const ring of path.rings) {\n if (ring.length < 2) continue\n const n = ring.length\n const limit = path.closed ? n : n - 1\n for (let i = 0; i < limit; i++) {\n const a = ring[i]!\n const b = ring[(i + 1) % n]!\n const len = Math.hypot(b.x - a.x, b.y - a.y)\n const steps = Math.max(1, Math.ceil(len / lim))\n for (let s = 0; s < steps; s++) {\n const t = s / steps\n pts.push({ x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t })\n }\n }\n }\n return pts\n}\n\nfunction distPointSeg(p: Vec2, a: Vec2, b: Vec2): number {\n const dx = b.x - a.x\n const dy = b.y - a.y\n const len2 = dx * dx + dy * dy\n if (len2 < 1e-18) return Math.hypot(p.x - a.x, p.y - a.y)\n let t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2\n t = Math.max(0, Math.min(1, t))\n return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy))\n}\n","import { Delaunay } from 'd3-delaunay'\nimport type { Group, Path, Vec2 } from '../types/index.js'\nimport { polyline, segment } from '../types/index.js'\nimport { containsPoint, bounds } from '../predicates/index.js'\nimport { maximumInscribedCircle } from '../optimisation/index.js'\nimport { densify } from '../processing/index.js'\nimport { dissolveSegments } from './dissolve.js'\nimport { sampleBoundary } from './boundaryDistance.js'\n\nexport type MedialNode = {\n id: number\n position: Vec2\n radius: number\n parent: number | null\n children: number[]\n /** Path distance from root along the axis. */\n rootDist: number\n /** Aggregate descendant feature area (π r² style contribution). */\n featureArea: number\n}\n\nexport type MedialEdge = {\n head: number\n tail: number\n axial: number\n length: number\n}\n\nexport type MedialAxisGraph = {\n nodes: MedialNode[]\n edges: MedialEdge[]\n root: number\n}\n\n/**\n * Approximate medial axis via Voronoi edges of densified boundary samples.\n * Returns pruned dissolved polylines.\n *\n * Thresholds in [0,1]: 0 = no pruning, 1 = maximum pruning.\n */\nexport function medialAxis(\n shape: Path,\n axialThreshold = 0,\n distanceThreshold = 0,\n areaThreshold = 0,\n): Group {\n const g = buildMedialAxisGraph(shape)\n if (!g) return dissolveSegments([])\n const kept = pruneEdges(g, axialThreshold, distanceThreshold, areaThreshold)\n const segs = kept.map((e) => {\n const a = g.nodes[e.head]!.position\n const b = g.nodes[e.tail]!.position\n return segment(a, b)\n })\n return dissolveSegments(segs)\n}\n\nexport function buildMedialAxisGraph(shape: Path): MedialAxisGraph | null {\n if (!shape.closed || shape.rings.length === 0) return null\n\n const b = bounds(shape)\n const span = Math.max(b.maxX - b.minX, b.maxY - b.minY, 1)\n const densified = densify(shape, Math.max(span / 60, 1e-3))\n const samples = sampleBoundary(densified, Math.max(span / 80, 1e-3))\n if (samples.length < 3) return null\n\n // Deduplicate sites\n const uniq: Vec2[] = []\n const seen = new Set<string>()\n for (const p of samples) {\n const k = `${p.x.toFixed(6)},${p.y.toFixed(6)}`\n if (seen.has(k)) continue\n seen.add(k)\n uniq.push(p)\n }\n if (uniq.length < 3) return null\n\n const delaunay = Delaunay.from(\n uniq,\n (d) => d.x,\n (d) => d.y,\n )\n const pad = span * 0.5\n const voronoi = delaunay.voronoi([\n b.minX - pad,\n b.minY - pad,\n b.maxX + pad,\n b.maxY + pad,\n ])\n\n // Collect unique interior Voronoi edges\n type RawEdge = { a: Vec2; b: Vec2; radius: number }\n const raw: RawEdge[] = []\n const edgeSeen = new Set<string>()\n\n for (let i = 0; i < uniq.length; i++) {\n const poly = voronoi.cellPolygon(i)\n if (!poly || poly.length < 2) continue\n for (let j = 0; j < poly.length - 1; j++) {\n const p0 = poly[j]!\n const p1 = poly[j + 1]!\n const a = { x: p0[0], y: p0[1] }\n const bb = { x: p1[0], y: p1[1] }\n if (!containsPoint(shape, a) || !containsPoint(shape, bb)) continue\n const ek = edgeKey(a, bb)\n if (edgeSeen.has(ek)) continue\n edgeSeen.add(ek)\n const mid = { x: (a.x + bb.x) / 2, y: (a.y + bb.y) / 2 }\n const site = uniq[i]!\n const radius = Math.hypot(mid.x - site.x, mid.y - site.y)\n raw.push({ a, b: bb, radius })\n }\n }\n\n if (raw.length === 0) return null\n\n // Build node list\n const nodeIndex = new Map<string, number>()\n const nodes: MedialNode[] = []\n const ensure = (p: Vec2, radius: number): number => {\n const k = key(p)\n let id = nodeIndex.get(k)\n if (id !== undefined) {\n nodes[id]!.radius = Math.max(nodes[id]!.radius, radius)\n return id\n }\n id = nodes.length\n nodeIndex.set(k, id)\n nodes.push({\n id,\n position: p,\n radius,\n parent: null,\n children: [],\n rootDist: 0,\n featureArea: Math.PI * radius * radius,\n })\n return id\n }\n\n const undirected: { u: number; v: number; axial: number; length: number }[] =\n []\n for (const e of raw) {\n const midR = e.radius\n const u = ensure(e.a, midR)\n const v = ensure(e.b, midR)\n if (u === v) continue\n const length = Math.hypot(\n nodes[u]!.position.x - nodes[v]!.position.x,\n nodes[u]!.position.y - nodes[v]!.position.y,\n )\n const axial =\n length > 1e-12\n ? Math.abs(nodes[u]!.radius - nodes[v]!.radius) / length\n : 0\n undirected.push({ u, v, axial, length })\n }\n\n // Root near MIC center\n const mic = maximumInscribedCircle(shape, Math.max(span * 0.01, 0.1))\n const rootPos = mic\n ? { x: mic.x, y: mic.y }\n : {\n x: (b.minX + b.maxX) / 2,\n y: (b.minY + b.maxY) / 2,\n }\n let root = 0\n let bestD = Infinity\n for (const n of nodes) {\n const d = Math.hypot(n.position.x - rootPos.x, n.position.y - rootPos.y)\n if (d < bestD) {\n bestD = d\n root = n.id\n }\n }\n\n // BFS tree from root\n const adj = new Map<number, { to: number; axial: number; length: number }[]>()\n for (const e of undirected) {\n if (!adj.has(e.u)) adj.set(e.u, [])\n if (!adj.has(e.v)) adj.set(e.v, [])\n adj.get(e.u)!.push({ to: e.v, axial: e.axial, length: e.length })\n adj.get(e.v)!.push({ to: e.u, axial: e.axial, length: e.length })\n }\n\n const edges: MedialEdge[] = []\n const visited = new Set<number>([root])\n const queue = [root]\n nodes[root]!.rootDist = 0\n\n while (queue.length) {\n const u = queue.shift()!\n for (const link of adj.get(u) ?? []) {\n if (visited.has(link.to)) continue\n visited.add(link.to)\n nodes[link.to]!.parent = u\n nodes[u]!.children.push(link.to)\n nodes[link.to]!.rootDist = nodes[u]!.rootDist + link.length\n edges.push({\n head: u,\n tail: link.to,\n axial: link.axial,\n length: link.length,\n })\n queue.push(link.to)\n }\n }\n\n // Aggregate feature area bottom-up\n const post: number[] = []\n const stack = [root]\n const seenN = new Set<number>()\n while (stack.length) {\n const u = stack.pop()!\n if (seenN.has(u)) {\n post.push(u)\n continue\n }\n seenN.add(u)\n stack.push(u)\n for (const c of nodes[u]!.children) stack.push(c)\n }\n for (const u of post) {\n let area = nodes[u]!.featureArea\n for (const c of nodes[u]!.children) area += nodes[c]!.featureArea\n nodes[u]!.featureArea = area\n }\n\n return { nodes, edges, root }\n}\n\nfunction pruneEdges(\n g: MedialAxisGraph,\n axialT: number,\n distT: number,\n areaT: number,\n): MedialEdge[] {\n const maxDist = Math.max(...g.nodes.map((n) => n.rootDist), 1e-9)\n const maxArea = Math.max(...g.nodes.map((n) => n.featureArea), 1e-9)\n const maxAxial = Math.max(...g.edges.map((e) => e.axial), 1e-9)\n\n const aT = clamp01(axialT)\n const dT = clamp01(distT)\n const arT = clamp01(areaT)\n\n return g.edges.filter((e) => {\n const tail = g.nodes[e.tail]!\n // Keep edge unless pruning criteria reject the feature tip\n if (aT > 0 && e.axial / maxAxial < aT * 0.15 && aT > 0.05) {\n // high axial threshold prunes low-gradient (noisy tip) edges near leaves\n if (tail.children.length === 0 && e.axial / maxAxial < aT) return false\n }\n if (dT > 0) {\n const nd = tail.rootDist / maxDist\n // prune tips beyond (1 - dT) of max distance? PGS: higher threshold = more pruning of far features\n // Interpret: prune leaf edges whose normalized root distance is below dT (short stubs) when dT high...\n // From PGS javadoc: pruning based on spatial distance from root to tail — higher = more pruning\n // So we prune edges where the feature is \"small\" in distance sense — typically leaf branches\n // with small contribution. Use: prune if feature depth from max is shallow relative to threshold.\n if (tail.children.length === 0 && nd > 1 - dT && dT > 0) {\n // actually prune peripheral: when dT high, remove edges with high rootDist (far tips)\n // Wait - \"distance from root to tail\" pruning typically removes short branches near tips\n // JMedialAxis style: prune if feature's path distance metric is below threshold\n // We'll prune leaf edges if their length-normalized importance is low:\n }\n if (tail.children.length === 0 && (1 - nd) < dT * 0.5 && dT >= 0.5) {\n return false\n }\n // More aggressive: prune any leaf whose rootDist fraction exceeds (1-dT) when... \n // Simpler approach matching \"more threshold = more prune\":\n if (tail.children.length === 0 && nd * dT > 0.85) return false\n }\n if (arT > 0) {\n const na = tail.featureArea / maxArea\n // prune small-area features\n if (na < arT) return false\n }\n // axial: prune high axial-gradient tips (serrations)\n if (aT > 0 && e.axial / maxAxial > 1 - aT * 0.5 && tail.children.length === 0) {\n return false\n }\n return true\n })\n}\n\n/**\n * Longest center line through the medial axis, smoothed.\n */\nexport function centerLine(\n shape: Path,\n straightnessWeighting = 0.7,\n smoothing = 50,\n): Path {\n const g = buildMedialAxisGraph(shape)\n if (!g || g.nodes.length < 2) {\n return polyline([])\n }\n\n const root = g.nodes[g.root]!\n const childRoots = root.children\n const leavesOf = (start: number): MedialNode[] => {\n const out: MedialNode[] = []\n const stack = [start]\n while (stack.length) {\n const u = stack.pop()!\n const n = g.nodes[u]!\n if (n.children.length === 0) out.push(n)\n else stack.push(...n.children)\n }\n return out\n }\n\n let bestPath: number[] = []\n\n if (childRoots.length <= 1) {\n // Degenerate: take diameter of the tree\n bestPath = longestPathNodes(g)\n } else if (childRoots.length === 2) {\n bestPath = pathBetweenLeaves(\n g,\n leavesOf(childRoots[0]!),\n leavesOf(childRoots[1]!),\n root,\n straightnessWeighting,\n )\n } else {\n const groups = childRoots.map(leavesOf)\n let bestW = -Infinity\n for (let i = 0; i < groups.length; i++) {\n for (let j = i + 1; j < groups.length; j++) {\n const { path: p, weight } = bestLeafPair(\n g,\n groups[i]!,\n groups[j]!,\n root,\n straightnessWeighting,\n )\n if (weight > bestW) {\n bestW = weight\n bestPath = p\n }\n }\n }\n }\n\n if (bestPath.length < 2) bestPath = longestPathNodes(g)\n const pts = bestPath.map((id) => g.nodes[id]!.position)\n return polyline(gaussianSmooth(pts, smoothing))\n}\n\nfunction bestLeafPair(\n g: MedialAxisGraph,\n a: MedialNode[],\n b: MedialNode[],\n root: MedialNode,\n straightness: number,\n): { path: number[]; weight: number } {\n let bestW = -Infinity\n let best: number[] = []\n for (const d1 of a) {\n for (const d2 of b) {\n const angle = angleBetween(d1.position, root.position, d2.position)\n const aw = Math.pow(1 + angle, straightness)\n const weight = (d1.rootDist + d2.rootDist) * Math.max(aw - 1, 1)\n if (weight > bestW) {\n bestW = weight\n best = [...pathToRoot(g, d1.id), ...pathToRoot(g, d2.id).reverse().slice(1)]\n }\n }\n }\n return { path: best, weight: bestW }\n}\n\nfunction pathBetweenLeaves(\n g: MedialAxisGraph,\n a: MedialNode[],\n b: MedialNode[],\n root: MedialNode,\n straightness: number,\n): number[] {\n return bestLeafPair(g, a, b, root, straightness).path\n}\n\nfunction pathToRoot(g: MedialAxisGraph, id: number): number[] {\n const path = [id]\n let cur = id\n while (g.nodes[cur]!.parent !== null) {\n cur = g.nodes[cur]!.parent!\n path.push(cur)\n }\n return path\n}\n\nfunction longestPathNodes(g: MedialAxisGraph): number[] {\n // Two BFS from arbitrary leaf\n const leaves = g.nodes.filter((n) => n.children.length === 0 && n.id !== g.root)\n if (leaves.length === 0) return g.nodes.map((n) => n.id)\n let farthest = leaves[0]!\n let best = -1\n for (const L of leaves) {\n if (L.rootDist > best) {\n best = L.rootDist\n farthest = L\n }\n }\n // From farthest, find other leaf maximizing path\n let bestPath = pathToRoot(g, farthest.id)\n let bestLen = farthest.rootDist\n for (const L of leaves) {\n if (L.id === farthest.id) continue\n // path via root\n const p = [\n ...pathToRoot(g, farthest.id),\n ...pathToRoot(g, L.id).reverse().slice(1),\n ]\n const len = farthest.rootDist + L.rootDist\n if (len > bestLen) {\n bestLen = len\n bestPath = p\n }\n }\n return bestPath\n}\n\nfunction angleBetween(a: Vec2, apex: Vec2, b: Vec2): number {\n const ax = a.x - apex.x\n const ay = a.y - apex.y\n const bx = b.x - apex.x\n const by = b.y - apex.y\n const la = Math.hypot(ax, ay) || 1\n const lb = Math.hypot(bx, by) || 1\n const cos = Math.max(-1, Math.min(1, (ax * bx + ay * by) / (la * lb)))\n return Math.acos(cos)\n}\n\nfunction gaussianSmooth(pts: Vec2[], sigma: number): Vec2[] {\n if (pts.length < 3 || sigma <= 0) return pts\n // Map sigma~50 to a modest kernel width in vertex units\n const radius = Math.max(1, Math.round(Math.min(pts.length / 4, sigma / 10)))\n const out: Vec2[] = []\n for (let i = 0; i < pts.length; i++) {\n let sx = 0\n let sy = 0\n let w = 0\n for (let k = -radius; k <= radius; k++) {\n const j = Math.max(0, Math.min(pts.length - 1, i + k))\n const wk = Math.exp(-(k * k) / (2 * (radius * 0.5) ** 2 + 1e-9))\n sx += pts[j]!.x * wk\n sy += pts[j]!.y * wk\n w += wk\n }\n out.push({ x: sx / w, y: sy / w })\n }\n // Keep endpoints pinned\n out[0] = pts[0]!\n out[out.length - 1] = pts[pts.length - 1]!\n return out\n}\n\nfunction key(p: Vec2): string {\n return `${p.x.toFixed(7)},${p.y.toFixed(7)}`\n}\n\nfunction edgeKey(a: Vec2, b: Vec2): string {\n const ka = key(a)\n const kb = key(b)\n return ka < kb ? `${ka}|${kb}` : `${kb}|${ka}`\n}\n\nfunction clamp01(v: number): number {\n return Math.max(0, Math.min(1, v))\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { group, polygon, segment } from '../types/index.js'\nimport { densify } from '../processing/index.js'\nimport { bounds, containsPoint, centroid } from '../predicates/index.js'\nimport { buffer } from '../morphology/buffer.js'\nimport { dissolveSegments } from './dissolve.js'\n\nexport type StraightSkeletonParts = {\n faces: Group\n branches: Group\n bones: Group\n}\n\n/**\n * Straight skeleton approximation via successive inward miter offsets.\n *\n * Returns a flat GROUP: closed face paths, then branch polylines, then bone\n * polylines. Prefer {@link straightSkeletonParts} for structured access.\n *\n * Exact kinetic straight skeletons are deferred; this offset-trace method is\n * robust, terminates, and yields plotter-useful bones/branches/faces.\n */\nexport function straightSkeleton(shape: Path): Group {\n const parts = straightSkeletonParts(shape)\n return group([\n ...parts.faces.paths,\n ...parts.branches.paths,\n ...parts.bones.paths,\n ])\n}\n\nexport function straightSkeletonParts(shape: Path): StraightSkeletonParts {\n const empty: StraightSkeletonParts = {\n faces: group([]),\n branches: group([]),\n bones: group([]),\n }\n if (!shape.closed || !shape.rings[0] || shape.rings[0].length < 3) {\n return empty\n }\n\n const b = bounds(shape)\n const span = Math.max(b.maxX - b.minX, b.maxY - b.minY, 1)\n const delta = Math.max(span / 40, 0.5)\n const densified = densify(shape, Math.max(span / 40, 1e-3))\n\n const levels: Path[] = [densified]\n let current = densified\n for (let i = 0; i < 40; i++) {\n const next = buffer(current, -delta)\n if (next.paths.length === 0) break\n // Pick largest remaining component\n let best = next.paths[0]!\n let bestA = -1\n for (const p of next.paths) {\n const bb = bounds(p)\n const a = (bb.maxX - bb.minX) * (bb.maxY - bb.minY)\n if (a > bestA) {\n bestA = a\n best = p\n }\n }\n if (!best.rings[0] || best.rings[0].length < 3) break\n levels.push(best)\n current = best\n }\n\n const boneSegs = []\n for (let i = 0; i < levels.length - 1; i++) {\n const a = levels[i]!\n const bb = levels[i + 1]!\n const ca = centroid(a)\n const cb = centroid(bb)\n if (containsPoint(shape, mid(ca, cb))) {\n boneSegs.push(segment(ca, cb))\n }\n // Vertex traces: each vertex of level i → nearest on level i+1\n for (const ring of a.rings) {\n for (const p of ring) {\n const q = nearestOnPath(bb, p)\n if (q && containsPoint(shape, mid(p, q))) {\n boneSegs.push(segment(p, q))\n }\n }\n }\n }\n\n // Branches: exterior edge midpoints → nearest point on first inset (or bone)\n const branchSegs = []\n const outer = densified.rings[0]!\n const target = levels[1] ?? levels[0]!\n for (let i = 0; i < outer.length; i++) {\n const a = outer[i]!\n const bb = outer[(i + 1) % outer.length]!\n const m = mid(a, bb)\n const q = nearestOnPath(target, m)\n if (q) branchSegs.push(segment(m, q))\n }\n\n // Faces: each original edge + path to corresponding inset edge midpoints\n const faces: Path[] = []\n if (levels.length >= 2) {\n const inner = levels[1]!.rings[0] ?? []\n for (let i = 0; i < outer.length; i++) {\n const a = outer[i]!\n const bb = outer[(i + 1) % outer.length]!\n const ia = nearestOnRing(inner, a)\n const ib = nearestOnRing(inner, bb)\n if (ia && ib) {\n const face = [a, bb, ib, ia]\n const c = {\n x: (a.x + bb.x + ib.x + ia.x) / 4,\n y: (a.y + bb.y + ib.y + ia.y) / 4,\n }\n if (containsPoint(shape, c)) faces.push(polygon(face))\n }\n }\n }\n\n return {\n faces: group(faces),\n branches: dissolveSegments(branchSegs),\n bones: dissolveSegments(boneSegs),\n }\n}\n\nfunction mid(a: Vec2, b: Vec2): Vec2 {\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 }\n}\n\nfunction nearestOnPath(p: Path, q: Vec2): Vec2 | null {\n let best: Vec2 | null = null\n let bestD = Infinity\n for (const ring of p.rings) {\n for (const v of ring) {\n const d = Math.hypot(v.x - q.x, v.y - q.y)\n if (d < bestD) {\n bestD = d\n best = v\n }\n }\n }\n return best\n}\n\nfunction nearestOnRing(ring: Vec2[], q: Vec2): Vec2 | null {\n if (ring.length === 0) return null\n let best = ring[0]!\n let bestD = Infinity\n for (const v of ring) {\n const d = Math.hypot(v.x - q.x, v.y - q.y)\n if (d < bestD) {\n bestD = d\n best = v\n }\n }\n return best\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { group, segment } from '../types/index.js'\nimport { dissolveSegments } from './dissolve.js'\n\nexport type ScalarField = (x: number, y: number) => number\n\n/**\n * Extract isolines of `fn` over an axis-aligned box via marching squares.\n * Contours are generated at multiples of `contourInterval` between\n * `isolineMin`/`isolineMax` (auto-scanned when omitted).\n */\nexport function isolinesFromFunction(\n bounds: [number, number, number, number],\n sampleSpacing: number,\n contourInterval: number,\n fn: ScalarField,\n isolineMin = Number.NaN,\n isolineMax = Number.NaN,\n): Group {\n const [xmin, ymin, xmax, ymax] = bounds\n const dx = Math.max(sampleSpacing, 1e-9)\n const dy = dx\n const nx = Math.max(2, Math.ceil((xmax - xmin) / dx) + 1)\n const ny = Math.max(2, Math.ceil((ymax - ymin) / dy) + 1)\n\n const grid: number[][] = []\n let gmin = Infinity\n let gmax = -Infinity\n for (let j = 0; j < ny; j++) {\n const row: number[] = []\n const y = ymin + j * ((ymax - ymin) / (ny - 1))\n for (let i = 0; i < nx; i++) {\n const x = xmin + i * ((xmax - xmin) / (nx - 1))\n let v = fn(x, y)\n if (!Number.isFinite(v)) v = Number.NEGATIVE_INFINITY\n row.push(v)\n if (Number.isFinite(v)) {\n gmin = Math.min(gmin, v)\n gmax = Math.max(gmax, v)\n }\n }\n grid.push(row)\n }\n\n const z0 = Number.isFinite(isolineMin) ? isolineMin : gmin\n const z1 = Number.isFinite(isolineMax) ? isolineMax : gmax\n if (!Number.isFinite(z0) || !Number.isFinite(z1) || contourInterval <= 0) {\n return group([])\n }\n\n const levels: number[] = []\n const start = Math.ceil(z0 / contourInterval) * contourInterval\n for (let z = start; z <= z1 + 1e-12; z += contourInterval) {\n levels.push(z)\n }\n\n const segs = []\n for (const level of levels) {\n segs.push(...marchLevel(grid, xmin, ymin, xmax, ymax, nx, ny, level))\n }\n return dissolveSegments(segs)\n}\n\n/** Isolines where `fn(x,y) === 0`. */\nexport function isolineZeroFromFunction(\n bounds: [number, number, number, number],\n sampleSpacing: number,\n fn: ScalarField,\n): Group {\n return isolinesFromFunction(bounds, sampleSpacing, 1, fn, 0, 0)\n}\n\nfunction marchLevel(\n grid: number[][],\n xmin: number,\n ymin: number,\n xmax: number,\n ymax: number,\n nx: number,\n ny: number,\n level: number,\n) {\n const segs: ReturnType<typeof segment>[] = []\n const xAt = (i: number) => xmin + (i / (nx - 1)) * (xmax - xmin)\n const yAt = (j: number) => ymin + (j / (ny - 1)) * (ymax - ymin)\n\n const lerp = (\n x0: number,\n y0: number,\n v0: number,\n x1: number,\n y1: number,\n v1: number,\n ): Vec2 => {\n const t = (level - v0) / (v1 - v0 || 1e-15)\n return { x: x0 + t * (x1 - x0), y: y0 + t * (y1 - y0) }\n }\n\n for (let j = 0; j < ny - 1; j++) {\n for (let i = 0; i < nx - 1; i++) {\n const v00 = grid[j]![i]!\n const v10 = grid[j]![i + 1]!\n const v11 = grid[j + 1]![i + 1]!\n const v01 = grid[j + 1]![i]!\n const x0 = xAt(i)\n const x1 = xAt(i + 1)\n const y0 = yAt(j)\n const y1 = yAt(j + 1)\n\n let code = 0\n if (v00 >= level) code |= 1\n if (v10 >= level) code |= 2\n if (v11 >= level) code |= 4\n if (v01 >= level) code |= 8\n if (code === 0 || code === 15) continue\n\n const bottom = () => lerp(x0, y0, v00, x1, y0, v10)\n const right = () => lerp(x1, y0, v10, x1, y1, v11)\n const top = () => lerp(x0, y1, v01, x1, y1, v11)\n const left = () => lerp(x0, y0, v00, x0, y1, v01)\n\n const add = (a: Vec2, b: Vec2) => segs.push(segment(a, b))\n\n switch (code) {\n case 1:\n case 14:\n add(left(), bottom())\n break\n case 2:\n case 13:\n add(bottom(), right())\n break\n case 3:\n case 12:\n add(left(), right())\n break\n case 4:\n case 11:\n add(right(), top())\n break\n case 6:\n case 9:\n add(bottom(), top())\n break\n case 7:\n case 8:\n add(left(), top())\n break\n case 5: {\n // saddle — average ambiguity\n const avg = (v00 + v10 + v11 + v01) / 4\n if (avg >= level) {\n add(left(), top())\n add(bottom(), right())\n } else {\n add(left(), bottom())\n add(right(), top())\n }\n break\n }\n case 10: {\n const avg = (v00 + v10 + v11 + v01) / 4\n if (avg >= level) {\n add(left(), bottom())\n add(right(), top())\n } else {\n add(left(), top())\n add(bottom(), right())\n }\n break\n }\n default:\n break\n }\n }\n }\n return segs\n}\n\n/** Point-set isolines: each point carries z in `.z` via a parallel array. */\nexport function isolinesFromPoints(\n points: Vec2[],\n values: number[],\n intervals: number,\n _smoothing = 0,\n): Group {\n if (points.length < 3 || intervals < 1) return group([])\n let minZ = Infinity\n let maxZ = -Infinity\n for (const v of values) {\n minZ = Math.min(minZ, v)\n maxZ = Math.max(maxZ, v)\n }\n if (!Number.isFinite(minZ) || maxZ - minZ < 1e-15) return group([])\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const p of points) {\n minX = Math.min(minX, p.x)\n minY = Math.min(minY, p.y)\n maxX = Math.max(maxX, p.x)\n maxY = Math.max(maxY, p.y)\n }\n const span = Math.max(maxX - minX, maxY - minY, 1)\n const sampleSpacing = span / Math.max(20, Math.sqrt(points.length))\n const interval = (maxZ - minZ) / intervals\n\n // Inverse-distance weighted interpolation from samples\n const fn: ScalarField = (x, y) => {\n let num = 0\n let den = 0\n for (let i = 0; i < points.length; i++) {\n const p = points[i]!\n const d2 = (x - p.x) ** 2 + (y - p.y) ** 2\n const w = 1 / Math.max(d2, 1e-12)\n num += w * values[i]!\n den += w\n }\n return num / den\n }\n\n return isolinesFromFunction(\n [minX, minY, maxX, maxY],\n sampleSpacing,\n interval,\n fn,\n minZ,\n maxZ,\n )\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { group } from '../types/index.js'\nimport { bounds, containsPoint } from '../predicates/index.js'\nimport { maximumInscribedCircle } from '../optimisation/index.js'\nimport { poisson } from '../pointSet/index.js'\nimport { distanceToBoundary } from './boundaryDistance.js'\nimport {\n isolinesFromFunction,\n isolinesFromPoints,\n} from './marchingSquares.js'\n\n/**\n * Interior isolines of field `d_boundary − d_pole`.\n * Default pole is the maximum inscribed circle center.\n */\nexport function distanceField(\n shape: Path,\n spacing: number,\n pole?: Vec2,\n): Group {\n if (!shape.closed || shape.rings.length === 0 || spacing <= 0) return group([])\n\n const b = bounds(shape)\n const span = Math.max(b.maxX - b.minX, b.maxY - b.minY, 1)\n let polePt = pole\n if (!polePt) {\n const mic = maximumInscribedCircle(shape, Math.max(span * 0.01, 0.1))\n polePt = mic\n ? { x: mic.x, y: mic.y }\n : { x: (b.minX + b.maxX) / 2, y: (b.minY + b.maxY) / 2 }\n }\n\n const pad = Math.max(spacing, 1)\n const box: [number, number, number, number] = [\n b.minX - pad,\n b.minY - pad,\n b.maxX + pad,\n b.maxY + pad,\n ]\n const sampleSpacing = Math.max(spacing / 10, span / 80)\n\n const fn = (x: number, y: number) => {\n const p = { x, y }\n if (!insideSafe(shape, p)) return Number.NEGATIVE_INFINITY\n const dGeo = distanceToBoundary(shape, p)\n const dPoint = Math.hypot(x - polePt!.x, y - polePt!.y)\n return dGeo - dPoint\n }\n\n const raw = isolinesFromFunction(box, sampleSpacing, spacing, fn)\n // Clip to shape by intersecting open paths as thin regions is hard;\n // filter vertices / keep only segments whose midpoint is inside.\n return clipPolylinesToPath(raw, shape)\n}\n\n/**\n * Contrast field isolines: `|d_boundary − d_reference|`.\n */\nexport function contrastField(\n shape: Path,\n intervals: number,\n reference: Vec2,\n): Group {\n if (!shape.closed || shape.rings.length === 0 || intervals < 1) {\n return group([])\n }\n\n const b = bounds(shape)\n const areaApprox =\n (b.maxX - b.minX) * (b.maxY - b.minY)\n const count = Math.max(100, Math.floor(areaApprox / 100))\n const minDist = Math.sqrt(areaApprox / (count * 1.5))\n const samples = poisson(\n Math.max(minDist, 1e-3),\n b.minX,\n b.minY,\n b.maxX,\n b.maxY,\n 1337,\n ).filter((p) => containsPoint(shape, p))\n\n if (samples.length < 3) return group([])\n\n const values = samples.map((p) => {\n const dB = distanceToBoundary(shape, p)\n const dR = Math.hypot(p.x - reference.x, p.y - reference.y)\n return Math.abs(dB - dR)\n })\n\n const lines = isolinesFromPoints(samples, values, Math.max(1, intervals), 0)\n return clipPolylinesToPath(lines, shape)\n}\n\n/**\n * Isolines from a high point inside a shape (topographic style).\n * Height ≈ distance from highPoint (negated outside).\n */\nexport function isolines(\n shape: Path,\n highPoint: Vec2,\n intervalSpacing: number,\n): Group {\n if (!shape.closed || intervalSpacing <= 0) return group([])\n const b = bounds(shape)\n const span = Math.max(b.maxX - b.minX, b.maxY - b.minY, 1)\n const pad = intervalSpacing\n const box: [number, number, number, number] = [\n b.minX - pad,\n b.minY - pad,\n b.maxX + pad,\n b.maxY + pad,\n ]\n const fn = (x: number, y: number) => {\n if (!containsPoint(shape, { x, y })) return -1\n return Math.hypot(x - highPoint.x, y - highPoint.y)\n }\n const raw = isolinesFromFunction(\n box,\n Math.max(intervalSpacing / 8, span / 100),\n intervalSpacing,\n fn,\n 0,\n span,\n )\n return clipPolylinesToPath(raw, shape)\n}\n\nfunction clipPolylinesToPath(g: Group, shape: Path): Group {\n const paths: Path[] = []\n for (const p of g.paths) {\n const ring = p.rings[0]\n if (!ring || ring.length < 2) continue\n let current: Vec2[] = []\n const flush = () => {\n if (current.length >= 2) {\n paths.push({ rings: [current], closed: false })\n }\n current = []\n }\n for (let i = 0; i < ring.length - 1; i++) {\n const a = ring[i]!\n const b = ring[i + 1]!\n if (!finitePt(a) || !finitePt(b)) {\n flush()\n continue\n }\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 }\n if (insideSafe(shape, mid)) {\n if (current.length === 0) current.push(a)\n current.push(b)\n } else {\n flush()\n }\n }\n flush()\n }\n return group(paths)\n}\n\nfunction finitePt(p: Vec2): boolean {\n return Number.isFinite(p.x) && Number.isFinite(p.y)\n}\n\n/** Ray-cast PIP avoiding Clipper scale overflow on extreme coords. */\nfunction insideSafe(shape: Path, point: Vec2): boolean {\n if (!finitePt(point)) return false\n try {\n return containsPoint(shape, point)\n } catch {\n return pointInPoly(point, shape.rings[0]!) &&\n shape.rings.slice(1).every((h) => !pointInPoly(point, h))\n }\n}\n\nfunction pointInPoly(point: Vec2, ring: Vec2[]): boolean {\n let inside = false\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const pi = ring[i]!\n const pj = ring[j]!\n if (\n pi.y > point.y !== pj.y > point.y &&\n point.x <\n ((pj.x - pi.x) * (point.y - pi.y)) / (pj.y - pi.y + 1e-15) + pi.x\n ) {\n inside = !inside\n }\n }\n return inside\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { group, polyline, segment } from '../types/index.js'\nimport { dissolveSegments } from './dissolve.js'\n\nfunction key(v: Vec2): string {\n return `${v.x.toFixed(8)},${v.y.toFixed(8)}`\n}\n\n/**\n * BFS shortest-path tree on a mesh (GROUP of polygonal faces).\n * `flatten`: unique tree edges as polylines; else one path per target vertex.\n */\nexport function distanceTree(\n mesh: Group,\n source: Vec2,\n flatten: boolean,\n): Group {\n const adj = new Map<string, { to: string; pt: Vec2 }[]>()\n const pts = new Map<string, Vec2>()\n\n const addEdge = (a: Vec2, b: Vec2) => {\n const ka = key(a)\n const kb = key(b)\n if (ka === kb) return\n pts.set(ka, a)\n pts.set(kb, b)\n if (!adj.has(ka)) adj.set(ka, [])\n if (!adj.has(kb)) adj.set(kb, [])\n adj.get(ka)!.push({ to: kb, pt: b })\n adj.get(kb)!.push({ to: ka, pt: a })\n }\n\n for (const face of mesh.paths) {\n for (const ring of face.rings) {\n if (ring.length < 2) continue\n const n = ring.length\n const closed = face.closed\n const limit = closed ? n : n - 1\n for (let i = 0; i < limit; i++) {\n addEdge(ring[i]!, ring[(i + 1) % n]!)\n }\n }\n }\n\n if (pts.size === 0) return group([])\n\n // Snap source to nearest mesh vertex\n let sourceKey = ''\n let best = Infinity\n for (const [k, p] of pts) {\n const d = Math.hypot(p.x - source.x, p.y - source.y)\n if (d < best) {\n best = d\n sourceKey = k\n }\n }\n\n // BFS\n const parent = new Map<string, string | null>()\n parent.set(sourceKey, null)\n const q = [sourceKey]\n while (q.length) {\n const u = q.shift()!\n for (const { to } of adj.get(u) ?? []) {\n if (parent.has(to)) continue\n parent.set(to, u)\n q.push(to)\n }\n }\n\n if (flatten) {\n const segs = []\n const seen = new Set<string>()\n for (const [v, p] of parent) {\n if (p === null) continue\n const ek = v < p ? `${v}|${p}` : `${p}|${v}`\n if (seen.has(ek)) continue\n seen.add(ek)\n segs.push(segment(pts.get(p)!, pts.get(v)!))\n }\n return dissolveSegments(segs)\n }\n\n const paths: Path[] = []\n for (const [v] of parent) {\n if (v === sourceKey) continue\n const chain: Vec2[] = []\n let cur: string | null = v\n while (cur !== null) {\n chain.push(pts.get(cur)!)\n cur = parent.get(cur) ?? null\n }\n chain.reverse()\n if (chain.length >= 2) paths.push(polyline(chain))\n }\n return group(paths)\n}\n","import type { Group, Path, Vec2 } from '../types/index.js'\nimport { buffer } from '../morphology/buffer.js'\nimport { chordalAxis } from './chordalAxis.js'\nimport { medialAxis, centerLine } from './medialAxis.js'\nimport { straightSkeleton, straightSkeletonParts } from './straightSkeleton.js'\nimport type { StraightSkeletonParts } from './straightSkeleton.js'\nimport {\n distanceField,\n contrastField,\n isolines,\n} from './fields.js'\nimport { distanceTree } from './distanceTree.js'\nimport {\n isolinesFromFunction,\n isolineZeroFromFunction,\n isolinesFromPoints,\n} from './marchingSquares.js'\nimport type { ScalarField } from './marchingSquares.js'\nimport { dissolveSegments } from './dissolve.js'\n\n/**\n * Offset the path outward by `distance` (positive buffer).\n * Returns possibly multiple closed contours.\n */\nexport function offsetCurvesOutward(p: Path, distance: number): Group {\n return buffer(p, Math.abs(distance))\n}\n\n/**\n * Offset the path inward by `distance` (negative buffer / erosion).\n * May return empty group if distance exceeds inradius.\n */\nexport function offsetCurvesInward(p: Path, distance: number): Group {\n return buffer(p, -Math.abs(distance))\n}\n\nexport const contour = {\n offsetCurvesOutward,\n offsetCurvesInward,\n medialAxis,\n chordalAxis,\n straightSkeleton,\n straightSkeletonParts,\n centerLine,\n distanceField,\n contrastField,\n distanceTree,\n isolines,\n isolinesFromFunction,\n isolineZeroFromFunction,\n isolinesFromPoints,\n dissolveSegments,\n}\n\nexport {\n medialAxis,\n centerLine,\n chordalAxis,\n straightSkeleton,\n straightSkeletonParts,\n distanceField,\n contrastField,\n distanceTree,\n isolines,\n isolinesFromFunction,\n isolineZeroFromFunction,\n isolinesFromPoints,\n dissolveSegments,\n}\n\nexport type { StraightSkeletonParts, ScalarField, Vec2 }\n"]}
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ export { BufferOptions, buffer, chaikinCut, dilationErosion, erosionDilation, mi
16
16
  export { flipHorizontal, flipVertical, originScale, resizeByHeight, resizeByWidth, rotate, rotateAroundCenter, scale, shear, transformation, translate, translateCentroidTo, translateCornerTo, translateToOrigin } from './transformation/index.js';
17
17
  export { centroidSplit, densify, dissolve, extractBoundary, extractHoles, extractPerimeter, generateRandomGridPoints, generateRandomPoints, intersectionPoints, pointsOnExterior, processing, removeSmallHoles, segmentsOnExterior, slice } from './processing/index.js';
18
18
  export { conversion, copy, flatten, fromArray, fromContours, roundVertexCoords, toArray, toContours } from './conversion/index.js';
19
- export { contour, offsetCurvesInward, offsetCurvesOutward } from './contour/index.js';
19
+ export { ScalarField, StraightSkeletonParts, centerLine, chordalAxis, contour, contrastField, dissolveSegments, distanceField, distanceTree, isolineZeroFromFunction, isolines, isolinesFromFunction, isolinesFromPoints, medialAxis, offsetCurvesInward, offsetCurvesOutward, straightSkeleton, straightSkeletonParts } from './contour/index.js';
20
20
  export { boundingBox, convexHull, convexHullPath, hull } from './hull/index.js';
21
21
  export { RefineOptions, delaunayTriangulation, delaunayTriangulationPoints, earCutTriangulation, poissonTriangulation, poissonTriangulationPoints, refine, triangulation } from './triangulation/index.js';
22
22
  export { hexGrid, ring as pointRing, pointSet, poisson, prunePointsWithinDistance, random as randomPoints, squareGrid } from './pointSet/index.js';