pantograph2d 0.7.0 → 0.8.1
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/LICENSE +4 -658
- package/dist/QuadraticBezier-BAVasVfu.cjs +9 -0
- package/dist/QuadraticBezier-BAVasVfu.cjs.map +1 -0
- package/dist/QuadraticBezier-BzVqiExF.js +4736 -0
- package/dist/QuadraticBezier-BzVqiExF.js.map +1 -0
- package/dist/draw-DqsKIWJD.js +337 -0
- package/dist/draw-DqsKIWJD.js.map +1 -0
- package/dist/draw-NcYfDZjT.cjs +2 -0
- package/dist/draw-NcYfDZjT.cjs.map +1 -0
- package/dist/models-Dxwusy3i.cjs +4 -0
- package/dist/models-Dxwusy3i.cjs.map +1 -0
- package/dist/models-WQ-B7GSL.js +1749 -0
- package/dist/models-WQ-B7GSL.js.map +1 -0
- package/dist/pantograph/drawShape.cjs +1 -1
- package/dist/pantograph/drawShape.cjs.map +1 -1
- package/dist/pantograph/drawShape.js +12 -13
- package/dist/pantograph/drawShape.js.map +1 -1
- package/dist/pantograph/models.cjs +1 -1
- package/dist/pantograph/models.js +15 -12
- package/dist/pantograph/models.js.map +1 -1
- package/dist/pantograph/svg.cjs +2 -0
- package/dist/pantograph/svg.cjs.map +1 -0
- package/dist/pantograph/svg.js +10 -0
- package/dist/pantograph/svg.js.map +1 -0
- package/dist/pantograph.cjs +2 -8
- package/dist/pantograph.cjs.map +1 -1
- package/dist/pantograph.js +406 -452
- package/dist/pantograph.js.map +1 -1
- package/dist/svg-BylQQgsL.js +62 -0
- package/dist/svg-BylQQgsL.js.map +1 -0
- package/dist/svg-D0nYyMk7.cjs +8 -0
- package/dist/svg-D0nYyMk7.cjs.map +1 -0
- package/dist/types/examples/importSVG.d.ts +4 -0
- package/dist/types/{algorithms → src/algorithms}/boolean/figureBooleans.d.ts +1 -1
- package/dist/types/{algorithms → src/algorithms}/boolean/loopBooleans.d.ts +1 -1
- package/dist/types/{algorithms → src/algorithms}/boolean/strandBoolean.d.ts +4 -4
- package/dist/types/{algorithms → src/algorithms}/boolean/strandsBetweenIntersections.d.ts +3 -3
- package/dist/types/{algorithms → src/algorithms}/distances/arcArcDistance.d.ts +1 -1
- package/dist/types/{algorithms → src/algorithms}/distances/genericDistance.d.ts +1 -1
- package/dist/types/{algorithms → src/algorithms}/distances/index.d.ts +1 -1
- package/dist/types/src/algorithms/distances/lineArcDistance.d.ts +3 -0
- package/dist/types/{algorithms → src/algorithms}/distances/lineLineDistance.d.ts +1 -1
- package/dist/types/{algorithms → src/algorithms}/filletSegments.d.ts +1 -1
- package/dist/types/{algorithms → src/algorithms}/intersections/arcArcIntersection.d.ts +2 -2
- package/dist/types/src/algorithms/intersections/arcEllipseArcIntersection.d.ts +3 -0
- package/dist/types/src/algorithms/intersections/arcsCubicBezierIntersection.d.ts +5 -0
- package/dist/types/src/algorithms/intersections/arcsQuadraticBezierIntersection.d.ts +5 -0
- package/dist/types/{algorithms → src/algorithms}/intersections/bezierClip.d.ts +3 -3
- package/dist/types/{algorithms → src/algorithms}/intersections/cubicBezierCubicBezierIntersection.d.ts +2 -2
- package/dist/types/{algorithms → src/algorithms}/intersections/ellipseArcEllipseArcIntersection.d.ts +2 -2
- package/dist/types/src/algorithms/intersections/ellipseEllipseIntersection.d.ts +4 -0
- package/dist/types/{algorithms → src/algorithms}/intersections/index.d.ts +2 -2
- package/dist/types/src/algorithms/intersections/lineArcIntersection.d.ts +4 -0
- package/dist/types/src/algorithms/intersections/lineBezierIntersection.d.ts +5 -0
- package/dist/types/src/algorithms/intersections/lineEllipseArcIntersection.d.ts +4 -0
- package/dist/types/{algorithms → src/algorithms}/intersections/lineLineIntersection.d.ts +4 -4
- package/dist/types/{algorithms → src/algorithms}/intersections/quadraticBezierQuadraticBezierIntersection.d.ts +2 -2
- package/dist/types/src/algorithms/intersections/rayIntersections.d.ts +3 -0
- package/dist/types/{algorithms → src/algorithms}/offsets/offsetFigure.d.ts +2 -2
- package/dist/types/{algorithms → src/algorithms}/offsets/offsetSegment.d.ts +4 -4
- package/dist/types/{algorithms → src/algorithms}/offsets/offsetStroke.d.ts +5 -5
- package/dist/types/{algorithms → src/algorithms}/organiseLoops.d.ts +2 -2
- package/dist/types/src/algorithms/simplify.d.ts +3 -0
- package/dist/types/src/algorithms/solvers/findZeroViaNewton.d.ts +1 -0
- package/dist/types/src/algorithms/solvers/zeroViaNewton.d.ts +1 -0
- package/dist/types/{algorithms → src/algorithms}/stitchSegments.d.ts +1 -1
- package/dist/types/src/api/drawShape.d.ts +2 -0
- package/dist/types/src/api/models.d.ts +1 -0
- package/dist/types/src/api/svg.d.ts +1 -0
- package/dist/types/{booleanOperations.d.ts → src/booleanOperations.d.ts} +5 -5
- package/dist/types/{draw.d.ts → src/draw.d.ts} +4 -4
- package/dist/types/{drawShape → src/drawShape}/drawCircle.d.ts +1 -1
- package/dist/types/src/drawShape/drawEllipse.d.ts +2 -0
- package/dist/types/{drawShape → src/drawShape}/drawRect.d.ts +1 -1
- package/dist/types/src/drawShape/drawSVGPath.d.ts +2 -0
- package/dist/types/src/drawShape/index.d.ts +4 -0
- package/dist/types/{export → src/export}/json/exportJSON.d.ts +94 -94
- package/dist/types/{export → src/export}/json/jsonDiagram.d.ts +31 -31
- package/dist/types/{export → src/export}/json/jsonFigure.d.ts +31 -31
- package/dist/types/{export → src/export}/json/jsonLoop.d.ts +16 -16
- package/dist/types/{export → src/export}/json/jsonSegment.d.ts +16 -16
- package/dist/types/src/export/svg/api.d.ts +6 -0
- package/dist/types/{export → src/export}/svg/exportSVG.d.ts +6 -6
- package/dist/types/{export → src/export}/svg/svgDiagram.d.ts +1 -1
- package/dist/types/{export → src/export}/svg/svgFigure.d.ts +1 -1
- package/dist/types/{export → src/export}/svg/svgLoop.d.ts +1 -1
- package/dist/types/{export → src/export}/svg/svgSegment.d.ts +1 -1
- package/dist/types/{export → src/export}/svg/svgStrand.d.ts +1 -1
- package/dist/types/{export → src/export}/svg/wrapSVG.d.ts +2 -2
- package/dist/types/src/import/json/importJSON.d.ts +9 -0
- package/dist/types/{main.d.ts → src/main.d.ts} +7 -7
- package/dist/types/{models → src/models}/BoundingBox.d.ts +1 -1
- package/dist/types/{models → src/models}/Diagram.d.ts +7 -7
- package/dist/types/{models → src/models}/Figure.d.ts +7 -7
- package/dist/types/{models → src/models}/Loop.d.ts +4 -4
- package/dist/types/{models → src/models}/Strand.d.ts +2 -2
- package/dist/types/{models → src/models}/Stroke.d.ts +5 -5
- package/dist/types/{models → src/models}/TransformationMatrix.d.ts +1 -1
- package/dist/types/src/models/exports.d.ts +15 -0
- package/dist/types/src/models/segments/AbstractSegment.d.ts +25 -0
- package/dist/types/{models → src/models}/segments/Arc.d.ts +4 -4
- package/dist/types/{models → src/models}/segments/CubicBezier.d.ts +4 -4
- package/dist/types/{models → src/models}/segments/EllipseArc.d.ts +5 -5
- package/dist/types/{models → src/models}/segments/Line.d.ts +4 -4
- package/dist/types/{models → src/models}/segments/QuadraticBezier.d.ts +4 -4
- package/dist/types/{models → src/models}/segments/Segment.d.ts +4 -4
- package/dist/types/{models → src/models}/segments/utils/deCasteljau.d.ts +1 -1
- package/dist/types/src/models/segments/utils/isSegment.d.ts +8 -0
- package/dist/types/{models → src/models}/utils/Transformable.d.ts +2 -2
- package/dist/types/{offsetOperations.d.ts → src/offsetOperations.d.ts} +4 -4
- package/dist/types/src/operations.d.ts +2 -0
- package/dist/types/src/utils/applyMixins.d.ts +1 -0
- package/dist/types/src/utils/listOfFigures.d.ts +4 -0
- package/dist/types/src/utils/projectPointOnLine.d.ts +3 -0
- package/dist/types/{utils → src/utils}/removeDuplicatePoints.d.ts +1 -1
- package/dist/types/{vectorOperations.d.ts → src/vectorOperations.d.ts} +1 -1
- package/package.json +33 -25
- package/dist/Diagram-8c3c5e1b.js +0 -5301
- package/dist/Diagram-8c3c5e1b.js.map +0 -1
- package/dist/Diagram-d8288579.cjs +0 -11
- package/dist/Diagram-d8288579.cjs.map +0 -1
- package/dist/draw-3ee546c3.cjs +0 -2
- package/dist/draw-3ee546c3.cjs.map +0 -1
- package/dist/draw-825692f1.js +0 -336
- package/dist/draw-825692f1.js.map +0 -1
- package/dist/types/algorithms/distances/lineArcDistance.d.ts +0 -3
- package/dist/types/algorithms/intersections/arcEllipseArcIntersection.d.ts +0 -3
- package/dist/types/algorithms/intersections/arcsCubicBezierIntersection.d.ts +0 -5
- package/dist/types/algorithms/intersections/arcsQuadraticBezierIntersection.d.ts +0 -5
- package/dist/types/algorithms/intersections/ellipseEllipseIntersection.d.ts +0 -4
- package/dist/types/algorithms/intersections/lineArcIntersection.d.ts +0 -4
- package/dist/types/algorithms/intersections/lineBezierIntersection.d.ts +0 -5
- package/dist/types/algorithms/intersections/lineEllipseArcIntersection.d.ts +0 -4
- package/dist/types/algorithms/intersections/rayIntersections.d.ts +0 -3
- package/dist/types/algorithms/simplify.d.ts +0 -3
- package/dist/types/api/drawShape.d.ts +0 -2
- package/dist/types/api/models.d.ts +0 -1
- package/dist/types/import/json/importJSON.d.ts +0 -9
- package/dist/types/models/exports.d.ts +0 -13
- package/dist/types/models/segments/utils/isSegment.d.ts +0 -8
- package/dist/types/operations.d.ts +0 -2
- package/dist/types/utils/listOfFigures.d.ts +0 -4
- package/dist/types/utils/projectPointOnLine.d.ts +0 -3
- /package/dist/types/{algorithms → src/algorithms}/optimisation/Brent.d.ts +0 -0
- /package/dist/types/{algorithms → src/algorithms}/optimisation/DiRect.d.ts +0 -0
- /package/dist/types/{algorithms → src/algorithms}/solvers/solvePolynomials.d.ts +0 -0
- /package/dist/types/{definitions.d.ts → src/definitions.d.ts} +0 -0
- /package/dist/types/{utils → src/utils}/allCombinations.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/allPairs.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/angularDistance.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/range.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/removeDuplicateValues.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/unitAngle.d.ts +0 -0
- /package/dist/types/{utils → src/utils}/zip.d.ts +0 -0
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/offsets/offsetStroke.ts","../src/algorithms/offsets/offsetFigure.ts","../src/offsetOperations.ts","../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","../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(public x: number, public y: number) {\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 { 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 { offsetSegment, DegenerateSegment } 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\";\n\nconst PRECISION = 1e-8;\n\nexport function rawOffsets(\n segmentsToOffset: Segment[],\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\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 offsettedArray = rawOffsets(loop.segments, 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 offsettedArray = rawOffsets(strand.segments, offset, false);\n const backOffsettedArray = rawOffsets(strand.segments, -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 frontOffsettedArray = rawOffsets(strand.segments, offset, false);\n const backOffsettedArray = rawOffsets(strand.segments, -offset, false).map(\n (s) => s.reverse()\n );\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 { 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=\"black\" stroke-width=\"0.2%\" vector-effect=\"non-scaling-stroke\" ${sizes}>\n ${body}\n</svg>`;\n}\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 } 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} 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","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","PRECISION","rawOffsets","segmentsToOffset","offset","offsetSegments","c","offsetSegment","offsettedArray","savedLastSegment","previousSegment","appendSegment","DegenerateSegment","sameVector","iterateOffsetSegments","previousLastPoint","firstPoint","pointIntersections","intersection","originalEndpoint","distances","splitPreviousSegment","splitSegment","clockwise","crossProduct","joiner","findOffsetSelfIntersections","segments","updateIntersections","newPoints","firstSegment","firstIndex","secondSegment","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","splitSegmentsAtIntersections","segmentIntersections","pruneDegenerateSegments","originalStroke","offsetLoop","correctedOffset","offsettedLoop","splitSegments","prunedSegments","newLoops","stitchSegments","l","outlineStrand","width","endCap","frontOffsettedArray","backOffsettedArray","makeJoiner","fromSegment","toSegment","tangentArc","offsetFigures","figures","offsetDistance","innerShape","outlineStrokeFigures","absOffset","outlineStroke","outlineDistance","formatPoint","svgSegmentToPath","EllipseArc","RAD2DEG","QuadraticBezier","CubicBezier","svgLoop","start","svgFigure","svgDiagram","svgStrand","SVGViewbox","bbox","margin","minX","minY","wrapSVG","body","boundingBox","unit","vbox","sizes","svgBody","isSegment","extractShape","addConfig","color","flibBbox","BoundingBox","exportSVG","viewBox","flipped","importSegment","json","importLoop","importFigure","contour","holes","importDiagram","importJSON","DEG2RAD","polarToCartesian","r","theta","cartesianToPolar"],"mappings":";;;;AAIO,SAASA,EAAcC,GAA0C;AACtE,MAAIA,aAAiBC;AACnB,WAAO,CAACD,CAAK;AACf,MAAWA,aAAiBE;AAC1B,WAAO,CAAC,IAAID,EAAOD,CAAK,CAAC;AAC3B,MAAWA,aAAiBG;AAC1B,WAAOH,EAAM;AAET,QAAA,IAAI,MAAM,eAAe;AACjC;ACFA,SAASI,GACPC,GACAC,GACAC,IAAY,MACF;AACV,MAAIC,IAA6B,CAAA;AACjC,QAAMC,IAA+B,CAAA,GAE/BC,IAA0B,IAAI,MAAMJ,EAAO,SAAS,MAAM,EAC7D,KAAK,CAAC,EACN,IAAI,MAAM,CAAE,CAAA;AAEf,EAAAA,EAAO,SAAS,QAAQ,CAACK,GAAeC,MAAgB;AACjD,IAAAP,EAAA,SAAS,QAAQ,CAACQ,MAAgB;AAC/B,YAAA,EAAE,eAAAC,GAAe,UAAAC,EAAA,IAAaC;AAAA,QAClCL;AAAA,QACAE;AAAA,QACAN;AAAA,MAAA;AAGe,MAAAC,EAAA,KAAK,GAAGM,CAAa,GACtCJ,EAAYE,CAAW,EAAE,KAAK,GAAGE,CAAa,GAE5BL,EAAA,KAAK,GAAGM,CAAQ;AAClC,YAAME,IAAuBF,EAAS,QAAQ,CAACG,MAAM;AAAA,QACnDA,EAAE;AAAA,QACFA,EAAE;AAAA,MAAA,CACH;AACgB,MAAAV,EAAA,KAAK,GAAGS,CAAoB,GAC7CP,EAAYE,CAAW,EAAE,KAAK,GAAGK,CAAoB;AAAA,IAAA,CACtD;AAAA,EAAA,CACF,GAEkBT,IAAAW,GAAsBX,GAAkBD,CAAS;AAEpE,QAAMa,IAAiBC,GAAI,CAACf,EAAO,UAAUI,CAAW,CAGvD,EAAE,QAAQ,CAAC,CAACY,GAASR,CAAa,MAC5BA,EAAc,SACZQ,EAAQ,QAAQR,CAAa,IADF,CAACQ,CAAO,CAE3C;AAED,SAAO,MAAM;AAAA,IACXC;AAAA,MACEH;AAAA,MACAZ;AAAA,MACAC;AAAA,IACF;AAAA,EAAA;AAEJ;AAEO,SAASe,EACdlB,GACAD,GACAoB,IAAgB,IAChB;AAIO,SAHSrB,GAAmBC,GAAMC,CAAM,EAGhC,OAAO,CAACA,MAAW;AAChC,UAAMoB,IAAepB,EAAO,SAAS,CAAC,EAAE;AACpC,WAAAD,EAAK,SAASqB,CAAY,IAAU,CAACD,IAElC,CAACpB,EAAK,SAASqB,CAAY;AAAA,EAAA,CACnC;AACH;AAEO,SAASC,EACdrB,GACAD,GACAoB,IAAgB,IAChB;AAIO,SAHSrB,GAAmBC,GAAMC,CAAM,EAGhC,OAAO,CAACA,MAAW;AAChC,UAAMoB,IAAepB,EAAO,SAAS,CAAC,EAAE;AACpC,WAAAD,EAAK,SAASqB,CAAY,IAAU,CAACD,IAElCpB,EAAK,SAASqB,CAAY;AAAA,EAAA,CAClC;AACH;AAEO,SAASE,EACdtB,GACAuB,GACAJ,IAAgB,IAChB;AACA,QAAMK,IAAiBN;AAAA,IACrBlB;AAAA,IACAuB,EAAO;AAAA,IACPJ;AAAA,EAAA,GAGIM,IAAeF,EAAO,MAAM;AAAA,IAAQ,CAACG,MACzCL,EAAuBrB,GAAQ0B,GAAMP,CAAa;AAAA,EAAA;AAGpD,SAAO,CAAC,GAAGK,GAAgB,GAAGC,CAAY;AAC5C;AAEO,SAASE,EACd3B,GACAuB,GACAJ,IAAgB,IAChB;AACA,MAAIS,IAAgBP;AAAA,IAClBrB;AAAA,IACAuB,EAAO;AAAA,IACPJ;AAAA,EAAA;AAGK,SAAAI,EAAA,MAAM,QAAQ,CAACG,MAAe;AACnC,IAAAE,IAAgBA,EAAc;AAAA,MAAQ,CAAC5B,MACrCkB,EAAsBlB,GAAQ0B,GAAMP,CAAa;AAAA,IAAA;AAAA,EACnD,CACD,GAEMS;AACT;ACjHgB,SAAAC,GACdC,GACAC,GACS;AACT,SAAO,IAAIlC;AAAA,IACTmC,GAAiBvC,EAAcqC,CAAK,GAAGrC,EAAcsC,CAAM,CAAC;AAAA,EAAA;AAEhE;AAEO,SAASE,EAAQC,GAA8C;AACpE,SAAOA,EAAO;AAAA,IACZ,CAACC,GAAczC,MAAmCmC,GAAKM,GAAKzC,CAAK;AAAA,IACjE,IAAIG,EAAQ;AAAA,EAAA;AAEhB;AAEgB,SAAAuC,GACdN,GACAC,GACS;AACT,SAAO,IAAIlC;AAAA,IACTwC,GAAgB5C,EAAcqC,CAAK,GAAGrC,EAAcsC,CAAM,CAAC;AAAA,EAAA;AAE/D;AAEgB,SAAAO,GACdR,GACAC,GACS;AACT,SAAO,IAAIlC;AAAA,IACT0C,GAAsB9C,EAAcqC,CAAK,GAAGrC,EAAcsC,CAAM,CAAC;AAAA,EAAA;AAErE;AAEO,SAASS,GACdxC,GACAyC,GACAtB,IAAgB,IACN;AACV,MAAIsB,aAAmB7C;AACd,WAAAsB,EAAsBlB,GAAQyC,GAAStB,CAAa;AAG7D,MAAIsB,aAAmB9C;AACd,WAAA2B,EAAwBtB,GAAQyC,GAAStB,CAAa;AAG3D,MAAAuB,IAAuB,CAAC,IAAIC,EAAO,CAAC,GAAG3C,EAAO,QAAQ,CAAC,CAAC;AACpD,SAAAyC,EAAA,QAAQ,QAAQ,CAAClB,MAAmB;AAC7B,IAAAmB,IAAAA,EAAW,QAAQ,CAAC1C,MACxBsB,EAAwBtB,GAAQuB,GAAQJ,CAAa,CAC7D;AAAA,EAAA,CACF,GAEMuB;AACT;AAEO,SAASE,GACd5C,GACAyC,GACAtB,IAAgB,IACN;AACV,MAAIsB,aAAmB7C;AACd,WAAAyB,EAAuBrB,GAAQyC,GAAStB,CAAa;AAG9D,MAAIsB,aAAmB9C;AACd,WAAAgC,EAAyB3B,GAAQyC,GAAStB,CAAa;AAG5D,MAAAuB,IAAuB,CAAC,IAAIC,EAAO,CAAC,GAAG3C,EAAO,QAAQ,CAAC,CAAC;AACpD,SAAAyC,EAAA,QAAQ,QAAQ,CAAClB,MAAmB;AAC7B,IAAAmB,IAAAA,EAAW,QAAQ,CAAC1C,MACxB2B,EAAyB3B,GAAQuB,GAAQJ,CAAa,CAC9D;AAAA,EAAA,CACF,GAEMuB;AACT;AC5FA,SAASG,EAAgBC,GAA2B;AAClD,SAAIA,IAAoB,IAAU,WAC9BA,IAAoB,IAAU,UAC3B;AACT;AAEA,MAAMC,IAAgB,CACpBC,GACAC,GACAC,MACG;AACH,MAAIA,MAAkB;AACb,WAAAF,EAAY,aAAaC,EAAU,UAAU;AAAA,MAC7CC,MAAkB;AAClB,WAAAF,EAAY,aAAaC,EAAU,SAAS;AAC1C,QAAA,IAAI,MAAM,kBAAkB;AACzC;AAEgB,SAAAE,GAAiBC,GAAaC,GAAqB;AAC3D,QAAAC,IAAqBC,GAAeH,GAAOC,CAAK;AAEtD,MAAIC,MAAuB;AACzB,WAAO,KAAK;AAAA,MACVF,EAAM,aAAaC,EAAM,UAAU;AAAA,MACnCD,EAAM,aAAaC,EAAM,SAAS;AAAA,IAAA;AAIhC,QAAA,EAAE,oBAAAG,GAAoB,oBAAAC,EAAuB,IAAAH,GAE7CI,IAAgBb,EAAgBW,CAAkB,GAClDG,IAAiBd,EAAgBY,CAAkB;AAErD,MAAAC,MAAkB,aAAaC,MAAmB;AAC7C,WAAA;AACE,MAAAD,MAAkB,aAAaC,MAAmB;AACpD,WAAAZ,EAAcK,GAAOC,GAAOM,CAAc;AACxC,MAAAA,MAAmB,aAAaD,MAAkB;AACpD,WAAAX,EAAcM,GAAOD,GAAOM,CAAa;AACvC,MAAAA,MAAkB,YAAYC,MAAmB;AAC1D,WAAOC,EAASR,EAAM,YAAYC,EAAM,UAAU;AACzC,MAAAK,MAAkB,WAAWC,MAAmB;AACzD,WAAOC,EAASR,EAAM,WAAWC,EAAM,SAAS;AACvC,MAAAK,MAAkB,YAAYC,MAAmB;AAC1D,WAAOC,EAASR,EAAM,YAAYC,EAAM,SAAS;AACxC,MAAAK,MAAkB,WAAWC,MAAmB;AACzD,WAAOC,EAASR,EAAM,WAAWC,EAAM,UAAU;AAE3C,QAAA,IAAI,MAAM,kBAAkB;AAEtC;AC1CgB,SAAAQ,EAAgBC,GAAYC,GAAkB;AAG5D,MAAIC,GAAoBF,GAAMC,CAAG,EAAE,SAAS;AACnC,WAAA;AAGT,QAAME,IAAqBC,GAAmBJ,GAAMC,EAAI,MAAM;AAE1D,MAAAD,EAAK,YAAYG,CAAkB,GAAG;AACxC,UAAME,IAA2BP,EAASK,GAAoBF,EAAI,MAAM;AAGxE,QAAI,KAAK,IAAII,IAA2BJ,EAAI,MAAM,IAAID,EAAK,aACrDC,EAAI,YAAYE,CAAkB;AAC7B,aAAA;AAIX,QAAIE,IAA2BJ,EAAI,SAASD,EAAK,WAAW;AAC1D,YAAMM,IAAsBC;AAAA,QAC1BC,EAASL,GAAoBF,EAAI,MAAM;AAAA,MAAA,GAGnCQ,IAAuBC;AAAA,QAC3BT,EAAI;AAAA,QACJU,GAAeL,GAAqBL,EAAI,MAAM;AAAA,MAAA;AAG5C,UAAAA,EAAI,YAAYQ,CAAoB;AAC/B,eAAAX,EAASW,GAAsBN,CAAkB;AAAA,IAE5D;AAAA,EACF;AAEA,SAAO,KAAK;AAAA,IACVF,EAAI,aAAaD,EAAK,UAAU;AAAA,IAChCC,EAAI,aAAaD,EAAK,SAAS;AAAA,IAC/BA,EAAK,aAAaC,EAAI,UAAU;AAAA,IAChCD,EAAK,aAAaC,EAAI,SAAS;AAAA,EAAA;AAEnC;AC5CA,MAAMW,KAAoB,CAACC,GAAWC,MAAuB;AAC3D,QAAMC,IAAKF,EAAK,aAAaC,EAAK,UAAU;AACxC,MAAAD,EAAK,iBAAiBE,CAAE;AAAU,WAAA;AAEtC,QAAMC,IAAKH,EAAK,aAAaC,EAAK,SAAS;AACvC,SAAA,EAAAD,EAAK,iBAAiBG,CAAE;AAE9B;AAEgB,SAAAC,GAAeJ,GAAWC,GAAmB;AAC3D,MAAII,GAAmBL,GAAMC,GAAM,EAAI,EAAE,SAAS;AAAU,WAAA;AAE5D,QAAMK,IAAkBrB,EAASe,EAAK,QAAQC,EAAK,MAAM;AAErD,MAAAK,IAAkBN,EAAK,aACrBD,GAAkBC,GAAMC,CAAI;AAC9B,WAAO,KAAK,IAAID,EAAK,SAASC,EAAK,MAAM;AAI7C,QAAMM,IAAwBb,EAAUC,EAASM,EAAK,QAAQD,EAAK,MAAM,CAAC,GAEpEQ,IACJF,IAAkB,KAAK,IAAIN,EAAK,SAASC,EAAK,MAAM,IAAID,EAAK;AAE3D,MAAAS,IAAwBC,GAAWH,CAAqB;AAC5D,EAAIC,KAAoBP,EAAK,SAASD,EAAK,WACzCS,KAAyB,KAAK;AAEhC,QAAME,IAAwBH,IAC1BC,IACAA,IAAwB,KAAK,IAE3BP,IAAKF,EAAK,aAAaS,CAAqB,GAC5CN,IAAKF,EAAK,aAAaU,CAAqB;AAElD,SAAIX,EAAK,iBAAiBE,CAAE,KAAKD,EAAK,iBAAiBE,CAAE,IAEhDlB,EAASe,EAAK,WAAWE,CAAE,GAAGD,EAAK,WAAWE,CAAE,CAAC,IAGnD,KAAK;AAAA,IACVH,EAAK,aAAaC,EAAK,UAAU;AAAA,IACjCD,EAAK,aAAaC,EAAK,SAAS;AAAA,IAChCA,EAAK,aAAaD,EAAK,UAAU;AAAA,IACjCC,EAAK,aAAaD,EAAK,SAAS;AAAA,EAAA;AAEpC;AC/CA,SAASY,GACPC,GACAC,GACAC,GACQ;AACR,MAAIC,IAAM,GACNC,IAAOJ,EAAM,SAAS;AAC1B,SAAOG,KAAOC,KAAM;AAClB,UAAMC,IAAM,KAAK,OAAOF,IAAMC,KAAQ,CAAC,GACjCE,IAAMJ,EAAWF,EAAMK,CAAG,GAAGJ,CAAK;AACxC,QAAIK,IAAM;AACR,MAAAH,IAAME,IAAM;AAAA,aACHC,IAAM;AACf,MAAAF,IAAOC,IAAM;AAAA;AAEN,aAAAA;AAAA,EAEX;AACA,SAAO,EAAEF,IAAM;AACjB;AAEA,SAASI,GACPP,GACAC,GACAC,GACA;AACA,QAAMM,IAAQT,GAAaC,GAAOC,GAAOC,CAAU;AACnD,EAAIM,IAAQ,IACVR,EAAM,OAAO,EAAEQ,IAAQ,IAAI,GAAGP,CAAK,IAE7BD,EAAA,OAAOQ,GAAO,GAAGP,CAAK;AAEhC;AAEA,MAAMQ,GAAgB;AAAA,EAEpB,cAAc;AACZ,SAAK,UAAU;EACjB;AAAA,EAEA,YAAYC,GAAoB;AAC9B,UAAMC,IAAS,KAAK,QAAQD,EAAS,UAAU,mBAAmB;AAClE,IAAIC,MAAW,SACb,KAAK,QAAQD,EAAS,UAAU,mBAAmB,IAAI,CAACA,CAAQ,IAEnDH,GAAAI,GAAQD,GAAU,CAACE,GAAGC,MAAMD,EAAE,QAAQC,EAAE,KAAK;AAAA,EAE9D;AAAA,EAEA,eAAeH,GAAoB;AACjC,UAAMC,IAAS,KAAK,QAAQD,EAAS,UAAU,mBAAmB;AAClE,QAAIC,MAAW;AACP,YAAA,IAAI,MAAM,oBAAoB;AAEtC,IAAAA,EAAO,MAAM;AAAA,EACf;AAAA,EAEA,8BAA0C;AACxC,UAAMG,IAAwB,CAAA;AAC9B,aAASC,IAAI,KAAK,QAAQ,SAAS,GAAGA,KAAK,GAAGA,KAAK;AAC3C,YAAAJ,IAAS,KAAK,QAAQI,CAAC;AAE7B,UAAI,CAACJ,MAAW;AAAW;AACrB,YAAAD,IAAWC,EAAO,CAAC;AACzB,UAAID,MAAa,QAEb;AAAA,YAAA,CAACI,EAAU,QAAQ;AACrB,UAAAA,EAAU,KAAKJ,CAAQ;AACvB;AAAA,QACF;AAME,eAAAI,EAAU,UACVA,EAAUA,EAAU,SAAS,CAAC,EAAE,SAASJ,EAAS;AAElD,UAAAI,EAAU,IAAI;AAKT,eAAAA,EAAU,UAAU,KAAG;AAC5B,gBAAME,IAAeF,EAAUA,EAAU,SAAS,CAAC,GAC7CG,IAAuBH,EAAUA,EAAU,SAAS,CAAC,GAErDI,KACHR,EAAS,QAAQO,EAAqB,WACrCP,EAAS,UAAU,WACnBO,EAAqB,UAAU,YAC/B;AAQA,cANFA,EAAqB,SACnBD,EAAa,UAAU,WACvBC,EAAqB,UAAU,YAC/B,IACAC,IAEaF,EAAa;AAC5B,YAAAF,EAAU,IAAI;AAAA;AAEd;AAAA,QAEJ;AAEA,QAAAA,EAAU,KAAKJ,CAAQ;AAAA;AAAA,IACzB;AAEO,WAAAI;AAAA,EACT;AACF;AAEA,MAAMK,GAAkB;AAAA,EAStB,YAAmBC,GAAkBC,GAAW;AAA7B,SAAA,IAAAD,GAAkB,KAAA,IAAAC,GACnC,KAAK,UAAU,KAAK,IAAI,GAAG,CAACD,CAAC,GAC7B,KAAK,UAAU,KAAK,IAAI,GAAG,CAACC,CAAC,GAE7B,KAAK,WAAW,KAAK;AAAA,MACnB,KAAK,UAAU,KAAK,UAAU,KAAK,UAAU,KAAK;AAAA,IAAA,GAEpD,KAAK,sBAAsBD,IAAIC,GAE1B,KAAA,QAAQ,GAAGD,KAAKC;AAAA,EACvB;AACF;AAEO,MAAMC,GAAmB;AAAA,EAQ9B,YACSC,GACAC,IAAe,MACfC,IAAgB,KAChBC,IAAU,MACjB;AAJO,SAAA,MAAAH,GACA,KAAA,eAAAC,GACA,KAAA,gBAAAC,GACA,KAAA,UAAAC,GAEP,KAAK,MAAMH,GACX,KAAK,UAAUG,GACf,KAAK,eAAeF,GACpB,KAAK,gBAAgBC,GAEhB,KAAA,iCAAiB,OACjB,KAAA,UAAU,IAAIhB;AAEb,UAAAkB,IAA2B,CAAC,KAAK,GAAG,GACpCC,IAAO,KAAK,KAAK,GAAG,CAAC,GACrB3B,IAAQ,KAAK,IAAI0B,CAAM;AAE7B,SAAK,QAAQ,YAAY,IAAIE,EAASF,GAAQ1B,GAAO2B,CAAI,CAAC,GAC1D,KAAK,OAAO3B,GACZ,KAAK,SAAS0B,GACd,KAAK,MAAMC,EAAK;AAAA,EAClB;AAAA,EAEA,iBAAiBlB,GAAoB;AAC9B,SAAA,QAAQ,YAAYA,CAAQ,GAC7BA,EAAS,SAAS,KAAK,SACzB,KAAK,OAAOA,EAAS,OACrB,KAAK,SAASA,EAAS,QAClB,KAAA,MAAMA,EAAS,UAAU;AAAA,EAElC;AAAA,EAEA,KAAKU,GAAWC,GAA8B;AACtC,UAAAb,IAAQ,GAAGY,KAAKC;AACtB,WAAK,KAAK,WAAW,IAAIb,CAAK,KAC5B,KAAK,WAAW,IAAIA,GAAO,IAAIW,GAAkBC,GAAGC,CAAC,CAAC,GAEjD,KAAK,WAAW,IAAIb,CAAK;AAAA,EAClC;AAAA,EAEA,cAAcE,GAAoD;AAC5D,QAAAkB,GACAE,GAA8BC;AAElC,UAAM,CAACX,GAAGC,CAAC,IAAIX,EAAS;AAExB,WAAIA,EAAS,UAAU,KAAKA,EAAS,UAAU,KACtCkB,IAAA,KAAK,KAAKlB,EAAS,UAAU,IAAI,GAAGA,EAAS,UAAU,CAAC,GAC/DoB,IAAa,CAACV,IAAIQ,EAAK,SAASP,CAAC,GACjCU,IAAc,CAACX,IAAIQ,EAAK,SAASP,CAAC,MAE3BO,IAAA,KAAK,KAAKlB,EAAS,UAAU,GAAGA,EAAS,UAAU,IAAI,CAAC,GAC/DoB,IAAa,CAACV,GAAGC,IAAIO,EAAK,OAAO,GACjCG,IAAc,CAACX,GAAGC,IAAIO,EAAK,OAAO,IAG7B;AAAA,MACL,IAAIC,EAASC,GAAY,KAAK,IAAIA,CAAU,GAAGF,CAAI;AAAA,MACnD,IAAIC,EAASnB,EAAS,QAAQA,EAAS,OAAOkB,CAAI;AAAA,MAClD,IAAIC,EAASE,GAAa,KAAK,IAAIA,CAAW,GAAGH,CAAI;AAAA,IAAA;AAAA,EAEzD;AAAA,EAEA,mBAAmB;AACX,UAAAd,IAAY,KAAK,QAAQ,4BAA4B;AAKpD,WAAAA,EAAU,UAAU,KAAG;AAGtB,YAAAkB,IAAKlB,EAAU,CAAC,GAChBmB,IAAKnB,EAAU,CAAC,GAEhBoB,KACHD,EAAG,QAAQD,EAAG,WACbC,EAAG,UAAU,WAAWD,EAAG,UAAU,YAAY,IAC/CG,IAAgBH,EAAG,QAASE,IAAID,EAAG,QAAS;AAC7C,WAAA,KAAK,OAAOE,KAAiB,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK;AAC3D,QAAArB,EAAU,MAAM;AAAA;AAGhB;AAAA,IAEJ;AAEU,IAAAA,EAAA,QAAQ,CAACJ,MAAa;AACzB,WAAA,QAAQ,eAAeA,CAAQ;AAAA,IAAA,CACrC;AAED,eAAWA,KAAYI,GAAW;AAChC,YAAM,CAACsB,GAAMC,GAAQC,CAAK,IAAI,KAAK,cAAc5B,CAAQ;AAEzD,WAAK,iBAAiB0B,CAAI,GAC1B,KAAK,iBAAiBC,CAAM,GAC5B,KAAK,iBAAiBC,CAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM;AACJ,QAAIvB,IAAI;AACR,WAAO,KAAK,MAAM,KAAK,eAAe,MACpC,KAAK,iBAAiB,GACtBA,KACI,EAAAA,IAAI,KAAK;AAAT;AAIC,WAAA;AAAA,MACL,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,KAAK,KAAK;AAAA,MACV,YAAYA;AAAA,IAAA;AAAA,EAEhB;AACF;AAEA,MAAMc,EAAS;AAAA,EACb,YACSF,GACA1B,GACAsC,GACP;AAHO,SAAA,SAAAZ,GACA,KAAA,QAAA1B,GACA,KAAA,YAAAsC;AAAA,EACN;AACL;AAEO,SAASC,GACdC,GACAC,IAAY,MACZjB,IAAgB,KAChBC,IAAU,MACV;AAOA,SANkB,IAAIJ;AAAA,IACpBmB;AAAA,IACAC;AAAA,IACAjB;AAAA,IACAC;AAAA,EAAA,EAEe;AACnB;AC5RO,SAASiB,GACdC,GACAC,GACApI,IAAY,MACJ;AACF,QAAAqI,IAASN,GAAkB,CAACO,MAAM;AACtC,UAAM1D,IAAKuD,EAAS,WAAWG,EAAE,CAAC,CAAC,GAC7BzD,IAAKuD,EAAS,WAAWE,EAAE,CAAC,CAAC;AAC5B,WAAAC,EAAe3D,GAAIC,CAAE;AAAA,KAC3B7E,CAAS;AACL,SAAA,KAAK,KAAKqI,EAAO,IAAI;AAC9B;ACXgB,SAAA1E,GAASwE,GAAmBC,GAA2B;AACjE,SAAAD,aAAoBK,KAAQJ,aAAoBI,IAC3CtF,GAAiBiF,GAAUC,CAAQ,IAGxCD,aAAoBK,KAAQJ,aAAoBK,IAC3C7E,EAAgBuE,GAAUC,CAAQ,IAGvCD,aAAoBM,KAAOL,aAAoBI,IAC1C5E,EAAgBwE,GAAUD,CAAQ,IAGvCA,aAAoBM,KAAOL,aAAoBK,IAC1C3D,GAAeqD,GAAUC,CAAQ,IAGnCF,GAAgBC,GAAUC,CAAQ;AAC3C;ACNA,MAAMM,IAAY;AAEX,SAASC,EACdC,GACAC,GACA/I,IAAO,IACI;AACX,QAAMgJ,IAAsCF,EAAiB,IAAI,CAACG,OAAO;AAAA,IACvE,QAAQC,GAAcD,GAAGF,CAAM;AAAA,IAC/B,UAAUE;AAAA,EACV,EAAA,GAMIE,IAA4B,CAAA;AAElC,MAAIC,IAAmBpJ,IAAO,OAAOgJ,EAAe,GAAG,EAAE,GAErDK,IAAkBrJ,IAAOgJ,EAAe,GAAG,EAAE,IAAI;AAGrD,MAAIG,EAAe,WAAW;AAAU,WAAAA;AAElC,QAAAG,IAAgB,CAACrI,MAA+B;AACpD,IAAKmI,IAEQnI,EAAQ,kBAAkBsI,IAGpCC,EAAWvI,EAAQ,OAAO,YAAYA,EAAQ,OAAO,SAAS,KAEhDkI,EAAA;AAAA,MACb,IAAIT,EAAKzH,EAAQ,OAAO,YAAYA,EAAQ,OAAO,SAAS;AAAA,IAAA,IAL/CkI,EAAA,KAAKlI,EAAQ,MAAM,IAFfmI,IAAAnI;AAAA,EASrB,GAEIwI,IAAwB,aAA2C;AACvE,eAAWxI,KAAW+H,EAAe,MAAM,GAAG,EAAE;AACxC,YAAA/H;AAGR,QAAI,CAACmI;AAAwB,YAAA,IAAI,MAAM,6BAA6B;AAC9D,UAAAA;AAAA,EAAA;AAGG,aAAAnI,KAAWwI,KAAyB;AAC7C,QAAI,CAACJ,GAAiB;AACF,MAAAA,IAAApI;AAClB;AAAA,IACF;AACM,UAAAyI,IAAoBL,EAAgB,OAAO,WAC3CM,IAAa1I,EAAQ,OAAO;AAG9B,QAAAuI,EAAWE,GAAmBC,CAAU,GAAG;AAC7C,MAAAL,EAAcD,CAAe,GACXA,IAAApI;AAClB;AAAA,IACF;AAEA,QAAIR,IAA0B,CAAA;AAE9B,QACE,EAAE4I,EAAgB,kBAAkBE,MACpC,EAAEtI,EAAQ,kBAAkBsI,IAC5B;AAEA,YAAM,EAAE,eAAeK,GAAoB,UAAAlJ,EACzC,IAAAC;AAAA,QACE0I,EAAgB;AAAA,QAChBpI,EAAQ;AAAA,QACR2H,IAAY;AAAA,MAAA;AAEA,MAAAnI,IAAA;AAAA,QACd,GAAGmJ;AAAA,QACH,GAAGlJ,EAAS,QAAQ,CAACuI,MAAM,CAACA,EAAE,YAAYA,EAAE,SAAS,CAAC;AAAA,MAAA;AAAA,IAE1D;AAEI,QAAAxI,EAAc,SAAS,GAAG;AACxB,UAAAoJ,IAAepJ,EAAc,CAAC;AAC9B,UAAAA,EAAc,SAAS,GAAG;AAKtB,cAAAqJ,KAAmBT,KAAA,gBAAAA,EAAiB,SAAS,WAC7CU,IAAYtJ,EAAc;AAAA,UAAI,CAAC+F,OACnCiC,EAAejC,IAAGsD,EAAgB;AAAA,QAAA;AAErB,QAAAD,IAAApJ,EAAcsJ,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC,CAAC;AAAA,MACxE;AAKM,YAAAC,IAAwBX,EAAgB,OAAmB,QAAQ;AAAA,QACvEQ;AAAA,MAAA,CACD,EAAE,CAAC,GACEI,IAAgBhJ,EAAQ,OAC3B,QAAQ,CAAC4I,CAAY,CAAC,EACtB,GAAG,EAAE;AAER,UAAI,CAACI;AAAoB,cAAA,IAAI,MAAM,qCAAqC;AAE1D,MAAAX,EAAA;AAAA,QACZ,QAAQU;AAAA,QACR,UAAUX,EAAgB;AAAA,MAAA,CAC3B,GACDA,IAAkB,EAAE,QAAQY,GAAc,UAAUhJ,EAAQ;AAC5D;AAAA,IACF;AAIM,UAAAmG,IAASiC,EAAgB,SAAS,WAClCa,IACJC;AAAA,MACE5F,EAASoF,GAAYvC,CAAM;AAAA,MAC3B7C,EAASmF,GAAmBtC,CAAM;AAAA,IAChC,IAAA,GAEAgD,KAAS,IAAIzB,EAAIe,GAAmBC,GAAYvC,GAAQ8C,CAAS;AAEvE,IAAAZ,EAAcD,CAAe,GAC7BF,EAAe,KAAKiB,EAAM,GACRf,IAAApI;AAAA,EACpB;AAEI,SAAAoI,KAAiBC,EAAcD,CAAe,GAC3CF;AACT;AAOA,SAASkB,GACPC,GACuB;AAIjB,QAAAnK,wBAA8C,OAC9CoK,IAAsB,CAACtE,GAAeuE,MAAwB;AAClE,UAAM/J,IAAgBN,EAAiB,IAAI8F,CAAK,KAAK,CAAA;AACrD,IAAA9F,EAAiB,IAAI8F,GAAO,CAAC,GAAGxF,GAAe,GAAG+J,CAAS,CAAC;AAAA,EAAA;AAGrD,SAAAF,EAAA,QAAQ,CAACG,GAAcC,MAAe;AAC7C,IAAAJ,EAAS,MAAMI,IAAa,CAAC,EAAE,QAAQ,CAACC,GAAeC,MAAgB;AAC/D,YAAA,EAAE,eAAeC,GAAkB,UAAAnK,EAAA,IACvCC,EAA6B8J,GAAcE,GAAe/B,CAAS,GAE/DnI,IAAgB;AAAA,QACpB,GAAGoK;AAAA,QACH,GAAGnK,EAAS,QAAQ,CAACuI,MAAM,CAACA,EAAE,YAAYA,EAAE,SAAS,CAAC;AAAA,MAAA,EACtD,OAAO,CAACY,MAAiB;AACnB,cAAAiB,IACJtB,EAAWK,GAAcY,EAAa,UAAU,KAChDjB,EAAWK,GAAcY,EAAa,SAAS,GAE3CM,IACJvB,EAAWK,GAAcc,EAAc,UAAU,KACjDnB,EAAWK,GAAcc,EAAc,SAAS;AAElD,eAAO,EAAEG,KAA2BC;AAAA,MAAA,CACrC;AAED,MAAKtK,EAAc,WAEnB8J,EAAoBG,GAAYjK,CAAa,GACzB8J,EAAAK,IAAcF,IAAa,GAAGjK,CAAa;AAAA,IAAA,CAChE;AAAA,EAAA,CACF,GAEMN;AACT;AAkEA,SAAS6K,GACPvK,GACA6J,GACW;AACX,SAAOA,EAAS,QAAQ,CAACrJ,GAASgF,MAAU;AACtC,QAAA,CAACxF,EAAc,IAAIwF,CAAK;AAAU,aAAAhF;AAEhC,UAAAgK,IAAuBxK,EAAc,IAAIwF,CAAK;AACpD,WAAKgF,IAEEhK,EAAQ,QAAQgK,CAAoB,IAFThK;AAAA,EAES,CAC5C;AACH;AAEA,SAASiK,GACPZ,GACAa,GACApC,GACW;AAEJ,SAAAuB,EAAS,OAAO,CAACrJ,MAIf,CAHckK,EAAe,SAAS,KAAK,CAAClC,MAC1CpF,GAASoF,GAAGhI,CAAO,IAAI,KAAK,IAAI8H,CAAM,IAAIH,CAClD,CAEF;AACH;AAEgB,SAAAwC,EAAWpL,GAAY+I,GAAyB;AAC9D,QAAMsC,IAAkBrL,EAAK,YAAY+I,IAAS,CAACA,GAC7CI,IAAiBN,EAAW7I,EAAK,UAAUqL,CAAe;AAEhE,MAAIlC,EAAe,SAAS;AAAG,WAAO,IAAIrJ,EAAQ;AAK5C,QAAAK,IAAmBkK,GAA4BlB,CAAc;AAE/D,MAAA,CAAChJ,EAAiB,MAAM;AACpB,UAAAmL,IAAgB,IAAIzL,EAAKsJ,CAAc;AAC7C,WAAO,IAAIrJ,EAAQ,CAAC,IAAIF,EAAO0L,CAAa,CAAC,CAAC;AAAA,EAKhD;AACA,QAAMC,IAAgBP;AAAA,IACpB7K;AAAA,IACAgJ;AAAA,EAAA,GAIIqC,IAAiBN,GAAwBK,GAAevL,GAAM+I,CAAM;AAE1E,MAAI,CAACyC,EAAe;AAAQ,WAAO,IAAI1L,EAAQ;AAI/C,QAAM2L,IAFkBC,GAAeF,CAAc,EAGlD,OAAO,CAACvC,MAAMA,EAAE,SAAS,CAAC,EAC1B,OAAO,CAACA,MAAMO,EAAWP,EAAE,CAAC,EAAE,YAAYA,EAAE,GAAG,EAAE,EAAG,SAAS,CAAC,EAC9D,IAAI,CAACA,MAAM,IAAIpJ,EAAKoJ,CAAC,CAAC;AAEzB,SAAKwC,EAAS,SACP,IAAI3L,EAAQ2L,EAAS,IAAI,CAACE,MAAM,IAAI/L,EAAO+L,CAAC,CAAC,CAAC,IADxB,IAAI7L,EAAQ;AAE3C;AAoCO,SAAS8L,GACd3L,GACA4L,GACAC,IAA2B,SAClB;AACT,QAAM/C,IAAS8C,IAAQ,GACjBE,IAAsBlD,EAAW5I,EAAO,UAAU8I,GAAQ,EAAK,GAC/DiD,IAAqBnD,EAAW5I,EAAO,UAAU,CAAC8I,GAAQ,EAAK,EAAE;AAAA,IACrE,CAAClI,MAAMA,EAAE,QAAQ;AAAA,EAAA;AAEnB,EAAAmL,EAAmB,QAAQ;AAErB,QAAAC,IAAa,CAACC,GAAsBC,MACpCL,MAAW,UACNM;AAAA,IACLF,EAAY;AAAA,IACZC,EAAU;AAAA,IACVD,EAAY;AAAA,EAAA,IAGT,IAAIxD,EAAKwD,EAAY,WAAWC,EAAU,UAAU,GAGvDhD,IAAiB;AAAA,IACrB,GAAG4C;AAAA,IACHE;AAAA,MACEF,EAAoBA,EAAoB,SAAS,CAAC;AAAA,MAClDC,EAAmB,CAAC;AAAA,IACtB;AAAA,IACA,GAAGA;AAAA,IACHC;AAAA,MACED,EAAmBA,EAAmB,SAAS,CAAC;AAAA,MAChDD,EAAoB,CAAC;AAAA,IACvB;AAAA,EAAA,GAGI5L,IAAmBkK,GAA4BlB,CAAc;AAE/D,MAAA,CAAChJ,EAAiB,MAAM;AACpB,UAAAmL,IAAgB,IAAIzL,EAAKsJ,CAAc;AAC7C,WAAO,IAAIrJ,EAAQ,CAAC,IAAIF,EAAO0L,CAAa,CAAC,CAAC;AAAA,EAChD;AACA,QAAMC,IAAgBP;AAAA,IACpB7K;AAAA,IACAgJ;AAAA,EAAA,GAIIqC,IAAiBN,GAAwBK,GAAetL,GAAQ8I,CAAM;AAE5E,MAAI,CAACyC,EAAe;AAAQ,WAAO,IAAI1L,EAAQ;AAI/C,QAAM2L,IAFkBC,GAAeF,CAAc,EAGlD,OAAO,CAACvC,MAAMA,EAAE,SAAS,CAAC,EAC1B,OAAO,CAACA,MAAMO,EAAWP,EAAE,CAAC,EAAE,YAAYA,EAAE,GAAG,EAAE,EAAG,SAAS,CAAC,EAC9D,IAAI,CAACA,MAAM,IAAIpJ,EAAKoJ,CAAC,CAAC;AAEzB,SAAKwC,EAAS,SACP,IAAI3L,EAAQ2L,EAAS,IAAI,CAAC,MAAM,IAAI7L,EAAO,CAAC,CAAC,CAAC,IADxB,IAAIE,EAAQ;AAE3C;ACxagB,SAAAuM,GACdC,GACAC,GACS;AACT,QAAMF,IAAgBC,EAAQ,IAAI,CAAC9K,MAAW;AAC5C,UAAMgL,IAAatK;AAAA,MACjBV,EAAO,MAAM,IAAI,CAACmK,MAAMP,EAAWO,GAAGY,CAAc,CAAC;AAAA,IAAA;AAEvD,WAAOlK,GAAI+I,EAAW5J,EAAO,SAAS+K,CAAc,GAAGC,CAAU;AAAA,EAAA,CAClE;AAED,SAAOtK,EAAQmK,CAAa;AAC9B;AAEgB,SAAAI,GACdH,GACAT,GACS;AACT,QAAMa,IAAY,KAAK,IAAIb,IAAQ,CAAC,GAE9BQ,IAAgBC,EAAQ;AAAA,IAAI,CAAC9K,MACjCU;AAAA,MACEV,EAAO,SAAS,IAAI,CAACmK,MACZtJ,GAAI+I,EAAWO,GAAGe,CAAS,GAAGtB,EAAWO,GAAG,CAACe,CAAS,CAAC,CAC/D;AAAA,IACH;AAAA,EAAA;AAGF,SAAOxK,EAAQmK,CAAa;AAC9B;ACvBgB,SAAAtD,GACdpJ,GACA4M,GACS;AACT,SAAOF,GAAc3M,EAAcC,CAAK,GAAG4M,CAAc;AAC3D;AAEgB,SAAAI,GACdhN,GACAiN,GACA,EAAE,QAAAd,IAAS,QAAQ,IAAmC,IAC7C;AACT,SAAInM,aAAiBiD,IACZgJ,GAAcjM,GAAOiN,GAAiBd,CAAM,IAE9CW,GAAqB/M,EAAcC,CAAK,GAAGiN,CAAe;AACnE;ACnBA,SAASC,EAAY,CAAChG,GAAGC,CAAC,GAAqB;AAC7C,SAAO,GAAGD,KAAKC;AACjB;AAEO,SAASgG,EAAiB7L,GAAkB;AACjD,MAAIA,aAAmByH;AACd,WAAA,KAAKmE,EAAY5L,EAAQ,SAAS;AAE3C,MAAIA,aAAmB0H;AACrB,WAAO,KAAK1H,EAAQ,UAAUA,EAAQ,YACpCA,EAAQ,gBAAgB,KAAK,KAAK,MAAM,OACtCA,EAAQ,YAAY,MAAM,OAAO4L,EAAY5L,EAAQ,SAAS;AAEpE,MAAIA,aAAmB8L;AACd,WAAA,KAAK9L,EAAQ,eAAeA,EAAQ,eACzCA,EAAQ,YAAY+L,MAClB/L,EAAQ,aAAa,KAAK,KAAK,MAAM,OACvCA,EAAQ,YAAY,MAAM,OACxB4L,EAAY5L,EAAQ,SAAS;AAGnC,MAAIA,aAAmBgM;AACrB,WAAO,KAAK;AAAA,MACVJ,EAAY5L,EAAQ,YAAY;AAAA,MAChC4L,EAAY5L,EAAQ,SAAS;AAAA,IAAA,EAC7B,KAAK,GAAG;AAGZ,MAAIA,aAAmBiM;AACrB,WAAO,KAAK;AAAA,MACVL,EAAY5L,EAAQ,iBAAiB;AAAA,MACrC4L,EAAY5L,EAAQ,gBAAgB;AAAA,MACpC4L,EAAY5L,EAAQ,SAAS;AAAA,IAAA,EAC7B,KAAK,GAAG;AAGN,QAAA,IAAI,MAAM,sBAAsB;AACxC;AC1CO,SAASkM,GAAQnN,GAAY;AAClC,QAAMoN,IAAQ,KAAKpN,EAAK,WAAW,KAAK,GAAG,KACrCsK,IAAWtK,EAAK,SAAS,IAAI8M,CAAgB,EAAE,KAAK,GAAG;AAC7D,SAAO,GAAGM,KAAS9C;AACrB;ACJO,SAAS+C,GAAU7L,GAAgB;AAExC,SAAO,YADMA,EAAO,SAAS,IAAI2L,EAAO,EAAE,KAAK,GAAG;AAEpD;ACHO,SAASG,GAAW5K,GAAkB;AACpC,SAAA;AAAA,IACLA,EAAQ,QAAQ,IAAI2K,EAAS,EAAE,KAAK;AAAA,CAAI;AAAA;AAE5C;ACJO,SAASE,GAAUtN,GAAgB;AACxC,QAAMmN,IAAQ,KAAKnN,EAAO,WAAW,KAAK,GAAG,KACvCqK,IAAWrK,EAAO,SAAS,IAAI6M,CAAgB,EAAE,KAAK,GAAG;AAC/D,SAAO,GAAGM,KAAS9C;AACrB;ACLgB,SAAAkD,GAAWC,GAAmBC,IAAS,GAAG;AAClD,QAAAC,IAAOF,EAAK,OAAOC,GACnBE,IAAOH,EAAK,OAAOC;AAElB,SAAA,GAAGC,KAAQC,KAAQH,EAAK,QAAQ,IAAIC,KACzCD,EAAK,SAAS,IAAIC;AAEtB;AAKO,SAASG,EACdC,GACAC,GACAL,IAAS,GACTM,GACA;AACM,QAAAC,IAAOT,GAAWO,GAAaL,CAAM,GACrCQ,IAAQF,IACV,UAAUD,EAAY,QAAQ,IAAIL,IAASM,cACzCD,EAAY,SAAS,IAAIL,IACxBM,OACH;AAEG,SAAA;AAAA,iEACwDC,wFAA2FC;AAAA,MACtJJ;AAAA;AAEN;ACdO,SAASK,EAAQxO,GAAc;AACpC,MAAIA,aAAiBG;AACnB,WAAOwN,GAAW3N,CAAK;AACzB,MAAWA,aAAiBC;AAC1B,WAAOyN,GAAU1N,CAAK;AACxB,MAAWA,aAAiBE;AACnB,WAAA,YAAYsN,GAAQxN,CAAK;AAClC,MAAWA,aAAiBiD;AACnB,WAAA,YAAY2K,GAAU5N,CAAK;AACpC,MAAWyO,GAAUzO,CAAK;AACxB,WAAO,YAAY,KAAKA,EAAM,WAAW,KAAK,GAAG,OAAOmN;AAAA,MACtDnN;AAAA,IACF;AAEM,QAAA,IAAI,MAAM,oBAAoB;AAExC;AAIA,MAAM0O,IAAe,CAAC1O,MACpB,WAAWA,IAAQA,EAAM,QAAQA,GAE7B2O,IAAY,CAAC3O,GAAwBmO,MAAiB;AAC1D,MAAI,EAAE,WAAWnO;AAAe,WAAAmO;AAC1B,QAAA,EAAE,OAAAS,EAAU,IAAA5O;AAClB,SAAK4O,IACE,cAAcA,MAAUT,UADZA;AAErB,GAEMU,IAAW,CAACf,MACT,IAAIgB,GAAYhB,EAAK,MAAM,CAACA,EAAK,MAAMA,EAAK,MAAM,CAACA,EAAK,IAAI;AAG9D,SAASiB,GACd/O,GACA;AAAA,EACE,QAAA+N,IAAS;AAAA,EACT,MAAAM,IAAO;AAAA,EACP,SAAAW;AACF,IAII,IACJ;AACI,MAAA,MAAM,QAAQhP,CAAK,GAAG;AAClBiP,UAAAA,IAAUjP,EAAM,IAAI,CAACkB,MAAMwN,EAAaxN,CAAC,EAAE,OAAA,CAAQ,GACnDiN,IAAOc,EACV,IAAI,CAAC/N,GAAG2F,MAAM8H,EAAU3O,EAAM6G,CAAC,GAAG2H,EAAQtN,CAAC,CAAC,CAAC,EAC7C,KAAK;AAAA,CAAI,GACN4M,IAAOmB,EACV,MAAM,CAAC,EACP,OAAO,CAACnB,GAAM5M,MAAM4M,EAAK,MAAM5M,EAAE,WAAW,GAAG+N,EAAQ,CAAC,EAAE,WAAW;AAEjE,WAAAf,EAAQC,GAAMa,IAAUH,EAASG,CAAO,IAAIlB,GAAMC,GAAQM,CAAI;AAAA,EACvE;AACA,QAAMY,IAAUP,EAAa1O,CAAK,EAAE,OAAO;AACpC,SAAAkO;AAAA,IACLS,EAAU3O,GAAOwO,EAAQS,CAAO,CAAC;AAAA,IACjCD,IAAUH,EAASG,CAAO,IAAIC,EAAQ;AAAA,IACtClB;AAAA,IACAM;AAAA,EAAA;AAEJ;ACxEA,MAAMa,KAAgB,CAACC,MAAc;AAC/B,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAIpG,EAAKoG,EAAK,YAAYA,EAAK,SAAS;AAE7C,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAInG;AAAA,MACTmG,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,IAAA;AAGL,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAI/B;AAAA,MACT+B,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACL,EAAE,YAAY,MAAM;AAAA,IAAA;AAGpB,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAI7B;AAAA,MACT6B,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,IAAA;AAGL,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAI5B;AAAA,MACT4B,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,IAAA;AAGH,QAAA,IAAI,MAAM,sBAAsB;AACxC,GAEMC,IAAa,CAACD,MAAc;AAChC,QAAMxE,IAAWwE,EAAK,SAAS,IAAID,EAAa;AACzC,SAAA,IAAIhP,EAAKyK,CAAQ;AAC1B,GAEM0E,KAAe,CAACF,MAAc;AAC5B,QAAAG,IAAUF,EAAWD,EAAK,OAAO,GACjCI,IAAQJ,EAAK,MAAM,IAAIC,CAAU;AAChC,SAAA,IAAInP,EAAOqP,GAASC,CAAK;AAClC,GAEMC,KAAgB,CAACL,MAAc;AACnC,QAAMxC,IAAUwC,EAAK,QAAQ,IAAIE,EAAY;AACtC,SAAA,IAAIlP,EAAQwM,CAAO;AAC5B;AAEO,SAAS8C,GAAWN,GAAW;AAChC,MAAAA,EAAK,SAAS;AAChB,WAAOK,GAAcL,CAAI;AAEvB,MAAAA,EAAK,SAAS;AAChB,WAAOE,GAAaF,CAAI;AAEtB,MAAAA,EAAK,SAAS;AAChB,WAAOC,EAAWD,CAAI;AAGtB,MAAAA,EAAK,SAAS,UACdA,EAAK,SAAS,SACdA,EAAK,SAAS,iBACdA,EAAK,SAAS;AAEd,WAAOD,GAAcC,CAAI;AAErB,QAAA,IAAI,MAAM,oBAAoB;AACtC;ACnFa,MAAAO,IAAU,KAAK,KAAK,KACpBrC,KAAU,MAAM,KAAK;AAElB,SAAAsC,GAAiBC,GAAWC,GAAuB;AACjE,QAAM3I,IAAI,KAAK,IAAI2I,IAAQH,CAAO,IAAIE,GAChCzI,IAAI,KAAK,IAAI0I,IAAQH,CAAO,IAAIE;AAC/B,SAAA,CAAC1I,GAAGC,CAAC;AACd;AAEO,SAAS2I,GAAiB,CAAC5I,GAAGC,CAAC,GAA6B;AACjE,QAAMyI,IAAI,KAAK,KAAK1I,IAAIA,IAAIC,IAAIA,CAAC,GAC3B0I,IAAQ,KAAK,MAAM1I,GAAGD,CAAC,IAAImG;AAC1B,SAAA,CAACuC,GAAGC,CAAK;AAClB;"}
|
|
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/offsets/offsetStroke.ts","../src/algorithms/offsets/offsetFigure.ts","../src/offsetOperations.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 { 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 { offsetSegment, DegenerateSegment } 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\";\n\nconst PRECISION = 1e-8;\n\nexport function rawOffsets(\n segmentsToOffset: Segment[],\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\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 offsettedArray = rawOffsets(loop.segments, 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 offsettedArray = rawOffsets(strand.segments, offset, false);\n const backOffsettedArray = rawOffsets(strand.segments, -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 frontOffsettedArray = rawOffsets(strand.segments, offset, false);\n const backOffsettedArray = rawOffsets(strand.segments, -offset, false).map(\n (s) => s.reverse(),\n );\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 { 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 } 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} 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","PRECISION","rawOffsets","segmentsToOffset","offset","offsetSegments","c","offsetSegment","offsettedArray","savedLastSegment","previousSegment","appendSegment","DegenerateSegment","sameVector","iterateOffsetSegments","previousLastPoint","firstPoint","pointIntersections","intersection","originalEndpoint","distances","splitPreviousSegment","splitSegment","clockwise","crossProduct","joiner","findOffsetSelfIntersections","segments","updateIntersections","newPoints","firstSegment","firstIndex","secondSegment","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","splitSegmentsAtIntersections","segmentIntersections","pruneDegenerateSegments","originalStroke","offsetLoop","correctedOffset","offsettedLoop","splitSegments","prunedSegments","newLoops","stitchSegments","l","outlineStrand","width","endCap","frontOffsettedArray","backOffsettedArray","makeJoiner","fromSegment","toSegment","tangentArc","offsetFigures","figures","offsetDistance","innerShape","outlineStrokeFigures","absOffset","outlineStroke","outlineDistance","svgBody","svgDiagram","svgFigure","svgLoop","svgStrand","isSegment","svgSegmentToPath","extractShape","addConfig","body","color","flibBbox","bbox","BoundingBox","exportSVG","margin","unit","viewBox","flipped","wrapSVG","importSegment","json","EllipseArc","QuadraticBezier","CubicBezier","importLoop","importFigure","contour","holes","importDiagram","importJSON","DEG2RAD","RAD2DEG","polarToCartesian","r","theta","cartesianToPolar"],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { L as $, A as f, E as l, R as u, Q as e, C as h } from "./QuadraticBezier-BzVqiExF.js";
|
|
2
|
+
function i([t, n]) {
|
|
3
|
+
return `${t} ${n}`;
|
|
4
|
+
}
|
|
5
|
+
function s(t) {
|
|
6
|
+
if (t instanceof $)
|
|
7
|
+
return `L ${i(t.lastPoint)}`;
|
|
8
|
+
if (t instanceof f)
|
|
9
|
+
return `A ${t.radius} ${t.radius} 0 ${t.angularLength > Math.PI ? "1" : "0"} ${t.clockwise ? "0" : "1"} ${i(t.lastPoint)}`;
|
|
10
|
+
if (t instanceof l)
|
|
11
|
+
return `A ${t.majorRadius} ${t.minorRadius} ${t.tiltAngle * u} ${t.deltaAngle > Math.PI ? "1" : "0"} ${t.clockwise ? "0" : "1"} ${i(t.lastPoint)}`;
|
|
12
|
+
if (t instanceof e)
|
|
13
|
+
return `Q ${[
|
|
14
|
+
i(t.controlPoint),
|
|
15
|
+
i(t.lastPoint)
|
|
16
|
+
].join(" ")}`;
|
|
17
|
+
if (t instanceof h)
|
|
18
|
+
return `C ${[
|
|
19
|
+
i(t.firstControlPoint),
|
|
20
|
+
i(t.lastControlPoint),
|
|
21
|
+
i(t.lastPoint)
|
|
22
|
+
].join(" ")}`;
|
|
23
|
+
throw new Error("Unknown segment type");
|
|
24
|
+
}
|
|
25
|
+
function w(t) {
|
|
26
|
+
const n = `M ${t.firstPoint.join(" ")}`, o = t.segments.map(s).join(" ");
|
|
27
|
+
return `${n} ${o} Z`;
|
|
28
|
+
}
|
|
29
|
+
function p(t) {
|
|
30
|
+
return `<path d="${t.allLoops.map(w).join(" ")}" />`;
|
|
31
|
+
}
|
|
32
|
+
function d(t) {
|
|
33
|
+
return `<g>
|
|
34
|
+
${t.figures.map(p).join(`
|
|
35
|
+
`)}
|
|
36
|
+
</g>`;
|
|
37
|
+
}
|
|
38
|
+
function j(t) {
|
|
39
|
+
const n = `M ${t.firstPoint.join(" ")}`, o = t.segments.map(s).join(" ");
|
|
40
|
+
return `${n} ${o}`;
|
|
41
|
+
}
|
|
42
|
+
function v(t, n = 1) {
|
|
43
|
+
const o = t.xMin - n, r = t.yMin - n;
|
|
44
|
+
return `${o} ${r} ${t.width + 2 * n} ${t.height + 2 * n}`;
|
|
45
|
+
}
|
|
46
|
+
function A(t, n, o = 1, r) {
|
|
47
|
+
const a = v(n, o), c = r ? `width="${n.width + 2 * o}${r}" height="${n.height + 2 * o}${r}"` : "";
|
|
48
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
49
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="${a}" fill="none" stroke="black" stroke-width="0.2%" vector-effect="non-scaling-stroke" ${c}>
|
|
50
|
+
${t}
|
|
51
|
+
</svg>`;
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
p as a,
|
|
55
|
+
w as b,
|
|
56
|
+
j as c,
|
|
57
|
+
s as d,
|
|
58
|
+
v as e,
|
|
59
|
+
d as s,
|
|
60
|
+
A as w
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=svg-BylQQgsL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg-BylQQgsL.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=\"black\" 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,uFAAuFC,CAAK;AAAA,MAC3JJ,CAAI;AAAA;AAEV;"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";const r=require("./QuadraticBezier-BAVasVfu.cjs");function o([t,i]){return`${t} ${i}`}function a(t){if(t instanceof r.Line)return`L ${o(t.lastPoint)}`;if(t instanceof r.Arc)return`A ${t.radius} ${t.radius} 0 ${t.angularLength>Math.PI?"1":"0"} ${t.clockwise?"0":"1"} ${o(t.lastPoint)}`;if(t instanceof r.EllipseArc)return`A ${t.majorRadius} ${t.minorRadius} ${t.tiltAngle*r.RAD2DEG} ${t.deltaAngle>Math.PI?"1":"0"} ${t.clockwise?"0":"1"} ${o(t.lastPoint)}`;if(t instanceof r.QuadraticBezier)return`Q ${[o(t.controlPoint),o(t.lastPoint)].join(" ")}`;if(t instanceof r.CubicBezier)return`C ${[o(t.firstControlPoint),o(t.lastControlPoint),o(t.lastPoint)].join(" ")}`;throw new Error("Unknown segment type")}function c(t){const i=`M ${t.firstPoint.join(" ")}`,n=t.segments.map(a).join(" ");return`${i} ${n} Z`}function $(t){return`<path d="${t.allLoops.map(c).join(" ")}" />`}function l(t){return`<g>
|
|
2
|
+
${t.figures.map($).join(`
|
|
3
|
+
`)}
|
|
4
|
+
</g>`}function h(t){const i=`M ${t.firstPoint.join(" ")}`,n=t.segments.map(a).join(" ");return`${i} ${n}`}function e(t,i=1){const n=t.xMin-i,s=t.yMin-i;return`${n} ${s} ${t.width+2*i} ${t.height+2*i}`}function v(t,i,n=1,s){const u=e(i,n),f=s?`width="${i.width+2*n}${s}" height="${i.height+2*n}${s}"`:"";return`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
5
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="${u}" fill="none" stroke="black" stroke-width="0.2%" vector-effect="non-scaling-stroke" ${f}>
|
|
6
|
+
${t}
|
|
7
|
+
</svg>`}exports.svgDiagram=l;exports.svgFigure=$;exports.svgLoop=c;exports.svgSegmentToPath=a;exports.svgStrand=h;exports.svgViewbox=e;exports.wrapSVG=v;
|
|
8
|
+
//# sourceMappingURL=svg-D0nYyMk7.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg-D0nYyMk7.cjs","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=\"black\" 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":"+DAQA,SAASA,EAAY,CAACC,EAAGC,CAAC,EAAqB,CACtC,MAAA,GAAGD,CAAC,IAAIC,CAAC,EAClB,CAEO,SAASC,EAAiBC,EAAkB,CACjD,GAAIA,aAAmBC,EAAAA,KACrB,MAAO,KAAKL,EAAYI,EAAQ,SAAS,CAAC,GAE5C,GAAIA,aAAmBE,EAAAA,IACd,MAAA,KAAKF,EAAQ,MAAM,IAAIA,EAAQ,MAAM,MAC1CA,EAAQ,cAAgB,KAAK,GAAK,IAAM,GAC1C,IAAIA,EAAQ,UAAY,IAAM,GAAG,IAAIJ,EAAYI,EAAQ,SAAS,CAAC,GAErE,GAAIA,aAAmBG,EAAAA,WACd,MAAA,KAAKH,EAAQ,WAAW,IAAIA,EAAQ,WAAW,IACpDA,EAAQ,UAAYI,EACtB,OAAA,IAAIJ,EAAQ,WAAa,KAAK,GAAK,IAAM,GAAG,IAC1CA,EAAQ,UAAY,IAAM,GAC5B,IAAIJ,EAAYI,EAAQ,SAAS,CAAC,GAGpC,GAAIA,aAAmBK,EAAAA,gBACrB,MAAO,KAAK,CACVT,EAAYI,EAAQ,YAAY,EAChCJ,EAAYI,EAAQ,SAAS,CAAA,EAC7B,KAAK,GAAG,CAAC,GAGb,GAAIA,aAAmBM,EAAAA,YACrB,MAAO,KAAK,CACVV,EAAYI,EAAQ,iBAAiB,EACrCJ,EAAYI,EAAQ,gBAAgB,EACpCJ,EAAYI,EAAQ,SAAS,CAAA,EAC7B,KAAK,GAAG,CAAC,GAGP,MAAA,IAAI,MAAM,sBAAsB,CACxC,CC1CO,SAASO,EAAQC,EAAY,CAClC,MAAMC,EAAQ,KAAKD,EAAK,WAAW,KAAK,GAAG,CAAC,GACtCE,EAAWF,EAAK,SAAS,IAAIT,CAAgB,EAAE,KAAK,GAAG,EACtD,MAAA,GAAGU,CAAK,IAAIC,CAAQ,IAC7B,CCJO,SAASC,EAAUC,EAAgB,CAExC,MAAO,YADMA,EAAO,SAAS,IAAIL,CAAO,EAAE,KAAK,GAAG,CAC3B,MACzB,CCHO,SAASM,EAAWC,EAAkB,CACpC,MAAA;AAAA,IACLA,EAAQ,QAAQ,IAAIH,CAAS,EAAE,KAAK;AAAA,CAAI,CAAC;AAAA,KAE7C,CCJO,SAASI,EAAUC,EAAgB,CACxC,MAAMP,EAAQ,KAAKO,EAAO,WAAW,KAAK,GAAG,CAAC,GACxCN,EAAWM,EAAO,SAAS,IAAIjB,CAAgB,EAAE,KAAK,GAAG,EACxD,MAAA,GAAGU,CAAK,IAAIC,CAAQ,EAC7B,CCLgB,SAAAO,EAAWC,EAAmBC,EAAS,EAAG,CAClD,MAAAC,EAAOF,EAAK,KAAOC,EACnBE,EAAOH,EAAK,KAAOC,EAEzB,MAAO,GAAGC,CAAI,IAAIC,CAAI,IAAIH,EAAK,MAAQ,EAAIC,CAAM,IAC/CD,EAAK,OAAS,EAAIC,CACpB,EACF,CAKO,SAASG,EACdC,EACAC,EACAL,EAAS,EACTM,EACA,CACM,MAAAC,EAAOT,EAAWO,EAAaL,CAAM,EACrCQ,EAAQF,EACV,UAAUD,EAAY,MAAQ,EAAIL,CAAM,GAAGM,CAAI,aAC7CD,EAAY,OAAS,EAAIL,CAC3B,GAAGM,CAAI,IACP,GAEG,MAAA;AAAA,iEACwDC,CAAI,uFAAuFC,CAAK;AAAA,MAC3JJ,CAAI;AAAA,OAEV"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Figure } from
|
|
1
|
+
import { Figure } from '../../models/Figure';
|
|
2
2
|
export declare function fuseIntersectingFigures(figures: Figure[]): Figure[];
|
|
3
3
|
export declare function fuseFigures(first: Figure, second: Figure): Figure[];
|
|
4
4
|
export declare function cutFigures(first: Figure, second: Figure): Figure[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Loop } from
|
|
2
|
-
import { Strand } from
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import { Loop } from '../../models/Loop';
|
|
2
|
+
import { Strand } from '../../models/Strand';
|
|
3
|
+
import { Figure } from '../../models/Figure';
|
|
4
|
+
import { Stroke } from '../../models/Stroke';
|
|
5
5
|
export declare function eraseStrandWithinLoop(strand: Stroke, loop: Loop, eraseOnBorder?: boolean): Strand[];
|
|
6
6
|
export declare function eraseStrandOutsideLoop(strand: Stroke, loop: Loop, eraseOnBorder?: boolean): Strand[];
|
|
7
7
|
export declare function eraseStrandWithinFigure(strand: Stroke, figure: Figure, eraseOnBorder?: boolean): Strand[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Vector } from
|
|
2
|
-
import { Segment } from
|
|
3
|
-
import { Strand } from
|
|
1
|
+
import { Vector } from '../../definitions';
|
|
2
|
+
import { Segment } from '../../models/segments/Segment';
|
|
3
|
+
import { Strand } from '../../models/Strand';
|
|
4
4
|
export declare function strandsBetweenIntersections(segments: Segment[], allIntersections: Vector[], allCommonSegments: Segment[]): Generator<Strand>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Arc } from '../../models/segments/Arc.js';
|
|
2
2
|
export declare function arcArcDistance(arc1: Arc, arc2: Arc): number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Segment } from '../../models/segments/Segment.js';
|
|
2
2
|
export declare function distance(segment1: Segment, segment2: Segment): number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Line } from '../../models/segments/Line.js';
|
|
2
2
|
export declare function lineLineDistance(line1: Line, line2: Line): number;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Segment } from '../models/segments/Segment.js';
|
|
2
2
|
export declare function filletSegments(firstSegment: Segment, secondSegment: Segment, radius: number): any[];
|
|
3
3
|
export declare function chamferSegments(firstSegment: Segment, secondSegment: Segment, radius: number): any[];
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Vector } from
|
|
2
|
-
import { Arc } from
|
|
1
|
+
import { Vector } from '../../definitions.js';
|
|
2
|
+
import { Arc } from '../../models/segments/Arc.js';
|
|
3
3
|
export declare function arcArcIntersection(arc1: Arc, arc2: Arc, includeOverlaps?: boolean, precision?: number): Vector[] | Arc[];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { EllipseArc } from '../../models/segments/EllipseArc.js';
|
|
2
|
+
import { Arc } from '../../models/segments/Arc.js';
|
|
3
|
+
import { Vector } from '../../definitions.js';
|
|
4
|
+
import { CubicBezier } from '../../models/segments/CubicBezier.js';
|
|
5
|
+
export declare function arcsCubicBezierIntersection(arc: EllipseArc | Arc, curve: CubicBezier): Vector[];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { EllipseArc } from '../../models/segments/EllipseArc.js';
|
|
2
|
+
import { Arc } from '../../models/segments/Arc.js';
|
|
3
|
+
import { Vector } from '../../definitions.js';
|
|
4
|
+
import { QuadraticBezier } from '../../models/segments/QuadraticBezier.js';
|
|
5
|
+
export declare function arcsQuadraticBezierIntersection(arc: EllipseArc | Arc, curve: QuadraticBezier): Vector[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Vector } from
|
|
2
|
-
import { CubicBezier } from
|
|
3
|
-
import { QuadraticBezier } from
|
|
1
|
+
import { Vector } from '../../definitions.js';
|
|
2
|
+
import { CubicBezier } from '../../models/segments/CubicBezier.js';
|
|
3
|
+
import { QuadraticBezier } from '../../models/segments/QuadraticBezier.js';
|
|
4
4
|
declare class FatLine {
|
|
5
5
|
readonly firstPoint: Vector;
|
|
6
6
|
readonly lastPoint: Vector;
|