pantograph2d 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{QuadraticBezier-DCa0WGs0.js → QuadraticBezier-B2g_Iyyl.js} +5 -5
- package/dist/{QuadraticBezier-DCa0WGs0.js.map → QuadraticBezier-B2g_Iyyl.js.map} +1 -1
- package/dist/{draw-CJWiicbK.js → draw-BJW5kfm9.js} +3 -3
- package/dist/{draw-CJWiicbK.js.map → draw-BJW5kfm9.js.map} +1 -1
- package/dist/{models-CFd5lRKc.js → models-DdZq-waE.js} +2 -2
- package/dist/{models-CFd5lRKc.js.map → models-DdZq-waE.js.map} +1 -1
- package/dist/pantograph/drawShape.js +2 -2
- package/dist/pantograph/models.js +2 -2
- package/dist/pantograph/svg.js +1 -1
- package/dist/pantograph.cjs +2 -2
- package/dist/pantograph.cjs.map +1 -1
- package/dist/pantograph.js +674 -568
- package/dist/pantograph.js.map +1 -1
- package/dist/{svg-CD4q2GBE.js → svg-D8vwkQf7.js} +2 -2
- package/dist/{svg-CD4q2GBE.js.map → svg-D8vwkQf7.js.map} +1 -1
- package/dist/types/src/algorithms/tesselate/tesselateSegment.d.ts +7 -0
- package/dist/types/src/main.d.ts +1 -1
- package/dist/types/src/operations.d.ts +1 -0
- package/dist/types/src/tesselationOperations.d.ts +15 -0
- package/package.json +2 -2
package/dist/pantograph.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pantograph.js","sources":["../src/utils/listOfFigures.ts","../src/algorithms/boolean/strandBoolean.ts","../src/booleanOperations.ts","../src/algorithms/distances/lineLineDistance.ts","../src/algorithms/distances/lineArcDistance.ts","../src/algorithms/distances/arcArcDistance.ts","../src/algorithms/optimisation/DiRect.ts","../src/algorithms/distances/genericDistance.ts","../src/algorithms/distances/index.ts","../src/algorithms/conversions/bezierToSafeBezier.ts","../src/algorithms/conversions/ellipseToBezier.ts","../src/algorithms/offsets/offsetStroke.ts","../src/algorithms/offsets/offsetFigure.ts","../src/offsetOperations.ts","../src/featureOperations.ts","../src/export/svg/exportSVG.ts","../src/import/json/importJSON.ts","../src/main.ts"],"sourcesContent":["import { Diagram } from \"../models/Diagram.js\";\nimport { Figure } from \"../models/Figure.js\";\nimport { Loop } from \"../models/Loop.js\";\n\nexport function listOfFigures(shape: Diagram | Figure | Loop): Figure[] {\n if (shape instanceof Figure) {\n return [shape];\n } else if (shape instanceof Loop) {\n return [new Figure(shape)];\n } else if (shape instanceof Diagram) {\n return shape.figures;\n }\n throw new Error(\"Unknown shape\");\n}\n","import { Vector } from \"../../definitions\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport { Loop } from \"../../models/Loop\";\nimport { Strand } from \"../../models/Strand\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport removeDuplicatePoints from \"../../utils/removeDuplicatePoints\";\nimport zip from \"../../utils/zip\";\nimport { strandsBetweenIntersections } from \"./strandsBetweenIntersections\";\nimport type { Figure } from \"../../models/Figure\";\nimport type { Stroke } from \"../../models/Stroke\";\n\nfunction strandLoopSections(\n loop: Loop,\n strand: Stroke,\n precision = 1e-9,\n): Strand[] {\n let allIntersections: Vector[] = [];\n const allCommonSegments: Segment[] = [];\n\n const splitPoints: Vector[][] = new Array(strand.segments.length)\n .fill(0)\n .map(() => []);\n\n strand.segments.forEach((strandSegment, strandIndex) => {\n loop.segments.forEach((loopSegment) => {\n const { intersections, overlaps } = findIntersectionsAndOverlaps(\n strandSegment,\n loopSegment,\n precision,\n );\n\n allIntersections.push(...intersections);\n splitPoints[strandIndex].push(...intersections);\n\n allCommonSegments.push(...overlaps);\n const commonSegmentsPoints = overlaps.flatMap((s) => [\n s.firstPoint,\n s.lastPoint,\n ]);\n allIntersections.push(...commonSegmentsPoints);\n splitPoints[strandIndex].push(...commonSegmentsPoints);\n });\n });\n\n allIntersections = removeDuplicatePoints(allIntersections, precision);\n\n const strandSegments = zip([strand.segments, splitPoints] as [\n Segment[],\n Vector[][],\n ]).flatMap(([segment, intersections]: [Segment, Vector[]]): Segment[] => {\n if (!intersections.length) return [segment];\n return segment.splitAt(intersections);\n });\n\n return Array.from(\n strandsBetweenIntersections(\n strandSegments,\n allIntersections,\n allCommonSegments,\n ),\n );\n}\n\nexport function eraseStrandWithinLoop(\n strand: Stroke,\n loop: Loop,\n eraseOnBorder = false,\n) {\n const strands = strandLoopSections(loop, strand);\n\n // We keep only the strands that are outside the loop\n return strands.filter((strand) => {\n const strandCenter = strand.segments[0].midPoint;\n if (loop.onStroke(strandCenter)) return !eraseOnBorder;\n\n return !loop.contains(strandCenter);\n });\n}\n\nexport function eraseStrandOutsideLoop(\n strand: Stroke,\n loop: Loop,\n eraseOnBorder = false,\n) {\n const strands = strandLoopSections(loop, strand);\n\n // We keep only the strands that are outside the loop\n return strands.filter((strand) => {\n const strandCenter = strand.segments[0].midPoint;\n if (loop.onStroke(strandCenter)) return !eraseOnBorder;\n\n return loop.contains(strandCenter);\n });\n}\n\nexport function eraseStrandWithinFigure(\n strand: Stroke,\n figure: Figure,\n eraseOnBorder = false,\n) {\n const outsideStrands = eraseStrandWithinLoop(\n strand,\n figure.contour,\n eraseOnBorder,\n );\n\n const inLoopStrand = figure.holes.flatMap((hole: Loop) =>\n eraseStrandOutsideLoop(strand, hole, eraseOnBorder),\n );\n\n return [...outsideStrands, ...inLoopStrand];\n}\n\nexport function eraseStrandOutsideFigure(\n strand: Stroke,\n figure: Figure,\n eraseOnBorder = false,\n) {\n let insideStrands = eraseStrandOutsideLoop(\n strand,\n figure.contour,\n eraseOnBorder,\n );\n\n figure.holes.forEach((hole: Loop) => {\n insideStrands = insideStrands.flatMap((strand) =>\n eraseStrandWithinLoop(strand, hole, eraseOnBorder),\n );\n });\n\n return insideStrands;\n}\n","import {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"./algorithms/boolean/figureBooleans\";\nimport { Strand } from \"./models/Strand\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\nimport {\n eraseStrandOutsideFigure,\n eraseStrandOutsideLoop,\n eraseStrandWithinFigure,\n eraseStrandWithinLoop,\n} from \"./algorithms/boolean/strandBoolean\";\nimport { Stroke } from \"./main\";\n\nexport function fuse(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop,\n): Diagram {\n return new Diagram(\n fuseFiguresLists(listOfFigures(first), listOfFigures(second)),\n );\n}\n\nexport function fuseAll(shapes: (Diagram | Figure | Loop)[]): Diagram {\n return shapes.reduce(\n (acc: Diagram, shape: Diagram | Figure | Loop) => fuse(acc, shape),\n new Diagram(),\n );\n}\n\nexport function cut(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop,\n): Diagram {\n return new Diagram(\n cutFiguresLists(listOfFigures(first), listOfFigures(second)),\n );\n}\n\nexport function intersect(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop,\n): Diagram {\n return new Diagram(\n intersectFiguresLists(listOfFigures(first), listOfFigures(second)),\n );\n}\n\nexport function eraseStrand(\n strand: Stroke,\n diagram: Diagram | Figure | Loop,\n eraseOnBorder = true,\n): Strand[] {\n if (diagram instanceof Loop) {\n return eraseStrandWithinLoop(strand, diagram, eraseOnBorder);\n }\n\n if (diagram instanceof Figure) {\n return eraseStrandWithinFigure(strand, diagram, eraseOnBorder);\n }\n\n let outStrands: Strand[] = [new Strand([...strand.segments])];\n diagram.figures.forEach((figure: Figure) => {\n outStrands = outStrands.flatMap((strand: Strand) => {\n return eraseStrandWithinFigure(strand, figure, eraseOnBorder);\n });\n });\n\n return outStrands;\n}\n\nexport function confineStrand(\n strand: Stroke,\n diagram: Diagram | Figure | Loop,\n eraseOnBorder = false,\n): Strand[] {\n if (diagram instanceof Loop) {\n return eraseStrandOutsideLoop(strand, diagram, eraseOnBorder);\n }\n\n if (diagram instanceof Figure) {\n return eraseStrandOutsideFigure(strand, diagram, eraseOnBorder);\n }\n\n let outStrands: Strand[] = [new Strand([...strand.segments])];\n diagram.figures.forEach((figure: Figure) => {\n outStrands = outStrands.flatMap((strand: Strand) => {\n return eraseStrandOutsideFigure(strand, figure, eraseOnBorder);\n });\n });\n\n return outStrands;\n}\n","import { lineLineParams } from \"../intersections/lineLineIntersection.js\";\nimport type { Line } from \"../../models/segments/Line.js\";\nimport { distance } from \"../../vectorOperations.js\";\n\nfunction segmentPosition(intersectionParam: number) {\n if (intersectionParam < 0) return \"before\";\n if (intersectionParam > 1) return \"after\";\n return \"between\";\n}\n\nconst handleBetween = (\n lineBetween: Line,\n otherLine: Line,\n otherPosition: \"before\" | \"after\",\n) => {\n if (otherPosition === \"before\")\n return lineBetween.distanceFrom(otherLine.firstPoint);\n else if (otherPosition === \"after\")\n return lineBetween.distanceFrom(otherLine.lastPoint);\n else throw new Error(\"Invalid position\");\n};\n\nexport function lineLineDistance(line1: Line, line2: Line): number {\n const intersectionParams = lineLineParams(line1, line2);\n\n if (intersectionParams === \"parallel\") {\n return Math.min(\n line1.distanceFrom(line2.firstPoint),\n line1.distanceFrom(line2.lastPoint),\n );\n }\n\n const { intersectionParam1, intersectionParam2 } = intersectionParams;\n\n const firstPosition = segmentPosition(intersectionParam1);\n const secondPosition = segmentPosition(intersectionParam2);\n\n if (firstPosition === \"between\" && secondPosition === \"between\") {\n return 0;\n } else if (firstPosition === \"between\" && secondPosition !== \"between\") {\n return handleBetween(line1, line2, secondPosition);\n } else if (secondPosition === \"between\" && firstPosition !== \"between\") {\n return handleBetween(line2, line1, firstPosition);\n } else if (firstPosition === \"before\" && secondPosition === \"before\") {\n return distance(line1.firstPoint, line2.firstPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"after\") {\n return distance(line1.lastPoint, line2.lastPoint);\n } else if (firstPosition === \"before\" && secondPosition === \"after\") {\n return distance(line1.firstPoint, line2.lastPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"before\") {\n return distance(line1.lastPoint, line2.firstPoint);\n } else {\n throw new Error(\"Invalid position\");\n }\n}\n","import type { Line } from \"../../models/segments/Line.js\";\nimport type { Arc } from \"../../models/segments/Arc.js\";\nimport {\n normalize,\n subtract,\n distance,\n add,\n scalarMultiply,\n} from \"../../vectorOperations\";\nimport { projectPointOnLine } from \"../../utils/projectPointOnLine.js\";\nimport { lineArcIntersection } from \"../intersections/lineArcIntersection.js\";\n\nexport function lineArcDistance(line: Line, arc: Arc): number {\n // We might be able to optimise this if necessary\n\n if (lineArcIntersection(line, arc).length > 0) {\n return 0;\n }\n\n const closestPointOnLine = projectPointOnLine(line, arc.center);\n\n if (line.isOnSegment(closestPointOnLine)) {\n const circleCenterLineDistance = distance(closestPointOnLine, arc.center);\n\n // The line is tangent to the circle\n if (Math.abs(circleCenterLineDistance - arc.radius) < line.precision) {\n if (arc.isOnSegment(closestPointOnLine)) {\n return 0;\n }\n }\n\n if (circleCenterLineDistance - arc.radius > line.precision) {\n const centerLineDirection = normalize(\n subtract(closestPointOnLine, arc.center),\n );\n\n const closestPointOnCircle = add(\n arc.center,\n scalarMultiply(centerLineDirection, arc.radius),\n );\n\n if (arc.isOnSegment(closestPointOnCircle)) {\n return distance(closestPointOnCircle, closestPointOnLine);\n }\n }\n }\n\n return Math.min(\n arc.distanceFrom(line.firstPoint),\n arc.distanceFrom(line.lastPoint),\n line.distanceFrom(arc.firstPoint),\n line.distanceFrom(arc.lastPoint),\n );\n}\n","import {\n distance,\n normalize,\n polarAngle,\n subtract,\n} from \"../../vectorOperations\";\nimport type { Arc } from \"../../models/segments/Arc.js\";\nimport { arcArcIntersection } from \"../intersections/arcArcIntersection.js\";\n\nconst overlappingAngles = (arc1: Arc, arc2: Arc): boolean => {\n const p1 = arc1.angleToParam(arc2.firstAngle);\n if (arc1.isValidParameter(p1)) return true;\n\n const p2 = arc1.angleToParam(arc2.lastAngle);\n if (arc1.isValidParameter(p2)) return true;\n return false;\n};\n\nexport function arcArcDistance(arc1: Arc, arc2: Arc): number {\n if (arcArcIntersection(arc1, arc2, true).length > 0) return 0;\n\n const centersDistance = distance(arc1.center, arc2.center);\n\n if (centersDistance < arc1.precision) {\n if (overlappingAngles(arc1, arc2)) {\n return Math.abs(arc1.radius - arc2.radius);\n }\n }\n\n const centerCenterDirection = normalize(subtract(arc2.center, arc1.center));\n\n const containedCircles =\n centersDistance - Math.abs(arc1.radius - arc2.radius) < arc1.precision;\n\n let arc1ClosestPointAngle = polarAngle(centerCenterDirection);\n if (containedCircles && arc2.radius > arc1.radius) {\n arc1ClosestPointAngle += Math.PI;\n }\n const arc2ClosestPointAngle = containedCircles\n ? arc1ClosestPointAngle\n : arc1ClosestPointAngle + Math.PI;\n\n const p1 = arc1.angleToParam(arc1ClosestPointAngle);\n const p2 = arc2.angleToParam(arc2ClosestPointAngle);\n\n if (arc1.isValidParameter(p1) && arc2.isValidParameter(p2)) {\n // There might be some optimization here (with the center distance and radius differences)\n return distance(arc1.paramPoint(p1), arc2.paramPoint(p2));\n }\n\n return Math.min(\n arc1.distanceFrom(arc2.firstPoint),\n arc1.distanceFrom(arc2.lastPoint),\n arc2.distanceFrom(arc1.firstPoint),\n arc2.distanceFrom(arc1.lastPoint),\n );\n}\n","// An implementation of the direct algorithm for computing the global minimum of\n// a funciton defined between 0 and 1. The algorithm is described in:\n// Jones, D.R., Perttunen, C.D. and Stuckman, B.E., 1993. Lipschitzian\n// optimization without the Lipschitz constant. Journal of Optimization Theory\n// and Applications, 79(1), pp.157-181.\n//\n// Also inspired by the implementation in the Direct package for rust\n// https://gitlab.com/blei42/direct\n\nfunction binarySearch<T>(\n array: T[],\n value: T,\n comparator: (a: T, b: T) => number,\n): number {\n let low = 0;\n let high = array.length - 1;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const cmp = comparator(array[mid], value);\n if (cmp < 0) {\n low = mid + 1;\n } else if (cmp > 0) {\n high = mid - 1;\n } else {\n return mid;\n }\n }\n return -(low + 1);\n}\n\nfunction binaryInsert<T>(\n array: T[],\n value: T,\n comparator: (a: T, b: T) => number,\n) {\n const index = binarySearch(array, value, comparator);\n if (index < 0) {\n array.splice(-(index + 1), 0, value);\n } else {\n array.splice(index, 0, value);\n }\n}\n\nclass DiagonalBuckets {\n public readonly buckets: Interval[][];\n constructor() {\n this.buckets = [];\n }\n\n addInterval(interval: Interval) {\n const bucket = this.buckets[interval.rectangle.diagonalBucketIndex];\n if (bucket === undefined) {\n this.buckets[interval.rectangle.diagonalBucketIndex] = [interval];\n } else {\n binaryInsert(bucket, interval, (a, b) => a.value - b.value);\n }\n }\n\n removeInterval(interval: Interval) {\n const bucket = this.buckets[interval.rectangle.diagonalBucketIndex];\n if (bucket === undefined) {\n throw new Error(\"Interval not found\");\n }\n bucket.shift();\n }\n\n getBottomRightHullIntervals(): Interval[] {\n const intervals: Interval[] = [];\n for (let i = this.buckets.length - 1; i >= 0; i--) {\n const bucket = this.buckets[i];\n\n if (!bucket === undefined) continue;\n const interval = bucket[0];\n if (interval === undefined) continue;\n\n if (!intervals.length) {\n intervals.push(interval);\n continue;\n }\n\n // We want to keep only the right bottom hull of the intervals\n\n // First, we remove intervals with a bigger value\n while (\n intervals.length &&\n intervals[intervals.length - 1].value >= interval.value\n ) {\n intervals.pop();\n }\n\n // Then, we remove intervals that are covered by the previous interval\n // and the last updated\n while (intervals.length >= 2) {\n const lastInterval = intervals[intervals.length - 1];\n const secondToLastInterval = intervals[intervals.length - 2];\n\n const slope =\n (interval.value - secondToLastInterval.value) /\n ((interval.rectangle.diagonal -\n secondToLastInterval.rectangle.diagonal) *\n 2);\n const comparison =\n secondToLastInterval.value +\n ((lastInterval.rectangle.diagonal -\n secondToLastInterval.rectangle.diagonal) /\n 2.0) *\n slope;\n\n if (comparison < lastInterval.value) {\n intervals.pop();\n } else {\n break;\n }\n }\n\n intervals.push(interval);\n }\n\n return intervals;\n }\n}\n\nclass DivisionRectangle {\n public diagonal: number;\n public diagonalBucketIndex: number;\n\n public xLength: number;\n public yLength: number;\n\n public index: string;\n\n constructor(\n public x: number,\n public y: number,\n ) {\n this.xLength = Math.pow(3, -x);\n this.yLength = Math.pow(3, -y);\n\n this.diagonal = Math.sqrt(\n this.xLength * this.xLength + this.yLength * this.yLength,\n );\n this.diagonalBucketIndex = x + y;\n\n this.index = `${x},${y}`;\n }\n}\n\nexport class DiRectOptimisation {\n private rectangles: Map<string, DivisionRectangle>;\n private buckets: DiagonalBuckets;\n\n public fMin;\n public argMin;\n public tol;\n\n constructor(\n public fcn: ([x, y]: [number, number]) => number,\n public endTolerance = 1e-8,\n public maxIterations = 1000,\n public epsilon = 1e-6,\n ) {\n this.fcn = fcn;\n this.epsilon = epsilon;\n this.endTolerance = endTolerance;\n this.maxIterations = maxIterations;\n\n this.rectangles = new Map();\n this.buckets = new DiagonalBuckets();\n\n const center: [number, number] = [0.5, 0.5];\n const rect = this.rect(0, 0);\n const value = this.fcn(center);\n\n this.buckets.addInterval(new Interval(center, value, rect));\n this.fMin = value;\n this.argMin = center;\n this.tol = rect.diagonal;\n }\n\n registerInterval(interval: Interval) {\n this.buckets.addInterval(interval);\n if (interval.value <= this.fMin) {\n this.fMin = interval.value;\n this.argMin = interval.center;\n this.tol = interval.rectangle.diagonal;\n }\n }\n\n rect(x: number, y: number): DivisionRectangle {\n const index = `${x},${y}`;\n if (!this.rectangles.has(index)) {\n this.rectangles.set(index, new DivisionRectangle(x, y));\n }\n return this.rectangles.get(index)!;\n }\n\n splitInterval(interval: Interval): [Interval, Interval, Interval] {\n let rect: DivisionRectangle;\n let leftCenter: [number, number], rightCenter: [number, number];\n\n const [x, y] = interval.center;\n\n if (interval.rectangle.x <= interval.rectangle.y) {\n rect = this.rect(interval.rectangle.x + 1, interval.rectangle.y);\n leftCenter = [x - rect.xLength, y];\n rightCenter = [x + rect.xLength, y];\n } else {\n rect = this.rect(interval.rectangle.x, interval.rectangle.y + 1);\n leftCenter = [x, y - rect.yLength];\n rightCenter = [x, y + rect.yLength];\n }\n\n return [\n new Interval(leftCenter, this.fcn(leftCenter), rect),\n new Interval(interval.center, interval.value, rect),\n new Interval(rightCenter, this.fcn(rightCenter), rect),\n ];\n }\n\n single_iteration() {\n const intervals = this.buckets.getBottomRightHullIntervals();\n\n // We want to only keep the intervals that can significantly improve the\n // minimum\n\n while (intervals.length >= 2) {\n // Look at the left-most point, it's most heavily constrained by both slope and\n // possible distance.\n const i1 = intervals[0];\n const i2 = intervals[1];\n\n const k =\n (i2.value - i1.value) /\n ((i2.rectangle.diagonal - i1.rectangle.diagonal) / 2.0);\n const potentialFMin = i1.value - (k * i2.value) / 2.0;\n if ((this.fMin - potentialFMin) / Math.abs(this.fMin) < this.epsilon) {\n intervals.shift();\n } else {\n // The points to the right are even better than this one, bail out.\n break;\n }\n }\n\n intervals.forEach((interval) => {\n this.buckets.removeInterval(interval);\n });\n\n for (const interval of intervals) {\n const [left, middle, right] = this.splitInterval(interval);\n\n this.registerInterval(left);\n this.registerInterval(middle);\n this.registerInterval(right);\n }\n }\n\n run() {\n let i = 0;\n while (this.tol > this.endTolerance / 2) {\n this.single_iteration();\n i++;\n if (i > this.maxIterations) {\n break;\n }\n }\n return {\n fMin: this.fMin,\n argMin: this.argMin,\n tol: this.tol,\n iterations: i,\n };\n }\n}\n\nclass Interval {\n constructor(\n public center: [number, number],\n public value: number,\n public rectangle: DivisionRectangle,\n ) {}\n}\n\nexport function findGlobalMinimum(\n fun: (x: [number, number]) => number,\n tolerance = 1e-8,\n maxIterations = 1000,\n epsilon = 1e-6,\n) {\n const optimiser = new DiRectOptimisation(\n fun,\n tolerance,\n maxIterations,\n epsilon,\n );\n return optimiser.run();\n}\n","import { Vector } from \"../../definitions.js\";\nimport { squareDistance } from \"../../vectorOperations.js\";\nimport { findGlobalMinimum } from \"../optimisation/DiRect.js\";\n\ninterface WithParamPoint {\n paramPoint(t: number): Vector;\n}\n\nexport function genericDistance(\n segment1: WithParamPoint,\n segment2: WithParamPoint,\n precision = 1e-9,\n): number {\n const result = findGlobalMinimum((t) => {\n const p1 = segment1.paramPoint(t[0]);\n const p2 = segment2.paramPoint(t[1]);\n return squareDistance(p1, p2);\n }, precision);\n return Math.sqrt(result.fMin);\n}\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { lineLineDistance } from \"./lineLineDistance.js\";\nimport { lineArcDistance } from \"./lineArcDistance.js\";\nimport { arcArcDistance } from \"./arcArcDistance.js\";\nimport type { Segment } from \"../../models/segments/Segment.js\";\nimport { genericDistance } from \"./genericDistance.js\";\n\nexport function distance(segment1: Segment, segment2: Segment): number {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n return lineLineDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Line && segment2 instanceof Arc) {\n return lineArcDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Line) {\n return lineArcDistance(segment2, segment1);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Arc) {\n return arcArcDistance(segment1, segment2);\n }\n\n return genericDistance(segment1, segment2);\n}\n","import { CubicBezier } from \"../../models/segments/CubicBezier\";\nimport { QuadraticBezier } from \"../../models/segments/QuadraticBezier\";\nimport {\n angle,\n dotProduct,\n perpendicular,\n subtract,\n} from \"../../vectorOperations\";\n\n// This is based on https://github.com/Pomax/bezierjs\n\ntype Bezier = CubicBezier | QuadraticBezier;\n\nexport type SafeCubicBezier = CubicBezier & { readonly __safe: unique symbol };\nexport type SafeQuadraticBezier = QuadraticBezier & {\n readonly __safe: unique symbol;\n};\n\ntype SafeBezier = SafeCubicBezier | SafeQuadraticBezier;\n\nexport type SafeVersion<T> = T extends CubicBezier\n ? SafeCubicBezier\n : T extends QuadraticBezier\n ? SafeQuadraticBezier\n : never;\n\nfunction isOffsetSafeBezier(segment: Bezier): segment is SafeBezier {\n if (segment instanceof CubicBezier) {\n // We check that both control points are on the same side of the chord\n const chord = subtract(segment.lastPoint, segment.firstPoint);\n const v2 = subtract(segment.firstControlPoint, segment.firstPoint);\n const v3 = subtract(segment.lastControlPoint, segment.firstPoint);\n\n const a1 = angle(chord, v2);\n const a2 = angle(chord, v3);\n\n if ((a1 > 0 && a2 < 0) || (a1 < 0 && a2 > 0)) return false;\n }\n\n const n1 = perpendicular(segment.tangentAtFirstPoint);\n const n2 = perpendicular(segment.tangentAtLastPoint);\n\n let s = dotProduct(n1, n2);\n return Math.abs(Math.acos(s)) < Math.PI / 3;\n}\n\nfunction _splitIntoOffsetSafeBezier(\n segment: Bezier,\n): SafeVersion<typeof segment>[] {\n if (isOffsetSafeBezier(segment)) return [segment];\n\n const [left, right] = segment.splitAtParameters([0.5]);\n return [\n ..._splitIntoOffsetSafeBezier(left),\n ..._splitIntoOffsetSafeBezier(right),\n ];\n}\n\nexport function splitIntoOffsetSafeBezier(\n segment: Bezier,\n): SafeVersion<typeof segment>[] {\n if (isOffsetSafeBezier(segment)) return [segment];\n\n const segments = segment.splitAtParameters(segment.getParametersOfExtrema());\n return segments.flatMap(_splitIntoOffsetSafeBezier);\n}\n","import { CubicBezier } from \"../../models/segments/CubicBezier\";\nimport { TransformationMatrix } from \"../../models/TransformationMatrix\";\nimport type { EllipseArc } from \"../../models/segments/EllipseArc\";\n\nexport function approximateEllipticalArcAsCubicBeziers(\n ellipseArc: EllipseArc,\n): CubicBezier[] {\n const sweepAngle = ellipseArc.deltaAngle;\n const segments = Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2));\n const anglePerSegment = sweepAngle / segments;\n const kappa = (4 * Math.tan(anglePerSegment / 4)) / 3;\n\n const orientation = ellipseArc.clockwise ? -1 : 1;\n\n const angles = Array.from(\n { length: segments + 1 },\n (_, i) => ellipseArc.firstAngle + i * anglePerSegment * orientation,\n );\n\n const zippedAngles = angles\n .slice(0, -1)\n .map((angle, index) => [angle, angles[index + 1]]);\n\n return zippedAngles.map(([startAngle, endAngle]) => {\n const cosStart = Math.cos(startAngle);\n const sinStart = Math.sin(startAngle);\n const cosEnd = Math.cos(endAngle);\n const sinEnd = Math.sin(endAngle);\n\n const [centerX, centerY] = ellipseArc.center;\n const r = ellipseArc.minorRadius;\n const R = ellipseArc.majorRadius;\n\n const rotationMatrix = new TransformationMatrix().rotate(\n ellipseArc.tiltAngle,\n ellipseArc.center,\n );\n const rotateInFrame = (p: [number, number]) => rotationMatrix.transform(p);\n\n const p0 = rotateInFrame([centerX + R * cosStart, centerY + r * sinStart]);\n const c0 = rotateInFrame([\n centerX + R * (cosStart - kappa * sinStart * orientation),\n centerY + r * (sinStart + kappa * cosStart * orientation),\n ]);\n const c1 = rotateInFrame([\n centerX + R * (cosEnd + kappa * sinEnd * orientation),\n centerY + r * (sinEnd - kappa * cosEnd * orientation),\n ]);\n const p1 = rotateInFrame([centerX + R * cosEnd, centerY + r * sinEnd]);\n\n return new CubicBezier(p0, p1, c0, c1);\n });\n}\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Loop } from \"../../models/Loop.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport {\n crossProduct,\n sameVector,\n squareDistance,\n subtract,\n} from \"../../vectorOperations\";\nimport { distance } from \"../distances\";\nimport {\n offsetSegment,\n DegenerateSegment,\n OffsettableSegment,\n} from \"./offsetSegment.js\";\nimport { Vector } from \"../../definitions.js\";\nimport { Arc, tangentArc } from \"../../models/segments/Arc.js\";\nimport { Diagram } from \"../../models/Diagram.js\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport { Figure } from \"../../models/Figure.js\";\nimport { stitchSegments } from \"../stitchSegments.js\";\nimport { Stroke } from \"../../models/Stroke.js\";\nimport { Strand } from \"../../models/Strand.js\";\nimport { splitIntoOffsetSafeBezier } from \"../conversions/bezierToSafeBezier.js\";\nimport {\n CubicBezier,\n EllipseArc,\n QuadraticBezier,\n} from \"../../models/exports.js\";\nimport { approximateEllipticalArcAsCubicBeziers } from \"../conversions/ellipseToBezier.js\";\n\n\nconst PRECISION = 1e-8;\n\nexport const transformForOffset = (\n segments: Segment[],\n): OffsettableSegment[] => {\n return segments.flatMap((segment: Segment): OffsettableSegment[] => {\n if (segment instanceof Line) {\n return [segment];\n } else if (segment instanceof Arc) {\n return [segment];\n } else if (segment instanceof EllipseArc) {\n return approximateEllipticalArcAsCubicBeziers(segment).flatMap((c) =>\n splitIntoOffsetSafeBezier(c),\n );\n } else if (\n segment instanceof QuadraticBezier ||\n segment instanceof CubicBezier\n ) {\n return splitIntoOffsetSafeBezier(segment);\n } else {\n return [new Line(segment.firstPoint, segment.lastPoint)];\n }\n });\n};\n\nexport function rawOffsets(\n segmentsToOffset: OffsettableSegment[],\n offset: number,\n loop = true,\n): Segment[] {\n const offsetSegments: OffsetSegmentPair[] = segmentsToOffset.map((c) => ({\n offset: offsetSegment(c, offset),\n original: c,\n }));\n\n // Ideally we would use the length of the segment to make sure it is\n // not only a point, but the algo we have access to are a bit to\n // convoluted to be usable here\n\n const offsettedArray: Segment[] = [];\n\n let savedLastSegment = loop ? null : offsetSegments.at(-1)!;\n\n let previousSegment = loop ? offsetSegments.at(-1) : null;\n\n // We have no offseted segments\n if (offsettedArray.length === 1) return offsettedArray;\n\n const appendSegment = (segment: OffsetSegmentPair) => {\n if (!savedLastSegment) {\n savedLastSegment = segment;\n } else if (!(segment.offset instanceof DegenerateSegment)) {\n offsettedArray.push(segment.offset);\n } else if (\n !sameVector(segment.offset.firstPoint, segment.offset.lastPoint)\n ) {\n offsettedArray.push(\n new Line(segment.offset.firstPoint, segment.offset.lastPoint),\n );\n }\n };\n const iterateOffsetSegments = function* (): Generator<OffsetSegmentPair> {\n for (const segment of offsetSegments.slice(0, -1)) {\n yield segment;\n }\n // This should never happen\n if (!savedLastSegment) throw new Error(\"Bug in the offset algorithm\");\n yield savedLastSegment;\n };\n\n for (const segment of iterateOffsetSegments()) {\n if (!previousSegment) {\n previousSegment = segment;\n continue;\n }\n const previousLastPoint = previousSegment.offset.lastPoint;\n const firstPoint = segment.offset.firstPoint;\n\n // When the offset segments do still touch we do nothing\n if (sameVector(previousLastPoint, firstPoint)) {\n appendSegment(previousSegment);\n previousSegment = segment;\n continue;\n }\n\n let intersections: Vector[] = [];\n\n if (\n !(previousSegment.offset instanceof DegenerateSegment) &&\n !(segment.offset instanceof DegenerateSegment)\n ) {\n // When the offset segments intersect we cut them and save them at\n const { intersections: pointIntersections, overlaps } =\n findIntersectionsAndOverlaps(\n previousSegment.offset,\n segment.offset,\n PRECISION / 100,\n );\n intersections = [\n ...pointIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ];\n }\n\n if (intersections.length > 0) {\n let intersection = intersections[0];\n if (intersections.length > 1) {\n // We choose the intersection point the closest to the end of the\n // original segment endpoint (why? not sure, following\n // https://github.com/jbuckmccready/cavalier_contours/)\n\n const originalEndpoint = previousSegment?.original.lastPoint;\n const distances = intersections.map((i) =>\n squareDistance(i, originalEndpoint),\n );\n intersection = intersections[distances.indexOf(Math.min(...distances))];\n }\n\n // We need to be a lot more careful here with multiple intersections\n // as well as cases where segments overlap\n\n const splitPreviousSegment = (previousSegment.offset as Segment).splitAt([\n intersection,\n ])[0];\n const splitSegment = (segment.offset as Segment)\n .splitAt([intersection])\n .at(-1);\n\n if (!splitSegment) throw new Error(\"Bug in the splitting algo in offset\");\n\n appendSegment({\n offset: splitPreviousSegment,\n original: previousSegment.original,\n });\n previousSegment = { offset: splitSegment, original: segment.original };\n continue;\n }\n\n // When the offset segments do not intersect we link them with an arc of\n // radius offset\n const center = previousSegment.original.lastPoint;\n const clockwise =\n crossProduct(\n subtract(firstPoint, center),\n subtract(previousLastPoint, center),\n ) > 0;\n\n const joiner = new Arc(previousLastPoint, firstPoint, center, clockwise);\n //const joiner = new Line(previousLastPoint, firstPoint);\n\n appendSegment(previousSegment);\n offsettedArray.push(joiner);\n previousSegment = segment;\n }\n\n if (previousSegment) appendSegment(previousSegment);\n return offsettedArray;\n}\n\ninterface OffsetSegmentPair {\n offset: Segment | DegenerateSegment;\n original: Segment;\n}\n\nfunction findOffsetSelfIntersections(\n segments: Segment[],\n): Map<number, Vector[]> {\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections: Map<number, Vector[]> = new Map();\n const updateIntersections = (index: number, newPoints: Vector[]) => {\n const intersections = allIntersections.get(index) || [];\n allIntersections.set(index, [...intersections, ...newPoints]);\n };\n\n segments.forEach((firstSegment, firstIndex) => {\n segments.slice(firstIndex + 1).forEach((secondSegment, secondIndex) => {\n const { intersections: rawIntersections, overlaps } =\n findIntersectionsAndOverlaps(firstSegment, secondSegment, PRECISION);\n\n const intersections = [\n ...rawIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ].filter((intersection) => {\n const onFirstSegmentExtremity =\n sameVector(intersection, firstSegment.firstPoint) ||\n sameVector(intersection, firstSegment.lastPoint);\n\n const onSecondSegmentExtremity =\n sameVector(intersection, secondSegment.firstPoint) ||\n sameVector(intersection, secondSegment.lastPoint);\n\n return !(onFirstSegmentExtremity && onSecondSegmentExtremity);\n });\n\n if (!intersections.length) return;\n\n updateIntersections(firstIndex, intersections);\n updateIntersections(secondIndex + firstIndex + 1, intersections);\n });\n });\n\n return allIntersections;\n}\n\nfunction findIntersections(\n segments: Segment[],\n intersectWith: Segment[],\n): Map<number, Vector[]> {\n const allIntersections: Map<number, Vector[]> = new Map();\n const updateIntersections = (index: number, newPoints: Vector[]) => {\n const intersections = allIntersections.get(index) || [];\n allIntersections.set(index, [...intersections, ...newPoints]);\n };\n\n segments.forEach((firstSegment, firstIndex) => {\n intersectWith.forEach((segmentsToCheck) => {\n const { intersections: rawIntersections, overlaps } =\n findIntersectionsAndOverlaps(firstSegment, segmentsToCheck, PRECISION);\n\n const intersections = [\n ...rawIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ].filter((intersection) => {\n return (\n sameVector(intersection, firstSegment.firstPoint) ||\n sameVector(intersection, firstSegment.lastPoint)\n );\n });\n\n if (!intersections.length) return;\n\n updateIntersections(firstIndex, intersections);\n });\n });\n\n return allIntersections;\n}\n\nfunction findEndIntersections(\n segments: Segment[],\n strand: Strand,\n offset: number,\n) {\n const circle = new Loop([\n new Arc([-offset, 0], [offset, 0], [0, 0], true),\n new Arc([offset, 0], [-offset, 0], [0, 0], true),\n ]);\n\n const startCircle = circle.translateTo(strand.firstPoint);\n const endCircle = circle.translateTo(strand.lastPoint);\n\n return findIntersections(segments, [\n ...startCircle.segments,\n ...endCircle.segments,\n ]);\n}\n\nfunction mergeIntersectionMaps(maps: Map<number, Vector[]>[]) {\n const mergedMap = new Map<number, Vector[]>(maps[0]);\n maps.forEach((map) => {\n for (const [key, value] of map) {\n const previousValue = mergedMap.get(key) || [];\n mergedMap.set(key, [...previousValue, ...value]);\n }\n });\n return mergedMap;\n}\n\nfunction splitSegmentsAtIntersections(\n intersections: Map<number, Vector[]>,\n segments: Segment[],\n): Segment[] {\n return segments.flatMap((segment, index) => {\n if (!intersections.has(index)) return segment;\n\n const segmentIntersections = intersections.get(index);\n if (!segmentIntersections) return segment;\n\n return segment.splitAt(segmentIntersections);\n });\n}\n\nfunction pruneDegenerateSegments(\n segments: Segment[],\n originalStroke: Stroke,\n offset: number,\n): Segment[] {\n // We remove all the segments that are closer to the original segment than the offset\n return segments.filter((segment) => {\n const closeSegment = originalStroke.segments.some((c) => {\n return distance(c, segment) < Math.abs(offset) - PRECISION;\n });\n return !closeSegment;\n });\n}\n\nexport function offsetLoop(loop: Loop, offset: number): Diagram {\n const correctedOffset = loop.clockwise ? offset : -offset;\n const transformedSegments = transformForOffset(loop.segments);\n const offsettedArray = rawOffsets(transformedSegments, correctedOffset);\n\n if (offsettedArray.length < 2) return new Diagram();\n\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections = findOffsetSelfIntersections(offsettedArray);\n\n if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n /* this was in the replicad algorithm - not sure why\n if (!loop.intersects(offsettedLoop)) return offsettedLoop;\n return new Diagram();\n */\n }\n const splitSegments = splitSegmentsAtIntersections(\n allIntersections,\n offsettedArray,\n );\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = pruneDegenerateSegments(splitSegments, loop, offset);\n\n if (!prunedSegments.length) return new Diagram();\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n const newLoops = segmentsGrouped\n .filter((c) => c.length > 1)\n .filter((c) => sameVector(c[0].firstPoint, c.at(-1)!.lastPoint))\n .map((c) => new Loop(c));\n\n if (!newLoops.length) return new Diagram();\n return new Diagram(newLoops.map((l) => new Figure(l)));\n}\n\nexport function offsetStrand(strand: Strand, offset: number): Stroke[] {\n const transformedSegments = transformForOffset(strand.segments);\n const offsettedArray = rawOffsets(transformedSegments, offset, false);\n const backOffsettedArray = rawOffsets(transformedSegments, -offset, false);\n\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections = mergeIntersectionMaps([\n findOffsetSelfIntersections(offsettedArray),\n findIntersections(offsettedArray, backOffsettedArray),\n findEndIntersections(offsettedArray, strand, offset),\n ]);\n\n if (!allIntersections.size) {\n return [new Strand(offsettedArray)];\n }\n const splitSegments = splitSegmentsAtIntersections(\n allIntersections,\n offsettedArray,\n );\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = pruneDegenerateSegments(splitSegments, strand, offset);\n\n if (!prunedSegments.length) return [];\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n return segmentsGrouped.map((c) => {\n if (sameVector(c[0].firstPoint, c.at(-1)!.lastPoint)) return new Loop(c);\n return new Strand(c);\n });\n}\n\nexport function outlineStrand(\n strand: Strand,\n width: number,\n endCap: \"round\" | \"butt\" = \"round\",\n): Diagram {\n const offset = width / 2;\n const transformedSegments = transformForOffset(strand.segments);\n const frontOffsettedArray = rawOffsets(transformedSegments, offset, false);\n const backOffsettedArray = rawOffsets(\n transformedSegments,\n -offset,\n false,\n ).map((s) => s.reverse());\n backOffsettedArray.reverse();\n\n const makeJoiner = (fromSegment: Segment, toSegment: Segment) => {\n if (endCap === \"round\") {\n return tangentArc(\n fromSegment.lastPoint,\n toSegment.firstPoint,\n fromSegment.tangentAtLastPoint,\n );\n }\n return new Line(fromSegment.lastPoint, toSegment.firstPoint);\n };\n\n const offsettedArray = [\n ...frontOffsettedArray,\n makeJoiner(\n frontOffsettedArray[frontOffsettedArray.length - 1],\n backOffsettedArray[0],\n ),\n ...backOffsettedArray,\n makeJoiner(\n backOffsettedArray[backOffsettedArray.length - 1],\n frontOffsettedArray[0],\n ),\n ];\n\n const allIntersections = findOffsetSelfIntersections(offsettedArray);\n\n if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n }\n const splitSegments = splitSegmentsAtIntersections(\n allIntersections,\n offsettedArray,\n );\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = pruneDegenerateSegments(splitSegments, strand, offset);\n\n if (!prunedSegments.length) return new Diagram();\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n const newLoops = segmentsGrouped\n .filter((c) => c.length > 1)\n .filter((c) => sameVector(c[0].firstPoint, c.at(-1)!.lastPoint))\n .map((c) => new Loop(c));\n\n if (!newLoops.length) return new Diagram();\n return new Diagram(newLoops.map((l) => new Figure(l)));\n}\n","import { Figure } from \"../../models/Figure\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { cut, fuseAll } from \"../../booleanOperations\";\nimport { offsetLoop } from \"./offsetStroke\";\n\nexport function offsetFigures(\n figures: Figure[],\n offsetDistance: number,\n): Diagram {\n const offsetFigures = figures.map((figure) => {\n const innerShape = fuseAll(\n figure.holes.map((l) => offsetLoop(l, offsetDistance)),\n );\n return cut(offsetLoop(figure.contour, offsetDistance), innerShape);\n });\n\n return fuseAll(offsetFigures);\n}\n\nexport function outlineStrokeFigures(\n figures: Figure[],\n width: number,\n): Diagram {\n const absOffset = Math.abs(width / 2);\n\n const offsetFigures = figures.map((figure) =>\n fuseAll(\n figure.allLoops.map((l) => {\n return cut(offsetLoop(l, absOffset), offsetLoop(l, -absOffset));\n }),\n ),\n );\n\n return fuseAll(offsetFigures);\n}\n","import {\n offsetFigures,\n outlineStrokeFigures,\n} from \"./algorithms/offsets/offsetFigure\";\nimport { outlineStrand } from \"./algorithms/offsets/offsetStroke.js\";\nimport { Strand } from \"./models/Strand.js\";\nimport { Diagram } from \"./models/Diagram.js\";\nimport { Figure } from \"./models/Figure.js\";\nimport { Loop } from \"./models/Loop.js\";\nimport { listOfFigures } from \"./utils/listOfFigures.js\";\n\nexport function offset(\n shape: Diagram | Figure | Loop,\n offsetDistance: number,\n): Diagram {\n return offsetFigures(listOfFigures(shape), offsetDistance);\n}\n\nexport function outlineStroke(\n shape: Diagram | Figure | Loop | Strand,\n outlineDistance: number,\n { endCap = \"round\" }: { endCap?: \"butt\" | \"round\" } = {},\n): Diagram {\n if (shape instanceof Strand) {\n return outlineStrand(shape, outlineDistance, endCap);\n }\n return outlineStrokeFigures(listOfFigures(shape), outlineDistance);\n}\n","import { filletSegments } from \"./algorithms/filletSegments\";\nimport { Vector } from \"./definitions\";\nimport { Diagram, Figure, Loop, Segment, Strand } from \"./models/exports\";\nimport { angle, DEG2RAD, distance, sameVector } from \"./vectorOperations\";\n\nexport type FilterFcn<Type> = {\n element: Type;\n};\n\nexport abstract class FilterList<Type> {\n protected filters: (({ element }: FilterFcn<Type>) => boolean)[];\n\n abstract shouldKeep(t: Type): boolean;\n\n constructor() {\n this.filters = [];\n }\n\n delete() {\n this.filters = [];\n }\n\n /**\n * Combine logically a set of filter with an AND operation.\n *\n */\n and(findersList: ((f: this) => this)[]): this {\n findersList.forEach((f) => f(this));\n return this;\n }\n\n /**\n * Invert the result of a particular filter\n *\n */\n not(finderFun: (f: this) => this): this {\n const finder = new (<any>this.constructor)() as this;\n finderFun(finder);\n\n const notFilter = ({ element }: { element: Type }) =>\n !finder.shouldKeep(element);\n this.filters.push(notFilter);\n\n return this;\n }\n\n /**\n * Combine logically a set of filter with an OR operation.\n *\n */\n either(findersList: ((f: this) => this)[]): this {\n const builtFinders = findersList.map((finderFunction) => {\n const finder = new (<any>this.constructor)() as this;\n finderFunction(finder);\n return finder;\n });\n\n const eitherFilter = ({ element }: { element: Type }) =>\n builtFinders.some((finder) => finder.shouldKeep(element));\n this.filters.push(eitherFilter);\n\n return this;\n }\n}\n\nexport type Corner = {\n firstCurve: Segment;\n secondCurve: Segment;\n point: Vector;\n};\n\nconst PI_2 = 2 * Math.PI;\nconst positiveHalfAngle = (angle: number) => {\n const limitedAngle = angle % PI_2;\n\n const coterminalAngle = limitedAngle < 0 ? limitedAngle + PI_2 : limitedAngle;\n if (coterminalAngle < Math.PI) return coterminalAngle;\n if (coterminalAngle === Math.PI) return 0;\n return Math.abs(coterminalAngle - PI_2);\n};\n\nexport class CornerFilter extends FilterList<Corner> {\n clone(): CornerFilter {\n const ef = new CornerFilter();\n ef.filters = [...this.filters];\n return ef;\n }\n\n /**\n * Filter to find corner that have their point are in the list.\n *\n */\n inList(elementList: Vector[]): this {\n const elementInList = ({ element }: { element: Corner }) => {\n return !!elementList.find((e) => sameVector(e, element.point));\n };\n this.filters.push(elementInList);\n return this;\n }\n\n /**\n * Filter to find elements that are at a specified distance from a point.\n *\n */\n atDistance(dist: number, point: Vector = [0, 0]): this {\n function elementAtDistance({ element }: { element: Corner }) {\n return Math.abs(distance(point, element.point) - dist) < 1e-9;\n }\n this.filters.push(elementAtDistance);\n return this;\n }\n\n /**\n * Filter to find elements that contain a certain point\n *\n * @category Filter\n */\n atPoint(point: Vector): this {\n function elementAtPoint({ element }: { element: Corner }) {\n return sameVector(point, element.point);\n }\n this.filters.push(elementAtPoint);\n return this;\n }\n\n /**\n * Filter to find elements that are within a box\n *\n * @category Filter\n */\n inBox(corner1: Vector, corner2: Vector) {\n const [x1, y1] = corner1;\n const [x2, y2] = corner2;\n\n const minX = Math.min(x1, x2);\n const maxX = Math.max(x1, x2);\n\n const minY = Math.min(y1, y2);\n const maxY = Math.max(y1, y2);\n\n function elementInBox({ element }: { element: Corner }) {\n const [x, y] = element.point;\n return x >= minX && x <= maxX && y >= minY && y <= maxY;\n }\n this.filters.push(elementInBox);\n return this;\n }\n\n /**\n * Filter to find corner that a certain angle between them - only between\n * 0 and 180.\n *\n */\n ofAngle(theta: number) {\n function elementOfAngle({ element }: { element: Corner }) {\n const tgt1 = element.firstCurve.tangentAtLastPoint;\n const tgt2 = element.secondCurve.tangentAtFirstPoint;\n\n return (\n Math.abs(\n positiveHalfAngle(angle(tgt1, tgt2)) -\n positiveHalfAngle(DEG2RAD * theta),\n ) < 1e-9\n );\n }\n\n this.filters.push(elementOfAngle);\n return this;\n }\n\n above(yValue = 0) {\n function elementAbove({ element }: { element: Corner }) {\n return element.point[1] > yValue;\n }\n this.filters.push(elementAbove);\n return this;\n }\n\n below(yValue = 0) {\n function elementBelow({ element }: { element: Corner }) {\n return element.point[1] < yValue;\n }\n this.filters.push(elementBelow);\n return this;\n }\n\n leftOf(xValue = 0) {\n function elementLeftOf({ element }: { element: Corner }) {\n return element.point[0] < xValue;\n }\n this.filters.push(elementLeftOf);\n return this;\n }\n\n rightOf(xValue = 0) {\n function elementRightOf({ element }: { element: Corner }) {\n return element.point[0] > xValue;\n }\n this.filters.push(elementRightOf);\n return this;\n }\n\n shouldKeep(element: Corner): boolean {\n const shouldKeep = this.filters.every((filter) => filter({ element }));\n return shouldKeep;\n }\n\n asFilterFun() {\n return this.shouldKeep.bind(this);\n }\n}\n\ntype CornerMaker = (seg1: Segment, seg2: Segment, radius: number) => Segment[];\n\nfunction modifyStroke(\n makeCorner: CornerMaker,\n stroke: Loop | Strand,\n radius: number,\n filter: (c: Corner) => boolean = () => true,\n): Loop | Strand {\n const segments = [stroke.segments[0]];\n\n const addModifiedCorner = (firstCurve: Segment, secondCurve: Segment) => {\n if (filter({ firstCurve, secondCurve, point: firstCurve.lastPoint })) {\n segments.push(...makeCorner(firstCurve, secondCurve, radius));\n } else {\n segments.push(firstCurve, secondCurve);\n }\n };\n\n stroke.segments.slice(1).forEach((secondCurve) => {\n const firstCurve = segments.pop();\n if (!firstCurve) throw new Error(\"Bug in the stroke filletting algo\");\n addModifiedCorner(firstCurve, secondCurve);\n });\n\n const lastCurve = segments.at(-1);\n if (!lastCurve) throw new Error(\"Bug in the stroke corner algo\");\n\n if (stroke instanceof Loop) {\n const firstCurve = segments.pop();\n const secondCurve = segments.shift();\n if (!firstCurve || !secondCurve)\n throw new Error(\"Bug in the filletting algo\");\n addModifiedCorner(firstCurve, secondCurve);\n\n return new Loop(segments, { ignoreChecks: true });\n } else {\n return new Strand(segments, { ignoreChecks: true });\n }\n}\n\nexport type Shape = Loop | Strand | Figure | Diagram;\nexport type FilterArg = CornerFilter | ((c: CornerFilter) => CornerFilter);\n\nfunction fillet<T extends Shape>(\n shape: T,\n radius: number,\n filter?: FilterArg,\n): T;\nfunction fillet(shape: Loop, radius: number, filter?: FilterArg): Loop;\nfunction fillet(shape: Strand, radius: number, filter?: FilterArg): Strand;\nfunction fillet(shape: Figure, radius: number, filter?: FilterArg): Figure;\nfunction fillet(shape: Diagram, radius: number, filter?: FilterArg): Diagram;\n\nfunction fillet(\n shape: Shape,\n radius: number,\n filter?: CornerFilter | ((c: CornerFilter) => CornerFilter),\n): Shape {\n const filterObj =\n typeof filter === \"function\" ? filter(new CornerFilter()) : filter;\n const filterFcn = filterObj && filterObj.asFilterFun();\n\n if (shape instanceof Loop || shape instanceof Strand) {\n return modifyStroke(filletSegments, shape, radius, filterFcn);\n }\n\n if (shape instanceof Figure) {\n const newContour = fillet(shape.contour, radius, filterObj);\n const newHoles = shape.holes.map((l) => fillet(l, radius, filterObj));\n\n return new Figure(newContour, newHoles, { ignoreChecks: true });\n }\n\n if (shape instanceof Diagram) {\n const newFigs = shape.figures.map((f) => fillet(f, radius, filterObj));\n return new Diagram(newFigs, { ignoreChecks: true });\n }\n\n throw new Error(\"invalid shape to fillet\");\n}\n\nfunction chamfer<T extends Shape>(\n shape: T,\n radius: number,\n filter?: FilterArg,\n): T;\nfunction chamfer(shape: Loop, radius: number, filter?: FilterArg): Loop;\nfunction chamfer(shape: Strand, radius: number, filter?: FilterArg): Strand;\nfunction chamfer(shape: Figure, radius: number, filter?: FilterArg): Figure;\nfunction chamfer(shape: Diagram, radius: number, filter?: FilterArg): Diagram;\n\nfunction chamfer(shape: Shape, radius: number, filter?: FilterArg): Shape {\n const filterObj =\n typeof filter === \"function\" ? filter(new CornerFilter()) : filter;\n const filterFcn = filterObj && filterObj.asFilterFun();\n\n if (shape instanceof Loop || shape instanceof Strand) {\n return modifyStroke(filletSegments, shape, radius, filterFcn);\n }\n\n if (shape instanceof Figure) {\n const newContour = chamfer(shape.contour, radius, filterObj);\n const newHoles = shape.holes.map((l) => chamfer(l, radius, filterObj));\n\n return new Figure(newContour, newHoles, { ignoreChecks: true });\n }\n\n if (shape instanceof Diagram) {\n const newFigs = shape.figures.map((f) => chamfer(f, radius, filterObj));\n return new Diagram(newFigs, { ignoreChecks: true });\n }\n throw new Error(\"invalid shape to chamfer\");\n}\n\nclass CornerSelector<T extends Shape> extends CornerFilter {\n constructor(private readonly shape: T) {\n super();\n }\n\n fillet(radius: number): T {\n return fillet<T>(this.shape, radius, this.clone());\n }\n\n chamfer(radius: number): T {\n return chamfer<T>(this.shape, radius, this.clone());\n }\n}\n\nfunction selectCorners<T extends Shape>(s: T) {\n return new CornerSelector<T>(s);\n}\n\nexport { fillet, chamfer, selectCorners };\n","import { Strand } from \"../../models/Strand.js\";\nimport { Diagram } from \"../../models/Diagram.js\";\nimport { Figure } from \"../../models/Figure.js\";\nimport { Loop } from \"../../models/Loop.js\";\nimport { BoundingBox } from \"../../models/BoundingBox.js\";\nimport { svgDiagram } from \"./svgDiagram.js\";\nimport { svgFigure } from \"./svgFigure.js\";\nimport { svgLoop } from \"./svgLoop.js\";\nimport { svgSegmentToPath } from \"./svgSegment.js\";\nimport { svgStrand } from \"./svgStrand.js\";\nimport { SVGUnit, wrapSVG } from \"./wrapSVG.js\";\nimport type { Stroke } from \"../../models/Stroke.js\";\nimport { Segment } from \"../../main.js\";\nimport { isSegment } from \"../../models/segments/utils/isSegment.js\";\n\ntype Shape = Figure | Diagram | Stroke | Segment;\n\nexport function svgBody(shape: Shape) {\n if (shape instanceof Diagram) {\n return svgDiagram(shape);\n } else if (shape instanceof Figure) {\n return svgFigure(shape);\n } else if (shape instanceof Loop) {\n return `<path d=\"${svgLoop(shape)}\" />`;\n } else if (shape instanceof Strand) {\n return `<path d=\"${svgStrand(shape)}\" />`;\n } else if (isSegment(shape)) {\n return `<path d=\"${`M ${shape.firstPoint.join(\" \")}`} ${svgSegmentToPath(\n shape,\n )}\" />`;\n } else {\n throw new Error(\"Unknown shape type\");\n }\n}\n\ntype ConfiguredShape = Shape | { shape: Shape; color?: string };\n\nconst extractShape = (shape: ConfiguredShape) =>\n \"shape\" in shape ? shape.shape : shape;\n\nconst addConfig = (shape: ConfiguredShape, body: string) => {\n if (!(\"shape\" in shape)) return body;\n const { color } = shape;\n if (!color) return body;\n return `<g stroke=\"${color}\">${body}</g>`;\n};\n\nconst flibBbox = (bbox: BoundingBox) => {\n return new BoundingBox(bbox.xMin, -bbox.yMax, bbox.xMax, -bbox.yMin);\n};\n\nexport function exportSVG(\n shape: ConfiguredShape | ConfiguredShape[],\n {\n margin = 1,\n unit = null,\n viewBox,\n }: {\n margin?: number;\n unit?: null | SVGUnit;\n viewBox?: BoundingBox;\n } = {},\n) {\n if (Array.isArray(shape)) {\n const flipped = shape.map((s) => extractShape(s).mirror());\n const body = flipped\n .map((s, i) => addConfig(shape[i], svgBody(s)))\n .join(\"\\n\");\n const bbox = flipped\n .slice(1)\n .reduce((bbox, s) => bbox.merge(s.boundingBox), flipped[0].boundingBox);\n\n return wrapSVG(body, viewBox ? flibBbox(viewBox) : bbox, margin, unit);\n }\n const flipped = extractShape(shape).mirror();\n return wrapSVG(\n addConfig(shape, svgBody(flipped)),\n viewBox ? flibBbox(viewBox) : flipped.boundingBox,\n margin,\n unit,\n );\n}\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { Loop } from \"../../models/Loop.js\";\nimport { Figure } from \"../../models/Figure.js\";\nimport { Diagram } from \"../../models/Diagram.js\";\nimport { EllipseArc } from \"../../models/segments/EllipseArc.js\";\nimport { CubicBezier } from \"../../models/segments/CubicBezier.js\";\nimport { QuadraticBezier } from \"../../models/segments/QuadraticBezier.js\";\n\nconst importSegment = (json: any) => {\n if (json.type === \"LINE\") {\n return new Line(json.firstPoint, json.lastPoint);\n }\n if (json.type === \"ARC\") {\n return new Arc(\n json.firstPoint,\n json.lastPoint,\n json.center,\n json.clockwise,\n );\n }\n if (json.type === \"ELLIPSE_ARC\") {\n return new EllipseArc(\n json.firstPoint,\n json.lastPoint,\n json.center,\n json.majorRadius,\n json.minorRadius,\n json.tiltAngle,\n json.clockwise,\n { angleUnits: \"rad\" },\n );\n }\n if (json.type === \"QUADRATIC_BEZIER\") {\n return new QuadraticBezier(\n json.firstPoint,\n json.lastPoint,\n json.controlPoint,\n );\n }\n if (json.type === \"CUBIC_BEZIER\") {\n return new CubicBezier(\n json.firstPoint,\n json.lastPoint,\n json.firstControlPoint,\n json.lastControlPoint,\n );\n }\n throw new Error(\"Unknown segment type\");\n};\n\nconst importLoop = (json: any) => {\n const segments = json.segments.map(importSegment);\n return new Loop(segments);\n};\n\nconst importFigure = (json: any) => {\n const contour = importLoop(json.contour);\n const holes = json.holes.map(importLoop);\n return new Figure(contour, holes);\n};\n\nconst importDiagram = (json: any) => {\n const figures = json.figures.map(importFigure);\n return new Diagram(figures);\n};\n\nexport function importJSON(json: any) {\n if (json.type === \"DIAGRAM\") {\n return importDiagram(json);\n }\n if (json.type === \"FIGURE\") {\n return importFigure(json);\n }\n if (json.type === \"LOOP\") {\n return importLoop(json);\n }\n if (\n json.type === \"LINE\" ||\n json.type === \"ARC\" ||\n json.type === \"ELLIPSE_ARC\" ||\n json.type === \"CUBIC_BEZIER\"\n ) {\n return importSegment(json);\n }\n throw new Error(\"Unknown shape type\");\n}\n","import type { Vector } from \"./definitions.js\";\nexport { Vector };\n\nexport const DEG2RAD = Math.PI / 180;\nexport const RAD2DEG = 180 / Math.PI;\n\nexport function polarToCartesian(r: number, theta: number): Vector {\n const x = Math.cos(theta * DEG2RAD) * r;\n const y = Math.sin(theta * DEG2RAD) * r;\n return [x, y];\n}\n\nexport function cartesianToPolar([x, y]: Vector): [number, number] {\n const r = Math.sqrt(x * x + y * y);\n const theta = Math.atan2(y, x) * RAD2DEG;\n return [r, theta];\n}\n\nexport type {\n Diagram,\n Figure,\n Loop,\n Strand,\n Stroke,\n TransformationMatrix,\n BoundingBox,\n Segment,\n Line,\n Arc,\n EllipseArc,\n CubicBezier,\n} from \"./models/exports.js\";\n\nexport { draw, DrawingPen } from \"./draw.js\";\nexport {\n // Surface booleans\n fuseAll,\n fuse,\n cut,\n intersect,\n // Strand booleans\n eraseStrand,\n confineStrand,\n // Offset\n offset,\n outlineStroke,\n // Features\n fillet,\n chamfer,\n selectCorners,\n} from \"./operations.js\";\n\nexport { exportSVG, svgBody } from \"./export/svg/exportSVG.js\";\n\nexport { exportJSON } from \"./export/json/exportJSON.js\";\nexport { importJSON } from \"./import/json/importJSON.js\";\n"],"names":["listOfFigures","shape","Figure","Loop","Diagram","strandLoopSections","loop","strand","precision","allIntersections","allCommonSegments","splitPoints","strandSegment","strandIndex","loopSegment","intersections","overlaps","findIntersectionsAndOverlaps","commonSegmentsPoints","s","removeDuplicatePoints","strandSegments","zip","segment","strandsBetweenIntersections","eraseStrandWithinLoop","eraseOnBorder","strandCenter","eraseStrandOutsideLoop","eraseStrandWithinFigure","figure","outsideStrands","inLoopStrand","hole","eraseStrandOutsideFigure","insideStrands","fuse","first","second","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","eraseStrand","diagram","outStrands","Strand","confineStrand","segmentPosition","intersectionParam","handleBetween","lineBetween","otherLine","otherPosition","lineLineDistance","line1","line2","intersectionParams","lineLineParams","intersectionParam1","intersectionParam2","firstPosition","secondPosition","distance","lineArcDistance","line","arc","lineArcIntersection","closestPointOnLine","projectPointOnLine","circleCenterLineDistance","centerLineDirection","normalize","subtract","closestPointOnCircle","add","scalarMultiply","overlappingAngles","arc1","arc2","p1","p2","arcArcDistance","arcArcIntersection","centersDistance","centerCenterDirection","containedCircles","arc1ClosestPointAngle","polarAngle","arc2ClosestPointAngle","binarySearch","array","value","comparator","low","high","mid","cmp","binaryInsert","index","DiagonalBuckets","__publicField","interval","bucket","a","b","intervals","i","lastInterval","secondToLastInterval","slope","DivisionRectangle","x","y","DiRectOptimisation","fcn","endTolerance","maxIterations","epsilon","center","rect","Interval","leftCenter","rightCenter","i1","i2","k","potentialFMin","left","middle","right","rectangle","findGlobalMinimum","fun","tolerance","genericDistance","segment1","segment2","result","t","squareDistance","Line","Arc","isOffsetSafeBezier","CubicBezier","chord","v2","v3","a1","angle","a2","n1","perpendicular","n2","dotProduct","_splitIntoOffsetSafeBezier","splitIntoOffsetSafeBezier","approximateEllipticalArcAsCubicBeziers","ellipseArc","sweepAngle","segments","anglePerSegment","kappa","orientation","angles","_","startAngle","endAngle","cosStart","sinStart","cosEnd","sinEnd","centerX","centerY","r","R","rotationMatrix","TransformationMatrix","rotateInFrame","p","p0","c0","c1","PRECISION","transformForOffset","EllipseArc","c","QuadraticBezier","rawOffsets","segmentsToOffset","offset","offsetSegments","offsetSegment","offsettedArray","savedLastSegment","previousSegment","appendSegment","DegenerateSegment","sameVector","iterateOffsetSegments","previousLastPoint","firstPoint","pointIntersections","intersection","originalEndpoint","distances","splitPreviousSegment","splitSegment","clockwise","crossProduct","joiner","findOffsetSelfIntersections","updateIntersections","newPoints","firstSegment","firstIndex","secondSegment","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","splitSegmentsAtIntersections","segmentIntersections","pruneDegenerateSegments","originalStroke","offsetLoop","correctedOffset","transformedSegments","offsettedLoop","splitSegments","prunedSegments","newLoops","stitchSegments","outlineStrand","width","endCap","frontOffsettedArray","backOffsettedArray","makeJoiner","fromSegment","toSegment","tangentArc","l","offsetFigures","figures","offsetDistance","innerShape","outlineStrokeFigures","absOffset","outlineStroke","outlineDistance","FilterList","findersList","f","finderFun","finder","notFilter","element","builtFinders","finderFunction","eitherFilter","PI_2","positiveHalfAngle","limitedAngle","coterminalAngle","CornerFilter","ef","elementList","elementInList","e","dist","point","elementAtDistance","elementAtPoint","corner1","corner2","x1","y1","x2","y2","minX","maxX","minY","maxY","elementInBox","theta","elementOfAngle","tgt1","tgt2","DEG2RAD","yValue","elementAbove","elementBelow","xValue","elementLeftOf","elementRightOf","filter","modifyStroke","makeCorner","stroke","radius","addModifiedCorner","firstCurve","secondCurve","fillet","filterObj","filterFcn","filletSegments","newContour","newHoles","newFigs","chamfer","CornerSelector","selectCorners","svgBody","svgDiagram","svgFigure","svgLoop","svgStrand","isSegment","svgSegmentToPath","extractShape","addConfig","body","color","flibBbox","bbox","BoundingBox","exportSVG","margin","unit","viewBox","flipped","wrapSVG","importSegment","json","importLoop","importFigure","contour","holes","importDiagram","importJSON","RAD2DEG","polarToCartesian","cartesianToPolar"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pantograph.js","sources":["../src/utils/listOfFigures.ts","../src/algorithms/boolean/strandBoolean.ts","../src/booleanOperations.ts","../src/algorithms/distances/lineLineDistance.ts","../src/algorithms/distances/lineArcDistance.ts","../src/algorithms/distances/arcArcDistance.ts","../src/algorithms/optimisation/DiRect.ts","../src/algorithms/distances/genericDistance.ts","../src/algorithms/distances/index.ts","../src/algorithms/conversions/bezierToSafeBezier.ts","../src/algorithms/conversions/ellipseToBezier.ts","../src/algorithms/offsets/offsetStroke.ts","../src/algorithms/offsets/offsetFigure.ts","../src/offsetOperations.ts","../src/featureOperations.ts","../src/algorithms/tesselate/tesselateSegment.ts","../src/algorithms/conversions/helpers.ts","../src/tesselationOperations.ts","../src/export/svg/exportSVG.ts","../src/import/json/importJSON.ts","../src/main.ts"],"sourcesContent":["import { Diagram } from \"../models/Diagram.js\";\nimport { Figure } from \"../models/Figure.js\";\nimport { Loop } from \"../models/Loop.js\";\n\nexport function listOfFigures(shape: Diagram | Figure | Loop): Figure[] {\n if (shape instanceof Figure) {\n return [shape];\n } else if (shape instanceof Loop) {\n return [new Figure(shape)];\n } else if (shape instanceof Diagram) {\n return shape.figures;\n }\n throw new Error(\"Unknown shape\");\n}\n","import { Vector } from \"../../definitions\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport { Loop } from \"../../models/Loop\";\nimport { Strand } from \"../../models/Strand\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport removeDuplicatePoints from \"../../utils/removeDuplicatePoints\";\nimport zip from \"../../utils/zip\";\nimport { strandsBetweenIntersections } from \"./strandsBetweenIntersections\";\nimport type { Figure } from \"../../models/Figure\";\nimport type { Stroke } from \"../../models/Stroke\";\n\nfunction strandLoopSections(\n loop: Loop,\n strand: Stroke,\n precision = 1e-9,\n): Strand[] {\n let allIntersections: Vector[] = [];\n const allCommonSegments: Segment[] = [];\n\n const splitPoints: Vector[][] = new Array(strand.segments.length)\n .fill(0)\n .map(() => []);\n\n strand.segments.forEach((strandSegment, strandIndex) => {\n loop.segments.forEach((loopSegment) => {\n const { intersections, overlaps } = findIntersectionsAndOverlaps(\n strandSegment,\n loopSegment,\n precision,\n );\n\n allIntersections.push(...intersections);\n splitPoints[strandIndex].push(...intersections);\n\n allCommonSegments.push(...overlaps);\n const commonSegmentsPoints = overlaps.flatMap((s) => [\n s.firstPoint,\n s.lastPoint,\n ]);\n allIntersections.push(...commonSegmentsPoints);\n splitPoints[strandIndex].push(...commonSegmentsPoints);\n });\n });\n\n allIntersections = removeDuplicatePoints(allIntersections, precision);\n\n const strandSegments = zip([strand.segments, splitPoints] as [\n Segment[],\n Vector[][],\n ]).flatMap(([segment, intersections]: [Segment, Vector[]]): Segment[] => {\n if (!intersections.length) return [segment];\n return segment.splitAt(intersections);\n });\n\n return Array.from(\n strandsBetweenIntersections(\n strandSegments,\n allIntersections,\n allCommonSegments,\n ),\n );\n}\n\nexport function eraseStrandWithinLoop(\n strand: Stroke,\n loop: Loop,\n eraseOnBorder = false,\n) {\n const strands = strandLoopSections(loop, strand);\n\n // We keep only the strands that are outside the loop\n return strands.filter((strand) => {\n const strandCenter = strand.segments[0].midPoint;\n if (loop.onStroke(strandCenter)) return !eraseOnBorder;\n\n return !loop.contains(strandCenter);\n });\n}\n\nexport function eraseStrandOutsideLoop(\n strand: Stroke,\n loop: Loop,\n eraseOnBorder = false,\n) {\n const strands = strandLoopSections(loop, strand);\n\n // We keep only the strands that are outside the loop\n return strands.filter((strand) => {\n const strandCenter = strand.segments[0].midPoint;\n if (loop.onStroke(strandCenter)) return !eraseOnBorder;\n\n return loop.contains(strandCenter);\n });\n}\n\nexport function eraseStrandWithinFigure(\n strand: Stroke,\n figure: Figure,\n eraseOnBorder = false,\n) {\n const outsideStrands = eraseStrandWithinLoop(\n strand,\n figure.contour,\n eraseOnBorder,\n );\n\n const inLoopStrand = figure.holes.flatMap((hole: Loop) =>\n eraseStrandOutsideLoop(strand, hole, eraseOnBorder),\n );\n\n return [...outsideStrands, ...inLoopStrand];\n}\n\nexport function eraseStrandOutsideFigure(\n strand: Stroke,\n figure: Figure,\n eraseOnBorder = false,\n) {\n let insideStrands = eraseStrandOutsideLoop(\n strand,\n figure.contour,\n eraseOnBorder,\n );\n\n figure.holes.forEach((hole: Loop) => {\n insideStrands = insideStrands.flatMap((strand) =>\n eraseStrandWithinLoop(strand, hole, eraseOnBorder),\n );\n });\n\n return insideStrands;\n}\n","import {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"./algorithms/boolean/figureBooleans\";\nimport { Strand } from \"./models/Strand\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\nimport {\n eraseStrandOutsideFigure,\n eraseStrandOutsideLoop,\n eraseStrandWithinFigure,\n eraseStrandWithinLoop,\n} from \"./algorithms/boolean/strandBoolean\";\nimport { Stroke } from \"./main\";\n\nexport function fuse(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop,\n): Diagram {\n return new Diagram(\n fuseFiguresLists(listOfFigures(first), listOfFigures(second)),\n );\n}\n\nexport function fuseAll(shapes: (Diagram | Figure | Loop)[]): Diagram {\n return shapes.reduce(\n (acc: Diagram, shape: Diagram | Figure | Loop) => fuse(acc, shape),\n new Diagram(),\n );\n}\n\nexport function cut(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop,\n): Diagram {\n return new Diagram(\n cutFiguresLists(listOfFigures(first), listOfFigures(second)),\n );\n}\n\nexport function intersect(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop,\n): Diagram {\n return new Diagram(\n intersectFiguresLists(listOfFigures(first), listOfFigures(second)),\n );\n}\n\nexport function eraseStrand(\n strand: Stroke,\n diagram: Diagram | Figure | Loop,\n eraseOnBorder = true,\n): Strand[] {\n if (diagram instanceof Loop) {\n return eraseStrandWithinLoop(strand, diagram, eraseOnBorder);\n }\n\n if (diagram instanceof Figure) {\n return eraseStrandWithinFigure(strand, diagram, eraseOnBorder);\n }\n\n let outStrands: Strand[] = [new Strand([...strand.segments])];\n diagram.figures.forEach((figure: Figure) => {\n outStrands = outStrands.flatMap((strand: Strand) => {\n return eraseStrandWithinFigure(strand, figure, eraseOnBorder);\n });\n });\n\n return outStrands;\n}\n\nexport function confineStrand(\n strand: Stroke,\n diagram: Diagram | Figure | Loop,\n eraseOnBorder = false,\n): Strand[] {\n if (diagram instanceof Loop) {\n return eraseStrandOutsideLoop(strand, diagram, eraseOnBorder);\n }\n\n if (diagram instanceof Figure) {\n return eraseStrandOutsideFigure(strand, diagram, eraseOnBorder);\n }\n\n let outStrands: Strand[] = [new Strand([...strand.segments])];\n diagram.figures.forEach((figure: Figure) => {\n outStrands = outStrands.flatMap((strand: Strand) => {\n return eraseStrandOutsideFigure(strand, figure, eraseOnBorder);\n });\n });\n\n return outStrands;\n}\n","import { lineLineParams } from \"../intersections/lineLineIntersection.js\";\nimport type { Line } from \"../../models/segments/Line.js\";\nimport { distance } from \"../../vectorOperations.js\";\n\nfunction segmentPosition(intersectionParam: number) {\n if (intersectionParam < 0) return \"before\";\n if (intersectionParam > 1) return \"after\";\n return \"between\";\n}\n\nconst handleBetween = (\n lineBetween: Line,\n otherLine: Line,\n otherPosition: \"before\" | \"after\",\n) => {\n if (otherPosition === \"before\")\n return lineBetween.distanceFrom(otherLine.firstPoint);\n else if (otherPosition === \"after\")\n return lineBetween.distanceFrom(otherLine.lastPoint);\n else throw new Error(\"Invalid position\");\n};\n\nexport function lineLineDistance(line1: Line, line2: Line): number {\n const intersectionParams = lineLineParams(line1, line2);\n\n if (intersectionParams === \"parallel\") {\n return Math.min(\n line1.distanceFrom(line2.firstPoint),\n line1.distanceFrom(line2.lastPoint),\n );\n }\n\n const { intersectionParam1, intersectionParam2 } = intersectionParams;\n\n const firstPosition = segmentPosition(intersectionParam1);\n const secondPosition = segmentPosition(intersectionParam2);\n\n if (firstPosition === \"between\" && secondPosition === \"between\") {\n return 0;\n } else if (firstPosition === \"between\" && secondPosition !== \"between\") {\n return handleBetween(line1, line2, secondPosition);\n } else if (secondPosition === \"between\" && firstPosition !== \"between\") {\n return handleBetween(line2, line1, firstPosition);\n } else if (firstPosition === \"before\" && secondPosition === \"before\") {\n return distance(line1.firstPoint, line2.firstPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"after\") {\n return distance(line1.lastPoint, line2.lastPoint);\n } else if (firstPosition === \"before\" && secondPosition === \"after\") {\n return distance(line1.firstPoint, line2.lastPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"before\") {\n return distance(line1.lastPoint, line2.firstPoint);\n } else {\n throw new Error(\"Invalid position\");\n }\n}\n","import type { Line } from \"../../models/segments/Line.js\";\nimport type { Arc } from \"../../models/segments/Arc.js\";\nimport {\n normalize,\n subtract,\n distance,\n add,\n scalarMultiply,\n} from \"../../vectorOperations\";\nimport { projectPointOnLine } from \"../../utils/projectPointOnLine.js\";\nimport { lineArcIntersection } from \"../intersections/lineArcIntersection.js\";\n\nexport function lineArcDistance(line: Line, arc: Arc): number {\n // We might be able to optimise this if necessary\n\n if (lineArcIntersection(line, arc).length > 0) {\n return 0;\n }\n\n const closestPointOnLine = projectPointOnLine(line, arc.center);\n\n if (line.isOnSegment(closestPointOnLine)) {\n const circleCenterLineDistance = distance(closestPointOnLine, arc.center);\n\n // The line is tangent to the circle\n if (Math.abs(circleCenterLineDistance - arc.radius) < line.precision) {\n if (arc.isOnSegment(closestPointOnLine)) {\n return 0;\n }\n }\n\n if (circleCenterLineDistance - arc.radius > line.precision) {\n const centerLineDirection = normalize(\n subtract(closestPointOnLine, arc.center),\n );\n\n const closestPointOnCircle = add(\n arc.center,\n scalarMultiply(centerLineDirection, arc.radius),\n );\n\n if (arc.isOnSegment(closestPointOnCircle)) {\n return distance(closestPointOnCircle, closestPointOnLine);\n }\n }\n }\n\n return Math.min(\n arc.distanceFrom(line.firstPoint),\n arc.distanceFrom(line.lastPoint),\n line.distanceFrom(arc.firstPoint),\n line.distanceFrom(arc.lastPoint),\n );\n}\n","import {\n distance,\n normalize,\n polarAngle,\n subtract,\n} from \"../../vectorOperations\";\nimport type { Arc } from \"../../models/segments/Arc.js\";\nimport { arcArcIntersection } from \"../intersections/arcArcIntersection.js\";\n\nconst overlappingAngles = (arc1: Arc, arc2: Arc): boolean => {\n const p1 = arc1.angleToParam(arc2.firstAngle);\n if (arc1.isValidParameter(p1)) return true;\n\n const p2 = arc1.angleToParam(arc2.lastAngle);\n if (arc1.isValidParameter(p2)) return true;\n return false;\n};\n\nexport function arcArcDistance(arc1: Arc, arc2: Arc): number {\n if (arcArcIntersection(arc1, arc2, true).length > 0) return 0;\n\n const centersDistance = distance(arc1.center, arc2.center);\n\n if (centersDistance < arc1.precision) {\n if (overlappingAngles(arc1, arc2)) {\n return Math.abs(arc1.radius - arc2.radius);\n }\n }\n\n const centerCenterDirection = normalize(subtract(arc2.center, arc1.center));\n\n const containedCircles =\n centersDistance - Math.abs(arc1.radius - arc2.radius) < arc1.precision;\n\n let arc1ClosestPointAngle = polarAngle(centerCenterDirection);\n if (containedCircles && arc2.radius > arc1.radius) {\n arc1ClosestPointAngle += Math.PI;\n }\n const arc2ClosestPointAngle = containedCircles\n ? arc1ClosestPointAngle\n : arc1ClosestPointAngle + Math.PI;\n\n const p1 = arc1.angleToParam(arc1ClosestPointAngle);\n const p2 = arc2.angleToParam(arc2ClosestPointAngle);\n\n if (arc1.isValidParameter(p1) && arc2.isValidParameter(p2)) {\n // There might be some optimization here (with the center distance and radius differences)\n return distance(arc1.paramPoint(p1), arc2.paramPoint(p2));\n }\n\n return Math.min(\n arc1.distanceFrom(arc2.firstPoint),\n arc1.distanceFrom(arc2.lastPoint),\n arc2.distanceFrom(arc1.firstPoint),\n arc2.distanceFrom(arc1.lastPoint),\n );\n}\n","// An implementation of the direct algorithm for computing the global minimum of\n// a funciton defined between 0 and 1. The algorithm is described in:\n// Jones, D.R., Perttunen, C.D. and Stuckman, B.E., 1993. Lipschitzian\n// optimization without the Lipschitz constant. Journal of Optimization Theory\n// and Applications, 79(1), pp.157-181.\n//\n// Also inspired by the implementation in the Direct package for rust\n// https://gitlab.com/blei42/direct\n\nfunction binarySearch<T>(\n array: T[],\n value: T,\n comparator: (a: T, b: T) => number,\n): number {\n let low = 0;\n let high = array.length - 1;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const cmp = comparator(array[mid], value);\n if (cmp < 0) {\n low = mid + 1;\n } else if (cmp > 0) {\n high = mid - 1;\n } else {\n return mid;\n }\n }\n return -(low + 1);\n}\n\nfunction binaryInsert<T>(\n array: T[],\n value: T,\n comparator: (a: T, b: T) => number,\n) {\n const index = binarySearch(array, value, comparator);\n if (index < 0) {\n array.splice(-(index + 1), 0, value);\n } else {\n array.splice(index, 0, value);\n }\n}\n\nclass DiagonalBuckets {\n public readonly buckets: Interval[][];\n constructor() {\n this.buckets = [];\n }\n\n addInterval(interval: Interval) {\n const bucket = this.buckets[interval.rectangle.diagonalBucketIndex];\n if (bucket === undefined) {\n this.buckets[interval.rectangle.diagonalBucketIndex] = [interval];\n } else {\n binaryInsert(bucket, interval, (a, b) => a.value - b.value);\n }\n }\n\n removeInterval(interval: Interval) {\n const bucket = this.buckets[interval.rectangle.diagonalBucketIndex];\n if (bucket === undefined) {\n throw new Error(\"Interval not found\");\n }\n bucket.shift();\n }\n\n getBottomRightHullIntervals(): Interval[] {\n const intervals: Interval[] = [];\n for (let i = this.buckets.length - 1; i >= 0; i--) {\n const bucket = this.buckets[i];\n\n if (!bucket === undefined) continue;\n const interval = bucket[0];\n if (interval === undefined) continue;\n\n if (!intervals.length) {\n intervals.push(interval);\n continue;\n }\n\n // We want to keep only the right bottom hull of the intervals\n\n // First, we remove intervals with a bigger value\n while (\n intervals.length &&\n intervals[intervals.length - 1].value >= interval.value\n ) {\n intervals.pop();\n }\n\n // Then, we remove intervals that are covered by the previous interval\n // and the last updated\n while (intervals.length >= 2) {\n const lastInterval = intervals[intervals.length - 1];\n const secondToLastInterval = intervals[intervals.length - 2];\n\n const slope =\n (interval.value - secondToLastInterval.value) /\n ((interval.rectangle.diagonal -\n secondToLastInterval.rectangle.diagonal) *\n 2);\n const comparison =\n secondToLastInterval.value +\n ((lastInterval.rectangle.diagonal -\n secondToLastInterval.rectangle.diagonal) /\n 2.0) *\n slope;\n\n if (comparison < lastInterval.value) {\n intervals.pop();\n } else {\n break;\n }\n }\n\n intervals.push(interval);\n }\n\n return intervals;\n }\n}\n\nclass DivisionRectangle {\n public diagonal: number;\n public diagonalBucketIndex: number;\n\n public xLength: number;\n public yLength: number;\n\n public index: string;\n\n constructor(\n public x: number,\n public y: number,\n ) {\n this.xLength = Math.pow(3, -x);\n this.yLength = Math.pow(3, -y);\n\n this.diagonal = Math.sqrt(\n this.xLength * this.xLength + this.yLength * this.yLength,\n );\n this.diagonalBucketIndex = x + y;\n\n this.index = `${x},${y}`;\n }\n}\n\nexport class DiRectOptimisation {\n private rectangles: Map<string, DivisionRectangle>;\n private buckets: DiagonalBuckets;\n\n public fMin;\n public argMin;\n public tol;\n\n constructor(\n public fcn: ([x, y]: [number, number]) => number,\n public endTolerance = 1e-8,\n public maxIterations = 1000,\n public epsilon = 1e-6,\n ) {\n this.fcn = fcn;\n this.epsilon = epsilon;\n this.endTolerance = endTolerance;\n this.maxIterations = maxIterations;\n\n this.rectangles = new Map();\n this.buckets = new DiagonalBuckets();\n\n const center: [number, number] = [0.5, 0.5];\n const rect = this.rect(0, 0);\n const value = this.fcn(center);\n\n this.buckets.addInterval(new Interval(center, value, rect));\n this.fMin = value;\n this.argMin = center;\n this.tol = rect.diagonal;\n }\n\n registerInterval(interval: Interval) {\n this.buckets.addInterval(interval);\n if (interval.value <= this.fMin) {\n this.fMin = interval.value;\n this.argMin = interval.center;\n this.tol = interval.rectangle.diagonal;\n }\n }\n\n rect(x: number, y: number): DivisionRectangle {\n const index = `${x},${y}`;\n if (!this.rectangles.has(index)) {\n this.rectangles.set(index, new DivisionRectangle(x, y));\n }\n return this.rectangles.get(index)!;\n }\n\n splitInterval(interval: Interval): [Interval, Interval, Interval] {\n let rect: DivisionRectangle;\n let leftCenter: [number, number], rightCenter: [number, number];\n\n const [x, y] = interval.center;\n\n if (interval.rectangle.x <= interval.rectangle.y) {\n rect = this.rect(interval.rectangle.x + 1, interval.rectangle.y);\n leftCenter = [x - rect.xLength, y];\n rightCenter = [x + rect.xLength, y];\n } else {\n rect = this.rect(interval.rectangle.x, interval.rectangle.y + 1);\n leftCenter = [x, y - rect.yLength];\n rightCenter = [x, y + rect.yLength];\n }\n\n return [\n new Interval(leftCenter, this.fcn(leftCenter), rect),\n new Interval(interval.center, interval.value, rect),\n new Interval(rightCenter, this.fcn(rightCenter), rect),\n ];\n }\n\n single_iteration() {\n const intervals = this.buckets.getBottomRightHullIntervals();\n\n // We want to only keep the intervals that can significantly improve the\n // minimum\n\n while (intervals.length >= 2) {\n // Look at the left-most point, it's most heavily constrained by both slope and\n // possible distance.\n const i1 = intervals[0];\n const i2 = intervals[1];\n\n const k =\n (i2.value - i1.value) /\n ((i2.rectangle.diagonal - i1.rectangle.diagonal) / 2.0);\n const potentialFMin = i1.value - (k * i2.value) / 2.0;\n if ((this.fMin - potentialFMin) / Math.abs(this.fMin) < this.epsilon) {\n intervals.shift();\n } else {\n // The points to the right are even better than this one, bail out.\n break;\n }\n }\n\n intervals.forEach((interval) => {\n this.buckets.removeInterval(interval);\n });\n\n for (const interval of intervals) {\n const [left, middle, right] = this.splitInterval(interval);\n\n this.registerInterval(left);\n this.registerInterval(middle);\n this.registerInterval(right);\n }\n }\n\n run() {\n let i = 0;\n while (this.tol > this.endTolerance / 2) {\n this.single_iteration();\n i++;\n if (i > this.maxIterations) {\n break;\n }\n }\n return {\n fMin: this.fMin,\n argMin: this.argMin,\n tol: this.tol,\n iterations: i,\n };\n }\n}\n\nclass Interval {\n constructor(\n public center: [number, number],\n public value: number,\n public rectangle: DivisionRectangle,\n ) {}\n}\n\nexport function findGlobalMinimum(\n fun: (x: [number, number]) => number,\n tolerance = 1e-8,\n maxIterations = 1000,\n epsilon = 1e-6,\n) {\n const optimiser = new DiRectOptimisation(\n fun,\n tolerance,\n maxIterations,\n epsilon,\n );\n return optimiser.run();\n}\n","import { Vector } from \"../../definitions.js\";\nimport { squareDistance } from \"../../vectorOperations.js\";\nimport { findGlobalMinimum } from \"../optimisation/DiRect.js\";\n\ninterface WithParamPoint {\n paramPoint(t: number): Vector;\n}\n\nexport function genericDistance(\n segment1: WithParamPoint,\n segment2: WithParamPoint,\n precision = 1e-9,\n): number {\n const result = findGlobalMinimum((t) => {\n const p1 = segment1.paramPoint(t[0]);\n const p2 = segment2.paramPoint(t[1]);\n return squareDistance(p1, p2);\n }, precision);\n return Math.sqrt(result.fMin);\n}\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { lineLineDistance } from \"./lineLineDistance.js\";\nimport { lineArcDistance } from \"./lineArcDistance.js\";\nimport { arcArcDistance } from \"./arcArcDistance.js\";\nimport type { Segment } from \"../../models/segments/Segment.js\";\nimport { genericDistance } from \"./genericDistance.js\";\n\nexport function distance(segment1: Segment, segment2: Segment): number {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n return lineLineDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Line && segment2 instanceof Arc) {\n return lineArcDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Line) {\n return lineArcDistance(segment2, segment1);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Arc) {\n return arcArcDistance(segment1, segment2);\n }\n\n return genericDistance(segment1, segment2);\n}\n","import { CubicBezier } from \"../../models/segments/CubicBezier\";\nimport { QuadraticBezier } from \"../../models/segments/QuadraticBezier\";\nimport {\n angle,\n dotProduct,\n perpendicular,\n subtract,\n} from \"../../vectorOperations\";\n\n// This is based on https://github.com/Pomax/bezierjs\n\ntype Bezier = CubicBezier | QuadraticBezier;\n\nexport type SafeCubicBezier = CubicBezier & { readonly __safe: unique symbol };\nexport type SafeQuadraticBezier = QuadraticBezier & {\n readonly __safe: unique symbol;\n};\n\ntype SafeBezier = SafeCubicBezier | SafeQuadraticBezier;\n\nexport type SafeVersion<T> = T extends CubicBezier\n ? SafeCubicBezier\n : T extends QuadraticBezier\n ? SafeQuadraticBezier\n : never;\n\nfunction isOffsetSafeBezier(segment: Bezier): segment is SafeBezier {\n if (segment instanceof CubicBezier) {\n // We check that both control points are on the same side of the chord\n const chord = subtract(segment.lastPoint, segment.firstPoint);\n const v2 = subtract(segment.firstControlPoint, segment.firstPoint);\n const v3 = subtract(segment.lastControlPoint, segment.firstPoint);\n\n const a1 = angle(chord, v2);\n const a2 = angle(chord, v3);\n\n if ((a1 > 0 && a2 < 0) || (a1 < 0 && a2 > 0)) return false;\n }\n\n const n1 = perpendicular(segment.tangentAtFirstPoint);\n const n2 = perpendicular(segment.tangentAtLastPoint);\n\n let s = dotProduct(n1, n2);\n return Math.abs(Math.acos(s)) < Math.PI / 3;\n}\n\nfunction _splitIntoOffsetSafeBezier(\n segment: Bezier,\n): SafeVersion<typeof segment>[] {\n if (isOffsetSafeBezier(segment)) return [segment];\n\n const [left, right] = segment.splitAtParameters([0.5]);\n return [\n ..._splitIntoOffsetSafeBezier(left),\n ..._splitIntoOffsetSafeBezier(right),\n ];\n}\n\nexport function splitIntoOffsetSafeBezier(\n segment: Bezier,\n): SafeVersion<typeof segment>[] {\n if (isOffsetSafeBezier(segment)) return [segment];\n\n const segments = segment.splitAtParameters(segment.getParametersOfExtrema());\n return segments.flatMap(_splitIntoOffsetSafeBezier);\n}\n","import { CubicBezier } from \"../../models/segments/CubicBezier\";\nimport { TransformationMatrix } from \"../../models/TransformationMatrix\";\nimport type { EllipseArc } from \"../../models/segments/EllipseArc\";\n\nexport function approximateEllipticalArcAsCubicBeziers(\n ellipseArc: EllipseArc,\n): CubicBezier[] {\n const sweepAngle = ellipseArc.deltaAngle;\n const segments = Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2));\n const anglePerSegment = sweepAngle / segments;\n const kappa = (4 * Math.tan(anglePerSegment / 4)) / 3;\n\n const orientation = ellipseArc.clockwise ? -1 : 1;\n\n const angles = Array.from(\n { length: segments + 1 },\n (_, i) => ellipseArc.firstAngle + i * anglePerSegment * orientation,\n );\n\n const zippedAngles = angles\n .slice(0, -1)\n .map((angle, index) => [angle, angles[index + 1]]);\n\n return zippedAngles.map(([startAngle, endAngle]) => {\n const cosStart = Math.cos(startAngle);\n const sinStart = Math.sin(startAngle);\n const cosEnd = Math.cos(endAngle);\n const sinEnd = Math.sin(endAngle);\n\n const [centerX, centerY] = ellipseArc.center;\n const r = ellipseArc.minorRadius;\n const R = ellipseArc.majorRadius;\n\n const rotationMatrix = new TransformationMatrix().rotate(\n ellipseArc.tiltAngle,\n ellipseArc.center,\n );\n const rotateInFrame = (p: [number, number]) => rotationMatrix.transform(p);\n\n const p0 = rotateInFrame([centerX + R * cosStart, centerY + r * sinStart]);\n const c0 = rotateInFrame([\n centerX + R * (cosStart - kappa * sinStart * orientation),\n centerY + r * (sinStart + kappa * cosStart * orientation),\n ]);\n const c1 = rotateInFrame([\n centerX + R * (cosEnd + kappa * sinEnd * orientation),\n centerY + r * (sinEnd - kappa * cosEnd * orientation),\n ]);\n const p1 = rotateInFrame([centerX + R * cosEnd, centerY + r * sinEnd]);\n\n return new CubicBezier(p0, p1, c0, c1);\n });\n}\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Loop } from \"../../models/Loop.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport {\n crossProduct,\n sameVector,\n squareDistance,\n subtract,\n} from \"../../vectorOperations\";\nimport { distance } from \"../distances\";\nimport {\n offsetSegment,\n DegenerateSegment,\n OffsettableSegment,\n} from \"./offsetSegment.js\";\nimport { Vector } from \"../../definitions.js\";\nimport { Arc, tangentArc } from \"../../models/segments/Arc.js\";\nimport { Diagram } from \"../../models/Diagram.js\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport { Figure } from \"../../models/Figure.js\";\nimport { stitchSegments } from \"../stitchSegments.js\";\nimport { Stroke } from \"../../models/Stroke.js\";\nimport { Strand } from \"../../models/Strand.js\";\nimport { splitIntoOffsetSafeBezier } from \"../conversions/bezierToSafeBezier.js\";\nimport {\n CubicBezier,\n EllipseArc,\n QuadraticBezier,\n} from \"../../models/exports.js\";\nimport { approximateEllipticalArcAsCubicBeziers } from \"../conversions/ellipseToBezier.js\";\n\n\nconst PRECISION = 1e-8;\n\nexport const transformForOffset = (\n segments: Segment[],\n): OffsettableSegment[] => {\n return segments.flatMap((segment: Segment): OffsettableSegment[] => {\n if (segment instanceof Line) {\n return [segment];\n } else if (segment instanceof Arc) {\n return [segment];\n } else if (segment instanceof EllipseArc) {\n return approximateEllipticalArcAsCubicBeziers(segment).flatMap((c) =>\n splitIntoOffsetSafeBezier(c),\n );\n } else if (\n segment instanceof QuadraticBezier ||\n segment instanceof CubicBezier\n ) {\n return splitIntoOffsetSafeBezier(segment);\n } else {\n return [new Line(segment.firstPoint, segment.lastPoint)];\n }\n });\n};\n\nexport function rawOffsets(\n segmentsToOffset: OffsettableSegment[],\n offset: number,\n loop = true,\n): Segment[] {\n const offsetSegments: OffsetSegmentPair[] = segmentsToOffset.map((c) => ({\n offset: offsetSegment(c, offset),\n original: c,\n }));\n\n // Ideally we would use the length of the segment to make sure it is\n // not only a point, but the algo we have access to are a bit to\n // convoluted to be usable here\n\n const offsettedArray: Segment[] = [];\n\n let savedLastSegment = loop ? null : offsetSegments.at(-1)!;\n\n let previousSegment = loop ? offsetSegments.at(-1) : null;\n\n // We have no offseted segments\n if (offsettedArray.length === 1) return offsettedArray;\n\n const appendSegment = (segment: OffsetSegmentPair) => {\n if (!savedLastSegment) {\n savedLastSegment = segment;\n } else if (!(segment.offset instanceof DegenerateSegment)) {\n offsettedArray.push(segment.offset);\n } else if (\n !sameVector(segment.offset.firstPoint, segment.offset.lastPoint)\n ) {\n offsettedArray.push(\n new Line(segment.offset.firstPoint, segment.offset.lastPoint),\n );\n }\n };\n const iterateOffsetSegments = function* (): Generator<OffsetSegmentPair> {\n for (const segment of offsetSegments.slice(0, -1)) {\n yield segment;\n }\n // This should never happen\n if (!savedLastSegment) throw new Error(\"Bug in the offset algorithm\");\n yield savedLastSegment;\n };\n\n for (const segment of iterateOffsetSegments()) {\n if (!previousSegment) {\n previousSegment = segment;\n continue;\n }\n const previousLastPoint = previousSegment.offset.lastPoint;\n const firstPoint = segment.offset.firstPoint;\n\n // When the offset segments do still touch we do nothing\n if (sameVector(previousLastPoint, firstPoint)) {\n appendSegment(previousSegment);\n previousSegment = segment;\n continue;\n }\n\n let intersections: Vector[] = [];\n\n if (\n !(previousSegment.offset instanceof DegenerateSegment) &&\n !(segment.offset instanceof DegenerateSegment)\n ) {\n // When the offset segments intersect we cut them and save them at\n const { intersections: pointIntersections, overlaps } =\n findIntersectionsAndOverlaps(\n previousSegment.offset,\n segment.offset,\n PRECISION / 100,\n );\n intersections = [\n ...pointIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ];\n }\n\n if (intersections.length > 0) {\n let intersection = intersections[0];\n if (intersections.length > 1) {\n // We choose the intersection point the closest to the end of the\n // original segment endpoint (why? not sure, following\n // https://github.com/jbuckmccready/cavalier_contours/)\n\n const originalEndpoint = previousSegment?.original.lastPoint;\n const distances = intersections.map((i) =>\n squareDistance(i, originalEndpoint),\n );\n intersection = intersections[distances.indexOf(Math.min(...distances))];\n }\n\n // We need to be a lot more careful here with multiple intersections\n // as well as cases where segments overlap\n\n const splitPreviousSegment = (previousSegment.offset as Segment).splitAt([\n intersection,\n ])[0];\n const splitSegment = (segment.offset as Segment)\n .splitAt([intersection])\n .at(-1);\n\n if (!splitSegment) throw new Error(\"Bug in the splitting algo in offset\");\n\n appendSegment({\n offset: splitPreviousSegment,\n original: previousSegment.original,\n });\n previousSegment = { offset: splitSegment, original: segment.original };\n continue;\n }\n\n // When the offset segments do not intersect we link them with an arc of\n // radius offset\n const center = previousSegment.original.lastPoint;\n const clockwise =\n crossProduct(\n subtract(firstPoint, center),\n subtract(previousLastPoint, center),\n ) > 0;\n\n const joiner = new Arc(previousLastPoint, firstPoint, center, clockwise);\n //const joiner = new Line(previousLastPoint, firstPoint);\n\n appendSegment(previousSegment);\n offsettedArray.push(joiner);\n previousSegment = segment;\n }\n\n if (previousSegment) appendSegment(previousSegment);\n return offsettedArray;\n}\n\ninterface OffsetSegmentPair {\n offset: Segment | DegenerateSegment;\n original: Segment;\n}\n\nfunction findOffsetSelfIntersections(\n segments: Segment[],\n): Map<number, Vector[]> {\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections: Map<number, Vector[]> = new Map();\n const updateIntersections = (index: number, newPoints: Vector[]) => {\n const intersections = allIntersections.get(index) || [];\n allIntersections.set(index, [...intersections, ...newPoints]);\n };\n\n segments.forEach((firstSegment, firstIndex) => {\n segments.slice(firstIndex + 1).forEach((secondSegment, secondIndex) => {\n const { intersections: rawIntersections, overlaps } =\n findIntersectionsAndOverlaps(firstSegment, secondSegment, PRECISION);\n\n const intersections = [\n ...rawIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ].filter((intersection) => {\n const onFirstSegmentExtremity =\n sameVector(intersection, firstSegment.firstPoint) ||\n sameVector(intersection, firstSegment.lastPoint);\n\n const onSecondSegmentExtremity =\n sameVector(intersection, secondSegment.firstPoint) ||\n sameVector(intersection, secondSegment.lastPoint);\n\n return !(onFirstSegmentExtremity && onSecondSegmentExtremity);\n });\n\n if (!intersections.length) return;\n\n updateIntersections(firstIndex, intersections);\n updateIntersections(secondIndex + firstIndex + 1, intersections);\n });\n });\n\n return allIntersections;\n}\n\nfunction findIntersections(\n segments: Segment[],\n intersectWith: Segment[],\n): Map<number, Vector[]> {\n const allIntersections: Map<number, Vector[]> = new Map();\n const updateIntersections = (index: number, newPoints: Vector[]) => {\n const intersections = allIntersections.get(index) || [];\n allIntersections.set(index, [...intersections, ...newPoints]);\n };\n\n segments.forEach((firstSegment, firstIndex) => {\n intersectWith.forEach((segmentsToCheck) => {\n const { intersections: rawIntersections, overlaps } =\n findIntersectionsAndOverlaps(firstSegment, segmentsToCheck, PRECISION);\n\n const intersections = [\n ...rawIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ].filter((intersection) => {\n return (\n sameVector(intersection, firstSegment.firstPoint) ||\n sameVector(intersection, firstSegment.lastPoint)\n );\n });\n\n if (!intersections.length) return;\n\n updateIntersections(firstIndex, intersections);\n });\n });\n\n return allIntersections;\n}\n\nfunction findEndIntersections(\n segments: Segment[],\n strand: Strand,\n offset: number,\n) {\n const circle = new Loop([\n new Arc([-offset, 0], [offset, 0], [0, 0], true),\n new Arc([offset, 0], [-offset, 0], [0, 0], true),\n ]);\n\n const startCircle = circle.translateTo(strand.firstPoint);\n const endCircle = circle.translateTo(strand.lastPoint);\n\n return findIntersections(segments, [\n ...startCircle.segments,\n ...endCircle.segments,\n ]);\n}\n\nfunction mergeIntersectionMaps(maps: Map<number, Vector[]>[]) {\n const mergedMap = new Map<number, Vector[]>(maps[0]);\n maps.forEach((map) => {\n for (const [key, value] of map) {\n const previousValue = mergedMap.get(key) || [];\n mergedMap.set(key, [...previousValue, ...value]);\n }\n });\n return mergedMap;\n}\n\nfunction splitSegmentsAtIntersections(\n intersections: Map<number, Vector[]>,\n segments: Segment[],\n): Segment[] {\n return segments.flatMap((segment, index) => {\n if (!intersections.has(index)) return segment;\n\n const segmentIntersections = intersections.get(index);\n if (!segmentIntersections) return segment;\n\n return segment.splitAt(segmentIntersections);\n });\n}\n\nfunction pruneDegenerateSegments(\n segments: Segment[],\n originalStroke: Stroke,\n offset: number,\n): Segment[] {\n // We remove all the segments that are closer to the original segment than the offset\n return segments.filter((segment) => {\n const closeSegment = originalStroke.segments.some((c) => {\n return distance(c, segment) < Math.abs(offset) - PRECISION;\n });\n return !closeSegment;\n });\n}\n\nexport function offsetLoop(loop: Loop, offset: number): Diagram {\n const correctedOffset = loop.clockwise ? offset : -offset;\n const transformedSegments = transformForOffset(loop.segments);\n const offsettedArray = rawOffsets(transformedSegments, correctedOffset);\n\n if (offsettedArray.length < 2) return new Diagram();\n\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections = findOffsetSelfIntersections(offsettedArray);\n\n if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n /* this was in the replicad algorithm - not sure why\n if (!loop.intersects(offsettedLoop)) return offsettedLoop;\n return new Diagram();\n */\n }\n const splitSegments = splitSegmentsAtIntersections(\n allIntersections,\n offsettedArray,\n );\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = pruneDegenerateSegments(splitSegments, loop, offset);\n\n if (!prunedSegments.length) return new Diagram();\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n const newLoops = segmentsGrouped\n .filter((c) => c.length > 1)\n .filter((c) => sameVector(c[0].firstPoint, c.at(-1)!.lastPoint))\n .map((c) => new Loop(c));\n\n if (!newLoops.length) return new Diagram();\n return new Diagram(newLoops.map((l) => new Figure(l)));\n}\n\nexport function offsetStrand(strand: Strand, offset: number): Stroke[] {\n const transformedSegments = transformForOffset(strand.segments);\n const offsettedArray = rawOffsets(transformedSegments, offset, false);\n const backOffsettedArray = rawOffsets(transformedSegments, -offset, false);\n\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections = mergeIntersectionMaps([\n findOffsetSelfIntersections(offsettedArray),\n findIntersections(offsettedArray, backOffsettedArray),\n findEndIntersections(offsettedArray, strand, offset),\n ]);\n\n if (!allIntersections.size) {\n return [new Strand(offsettedArray)];\n }\n const splitSegments = splitSegmentsAtIntersections(\n allIntersections,\n offsettedArray,\n );\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = pruneDegenerateSegments(splitSegments, strand, offset);\n\n if (!prunedSegments.length) return [];\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n return segmentsGrouped.map((c) => {\n if (sameVector(c[0].firstPoint, c.at(-1)!.lastPoint)) return new Loop(c);\n return new Strand(c);\n });\n}\n\nexport function outlineStrand(\n strand: Strand,\n width: number,\n endCap: \"round\" | \"butt\" = \"round\",\n): Diagram {\n const offset = width / 2;\n const transformedSegments = transformForOffset(strand.segments);\n const frontOffsettedArray = rawOffsets(transformedSegments, offset, false);\n const backOffsettedArray = rawOffsets(\n transformedSegments,\n -offset,\n false,\n ).map((s) => s.reverse());\n backOffsettedArray.reverse();\n\n const makeJoiner = (fromSegment: Segment, toSegment: Segment) => {\n if (endCap === \"round\") {\n return tangentArc(\n fromSegment.lastPoint,\n toSegment.firstPoint,\n fromSegment.tangentAtLastPoint,\n );\n }\n return new Line(fromSegment.lastPoint, toSegment.firstPoint);\n };\n\n const offsettedArray = [\n ...frontOffsettedArray,\n makeJoiner(\n frontOffsettedArray[frontOffsettedArray.length - 1],\n backOffsettedArray[0],\n ),\n ...backOffsettedArray,\n makeJoiner(\n backOffsettedArray[backOffsettedArray.length - 1],\n frontOffsettedArray[0],\n ),\n ];\n\n const allIntersections = findOffsetSelfIntersections(offsettedArray);\n\n if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n }\n const splitSegments = splitSegmentsAtIntersections(\n allIntersections,\n offsettedArray,\n );\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = pruneDegenerateSegments(splitSegments, strand, offset);\n\n if (!prunedSegments.length) return new Diagram();\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n const newLoops = segmentsGrouped\n .filter((c) => c.length > 1)\n .filter((c) => sameVector(c[0].firstPoint, c.at(-1)!.lastPoint))\n .map((c) => new Loop(c));\n\n if (!newLoops.length) return new Diagram();\n return new Diagram(newLoops.map((l) => new Figure(l)));\n}\n","import { Figure } from \"../../models/Figure\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { cut, fuseAll } from \"../../booleanOperations\";\nimport { offsetLoop } from \"./offsetStroke\";\n\nexport function offsetFigures(\n figures: Figure[],\n offsetDistance: number,\n): Diagram {\n const offsetFigures = figures.map((figure) => {\n const innerShape = fuseAll(\n figure.holes.map((l) => offsetLoop(l, offsetDistance)),\n );\n return cut(offsetLoop(figure.contour, offsetDistance), innerShape);\n });\n\n return fuseAll(offsetFigures);\n}\n\nexport function outlineStrokeFigures(\n figures: Figure[],\n width: number,\n): Diagram {\n const absOffset = Math.abs(width / 2);\n\n const offsetFigures = figures.map((figure) =>\n fuseAll(\n figure.allLoops.map((l) => {\n return cut(offsetLoop(l, absOffset), offsetLoop(l, -absOffset));\n }),\n ),\n );\n\n return fuseAll(offsetFigures);\n}\n","import {\n offsetFigures,\n outlineStrokeFigures,\n} from \"./algorithms/offsets/offsetFigure\";\nimport { outlineStrand } from \"./algorithms/offsets/offsetStroke.js\";\nimport { Strand } from \"./models/Strand.js\";\nimport { Diagram } from \"./models/Diagram.js\";\nimport { Figure } from \"./models/Figure.js\";\nimport { Loop } from \"./models/Loop.js\";\nimport { listOfFigures } from \"./utils/listOfFigures.js\";\n\nexport function offset(\n shape: Diagram | Figure | Loop,\n offsetDistance: number,\n): Diagram {\n return offsetFigures(listOfFigures(shape), offsetDistance);\n}\n\nexport function outlineStroke(\n shape: Diagram | Figure | Loop | Strand,\n outlineDistance: number,\n { endCap = \"round\" }: { endCap?: \"butt\" | \"round\" } = {},\n): Diagram {\n if (shape instanceof Strand) {\n return outlineStrand(shape, outlineDistance, endCap);\n }\n return outlineStrokeFigures(listOfFigures(shape), outlineDistance);\n}\n","import { filletSegments } from \"./algorithms/filletSegments\";\nimport { Vector } from \"./definitions\";\nimport { Diagram, Figure, Loop, Segment, Strand } from \"./models/exports\";\nimport { angle, DEG2RAD, distance, sameVector } from \"./vectorOperations\";\n\nexport type FilterFcn<Type> = {\n element: Type;\n};\n\nexport abstract class FilterList<Type> {\n protected filters: (({ element }: FilterFcn<Type>) => boolean)[];\n\n abstract shouldKeep(t: Type): boolean;\n\n constructor() {\n this.filters = [];\n }\n\n delete() {\n this.filters = [];\n }\n\n /**\n * Combine logically a set of filter with an AND operation.\n *\n */\n and(findersList: ((f: this) => this)[]): this {\n findersList.forEach((f) => f(this));\n return this;\n }\n\n /**\n * Invert the result of a particular filter\n *\n */\n not(finderFun: (f: this) => this): this {\n const finder = new (<any>this.constructor)() as this;\n finderFun(finder);\n\n const notFilter = ({ element }: { element: Type }) =>\n !finder.shouldKeep(element);\n this.filters.push(notFilter);\n\n return this;\n }\n\n /**\n * Combine logically a set of filter with an OR operation.\n *\n */\n either(findersList: ((f: this) => this)[]): this {\n const builtFinders = findersList.map((finderFunction) => {\n const finder = new (<any>this.constructor)() as this;\n finderFunction(finder);\n return finder;\n });\n\n const eitherFilter = ({ element }: { element: Type }) =>\n builtFinders.some((finder) => finder.shouldKeep(element));\n this.filters.push(eitherFilter);\n\n return this;\n }\n}\n\nexport type Corner = {\n firstCurve: Segment;\n secondCurve: Segment;\n point: Vector;\n};\n\nconst PI_2 = 2 * Math.PI;\nconst positiveHalfAngle = (angle: number) => {\n const limitedAngle = angle % PI_2;\n\n const coterminalAngle = limitedAngle < 0 ? limitedAngle + PI_2 : limitedAngle;\n if (coterminalAngle < Math.PI) return coterminalAngle;\n if (coterminalAngle === Math.PI) return 0;\n return Math.abs(coterminalAngle - PI_2);\n};\n\nexport class CornerFilter extends FilterList<Corner> {\n clone(): CornerFilter {\n const ef = new CornerFilter();\n ef.filters = [...this.filters];\n return ef;\n }\n\n /**\n * Filter to find corner that have their point are in the list.\n *\n */\n inList(elementList: Vector[]): this {\n const elementInList = ({ element }: { element: Corner }) => {\n return !!elementList.find((e) => sameVector(e, element.point));\n };\n this.filters.push(elementInList);\n return this;\n }\n\n /**\n * Filter to find elements that are at a specified distance from a point.\n *\n */\n atDistance(dist: number, point: Vector = [0, 0]): this {\n function elementAtDistance({ element }: { element: Corner }) {\n return Math.abs(distance(point, element.point) - dist) < 1e-9;\n }\n this.filters.push(elementAtDistance);\n return this;\n }\n\n /**\n * Filter to find elements that contain a certain point\n *\n * @category Filter\n */\n atPoint(point: Vector): this {\n function elementAtPoint({ element }: { element: Corner }) {\n return sameVector(point, element.point);\n }\n this.filters.push(elementAtPoint);\n return this;\n }\n\n /**\n * Filter to find elements that are within a box\n *\n * @category Filter\n */\n inBox(corner1: Vector, corner2: Vector) {\n const [x1, y1] = corner1;\n const [x2, y2] = corner2;\n\n const minX = Math.min(x1, x2);\n const maxX = Math.max(x1, x2);\n\n const minY = Math.min(y1, y2);\n const maxY = Math.max(y1, y2);\n\n function elementInBox({ element }: { element: Corner }) {\n const [x, y] = element.point;\n return x >= minX && x <= maxX && y >= minY && y <= maxY;\n }\n this.filters.push(elementInBox);\n return this;\n }\n\n /**\n * Filter to find corner that a certain angle between them - only between\n * 0 and 180.\n *\n */\n ofAngle(theta: number) {\n function elementOfAngle({ element }: { element: Corner }) {\n const tgt1 = element.firstCurve.tangentAtLastPoint;\n const tgt2 = element.secondCurve.tangentAtFirstPoint;\n\n return (\n Math.abs(\n positiveHalfAngle(angle(tgt1, tgt2)) -\n positiveHalfAngle(DEG2RAD * theta),\n ) < 1e-9\n );\n }\n\n this.filters.push(elementOfAngle);\n return this;\n }\n\n above(yValue = 0) {\n function elementAbove({ element }: { element: Corner }) {\n return element.point[1] > yValue;\n }\n this.filters.push(elementAbove);\n return this;\n }\n\n below(yValue = 0) {\n function elementBelow({ element }: { element: Corner }) {\n return element.point[1] < yValue;\n }\n this.filters.push(elementBelow);\n return this;\n }\n\n leftOf(xValue = 0) {\n function elementLeftOf({ element }: { element: Corner }) {\n return element.point[0] < xValue;\n }\n this.filters.push(elementLeftOf);\n return this;\n }\n\n rightOf(xValue = 0) {\n function elementRightOf({ element }: { element: Corner }) {\n return element.point[0] > xValue;\n }\n this.filters.push(elementRightOf);\n return this;\n }\n\n shouldKeep(element: Corner): boolean {\n const shouldKeep = this.filters.every((filter) => filter({ element }));\n return shouldKeep;\n }\n\n asFilterFun() {\n return this.shouldKeep.bind(this);\n }\n}\n\ntype CornerMaker = (seg1: Segment, seg2: Segment, radius: number) => Segment[];\n\nfunction modifyStroke(\n makeCorner: CornerMaker,\n stroke: Loop | Strand,\n radius: number,\n filter: (c: Corner) => boolean = () => true,\n): Loop | Strand {\n const segments = [stroke.segments[0]];\n\n const addModifiedCorner = (firstCurve: Segment, secondCurve: Segment) => {\n if (filter({ firstCurve, secondCurve, point: firstCurve.lastPoint })) {\n segments.push(...makeCorner(firstCurve, secondCurve, radius));\n } else {\n segments.push(firstCurve, secondCurve);\n }\n };\n\n stroke.segments.slice(1).forEach((secondCurve) => {\n const firstCurve = segments.pop();\n if (!firstCurve) throw new Error(\"Bug in the stroke filletting algo\");\n addModifiedCorner(firstCurve, secondCurve);\n });\n\n const lastCurve = segments.at(-1);\n if (!lastCurve) throw new Error(\"Bug in the stroke corner algo\");\n\n if (stroke instanceof Loop) {\n const firstCurve = segments.pop();\n const secondCurve = segments.shift();\n if (!firstCurve || !secondCurve)\n throw new Error(\"Bug in the filletting algo\");\n addModifiedCorner(firstCurve, secondCurve);\n\n return new Loop(segments, { ignoreChecks: true });\n } else {\n return new Strand(segments, { ignoreChecks: true });\n }\n}\n\nexport type Shape = Loop | Strand | Figure | Diagram;\nexport type FilterArg = CornerFilter | ((c: CornerFilter) => CornerFilter);\n\nfunction fillet<T extends Shape>(\n shape: T,\n radius: number,\n filter?: FilterArg,\n): T;\nfunction fillet(shape: Loop, radius: number, filter?: FilterArg): Loop;\nfunction fillet(shape: Strand, radius: number, filter?: FilterArg): Strand;\nfunction fillet(shape: Figure, radius: number, filter?: FilterArg): Figure;\nfunction fillet(shape: Diagram, radius: number, filter?: FilterArg): Diagram;\n\nfunction fillet(\n shape: Shape,\n radius: number,\n filter?: CornerFilter | ((c: CornerFilter) => CornerFilter),\n): Shape {\n const filterObj =\n typeof filter === \"function\" ? filter(new CornerFilter()) : filter;\n const filterFcn = filterObj && filterObj.asFilterFun();\n\n if (shape instanceof Loop || shape instanceof Strand) {\n return modifyStroke(filletSegments, shape, radius, filterFcn);\n }\n\n if (shape instanceof Figure) {\n const newContour = fillet(shape.contour, radius, filterObj);\n const newHoles = shape.holes.map((l) => fillet(l, radius, filterObj));\n\n return new Figure(newContour, newHoles, { ignoreChecks: true });\n }\n\n if (shape instanceof Diagram) {\n const newFigs = shape.figures.map((f) => fillet(f, radius, filterObj));\n return new Diagram(newFigs, { ignoreChecks: true });\n }\n\n throw new Error(\"invalid shape to fillet\");\n}\n\nfunction chamfer<T extends Shape>(\n shape: T,\n radius: number,\n filter?: FilterArg,\n): T;\nfunction chamfer(shape: Loop, radius: number, filter?: FilterArg): Loop;\nfunction chamfer(shape: Strand, radius: number, filter?: FilterArg): Strand;\nfunction chamfer(shape: Figure, radius: number, filter?: FilterArg): Figure;\nfunction chamfer(shape: Diagram, radius: number, filter?: FilterArg): Diagram;\n\nfunction chamfer(shape: Shape, radius: number, filter?: FilterArg): Shape {\n const filterObj =\n typeof filter === \"function\" ? filter(new CornerFilter()) : filter;\n const filterFcn = filterObj && filterObj.asFilterFun();\n\n if (shape instanceof Loop || shape instanceof Strand) {\n return modifyStroke(filletSegments, shape, radius, filterFcn);\n }\n\n if (shape instanceof Figure) {\n const newContour = chamfer(shape.contour, radius, filterObj);\n const newHoles = shape.holes.map((l) => chamfer(l, radius, filterObj));\n\n return new Figure(newContour, newHoles, { ignoreChecks: true });\n }\n\n if (shape instanceof Diagram) {\n const newFigs = shape.figures.map((f) => chamfer(f, radius, filterObj));\n return new Diagram(newFigs, { ignoreChecks: true });\n }\n throw new Error(\"invalid shape to chamfer\");\n}\n\nclass CornerSelector<T extends Shape> extends CornerFilter {\n constructor(private readonly shape: T) {\n super();\n }\n\n fillet(radius: number): T {\n return fillet<T>(this.shape, radius, this.clone());\n }\n\n chamfer(radius: number): T {\n return chamfer<T>(this.shape, radius, this.clone());\n }\n}\n\nfunction selectCorners<T extends Shape>(s: T) {\n return new CornerSelector<T>(s);\n}\n\nexport { fillet, chamfer, selectCorners };\n","import type { Vector } from \"../../definitions.js\";\nimport type { Segment } from \"../../models/segments/Segment.js\";\nimport {\n DEG2RAD,\n dotProduct,\n length,\n normalize,\n subtract,\n} from \"../../vectorOperations.js\";\n\nexport type TesselateSegmentOptions = {\n maxAngle?: number;\n maxDepth?: number;\n};\n\nconst DEFAULT_MAX_ANGLE = 1 * DEG2RAD;\nconst DEFAULT_MAX_DEPTH = 24;\n\nfunction unitTangent(\n segment: Segment,\n t: number,\n fallback: Vector,\n precision: number,\n): Vector {\n const grad = segment.gradientAt(t);\n if (length(grad) <= precision) return fallback;\n return normalize(grad);\n}\n\nfunction tesselateSegmentRange(\n segment: Segment,\n t0: number,\n t1: number,\n options: Required<TesselateSegmentOptions>,\n cosTol: number,\n depth: number,\n): Vector[] {\n const p0 = segment.paramPoint(t0);\n const p1 = segment.paramPoint(t1);\n const chord = subtract(p1, p0);\n const chordLength = length(chord);\n\n if (chordLength <= segment.precision || depth >= options.maxDepth) {\n return [p0, p1];\n }\n\n const chordDir: Vector = [chord[0] / chordLength, chord[1] / chordLength];\n const tm = (t0 + t1) * 0.5;\n const tan0 = unitTangent(segment, t0, chordDir, segment.precision);\n const tanm = unitTangent(segment, tm, chordDir, segment.precision);\n const tan1 = unitTangent(segment, t1, chordDir, segment.precision);\n\n const cos0 = dotProduct(tan0, tanm);\n const cos1 = dotProduct(tanm, tan1);\n\n if (cos0 >= cosTol && cos1 >= cosTol) {\n return [p0, p1];\n }\n\n const pm = segment.paramPoint(tm);\n const left =\n cos0 >= cosTol\n ? [p0, pm]\n : tesselateSegmentRange(segment, t0, tm, options, cosTol, depth + 1);\n const right =\n cos1 >= cosTol\n ? [pm, p1]\n : tesselateSegmentRange(segment, tm, t1, options, cosTol, depth + 1);\n\n return [...left.slice(0, -1), ...right];\n}\n\nexport function tesselateSegment(\n segment: Segment,\n options: TesselateSegmentOptions = {},\n): Vector[] {\n const resolved: Required<TesselateSegmentOptions> = {\n maxAngle: options.maxAngle ?? DEFAULT_MAX_ANGLE,\n maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,\n };\n\n const cosTol = Math.cos(resolved.maxAngle);\n return tesselateSegmentRange(segment, 0, 1, resolved, cosTol, 0);\n}\n","import { Figure } from \"../../models/Figure\";\nimport { Strand } from \"../../models/Strand\";\nimport { Loop } from \"../../models/Loop\";\nimport { Diagram } from \"../../models/Diagram\";\nimport type { Segment } from \"../../models/segments/Segment\";\nimport { isSegment } from \"../../models/segments/utils/isSegment\";\n\ntype SegmentsMap = (s: Segment) => Segment[];\n\nexport function convertDiagramTo(diagram: Diagram, segmentsMap: SegmentsMap) {\n return new Diagram(\n diagram.figures.map((figure) => convertFigureTo(figure, segmentsMap)),\n );\n}\n\nexport function convertFigureTo(\n figure: Figure,\n segmentsMap: SegmentsMap,\n): Figure {\n return new Figure(\n convertLoopTo(figure.contour, segmentsMap),\n figure.holes.map((l) => convertLoopTo(l, segmentsMap)),\n );\n}\n\nexport function convertLoopTo(loop: Loop, segmentsMap: SegmentsMap): Loop {\n return new Loop(convertSegmentsTo(loop.segments, segmentsMap));\n}\n\nexport function converStrandTo(\n strand: Strand,\n segmentsMap: SegmentsMap,\n): Strand {\n return new Strand(convertSegmentsTo(strand.segments, segmentsMap));\n}\n\nexport function convertSegmentsTo(\n segments: Segment[],\n segmentsMap: SegmentsMap,\n): Segment[] {\n return segments.flatMap(segmentsMap);\n}\n\nfunction genericConversion(\n shape: Diagram | Figure | Loop | Strand | Segment,\n segmentsMap: SegmentsMap,\n): Diagram | Figure | Loop | Strand | Segment[] {\n if (shape instanceof Diagram) {\n return convertDiagramTo(shape, segmentsMap);\n }\n if (shape instanceof Figure) {\n return convertFigureTo(shape, segmentsMap);\n }\n\n if (shape instanceof Loop) {\n return convertLoopTo(shape, segmentsMap);\n }\n\n if (shape instanceof Strand) {\n return converStrandTo(shape, segmentsMap);\n }\n\n if (isSegment(shape)) {\n return convertSegmentsTo([shape], segmentsMap);\n }\n\n throw new Error(\"Unsupported shape type\");\n}\n\nexport { genericConversion };\n","import type { Vector } from \"./definitions.js\";\nimport { Line } from \"./models/segments/Line.js\";\nimport { Segment } from \"./models/segments/Segment.js\";\nimport { Diagram, Figure, Loop, Strand } from \"./models/exports\";\nimport { tesselateSegment } from \"./algorithms/tesselate/tesselateSegment.js\";\nimport type { TesselateSegmentOptions } from \"./algorithms/tesselate/tesselateSegment.js\";\nimport { genericConversion } from \"./algorithms/conversions/helpers.js\";\nimport { sameVector } from \"./vectorOperations.js\";\n\nfunction linesFromPoints(points: Vector[]): Line[] {\n if (points.length < 2) return [];\n const lines: Line[] = [];\n for (let index = 0; index < points.length - 1; index += 1) {\n lines.push(new Line(points[index], points[index + 1]));\n }\n return lines;\n}\n\nfunction tesselateToLines(\n segment: Segment,\n options?: TesselateSegmentOptions,\n): Segment[] {\n return linesFromPoints(tesselateSegment(segment, options));\n}\n\nfunction stitchSegmentPoints(\n segments: Segment[],\n options?: TesselateSegmentOptions,\n): Vector[] {\n const points: Vector[] = [];\n segments.forEach((segment, index) => {\n const segmentPoints = tesselateSegment(segment, options);\n if (segmentPoints.length === 0) return;\n if (index === 0) {\n points.push(...segmentPoints);\n return;\n }\n points.push(...segmentPoints.slice(1));\n });\n\n if (points.length > 1 && sameVector(points[0], points[points.length - 1])) {\n points.pop();\n }\n return points;\n}\n\nfunction isClockwise(points: Vector[]): boolean {\n if (points.length < 3) return false;\n const area = points\n .map((v1, i) => {\n const v2 = points[(i + 1) % points.length];\n return (v2[0] - v1[0]) * (v2[1] + v1[1]);\n })\n .reduce((a, b) => a + b, 0);\n return area > 0;\n}\n\nfunction orientPoints(points: Vector[], clockwise: boolean): Vector[] {\n if (points.length < 3) return points;\n if (isClockwise(points) === clockwise) return points;\n return [...points].reverse();\n}\n\nfunction tesselate(shape: Diagram, options?: TesselateSegmentOptions): Diagram;\nfunction tesselate(shape: Figure, options?: TesselateSegmentOptions): Figure;\nfunction tesselate(shape: Loop, options?: TesselateSegmentOptions): Loop;\nfunction tesselate(shape: Strand, options?: TesselateSegmentOptions): Strand;\nfunction tesselate(\n shape: Segment,\n options?: TesselateSegmentOptions,\n): Segment[];\nfunction tesselate(\n shape: Diagram | Figure | Loop | Strand | Segment,\n options: TesselateSegmentOptions = {},\n) {\n const mapper = (segment: Segment) => tesselateToLines(segment, options);\n return genericConversion(shape, mapper);\n}\n\nfunction tesselatePoints(\n shape: Diagram,\n options?: TesselateSegmentOptions,\n): Vector[][][];\nfunction tesselatePoints(\n shape: Figure,\n options?: TesselateSegmentOptions,\n): Vector[][];\nfunction tesselatePoints(\n shape: Loop,\n options?: TesselateSegmentOptions,\n): Vector[];\nfunction tesselatePoints(\n shape: Strand,\n options?: TesselateSegmentOptions,\n): Vector[];\nfunction tesselatePoints(\n shape: Segment,\n options?: TesselateSegmentOptions,\n): Vector[];\nfunction tesselatePoints(\n shape: Diagram | Figure | Loop | Strand | Segment,\n options: TesselateSegmentOptions = {},\n) {\n if (shape instanceof Diagram) {\n return shape.figures.map((figure) => tesselatePoints(figure, options));\n }\n\n if (shape instanceof Figure) {\n const contour = orientPoints(\n stitchSegmentPoints(shape.contour.segments, options),\n false,\n );\n const holes = shape.holes.map((hole) =>\n orientPoints(stitchSegmentPoints(hole.segments, options), true),\n );\n return [contour, ...holes];\n }\n\n if (shape instanceof Loop) {\n return orientPoints(stitchSegmentPoints(shape.segments, options), false);\n }\n\n if (shape instanceof Strand) {\n return stitchSegmentPoints(shape.segments, options);\n }\n\n return tesselateSegment(shape, options);\n}\n\nexport { tesselate, tesselatePoints };\n","import { Strand } from \"../../models/Strand.js\";\nimport { Diagram } from \"../../models/Diagram.js\";\nimport { Figure } from \"../../models/Figure.js\";\nimport { Loop } from \"../../models/Loop.js\";\nimport { BoundingBox } from \"../../models/BoundingBox.js\";\nimport { svgDiagram } from \"./svgDiagram.js\";\nimport { svgFigure } from \"./svgFigure.js\";\nimport { svgLoop } from \"./svgLoop.js\";\nimport { svgSegmentToPath } from \"./svgSegment.js\";\nimport { svgStrand } from \"./svgStrand.js\";\nimport { SVGUnit, wrapSVG } from \"./wrapSVG.js\";\nimport type { Stroke } from \"../../models/Stroke.js\";\nimport { Segment } from \"../../main.js\";\nimport { isSegment } from \"../../models/segments/utils/isSegment.js\";\n\ntype Shape = Figure | Diagram | Stroke | Segment;\n\nexport function svgBody(shape: Shape) {\n if (shape instanceof Diagram) {\n return svgDiagram(shape);\n } else if (shape instanceof Figure) {\n return svgFigure(shape);\n } else if (shape instanceof Loop) {\n return `<path d=\"${svgLoop(shape)}\" />`;\n } else if (shape instanceof Strand) {\n return `<path d=\"${svgStrand(shape)}\" />`;\n } else if (isSegment(shape)) {\n return `<path d=\"${`M ${shape.firstPoint.join(\" \")}`} ${svgSegmentToPath(\n shape,\n )}\" />`;\n } else {\n throw new Error(\"Unknown shape type\");\n }\n}\n\ntype ConfiguredShape = Shape | { shape: Shape; color?: string };\n\nconst extractShape = (shape: ConfiguredShape) =>\n \"shape\" in shape ? shape.shape : shape;\n\nconst addConfig = (shape: ConfiguredShape, body: string) => {\n if (!(\"shape\" in shape)) return body;\n const { color } = shape;\n if (!color) return body;\n return `<g stroke=\"${color}\">${body}</g>`;\n};\n\nconst flibBbox = (bbox: BoundingBox) => {\n return new BoundingBox(bbox.xMin, -bbox.yMax, bbox.xMax, -bbox.yMin);\n};\n\nexport function exportSVG(\n shape: ConfiguredShape | ConfiguredShape[],\n {\n margin = 1,\n unit = null,\n viewBox,\n }: {\n margin?: number;\n unit?: null | SVGUnit;\n viewBox?: BoundingBox;\n } = {},\n) {\n if (Array.isArray(shape)) {\n const flipped = shape.map((s) => extractShape(s).mirror());\n const body = flipped\n .map((s, i) => addConfig(shape[i], svgBody(s)))\n .join(\"\\n\");\n const bbox = flipped\n .slice(1)\n .reduce((bbox, s) => bbox.merge(s.boundingBox), flipped[0].boundingBox);\n\n return wrapSVG(body, viewBox ? flibBbox(viewBox) : bbox, margin, unit);\n }\n const flipped = extractShape(shape).mirror();\n return wrapSVG(\n addConfig(shape, svgBody(flipped)),\n viewBox ? flibBbox(viewBox) : flipped.boundingBox,\n margin,\n unit,\n );\n}\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { Loop } from \"../../models/Loop.js\";\nimport { Figure } from \"../../models/Figure.js\";\nimport { Diagram } from \"../../models/Diagram.js\";\nimport { EllipseArc } from \"../../models/segments/EllipseArc.js\";\nimport { CubicBezier } from \"../../models/segments/CubicBezier.js\";\nimport { QuadraticBezier } from \"../../models/segments/QuadraticBezier.js\";\n\nconst importSegment = (json: any) => {\n if (json.type === \"LINE\") {\n return new Line(json.firstPoint, json.lastPoint);\n }\n if (json.type === \"ARC\") {\n return new Arc(\n json.firstPoint,\n json.lastPoint,\n json.center,\n json.clockwise,\n );\n }\n if (json.type === \"ELLIPSE_ARC\") {\n return new EllipseArc(\n json.firstPoint,\n json.lastPoint,\n json.center,\n json.majorRadius,\n json.minorRadius,\n json.tiltAngle,\n json.clockwise,\n { angleUnits: \"rad\" },\n );\n }\n if (json.type === \"QUADRATIC_BEZIER\") {\n return new QuadraticBezier(\n json.firstPoint,\n json.lastPoint,\n json.controlPoint,\n );\n }\n if (json.type === \"CUBIC_BEZIER\") {\n return new CubicBezier(\n json.firstPoint,\n json.lastPoint,\n json.firstControlPoint,\n json.lastControlPoint,\n );\n }\n throw new Error(\"Unknown segment type\");\n};\n\nconst importLoop = (json: any) => {\n const segments = json.segments.map(importSegment);\n return new Loop(segments);\n};\n\nconst importFigure = (json: any) => {\n const contour = importLoop(json.contour);\n const holes = json.holes.map(importLoop);\n return new Figure(contour, holes);\n};\n\nconst importDiagram = (json: any) => {\n const figures = json.figures.map(importFigure);\n return new Diagram(figures);\n};\n\nexport function importJSON(json: any) {\n if (json.type === \"DIAGRAM\") {\n return importDiagram(json);\n }\n if (json.type === \"FIGURE\") {\n return importFigure(json);\n }\n if (json.type === \"LOOP\") {\n return importLoop(json);\n }\n if (\n json.type === \"LINE\" ||\n json.type === \"ARC\" ||\n json.type === \"ELLIPSE_ARC\" ||\n json.type === \"CUBIC_BEZIER\"\n ) {\n return importSegment(json);\n }\n throw new Error(\"Unknown shape type\");\n}\n","import type { Vector } from \"./definitions.js\";\nexport { Vector };\n\nexport const DEG2RAD = Math.PI / 180;\nexport const RAD2DEG = 180 / Math.PI;\n\nexport function polarToCartesian(r: number, theta: number): Vector {\n const x = Math.cos(theta * DEG2RAD) * r;\n const y = Math.sin(theta * DEG2RAD) * r;\n return [x, y];\n}\n\nexport function cartesianToPolar([x, y]: Vector): [number, number] {\n const r = Math.sqrt(x * x + y * y);\n const theta = Math.atan2(y, x) * RAD2DEG;\n return [r, theta];\n}\n\nexport type {\n Diagram,\n Figure,\n Loop,\n Strand,\n Stroke,\n TransformationMatrix,\n BoundingBox,\n Segment,\n Line,\n Arc,\n EllipseArc,\n CubicBezier,\n} from \"./models/exports.js\";\n\nexport { draw, DrawingPen } from \"./draw.js\";\nexport {\n // Surface booleans\n fuseAll,\n fuse,\n cut,\n intersect,\n // Strand booleans\n eraseStrand,\n confineStrand,\n // Offset\n offset,\n outlineStroke,\n // Features\n fillet,\n chamfer,\n selectCorners,\n // Tesselation\n tesselate,\n tesselatePoints,\n} from \"./operations.js\";\n\nexport { exportSVG, svgBody } from \"./export/svg/exportSVG.js\";\n\nexport { exportJSON } from \"./export/json/exportJSON.js\";\nexport { importJSON } from \"./import/json/importJSON.js\";\n"],"names":["listOfFigures","shape","Figure","Loop","Diagram","strandLoopSections","loop","strand","precision","allIntersections","allCommonSegments","splitPoints","strandSegment","strandIndex","loopSegment","intersections","overlaps","findIntersectionsAndOverlaps","commonSegmentsPoints","s","removeDuplicatePoints","strandSegments","zip","segment","strandsBetweenIntersections","eraseStrandWithinLoop","eraseOnBorder","strandCenter","eraseStrandOutsideLoop","eraseStrandWithinFigure","figure","outsideStrands","inLoopStrand","hole","eraseStrandOutsideFigure","insideStrands","fuse","first","second","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","eraseStrand","diagram","outStrands","Strand","confineStrand","segmentPosition","intersectionParam","handleBetween","lineBetween","otherLine","otherPosition","lineLineDistance","line1","line2","intersectionParams","lineLineParams","intersectionParam1","intersectionParam2","firstPosition","secondPosition","distance","lineArcDistance","line","arc","lineArcIntersection","closestPointOnLine","projectPointOnLine","circleCenterLineDistance","centerLineDirection","normalize","subtract","closestPointOnCircle","add","scalarMultiply","overlappingAngles","arc1","arc2","p1","p2","arcArcDistance","arcArcIntersection","centersDistance","centerCenterDirection","containedCircles","arc1ClosestPointAngle","polarAngle","arc2ClosestPointAngle","binarySearch","array","value","comparator","low","high","mid","cmp","binaryInsert","index","DiagonalBuckets","__publicField","interval","bucket","a","b","intervals","i","lastInterval","secondToLastInterval","slope","DivisionRectangle","x","y","DiRectOptimisation","fcn","endTolerance","maxIterations","epsilon","center","rect","Interval","leftCenter","rightCenter","i1","i2","k","potentialFMin","left","middle","right","rectangle","findGlobalMinimum","fun","tolerance","genericDistance","segment1","segment2","result","t","squareDistance","Line","Arc","isOffsetSafeBezier","CubicBezier","chord","v2","v3","a1","angle","a2","n1","perpendicular","n2","dotProduct","_splitIntoOffsetSafeBezier","splitIntoOffsetSafeBezier","approximateEllipticalArcAsCubicBeziers","ellipseArc","sweepAngle","segments","anglePerSegment","kappa","orientation","angles","_","startAngle","endAngle","cosStart","sinStart","cosEnd","sinEnd","centerX","centerY","r","R","rotationMatrix","TransformationMatrix","rotateInFrame","p","p0","c0","c1","PRECISION","transformForOffset","EllipseArc","c","QuadraticBezier","rawOffsets","segmentsToOffset","offset","offsetSegments","offsetSegment","offsettedArray","savedLastSegment","previousSegment","appendSegment","DegenerateSegment","sameVector","iterateOffsetSegments","previousLastPoint","firstPoint","pointIntersections","intersection","originalEndpoint","distances","splitPreviousSegment","splitSegment","clockwise","crossProduct","joiner","findOffsetSelfIntersections","updateIntersections","newPoints","firstSegment","firstIndex","secondSegment","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","splitSegmentsAtIntersections","segmentIntersections","pruneDegenerateSegments","originalStroke","offsetLoop","correctedOffset","transformedSegments","offsettedLoop","splitSegments","prunedSegments","newLoops","stitchSegments","l","outlineStrand","width","endCap","frontOffsettedArray","backOffsettedArray","makeJoiner","fromSegment","toSegment","tangentArc","offsetFigures","figures","offsetDistance","innerShape","outlineStrokeFigures","absOffset","outlineStroke","outlineDistance","FilterList","findersList","f","finderFun","finder","notFilter","element","builtFinders","finderFunction","eitherFilter","PI_2","positiveHalfAngle","limitedAngle","coterminalAngle","CornerFilter","ef","elementList","elementInList","e","dist","point","elementAtDistance","elementAtPoint","corner1","corner2","x1","y1","x2","y2","minX","maxX","minY","maxY","elementInBox","theta","elementOfAngle","tgt1","tgt2","DEG2RAD","yValue","elementAbove","elementBelow","xValue","elementLeftOf","elementRightOf","filter","modifyStroke","makeCorner","stroke","radius","addModifiedCorner","firstCurve","secondCurve","fillet","filterObj","filterFcn","filletSegments","newContour","newHoles","newFigs","chamfer","CornerSelector","selectCorners","DEFAULT_MAX_ANGLE","DEFAULT_MAX_DEPTH","unitTangent","fallback","grad","length","tesselateSegmentRange","t0","t1","options","cosTol","depth","chordLength","chordDir","tm","tan0","tanm","tan1","cos0","cos1","pm","tesselateSegment","resolved","convertDiagramTo","segmentsMap","convertFigureTo","convertLoopTo","convertSegmentsTo","converStrandTo","genericConversion","isSegment","linesFromPoints","points","lines","tesselateToLines","stitchSegmentPoints","segmentPoints","isClockwise","v1","orientPoints","tesselate","tesselatePoints","contour","holes","svgBody","svgDiagram","svgFigure","svgLoop","svgStrand","svgSegmentToPath","extractShape","addConfig","body","color","flibBbox","bbox","BoundingBox","exportSVG","margin","unit","viewBox","flipped","wrapSVG","importSegment","json","importLoop","importFigure","importDiagram","importJSON","RAD2DEG","polarToCartesian","cartesianToPolar"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as $, A as f, E as l, R as u, Q as e, C as h } from "./QuadraticBezier-
|
|
1
|
+
import { L as $, A as f, E as l, R as u, Q as e, C as h } from "./QuadraticBezier-B2g_Iyyl.js";
|
|
2
2
|
function i([t, n]) {
|
|
3
3
|
return `${t} ${n}`;
|
|
4
4
|
}
|
|
@@ -59,4 +59,4 @@ export {
|
|
|
59
59
|
d as s,
|
|
60
60
|
A as w
|
|
61
61
|
};
|
|
62
|
-
//# sourceMappingURL=svg-
|
|
62
|
+
//# sourceMappingURL=svg-D8vwkQf7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svg-
|
|
1
|
+
{"version":3,"file":"svg-D8vwkQf7.js","sources":["../src/export/svg/svgSegment.ts","../src/export/svg/svgLoop.ts","../src/export/svg/svgFigure.ts","../src/export/svg/svgDiagram.ts","../src/export/svg/svgStrand.ts","../src/export/svg/wrapSVG.ts"],"sourcesContent":["import { Arc } from \"../../models/segments/Arc.js\";\nimport { CubicBezier } from \"../../models/segments/CubicBezier.js\";\nimport { EllipseArc } from \"../../models/segments/EllipseArc.js\";\nimport { Line } from \"../../models/segments/Line.js\";\nimport { QuadraticBezier } from \"../../models/segments/QuadraticBezier.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport { RAD2DEG } from \"../../vectorOperations.js\";\n\nfunction formatPoint([x, y]: [number, number]) {\n return `${x} ${y}`;\n}\n\nexport function svgSegmentToPath(segment: Segment) {\n if (segment instanceof Line) {\n return `L ${formatPoint(segment.lastPoint)}`;\n }\n if (segment instanceof Arc) {\n return `A ${segment.radius} ${segment.radius} 0 ${\n segment.angularLength > Math.PI ? \"1\" : \"0\"\n } ${segment.clockwise ? \"0\" : \"1\"} ${formatPoint(segment.lastPoint)}`;\n }\n if (segment instanceof EllipseArc) {\n return `A ${segment.majorRadius} ${segment.minorRadius} ${\n segment.tiltAngle * RAD2DEG\n } ${segment.deltaAngle > Math.PI ? \"1\" : \"0\"} ${\n segment.clockwise ? \"0\" : \"1\"\n } ${formatPoint(segment.lastPoint)}`;\n }\n\n if (segment instanceof QuadraticBezier) {\n return `Q ${[\n formatPoint(segment.controlPoint),\n formatPoint(segment.lastPoint),\n ].join(\" \")}`;\n }\n\n if (segment instanceof CubicBezier) {\n return `C ${[\n formatPoint(segment.firstControlPoint),\n formatPoint(segment.lastControlPoint),\n formatPoint(segment.lastPoint),\n ].join(\" \")}`;\n }\n\n throw new Error(\"Unknown segment type\");\n}\n","import type { Loop } from \"../../models/Loop.js\";\nimport { svgSegmentToPath } from \"./svgSegment.js\";\n\nexport function svgLoop(loop: Loop) {\n const start = `M ${loop.firstPoint.join(\" \")}`;\n const segments = loop.segments.map(svgSegmentToPath).join(\" \");\n return `${start} ${segments} Z`;\n}\n","import type { Figure } from \"../../models/Figure.js\";\nimport { svgLoop } from \"./svgLoop.js\";\n\nexport function svgFigure(figure: Figure) {\n const path = figure.allLoops.map(svgLoop).join(\" \");\n return `<path d=\"${path}\" />`;\n}\n","import { Diagram } from \"../../models/Diagram.js\";\nimport { svgFigure } from \"./svgFigure.js\";\n\nexport function svgDiagram(diagram: Diagram) {\n return `<g>\n ${diagram.figures.map(svgFigure).join(\"\\n\")}\n</g>`;\n}\n","import type { Strand } from \"../../models/Strand.js\";\nimport { svgSegmentToPath } from \"./svgSegment.js\";\n\nexport function svgStrand(strand: Strand) {\n const start = `M ${strand.firstPoint.join(\" \")}`;\n const segments = strand.segments.map(svgSegmentToPath).join(\" \");\n return `${start} ${segments}`;\n}\n","import { BoundingBox } from \"../../models/BoundingBox.js\";\n\nexport function svgViewbox(bbox: BoundingBox, margin = 1) {\n const minX = bbox.xMin - margin;\n const minY = bbox.yMin - margin;\n\n return `${minX} ${minY} ${bbox.width + 2 * margin} ${\n bbox.height + 2 * margin\n }`;\n}\n\n// The list comes from https://oreillymedia.github.io/Using_SVG/guide/units.html\nexport type SVGUnit = \"mm\" | \"cm\" | \"in\" | \"pc\" | \"px\" | \"pt\";\n\nexport function wrapSVG(\n body: string,\n boundingBox: BoundingBox,\n margin = 1,\n unit: null | SVGUnit,\n) {\n const vbox = svgViewbox(boundingBox, margin);\n const sizes = unit\n ? `width=\"${boundingBox.width + 2 * margin}${unit}\" height=\"${\n boundingBox.height + 2 * margin\n }${unit}\"`\n : \"\";\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${vbox}\" fill=\"none\" stroke=\"grey\" stroke-width=\"0.2%\" vector-effect=\"non-scaling-stroke\" ${sizes}>\n ${body}\n</svg>`;\n}\n"],"names":["formatPoint","x","y","svgSegmentToPath","segment","Line","Arc","EllipseArc","RAD2DEG","QuadraticBezier","CubicBezier","svgLoop","loop","start","segments","svgFigure","figure","svgDiagram","diagram","svgStrand","strand","svgViewbox","bbox","margin","minX","minY","wrapSVG","body","boundingBox","unit","vbox","sizes"],"mappings":";AAQA,SAASA,EAAY,CAACC,GAAGC,CAAC,GAAqB;AACtC,SAAA,GAAGD,CAAC,IAAIC,CAAC;AAClB;AAEO,SAASC,EAAiBC,GAAkB;AACjD,MAAIA,aAAmBC;AACrB,WAAO,KAAKL,EAAYI,EAAQ,SAAS,CAAC;AAE5C,MAAIA,aAAmBE;AACd,WAAA,KAAKF,EAAQ,MAAM,IAAIA,EAAQ,MAAM,MAC1CA,EAAQ,gBAAgB,KAAK,KAAK,MAAM,GAC1C,IAAIA,EAAQ,YAAY,MAAM,GAAG,IAAIJ,EAAYI,EAAQ,SAAS,CAAC;AAErE,MAAIA,aAAmBG;AACd,WAAA,KAAKH,EAAQ,WAAW,IAAIA,EAAQ,WAAW,IACpDA,EAAQ,YAAYI,CACtB,IAAIJ,EAAQ,aAAa,KAAK,KAAK,MAAM,GAAG,IAC1CA,EAAQ,YAAY,MAAM,GAC5B,IAAIJ,EAAYI,EAAQ,SAAS,CAAC;AAGpC,MAAIA,aAAmBK;AACrB,WAAO,KAAK;AAAA,MACVT,EAAYI,EAAQ,YAAY;AAAA,MAChCJ,EAAYI,EAAQ,SAAS;AAAA,IAAA,EAC7B,KAAK,GAAG,CAAC;AAGb,MAAIA,aAAmBM;AACrB,WAAO,KAAK;AAAA,MACVV,EAAYI,EAAQ,iBAAiB;AAAA,MACrCJ,EAAYI,EAAQ,gBAAgB;AAAA,MACpCJ,EAAYI,EAAQ,SAAS;AAAA,IAAA,EAC7B,KAAK,GAAG,CAAC;AAGP,QAAA,IAAI,MAAM,sBAAsB;AACxC;AC1CO,SAASO,EAAQC,GAAY;AAClC,QAAMC,IAAQ,KAAKD,EAAK,WAAW,KAAK,GAAG,CAAC,IACtCE,IAAWF,EAAK,SAAS,IAAIT,CAAgB,EAAE,KAAK,GAAG;AACtD,SAAA,GAAGU,CAAK,IAAIC,CAAQ;AAC7B;ACJO,SAASC,EAAUC,GAAgB;AAExC,SAAO,YADMA,EAAO,SAAS,IAAIL,CAAO,EAAE,KAAK,GAAG,CAC3B;AACzB;ACHO,SAASM,EAAWC,GAAkB;AACpC,SAAA;AAAA,IACLA,EAAQ,QAAQ,IAAIH,CAAS,EAAE,KAAK;AAAA,CAAI,CAAC;AAAA;AAE7C;ACJO,SAASI,EAAUC,GAAgB;AACxC,QAAMP,IAAQ,KAAKO,EAAO,WAAW,KAAK,GAAG,CAAC,IACxCN,IAAWM,EAAO,SAAS,IAAIjB,CAAgB,EAAE,KAAK,GAAG;AACxD,SAAA,GAAGU,CAAK,IAAIC,CAAQ;AAC7B;ACLgB,SAAAO,EAAWC,GAAmBC,IAAS,GAAG;AAClD,QAAAC,IAAOF,EAAK,OAAOC,GACnBE,IAAOH,EAAK,OAAOC;AAEzB,SAAO,GAAGC,CAAI,IAAIC,CAAI,IAAIH,EAAK,QAAQ,IAAIC,CAAM,IAC/CD,EAAK,SAAS,IAAIC,CACpB;AACF;AAKO,SAASG,EACdC,GACAC,GACAL,IAAS,GACTM,GACA;AACM,QAAAC,IAAOT,EAAWO,GAAaL,CAAM,GACrCQ,IAAQF,IACV,UAAUD,EAAY,QAAQ,IAAIL,CAAM,GAAGM,CAAI,aAC7CD,EAAY,SAAS,IAAIL,CAC3B,GAAGM,CAAI,MACP;AAEG,SAAA;AAAA,iEACwDC,CAAI,sFAAsFC,CAAK;AAAA,MAC1JJ,CAAI;AAAA;AAEV;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Vector } from '../../definitions.js';
|
|
2
|
+
import { Segment } from '../../models/segments/Segment.js';
|
|
3
|
+
export type TesselateSegmentOptions = {
|
|
4
|
+
maxAngle?: number;
|
|
5
|
+
maxDepth?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function tesselateSegment(segment: Segment, options?: TesselateSegmentOptions): Vector[];
|
package/dist/types/src/main.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare function polarToCartesian(r: number, theta: number): Vector;
|
|
|
6
6
|
export declare function cartesianToPolar([x, y]: Vector): [number, number];
|
|
7
7
|
export type { Diagram, Figure, Loop, Strand, Stroke, TransformationMatrix, BoundingBox, Segment, Line, Arc, EllipseArc, CubicBezier, } from './models/exports.js';
|
|
8
8
|
export { draw, DrawingPen } from './draw.js';
|
|
9
|
-
export { fuseAll, fuse, cut, intersect, eraseStrand, confineStrand, offset, outlineStroke, fillet, chamfer, selectCorners, } from './operations.js';
|
|
9
|
+
export { fuseAll, fuse, cut, intersect, eraseStrand, confineStrand, offset, outlineStroke, fillet, chamfer, selectCorners, tesselate, tesselatePoints, } from './operations.js';
|
|
10
10
|
export { exportSVG, svgBody } from './export/svg/exportSVG.js';
|
|
11
11
|
export { exportJSON } from './export/json/exportJSON.js';
|
|
12
12
|
export { importJSON } from './import/json/importJSON.js';
|