pantograph2d 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/exportJSON-944c662d.cjs +4 -0
- package/dist/exportJSON-944c662d.cjs.map +1 -0
- package/dist/exportJSON-c42ca4ac.js +1427 -0
- package/dist/exportJSON-c42ca4ac.js.map +1 -0
- package/dist/models.d.ts +44 -0
- package/dist/pantograph/models.cjs +1 -1
- package/dist/pantograph/models.js +9 -8
- package/dist/pantograph.cjs +7 -7
- package/dist/pantograph.cjs.map +1 -1
- package/dist/pantograph.d.ts +178 -2
- package/dist/pantograph.js +762 -109
- package/dist/pantograph.js.map +1 -1
- package/package.json +7 -2
- package/dist/Diagram-81a7df15.cjs +0 -4
- package/dist/Diagram-81a7df15.cjs.map +0 -1
- package/dist/Diagram-8b41118e.js +0 -944
- package/dist/Diagram-8b41118e.js.map +0 -1
package/dist/pantograph.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pantograph.js","sources":["../src/draw.ts","../src/operations.ts","../src/export/svg/svgSegment.ts","../src/export/svg/svgLoop.ts","../src/export/svg/svgFigure.ts","../src/export/svg/svgDiagram.ts","../src/export/svg/wrapSVG.ts","../src/export/svg/exportSVG.ts"],"sourcesContent":["import { Vector } from \"./definitions\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { Line } from \"./models/segments/Line\";\nimport { Segment } from \"./models/segments/Segment\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n} from \"./vectorOperations\";\n\nfunction closeSegments(segments: Segment[]) {\n if (!segments.length) throw new Error(\"No segments to close\");\n const firstSegment = segments[0];\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = segments.at(-1)!;\n\n if (sameVector(firstSegment.firstPoint, lastSegment.lastPoint))\n return segments;\n return [\n ...segments,\n new Line(lastSegment.lastPoint, firstSegment.firstPoint),\n ];\n}\n\nfunction loopySegmentsToDiagram(segments: Segment[]) {\n // Here we will need to do our best to fix cases where the drawing is\n // broken in some way (i.e. self-intersecting loops)\n\n return new Diagram([new Figure(new Loop(segments))]);\n}\n\nexport class DrawingPen {\n protected pointer: Vector;\n protected firstPoint: Vector;\n protected pendingSegments: Segment[];\n\n constructor(origin: Vector = [0, 0]) {\n this.pointer = origin;\n this.firstPoint = origin;\n\n this.pendingSegments = [];\n }\n\n movePointerTo(point: Vector): this {\n if (this.pendingSegments.length)\n throw new Error(\n \"You can only move the pointer if there is no segment defined\"\n );\n\n this.pointer = point;\n this.firstPoint = point;\n return this;\n }\n\n protected saveSegment(segment: Segment) {\n this.pendingSegments.push(segment);\n return this;\n }\n\n lineTo(point: Vector): this {\n const segment = new Line(this.pointer, point);\n this.pointer = point;\n return this.saveSegment(segment);\n }\n\n line(xDist: number, yDist: number): this {\n return this.lineTo([this.pointer[0] + xDist, this.pointer[1] + yDist]);\n }\n\n vLine(distance: number): this {\n return this.line(0, distance);\n }\n\n hLine(distance: number): this {\n return this.line(distance, 0);\n }\n\n vLineTo(yPos: number): this {\n return this.lineTo([this.pointer[0], yPos]);\n }\n\n hLineTo(xPos: number): this {\n return this.lineTo([xPos, this.pointer[1]]);\n }\n\n polarLineTo([r, theta]: Vector): this {\n const angleInRads = theta * DEG2RAD;\n const point = polarToCartesian(r, angleInRads);\n return this.lineTo(point);\n }\n\n polarLine(distance: number, angle: number): this {\n const angleInRads = angle * DEG2RAD;\n const [x, y] = polarToCartesian(distance, angleInRads);\n return this.line(x, y);\n }\n\n tangentLine(distance: number): this {\n const previousCurve = this.pendingSegments.at(-1);\n\n if (!previousCurve)\n throw new Error(\"You need a previous segment to sketch a tangent line\");\n\n const [xDir, yDir] = previousCurve.tangentAtLastPoint;\n return this.line(xDir * distance, yDir * distance);\n }\n\n close(): Diagram {\n const segments = closeSegments(this.pendingSegments);\n return loopySegmentsToDiagram(segments);\n }\n\n closeWithMirror(): Diagram {\n if (!this.pendingSegments.length) throw new Error(\"No segments to close\");\n\n const firstSegment = this.pendingSegments[0];\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = this.pendingSegments.at(-1)!;\n\n const mirrorVector = subtract(\n lastSegment.lastPoint,\n firstSegment.firstPoint\n );\n const mirrorTranform = new TransformationMatrix().mirrorLine(\n mirrorVector,\n firstSegment.firstPoint\n );\n\n const mirroredSegments = this.pendingSegments.map((segment) =>\n segment.transform(mirrorTranform).reverse()\n );\n mirroredSegments.reverse();\n\n return loopySegmentsToDiagram([\n ...this.pendingSegments,\n ...mirroredSegments,\n ]);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n","import {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"./algorithms/boolean/figureBooleans\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\n\nfunction 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\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","import { Line } from \"../../models/segments/Line\";\nimport { Segment } from \"../../models/segments/Segment\";\n\nexport function svgSegmentToPath(segment: Segment) {\n if (segment instanceof Line) {\n return `L ${segment.lastPoint.join(\" \")}`;\n }\n throw new Error(\"Unknown segment type\");\n}\n","import type { Loop } from \"../../models/Loop\";\nimport { svgSegmentToPath } from \"./svgSegment\";\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\";\nimport { svgLoop } from \"./svgLoop\";\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\";\nimport { svgFigure } from \"./svgFigure\";\n\nexport function svgDiagram(diagram: Diagram) {\n return `<g>\n ${diagram.figures.map(svgFigure).join(\"\\n\")}\n</g>`;\n}\n","import { BoundingBox } from \"../../models/BoundingBox\";\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\nexport function wrapSVG(body: string, boundingBox: BoundingBox, margin = 1) {\n const vbox = SVGViewbox(boundingBox, margin);\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\">\n ${body}\n</svg>`;\n}\n","import { Diagram } from \"../../models/Diagram\";\nimport { Figure } from \"../../models/Figure\";\nimport { Loop } from \"../../models/Loop\";\nimport { svgDiagram } from \"./svgDiagram\";\nimport { svgFigure } from \"./svgFigure\";\nimport { svgLoop } from \"./svgLoop\";\nimport { wrapSVG } from \"./wrapSVG\";\n\ntype Shape = Loop | Figure | Diagram;\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 {\n throw new Error(\"Unknown shape type\");\n }\n}\n\nexport function exportSVG(shape: Shape | Shape[], margin = 1) {\n if (Array.isArray(shape)) {\n const flipped = shape.map((s) => s.mirror());\n const body = flipped.map((s) => svgBody(s)).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, bbox);\n }\n const flipped = shape.mirror();\n return wrapSVG(svgBody(flipped), flipped.boundingBox, margin);\n}\n"],"names":["closeSegments","segments","firstSegment","lastSegment","sameVector","Line","loopySegmentsToDiagram","Diagram","Figure","Loop","DrawingPen","origin","point","segment","xDist","yDist","distance","yPos","xPos","r","theta","angleInRads","DEG2RAD","polarToCartesian","angle","x","y","previousCurve","xDir","yDir","mirrorVector","subtract","mirrorTranform","TransformationMatrix","mirroredSegments","draw","listOfFigures","shape","fuse","first","second","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","svgSegmentToPath","svgLoop","loop","start","svgFigure","figure","svgDiagram","diagram","SVGViewbox","bbox","margin","minX","minY","wrapSVG","body","boundingBox","svgBody","exportSVG","flipped","s"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pantograph.js","sources":["../src/algorithms/offsets/offsetSegment.ts","../src/algorithms/filletSegments.ts","../src/draw.ts","../src/utils/listOfFigures.ts","../src/booleanOperations.ts","../src/algorithms/distances/lineLineDistance.ts","../src/algorithms/distances/lineArcDistance.ts","../src/algorithms/distances/arcArcDistance.ts","../src/algorithms/distances/index.ts","../../../node_modules/.pnpm/flatqueue@2.0.3/node_modules/flatqueue/index.js","../../../node_modules/.pnpm/flatbush@4.1.0/node_modules/flatbush/index.js","../src/algorithms/stitchSegments.ts","../src/algorithms/offsets/offsetLoop.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/wrapSVG.ts","../src/export/svg/exportSVG.ts","../src/import/json/importJSON.ts","../src/main.ts"],"sourcesContent":["import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport {\n add,\n normalize,\n perpendicular,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\nimport { Vector } from \"../../definitions\";\n\nexport class DegenerateSegment {\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector\n ) {}\n}\n\nexport function offsetSegment(\n segment: Segment,\n offset: number\n): Segment | DegenerateSegment {\n if (segment instanceof Line) {\n return offsetLine(segment, offset);\n }\n\n if (segment instanceof Arc) {\n return offsetArc(segment, offset);\n }\n\n throw new Error(\"Not implemented\");\n}\n\nexport function offsetLine(line: Line, offset: number): Line {\n const { firstPoint, lastPoint } = line;\n\n const normal = line.normalVector;\n return new Line(\n add(firstPoint, scalarMultiply(normal, offset)),\n add(lastPoint, scalarMultiply(normal, offset))\n );\n}\n\nexport function offsetArc(arc: Arc, offset: number): Arc | DegenerateSegment {\n const offsetStartPoint = add(\n arc.firstPoint,\n scalarMultiply(perpendicular(arc.tangentAtFirstPoint), offset)\n );\n const offsetEndPoint = add(\n arc.lastPoint,\n scalarMultiply(perpendicular(arc.tangentAtLastPoint), offset)\n );\n\n const orientedOffset = offset * (arc.clockwise ? 1 : -1);\n const newRadius = arc.radius + orientedOffset;\n if (newRadius < arc.precision) {\n return new DegenerateSegment(offsetStartPoint, offsetEndPoint);\n }\n\n return new Arc(offsetStartPoint, offsetEndPoint, arc.center, arc.clockwise);\n}\n","import { Vector } from \"../definitions\";\nimport { Line } from \"../models/segments/Line\";\nimport { tangentArc } from \"../models/segments/Arc\";\nimport type { Segment } from \"../models/segments/Segment\";\nimport {\n add,\n crossProduct,\n perpendicular,\n perpendicularClockwise,\n scalarMultiply,\n} from \"../vectorOperations\";\nimport { findIntersections } from \"./intersections\";\nimport { DegenerateSegment, offsetSegment } from \"./offsets/offsetSegment\";\nimport { exportJSON } from \"../main\";\n\nfunction removeCorner(\n firstSegment: Segment,\n secondSegment: Segment,\n radius: number\n) {\n const sinAngle = crossProduct(\n firstSegment.tangentAtLastPoint,\n secondSegment.tangentAtFirstPoint\n );\n\n // This cover the case when the segments are colinear\n if (Math.abs(sinAngle) < 1e-10) return null;\n\n const orientationCorrection = sinAngle > 0 ? 1 : -1;\n const offset = Math.abs(radius) * orientationCorrection;\n\n const firstOffset = offsetSegment(firstSegment, offset);\n const secondOffset = offsetSegment(secondSegment, offset);\n\n if (\n firstOffset instanceof DegenerateSegment ||\n secondOffset instanceof DegenerateSegment\n ) {\n return null;\n }\n\n let potentialCenter: Vector | undefined;\n try {\n const intersections = findIntersections(firstOffset, secondOffset, 1e-9);\n\n // We need to work on the case where there are more than one intersections\n potentialCenter = intersections.at(-1);\n } catch (e) {\n return null;\n }\n\n if (!potentialCenter) {\n return null;\n }\n const center = potentialCenter;\n\n const splitForFillet = (segment: Segment, offsetSegment: Segment) => {\n const tgt = offsetSegment.tangentAt(center);\n const normal = perpendicularClockwise(tgt);\n const splitPoint = add(center, scalarMultiply(normal, offset));\n return segment.splitAt(splitPoint);\n };\n\n const [first] = splitForFillet(firstSegment, firstOffset);\n const [, second] = splitForFillet(secondSegment, secondOffset);\n\n return { first, second, center };\n}\n\nexport function filletSegments(\n firstSegment: Segment,\n secondSegment: Segment,\n radius: number\n) {\n const cornerRemoved = removeCorner(firstSegment, secondSegment, radius);\n if (!cornerRemoved) {\n console.warn(\n \"Cannot fillet between segments\",\n firstSegment.repr,\n secondSegment.repr\n );\n return [firstSegment, secondSegment];\n }\n\n const { first, second } = cornerRemoved;\n\n return [\n first,\n tangentArc(first.lastPoint, second.firstPoint, first.tangentAtLastPoint),\n second,\n ];\n}\n\nexport function chamferSegments(\n firstSegment: Segment,\n secondSegment: Segment,\n radius: number\n) {\n const cornerRemoved = removeCorner(firstSegment, secondSegment, radius);\n if (!cornerRemoved) {\n console.warn(\n \"Cannot chamfer between segments\",\n firstSegment.repr,\n secondSegment.repr\n );\n return [firstSegment, secondSegment];\n }\n\n const { first, second } = cornerRemoved;\n\n return [first, new Line(first.lastPoint, second.firstPoint), second];\n}\n","import { chamferSegments, filletSegments } from \"./algorithms/filletSegments\";\nimport { Vector } from \"./definitions\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { tangentArc, threePointsArc } from \"./models/segments/Arc\";\nimport { Line } from \"./models/segments/Line\";\nimport { Segment } from \"./models/segments/Segment\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n perpendicular,\n add,\n scalarMultiply,\n distance,\n} from \"./vectorOperations\";\n\nfunction loopySegmentsToDiagram(segments: Segment[]) {\n // Here we will need to do our best to fix cases where the drawing is\n // broken in some way (i.e. self-intersecting loops)\n\n return new Diagram([new Figure(new Loop(segments))]);\n}\n\nexport class DrawingPen {\n protected pointer: Vector;\n protected firstPoint: Vector;\n protected pendingSegments: Segment[];\n\n protected _nextCorner: { radius: number; mode: \"fillet\" | \"chamfer\" } | null;\n\n constructor(origin: Vector = [0, 0]) {\n this.pointer = origin;\n this.firstPoint = origin;\n\n this.pendingSegments = [];\n this._nextCorner = null;\n }\n\n movePointerTo(point: Vector): this {\n if (this.pendingSegments.length)\n throw new Error(\n \"You can only move the pointer if there is no segment defined\"\n );\n\n this.pointer = point;\n this.firstPoint = point;\n return this;\n }\n\n protected saveSegment(segment: Segment) {\n if (sameVector(segment.firstPoint, segment.lastPoint)) {\n throw new Error(`Segment has no length, ${segment.repr}`);\n }\n\n if (!this._nextCorner) {\n this.pendingSegments.push(segment);\n return this;\n }\n\n const previousSegment = this.pendingSegments.pop();\n if (!previousSegment) throw new Error(\"bug in the custom corner algorithm\");\n\n const makeCorner =\n this._nextCorner.mode === \"chamfer\" ? chamferSegments : filletSegments;\n\n this.pendingSegments.push(\n ...makeCorner(previousSegment, segment, this._nextCorner.radius)\n );\n this._nextCorner = null;\n return this;\n }\n\n lineTo(point: Vector): this {\n const segment = new Line(this.pointer, point);\n this.pointer = point;\n return this.saveSegment(segment);\n }\n\n line(xDist: number, yDist: number): this {\n return this.lineTo([this.pointer[0] + xDist, this.pointer[1] + yDist]);\n }\n\n vLine(distance: number): this {\n return this.line(0, distance);\n }\n\n hLine(distance: number): this {\n return this.line(distance, 0);\n }\n\n vLineTo(yPos: number): this {\n return this.lineTo([this.pointer[0], yPos]);\n }\n\n hLineTo(xPos: number): this {\n return this.lineTo([xPos, this.pointer[1]]);\n }\n\n polarLineTo([r, theta]: Vector): this {\n const angleInRads = theta * DEG2RAD;\n const point = polarToCartesian(r, angleInRads);\n return this.lineTo(point);\n }\n\n polarLine(distance: number, angle: number): this {\n const angleInRads = angle * DEG2RAD;\n const [x, y] = polarToCartesian(distance, angleInRads);\n return this.line(x, y);\n }\n\n tangentLine(distance: number): this {\n const previousCurve = this.pendingSegments.at(-1);\n\n if (!previousCurve)\n throw new Error(\"You need a previous segment to sketch a tangent line\");\n\n const [xDir, yDir] = previousCurve.tangentAtLastPoint;\n return this.line(xDir * distance, yDir * distance);\n }\n\n threePointsArcTo(end: Vector, midPoint: Vector): this {\n this.saveSegment(threePointsArc(this.pointer, midPoint, end));\n this.pointer = end;\n return this;\n }\n\n threePointsArc(\n xDist: number,\n yDist: number,\n viaXDist: number,\n viaYDist: number\n ): this {\n const [x0, y0] = this.pointer;\n return this.threePointsArcTo(\n [x0 + xDist, y0 + yDist],\n [x0 + viaXDist, y0 + viaYDist]\n );\n }\n\n sagittaArcTo(end: Vector, sagitta: number): this {\n if (!sagitta) return this.lineTo(end);\n const chord = new Line(this.pointer, end);\n const norm = perpendicular(chord.tangentAtFirstPoint);\n\n const sagPoint: Vector = add(chord.midPoint, scalarMultiply(norm, sagitta));\n\n return this.threePointsArcTo(end, sagPoint);\n }\n\n sagittaArc(xDist: number, yDist: number, sagitta: number): this {\n return this.sagittaArcTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n sagitta\n );\n }\n\n vSagittaArc(distance: number, sagitta: number): this {\n return this.sagittaArc(0, distance, sagitta);\n }\n\n hSagittaArc(distance: number, sagitta: number): this {\n return this.sagittaArc(distance, 0, sagitta);\n }\n\n bulgeArcTo(end: Vector, bulge: number): this {\n if (!bulge) return this.lineTo(end);\n const halfChord = distance(this.pointer, end) / 2;\n const bulgeAsSagitta = -bulge * halfChord;\n\n return this.sagittaArcTo(end, bulgeAsSagitta);\n }\n\n bulgeArc(xDist: number, yDist: number, bulge: number): this {\n return this.bulgeArcTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n bulge\n );\n }\n\n vBulgeArc(distance: number, bulge: number): this {\n return this.bulgeArc(0, distance, bulge);\n }\n\n hBulgeArc(distance: number, bulge: number): this {\n return this.bulgeArc(distance, 0, bulge);\n }\n\n tangentArcTo(end: Vector): this {\n const previousCurve = this.pendingSegments.at(-1);\n\n if (!previousCurve)\n throw new Error(\"You need a previous curve to sketch a tangent arc\");\n\n this.saveSegment(\n tangentArc(this.pointer, end, previousCurve.tangentAtLastPoint)\n );\n\n this.pointer = end;\n return this;\n }\n\n tangentArc(xDist: number, yDist: number): this {\n const [x0, y0] = this.pointer;\n return this.tangentArcTo([xDist + x0, yDist + y0]);\n }\n\n customCorner(radius: number, mode: \"fillet\" | \"chamfer\" = \"fillet\") {\n if (!this.pendingSegments.length)\n throw new Error(\"You need a segment defined to fillet the angle\");\n\n this._nextCorner = { mode, radius };\n return this;\n }\n\n protected _customCornerLastWithFirst(\n radius: number,\n mode: \"fillet\" | \"chamfer\" = \"fillet\"\n ) {\n if (!radius) return;\n\n const lastSegment = this.pendingSegments.pop();\n const firstSegment = this.pendingSegments.shift();\n\n if (!lastSegment || !firstSegment)\n throw new Error(\"Not enough curves to close and fillet\");\n\n const makeCorner = mode === \"chamfer\" ? chamferSegments : filletSegments;\n\n this.pendingSegments.push(...makeCorner(lastSegment, firstSegment, radius));\n }\n\n close(): Diagram {\n if (!this.pendingSegments.length) throw new Error(\"No segments to close\");\n const firstSegment = this.pendingSegments[0];\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = this.pendingSegments.at(-1)!;\n\n if (!sameVector(firstSegment.firstPoint, lastSegment.lastPoint)) {\n this.lineTo(firstSegment.firstPoint);\n }\n\n if (this._nextCorner !== null) {\n this._customCornerLastWithFirst(\n this._nextCorner.radius,\n this._nextCorner.mode\n );\n this._nextCorner = null;\n }\n\n return loopySegmentsToDiagram(this.pendingSegments);\n }\n\n closeWithMirror(): Diagram {\n if (!this.pendingSegments.length) throw new Error(\"No segments to close\");\n\n const firstSegment = this.pendingSegments[0];\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = this.pendingSegments.at(-1)!;\n\n const mirrorVector = subtract(\n lastSegment.lastPoint,\n firstSegment.firstPoint\n );\n const mirrorTranform = new TransformationMatrix().mirrorLine(\n mirrorVector,\n firstSegment.firstPoint\n );\n\n const mirroredSegments = this.pendingSegments.map((segment) =>\n segment.transform(mirrorTranform).reverse()\n );\n mirroredSegments.reverse();\n\n return loopySegmentsToDiagram([\n ...this.pendingSegments,\n ...mirroredSegments,\n ]);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n","import { Diagram } from \"../models/Diagram\";\nimport { Figure } from \"../models/Figure\";\nimport { Loop } from \"../models/Loop\";\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 {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"./algorithms/boolean/figureBooleans\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\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","import { lineLineParams } from \"../intersections/lineLineIntersection\";\nimport type { Line } from \"../../models/segments/Line\";\nimport { distance } from \"../../vectorOperations\";\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\";\nimport type { Arc } from \"../../models/segments/Arc\";\nimport {\n normalize,\n subtract,\n distance,\n add,\n scalarMultiply,\n} from \"../../vectorOperations\";\nimport { projectPointOnLine } from \"../../utils/projectPointOnLine\";\nimport { lineArcIntersection } from \"../intersections/lineArcIntersection\";\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\";\nimport { arcArcIntersection } from \"../intersections/arcArcIntersection\";\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","import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { lineLineDistance } from \"./lineLineDistance\";\nimport { lineArcDistance } from \"./lineArcDistance\";\nimport { arcArcDistance } from \"./arcArcDistance\";\nimport type { Segment } from \"../../models/segments/Segment\";\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 throw new Error(\"Not implemented\");\n}\n","\nexport default class FlatQueue {\n\n constructor() {\n this.ids = [];\n this.values = [];\n this.length = 0;\n }\n\n clear() {\n this.length = 0;\n }\n\n push(id, value) {\n let pos = this.length++;\n\n while (pos > 0) {\n const parent = (pos - 1) >> 1;\n const parentValue = this.values[parent];\n if (value >= parentValue) break;\n this.ids[pos] = this.ids[parent];\n this.values[pos] = parentValue;\n pos = parent;\n }\n\n this.ids[pos] = id;\n this.values[pos] = value;\n }\n\n pop() {\n if (this.length === 0) return undefined;\n\n const top = this.ids[0];\n this.length--;\n\n if (this.length > 0) {\n const id = this.ids[0] = this.ids[this.length];\n const value = this.values[0] = this.values[this.length];\n const halfLength = this.length >> 1;\n let pos = 0;\n\n while (pos < halfLength) {\n let left = (pos << 1) + 1;\n const right = left + 1;\n let bestIndex = this.ids[left];\n let bestValue = this.values[left];\n const rightValue = this.values[right];\n\n if (right < this.length && rightValue < bestValue) {\n left = right;\n bestIndex = this.ids[right];\n bestValue = rightValue;\n }\n if (bestValue >= value) break;\n\n this.ids[pos] = bestIndex;\n this.values[pos] = bestValue;\n pos = left;\n }\n\n this.ids[pos] = id;\n this.values[pos] = value;\n }\n\n return top;\n }\n\n peek() {\n if (this.length === 0) return undefined;\n return this.ids[0];\n }\n\n peekValue() {\n if (this.length === 0) return undefined;\n return this.values[0];\n }\n\n shrink() {\n this.ids.length = this.values.length = this.length;\n }\n}\n","import FlatQueue from 'flatqueue';\n\nconst ARRAY_TYPES = [\n Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array,\n Int32Array, Uint32Array, Float32Array, Float64Array\n];\n\nconst VERSION = 3; // serialized format version\n\nexport default class Flatbush {\n\n static from(data) {\n if (!data || data.byteLength === undefined || data.buffer) {\n throw new Error('Data must be an instance of ArrayBuffer or SharedArrayBuffer.');\n }\n const [magic, versionAndType] = new Uint8Array(data, 0, 2);\n if (magic !== 0xfb) {\n throw new Error('Data does not appear to be in a Flatbush format.');\n }\n if (versionAndType >> 4 !== VERSION) {\n throw new Error(`Got v${versionAndType >> 4} data when expected v${VERSION}.`);\n }\n const [nodeSize] = new Uint16Array(data, 2, 1);\n const [numItems] = new Uint32Array(data, 4, 1);\n\n return new Flatbush(numItems, nodeSize, ARRAY_TYPES[versionAndType & 0x0f], undefined, data);\n }\n\n constructor(numItems, nodeSize = 16, ArrayType = Float64Array, ArrayBufferType = ArrayBuffer, data) {\n if (numItems === undefined) throw new Error('Missing required argument: numItems.');\n if (isNaN(numItems) || numItems <= 0) throw new Error(`Unexpected numItems value: ${numItems}.`);\n\n this.numItems = +numItems;\n this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535);\n\n // calculate the total number of nodes in the R-tree to allocate space for\n // and the index of each tree level (used in search later)\n let n = numItems;\n let numNodes = n;\n this._levelBounds = [n * 4];\n do {\n n = Math.ceil(n / this.nodeSize);\n numNodes += n;\n this._levelBounds.push(numNodes * 4);\n } while (n !== 1);\n\n this.ArrayType = ArrayType || Float64Array;\n this.IndexArrayType = numNodes < 16384 ? Uint16Array : Uint32Array;\n\n const arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType);\n const nodesByteSize = numNodes * 4 * this.ArrayType.BYTES_PER_ELEMENT;\n\n if (arrayTypeIndex < 0) {\n throw new Error(`Unexpected typed array class: ${ArrayType}.`);\n }\n\n if (data && data.byteLength !== undefined && !data.buffer) {\n this.data = data;\n this._boxes = new this.ArrayType(this.data, 8, numNodes * 4);\n this._indices = new this.IndexArrayType(this.data, 8 + nodesByteSize, numNodes);\n\n this._pos = numNodes * 4;\n this.minX = this._boxes[this._pos - 4];\n this.minY = this._boxes[this._pos - 3];\n this.maxX = this._boxes[this._pos - 2];\n this.maxY = this._boxes[this._pos - 1];\n\n } else {\n this.data = new ArrayBufferType(8 + nodesByteSize + numNodes * this.IndexArrayType.BYTES_PER_ELEMENT);\n this._boxes = new this.ArrayType(this.data, 8, numNodes * 4);\n this._indices = new this.IndexArrayType(this.data, 8 + nodesByteSize, numNodes);\n this._pos = 0;\n this.minX = Infinity;\n this.minY = Infinity;\n this.maxX = -Infinity;\n this.maxY = -Infinity;\n\n new Uint8Array(this.data, 0, 2).set([0xfb, (VERSION << 4) + arrayTypeIndex]);\n new Uint16Array(this.data, 2, 1)[0] = nodeSize;\n new Uint32Array(this.data, 4, 1)[0] = numItems;\n }\n\n // a priority queue for k-nearest-neighbors queries\n this._queue = new FlatQueue();\n }\n\n add(minX, minY, maxX, maxY) {\n const index = this._pos >> 2;\n const boxes = this._boxes;\n this._indices[index] = index;\n boxes[this._pos++] = minX;\n boxes[this._pos++] = minY;\n boxes[this._pos++] = maxX;\n boxes[this._pos++] = maxY;\n\n if (minX < this.minX) this.minX = minX;\n if (minY < this.minY) this.minY = minY;\n if (maxX > this.maxX) this.maxX = maxX;\n if (maxY > this.maxY) this.maxY = maxY;\n\n return index;\n }\n\n finish() {\n if (this._pos >> 2 !== this.numItems) {\n throw new Error(`Added ${this._pos >> 2} items when expected ${this.numItems}.`);\n }\n const boxes = this._boxes;\n\n if (this.numItems <= this.nodeSize) {\n // only one node, skip sorting and just fill the root box\n boxes[this._pos++] = this.minX;\n boxes[this._pos++] = this.minY;\n boxes[this._pos++] = this.maxX;\n boxes[this._pos++] = this.maxY;\n return;\n }\n\n const width = (this.maxX - this.minX) || 1;\n const height = (this.maxY - this.minY) || 1;\n const hilbertValues = new Uint32Array(this.numItems);\n const hilbertMax = (1 << 16) - 1;\n\n // map item centers into Hilbert coordinate space and calculate Hilbert values\n for (let i = 0, pos = 0; i < this.numItems; i++) {\n const minX = boxes[pos++];\n const minY = boxes[pos++];\n const maxX = boxes[pos++];\n const maxY = boxes[pos++];\n const x = Math.floor(hilbertMax * ((minX + maxX) / 2 - this.minX) / width);\n const y = Math.floor(hilbertMax * ((minY + maxY) / 2 - this.minY) / height);\n hilbertValues[i] = hilbert(x, y);\n }\n\n // sort items by their Hilbert value (for packing later)\n sort(hilbertValues, boxes, this._indices, 0, this.numItems - 1, this.nodeSize);\n\n // generate nodes at each tree level, bottom-up\n for (let i = 0, pos = 0; i < this._levelBounds.length - 1; i++) {\n const end = this._levelBounds[i];\n\n // generate a parent node for each block of consecutive <nodeSize> nodes\n while (pos < end) {\n const nodeIndex = pos;\n\n // calculate bbox for the new node\n let nodeMinX = boxes[pos++];\n let nodeMinY = boxes[pos++];\n let nodeMaxX = boxes[pos++];\n let nodeMaxY = boxes[pos++];\n for (let j = 1; j < this.nodeSize && pos < end; j++) {\n nodeMinX = Math.min(nodeMinX, boxes[pos++]);\n nodeMinY = Math.min(nodeMinY, boxes[pos++]);\n nodeMaxX = Math.max(nodeMaxX, boxes[pos++]);\n nodeMaxY = Math.max(nodeMaxY, boxes[pos++]);\n }\n\n // add the new node to the tree data\n this._indices[this._pos >> 2] = nodeIndex;\n boxes[this._pos++] = nodeMinX;\n boxes[this._pos++] = nodeMinY;\n boxes[this._pos++] = nodeMaxX;\n boxes[this._pos++] = nodeMaxY;\n }\n }\n }\n\n search(minX, minY, maxX, maxY, filterFn) {\n if (this._pos !== this._boxes.length) {\n throw new Error('Data not yet indexed - call index.finish().');\n }\n\n let nodeIndex = this._boxes.length - 4;\n const queue = [];\n const results = [];\n\n while (nodeIndex !== undefined) {\n // find the end index of the node\n const end = Math.min(nodeIndex + this.nodeSize * 4, upperBound(nodeIndex, this._levelBounds));\n\n // search through child nodes\n for (let pos = nodeIndex; pos < end; pos += 4) {\n // check if node bbox intersects with query bbox\n if (maxX < this._boxes[pos]) continue; // maxX < nodeMinX\n if (maxY < this._boxes[pos + 1]) continue; // maxY < nodeMinY\n if (minX > this._boxes[pos + 2]) continue; // minX > nodeMaxX\n if (minY > this._boxes[pos + 3]) continue; // minY > nodeMaxY\n\n const index = this._indices[pos >> 2] | 0;\n\n if (nodeIndex >= this.numItems * 4) {\n queue.push(index); // node; add it to the search queue\n\n } else if (filterFn === undefined || filterFn(index)) {\n results.push(index); // leaf item\n }\n }\n\n nodeIndex = queue.pop();\n }\n\n return results;\n }\n\n neighbors(x, y, maxResults = Infinity, maxDistance = Infinity, filterFn) {\n if (this._pos !== this._boxes.length) {\n throw new Error('Data not yet indexed - call index.finish().');\n }\n\n let nodeIndex = this._boxes.length - 4;\n const q = this._queue;\n const results = [];\n const maxDistSquared = maxDistance * maxDistance;\n\n while (nodeIndex !== undefined) {\n // find the end index of the node\n const end = Math.min(nodeIndex + this.nodeSize * 4, upperBound(nodeIndex, this._levelBounds));\n\n // add child nodes to the queue\n for (let pos = nodeIndex; pos < end; pos += 4) {\n const index = this._indices[pos >> 2] | 0;\n\n const dx = axisDist(x, this._boxes[pos], this._boxes[pos + 2]);\n const dy = axisDist(y, this._boxes[pos + 1], this._boxes[pos + 3]);\n const dist = dx * dx + dy * dy;\n\n if (nodeIndex >= this.numItems * 4) {\n q.push(index << 1, dist); // node (use even id)\n\n } else if (filterFn === undefined || filterFn(index)) {\n q.push((index << 1) + 1, dist); // leaf item (use odd id)\n }\n }\n\n // pop items from the queue\n while (q.length && (q.peek() & 1)) {\n const dist = q.peekValue();\n if (dist > maxDistSquared) {\n q.clear();\n return results;\n }\n results.push(q.pop() >> 1);\n\n if (results.length === maxResults) {\n q.clear();\n return results;\n }\n }\n\n nodeIndex = q.pop() >> 1;\n }\n\n q.clear();\n return results;\n }\n}\n\nfunction axisDist(k, min, max) {\n return k < min ? min - k : k <= max ? 0 : k - max;\n}\n\n// binary search for the first value in the array bigger than the given\nfunction upperBound(value, arr) {\n let i = 0;\n let j = arr.length - 1;\n while (i < j) {\n const m = (i + j) >> 1;\n if (arr[m] > value) {\n j = m;\n } else {\n i = m + 1;\n }\n }\n return arr[i];\n}\n\n// custom quicksort that partially sorts bbox data alongside the hilbert values\nfunction sort(values, boxes, indices, left, right, nodeSize) {\n if (Math.floor(left / nodeSize) >= Math.floor(right / nodeSize)) return;\n\n const pivot = values[(left + right) >> 1];\n let i = left - 1;\n let j = right + 1;\n\n while (true) {\n do i++; while (values[i] < pivot);\n do j--; while (values[j] > pivot);\n if (i >= j) break;\n swap(values, boxes, indices, i, j);\n }\n\n sort(values, boxes, indices, left, j, nodeSize);\n sort(values, boxes, indices, j + 1, right, nodeSize);\n}\n\n// swap two values and two corresponding boxes\nfunction swap(values, boxes, indices, i, j) {\n const temp = values[i];\n values[i] = values[j];\n values[j] = temp;\n\n const k = 4 * i;\n const m = 4 * j;\n\n const a = boxes[k];\n const b = boxes[k + 1];\n const c = boxes[k + 2];\n const d = boxes[k + 3];\n boxes[k] = boxes[m];\n boxes[k + 1] = boxes[m + 1];\n boxes[k + 2] = boxes[m + 2];\n boxes[k + 3] = boxes[m + 3];\n boxes[m] = a;\n boxes[m + 1] = b;\n boxes[m + 2] = c;\n boxes[m + 3] = d;\n\n const e = indices[i];\n indices[i] = indices[j];\n indices[j] = e;\n}\n\n// Fast Hilbert curve algorithm by http://threadlocalmutex.com/\n// Ported from C++ https://github.com/rawrunprotected/hilbert_curves (public domain)\nfunction hilbert(x, y) {\n let a = x ^ y;\n let b = 0xFFFF ^ a;\n let c = 0xFFFF ^ (x | y);\n let d = x & (y ^ 0xFFFF);\n\n let A = a | (b >> 1);\n let B = (a >> 1) ^ a;\n let C = ((c >> 1) ^ (b & (d >> 1))) ^ c;\n let D = ((a & (c >> 1)) ^ (d >> 1)) ^ d;\n\n a = A; b = B; c = C; d = D;\n A = ((a & (a >> 2)) ^ (b & (b >> 2)));\n B = ((a & (b >> 2)) ^ (b & ((a ^ b) >> 2)));\n C ^= ((a & (c >> 2)) ^ (b & (d >> 2)));\n D ^= ((b & (c >> 2)) ^ ((a ^ b) & (d >> 2)));\n\n a = A; b = B; c = C; d = D;\n A = ((a & (a >> 4)) ^ (b & (b >> 4)));\n B = ((a & (b >> 4)) ^ (b & ((a ^ b) >> 4)));\n C ^= ((a & (c >> 4)) ^ (b & (d >> 4)));\n D ^= ((b & (c >> 4)) ^ ((a ^ b) & (d >> 4)));\n\n a = A; b = B; c = C; d = D;\n C ^= ((a & (c >> 8)) ^ (b & (d >> 8)));\n D ^= ((b & (c >> 8)) ^ ((a ^ b) & (d >> 8)));\n\n a = C ^ (C >> 1);\n b = D ^ (D >> 1);\n\n let i0 = x ^ y;\n let i1 = b | (0xFFFF ^ (i0 | a));\n\n i0 = (i0 | (i0 << 8)) & 0x00FF00FF;\n i0 = (i0 | (i0 << 4)) & 0x0F0F0F0F;\n i0 = (i0 | (i0 << 2)) & 0x33333333;\n i0 = (i0 | (i0 << 1)) & 0x55555555;\n\n i1 = (i1 | (i1 << 8)) & 0x00FF00FF;\n i1 = (i1 | (i1 << 4)) & 0x0F0F0F0F;\n i1 = (i1 | (i1 << 2)) & 0x33333333;\n i1 = (i1 | (i1 << 1)) & 0x55555555;\n\n return ((i1 << 1) | i0) >>> 0;\n}\n","import Flatbush from \"flatbush\";\nimport { Segment } from \"../models/segments/Segment\";\n\nexport function stitchSegments(\n segments: Segment[],\n precision = 1e-7\n): Segment[][] {\n // We create a spacial index of the startpoints\n const startPoints = new Flatbush(segments.length);\n segments.forEach((c) => {\n const [x, y] = c.firstPoint;\n startPoints.add(x - precision, y - precision, x + precision, y + precision);\n });\n startPoints.finish();\n\n const stitchedSegments: Segment[][] = [];\n const visited = new Set<number>();\n\n segments.forEach((segment, index) => {\n if (visited.has(index)) return;\n\n const connectedSegments: Segment[] = [segment];\n let currentIndex = index;\n\n visited.add(index);\n\n // Once we have started a connected segment segment, we look for the next\n\n let maxLoops = segments.length;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (maxLoops-- < 0) {\n throw new Error(\"Infinite loop detected\");\n }\n\n const lastPoint =\n connectedSegments[connectedSegments.length - 1].lastPoint;\n\n const [x, y] = lastPoint;\n const neighbors = startPoints.search(\n x - precision,\n y - precision,\n x + precision,\n y + precision\n );\n\n const indexDistance = (otherIndex: number) =>\n Math.abs((currentIndex - otherIndex) % segments.length);\n const potentialNextSegments = neighbors\n .filter((neighborIndex) => !visited.has(neighborIndex))\n .map((neighborIndex): [Segment, number, number] => [\n segments[neighborIndex],\n neighborIndex,\n indexDistance(neighborIndex),\n ])\n .sort(([, , a], [, , b]) => indexDistance(a) - indexDistance(b));\n\n if (potentialNextSegments.length === 0) {\n // No more segments to connect we should have wrapped\n stitchedSegments.push(connectedSegments);\n break;\n }\n\n const [nextSegment, nextSegmentIndex] = potentialNextSegments[0];\n\n connectedSegments.push(nextSegment);\n visited.add(nextSegmentIndex);\n currentIndex = nextSegmentIndex;\n }\n });\n\n return stitchedSegments;\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Loop } from \"../../models/Loop\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport {\n crossProduct,\n sameVector,\n squareDistance,\n subtract,\n} from \"../../vectorOperations\";\nimport { distance } from \"../distances\";\nimport { offsetSegment, DegenerateSegment } from \"./offsetSegment\";\nimport { Vector } from \"../../definitions\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport { Figure } from \"../../models/Figure\";\nimport { stitchSegments } from \"../stitchSegments\";\n\nconst PRECISION = 1e-8;\n\nexport function rawOffsets(\n segmentsToOffset: Segment[],\n offset: number\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: null | OffsetSegmentPair = null;\n\n let previousSegment = offsetSegments.at(-1);\n\n // We have no offseted segments\n if (!previousSegment) return [];\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 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 appendSegment(previousSegment);\n return offsettedArray;\n}\n\ninterface OffsetSegmentPair {\n offset: Segment | DegenerateSegment;\n original: Segment;\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: 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 offsettedArray.forEach((firstSegment, firstIndex) => {\n offsettedArray\n .slice(firstIndex + 1)\n .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 if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n\n /* this was in the replicad algorithm - not sure why\n if (!loop.intersects(offsettedLoop)) return offsettedLoop;\n return new Diagram();\n */\n }\n\n const splitSegments = offsettedArray.flatMap((segment, index) => {\n if (!allIntersections.has(index)) return segment;\n\n const intersections = allIntersections.get(index) || [];\n const splitSegments = segment.splitAt(intersections);\n return splitSegments;\n });\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = splitSegments.filter((segment) => {\n const closeSegment = loop.segments.some((c) => {\n return distance(c, segment) < Math.abs(offset) - PRECISION;\n });\n return !closeSegment;\n });\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 \"./offsetLoop\";\n\nexport default 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","import offsetFigures from \"./algorithms/offsets/offsetFigure\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\n\nexport function offset(\n shape: Diagram | Figure | Loop,\n offsetDistance: number\n): Diagram {\n return offsetFigures(listOfFigures(shape), offsetDistance);\n}\n","import { Arc } from \"../../models/segments/Arc\";\nimport { Line } from \"../../models/segments/Line\";\nimport { Segment } from \"../../models/segments/Segment\";\n\nexport function svgSegmentToPath(segment: Segment) {\n if (segment instanceof Line) {\n return `L ${segment.lastPoint.join(\" \")}`;\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\"} ${segment.lastPoint.join(\" \")}`;\n }\n\n throw new Error(\"Unknown segment type\");\n}\n","import type { Loop } from \"../../models/Loop\";\nimport { svgSegmentToPath } from \"./svgSegment\";\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\";\nimport { svgLoop } from \"./svgLoop\";\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\";\nimport { svgFigure } from \"./svgFigure\";\n\nexport function svgDiagram(diagram: Diagram) {\n return `<g>\n ${diagram.figures.map(svgFigure).join(\"\\n\")}\n</g>`;\n}\n","import { BoundingBox } from \"../../models/BoundingBox\";\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\nexport function wrapSVG(body: string, boundingBox: BoundingBox, margin = 1) {\n const vbox = SVGViewbox(boundingBox, margin);\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\">\n ${body}\n</svg>`;\n}\n","import { Diagram } from \"../../models/Diagram\";\nimport { Figure } from \"../../models/Figure\";\nimport { Loop } from \"../../models/Loop\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Line } from \"../../models/segments/Line\";\nimport { svgDiagram } from \"./svgDiagram\";\nimport { svgFigure } from \"./svgFigure\";\nimport { svgLoop } from \"./svgLoop\";\nimport { svgSegmentToPath } from \"./svgSegment\";\nimport { wrapSVG } from \"./wrapSVG\";\n\ntype Shape = Loop | Figure | Diagram | Arc | Line;\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 Arc || shape instanceof Line) {\n return `<path d=\"${`M ${shape.firstPoint.join(\" \")}`} ${svgSegmentToPath(\n shape\n )}\" />`;\n } else {\n throw new Error(\"Unknown shape type\");\n }\n}\n\nexport function exportSVG(shape: Shape | Shape[], margin = 1) {\n if (Array.isArray(shape)) {\n const flipped = shape.map((s) => s.mirror());\n const body = flipped.map((s) => svgBody(s)).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, bbox);\n }\n const flipped = shape.mirror();\n return wrapSVG(svgBody(flipped), flipped.boundingBox, margin);\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Loop } from \"../../models/Loop\";\nimport { Figure } from \"../../models/Figure\";\nimport { Diagram } from \"../../models/Diagram\";\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 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 (json.type === \"LINE\" || json.type === \"ARC\") {\n return importSegment(json);\n }\n throw new Error(\"Unknown shape type\");\n}\n","import type { Vector } from \"./definitions\";\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} from \"./models/exports\";\n\nexport { draw } from \"./draw\";\nexport { fuse, fuseAll, cut, intersect, offset } from \"./operations\";\n\nexport { exportSVG, svgBody } from \"./export/svg/exportSVG\";\n\nexport { exportJSON } from \"./export/json/exportJSON\";\nexport { importJSON } from \"./import/json/importJSON\";\n"],"names":["DegenerateSegment","firstPoint","lastPoint","offsetSegment","segment","offset","Line","offsetLine","Arc","offsetArc","line","normal","add","scalarMultiply","arc","offsetStartPoint","perpendicular","offsetEndPoint","orientedOffset","removeCorner","firstSegment","secondSegment","radius","sinAngle","crossProduct","orientationCorrection","firstOffset","secondOffset","potentialCenter","findIntersections","center","splitForFillet","tgt","perpendicularClockwise","splitPoint","first","second","filletSegments","cornerRemoved","tangentArc","chamferSegments","loopySegmentsToDiagram","segments","Diagram","Figure","Loop","DrawingPen","origin","point","sameVector","previousSegment","makeCorner","xDist","yDist","distance","yPos","xPos","r","theta","angleInRads","DEG2RAD","polarToCartesian","angle","x","y","previousCurve","xDir","yDir","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","sagPoint","bulge","halfChord","bulgeAsSagitta","mode","lastSegment","mirrorVector","subtract","mirrorTranform","TransformationMatrix","mirroredSegments","draw","listOfFigures","shape","fuse","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","segmentPosition","intersectionParam","handleBetween","lineBetween","otherLine","otherPosition","lineLineDistance","line1","line2","intersectionParams","lineLineParams","intersectionParam1","intersectionParam2","firstPosition","secondPosition","lineArcDistance","lineArcIntersection","closestPointOnLine","projectPointOnLine","circleCenterLineDistance","centerLineDirection","normalize","closestPointOnCircle","overlappingAngles","arc1","arc2","p1","p2","arcArcDistance","arcArcIntersection","centersDistance","centerCenterDirection","containedCircles","arc1ClosestPointAngle","polarAngle","arc2ClosestPointAngle","segment1","segment2","FlatQueue","id","value","pos","parent","parentValue","top","halfLength","left","right","bestIndex","bestValue","rightValue","ARRAY_TYPES","VERSION","Flatbush","data","magic","versionAndType","nodeSize","numItems","ArrayType","ArrayBufferType","n","numNodes","arrayTypeIndex","nodesByteSize","minX","minY","maxX","maxY","index","boxes","width","height","hilbertValues","hilbertMax","i","hilbert","sort","nodeIndex","nodeMinX","nodeMinY","nodeMaxX","nodeMaxY","j","filterFn","queue","results","upperBound","maxResults","maxDistance","q","maxDistSquared","dx","axisDist","dy","dist","k","min","max","arr","m","values","indices","pivot","swap","temp","a","b","d","e","c","A","B","C","D","i0","i1","stitchSegments","precision","startPoints","stitchedSegments","visited","connectedSegments","currentIndex","maxLoops","neighbors","indexDistance","otherIndex","potentialNextSegments","neighborIndex","nextSegment","nextSegmentIndex","PRECISION","rawOffsets","segmentsToOffset","offsetSegments","offsettedArray","savedLastSegment","appendSegment","iterateOffsetSegments","previousLastPoint","intersections","pointIntersections","overlaps","findIntersectionsAndOverlaps","intersection","originalEndpoint","distances","squareDistance","splitPreviousSegment","splitSegment","clockwise","joiner","offsetLoop","loop","correctedOffset","allIntersections","updateIntersections","newPoints","firstIndex","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","offsettedLoop","prunedSegments","splitSegments","newLoops","l","offsetFigures","figures","offsetDistance","figure","innerShape","svgSegmentToPath","svgLoop","start","svgFigure","svgDiagram","diagram","SVGViewbox","bbox","margin","wrapSVG","body","boundingBox","svgBody","exportSVG","flipped","s","importSegment","json","importLoop","importFigure","contour","holes","importDiagram","importJSON","RAD2DEG","cartesianToPolar"],"mappings":";;AAYO,MAAMA,EAAkB;AAAA,EAC7B,YACkBC,GACAC,GAChB;AAFgB,SAAA,aAAAD,GACA,KAAA,YAAAC;AAAA,EACf;AACL;AAEgB,SAAAC,EACdC,GACAC,GAC6B;AAC7B,MAAID,aAAmBE;AACd,WAAAC,GAAWH,GAASC,CAAM;AAGnC,MAAID,aAAmBI;AACd,WAAAC,GAAUL,GAASC,CAAM;AAG5B,QAAA,IAAI,MAAM,iBAAiB;AACnC;AAEgB,SAAAE,GAAWG,GAAYL,GAAsB;AACrD,QAAA,EAAE,YAAAJ,GAAY,WAAAC,EAAc,IAAAQ,GAE5BC,IAASD,EAAK;AACpB,SAAO,IAAIJ;AAAA,IACTM,EAAIX,GAAYY,EAAeF,GAAQN,CAAM,CAAC;AAAA,IAC9CO,EAAIV,GAAWW,EAAeF,GAAQN,CAAM,CAAC;AAAA,EAAA;AAEjD;AAEgB,SAAAI,GAAUK,GAAUT,GAAyC;AAC3E,QAAMU,IAAmBH;AAAA,IACvBE,EAAI;AAAA,IACJD,EAAeG,EAAcF,EAAI,mBAAmB,GAAGT,CAAM;AAAA,EAAA,GAEzDY,IAAiBL;AAAA,IACrBE,EAAI;AAAA,IACJD,EAAeG,EAAcF,EAAI,kBAAkB,GAAGT,CAAM;AAAA,EAAA,GAGxDa,IAAiBb,KAAUS,EAAI,YAAY,IAAI;AAEjD,SADcA,EAAI,SAASI,IACfJ,EAAI,YACX,IAAId,EAAkBe,GAAkBE,CAAc,IAGxD,IAAIT,EAAIO,GAAkBE,GAAgBH,EAAI,QAAQA,EAAI,SAAS;AAC5E;AC9CA,SAASK,GACPC,GACAC,GACAC,GACA;AACA,QAAMC,IAAWC;AAAA,IACfJ,EAAa;AAAA,IACbC,EAAc;AAAA,EAAA;AAIZ,MAAA,KAAK,IAAIE,CAAQ,IAAI;AAAc,WAAA;AAEjC,QAAAE,IAAwBF,IAAW,IAAI,IAAI,IAC3ClB,IAAS,KAAK,IAAIiB,CAAM,IAAIG,GAE5BC,IAAcvB,EAAciB,GAAcf,CAAM,GAChDsB,IAAexB,EAAckB,GAAehB,CAAM;AAGtD,MAAAqB,aAAuB1B,KACvB2B,aAAwB3B;AAEjB,WAAA;AAGL,MAAA4B;AACA,MAAA;AAIgB,IAAAA,IAHIC,GAAkBH,GAAaC,GAAc,IAAI,EAGvC,GAAG,EAAE;AAAA;AAE9B,WAAA;AAAA,EACT;AAEA,MAAI,CAACC;AACI,WAAA;AAET,QAAME,IAASF,GAETG,IAAiB,CAAC3B,GAAkBD,MAA2B;AAC7D,UAAA6B,IAAM7B,EAAc,UAAU2B,CAAM,GACpCnB,IAASsB,GAAuBD,CAAG,GACnCE,IAAatB,EAAIkB,GAAQjB,EAAeF,GAAQN,CAAM,CAAC;AACtD,WAAAD,EAAQ,QAAQ8B,CAAU;AAAA,EAAA,GAG7B,CAACC,CAAK,IAAIJ,EAAeX,GAAcM,CAAW,GAClD,CAAG,EAAAU,CAAM,IAAIL,EAAeV,GAAeM,CAAY;AAEtD,SAAA,EAAE,OAAAQ,GAAO,QAAAC,GAAQ,QAAAN;AAC1B;AAEgB,SAAAO,EACdjB,GACAC,GACAC,GACA;AACA,QAAMgB,IAAgBnB,GAAaC,GAAcC,GAAeC,CAAM;AACtE,MAAI,CAACgB;AACK,mBAAA;AAAA,MACN;AAAA,MACAlB,EAAa;AAAA,MACbC,EAAc;AAAA,IAAA,GAET,CAACD,GAAcC,CAAa;AAG/B,QAAA,EAAE,OAAAc,GAAO,QAAAC,EAAW,IAAAE;AAEnB,SAAA;AAAA,IACLH;AAAA,IACAI,GAAWJ,EAAM,WAAWC,EAAO,YAAYD,EAAM,kBAAkB;AAAA,IACvEC;AAAA,EAAA;AAEJ;AAEgB,SAAAI,EACdpB,GACAC,GACAC,GACA;AACA,QAAMgB,IAAgBnB,GAAaC,GAAcC,GAAeC,CAAM;AACtE,MAAI,CAACgB;AACK,mBAAA;AAAA,MACN;AAAA,MACAlB,EAAa;AAAA,MACbC,EAAc;AAAA,IAAA,GAET,CAACD,GAAcC,CAAa;AAG/B,QAAA,EAAE,OAAAc,GAAO,QAAAC,EAAW,IAAAE;AAEnB,SAAA,CAACH,GAAO,IAAI7B,EAAK6B,EAAM,WAAWC,EAAO,UAAU,GAAGA,CAAM;AACrE;AC3FA,SAASK,EAAuBC,GAAqB;AAI5C,SAAA,IAAIC,EAAQ,CAAC,IAAIC,EAAO,IAAIC,EAAKH,CAAQ,CAAC,CAAC,CAAC;AACrD;AAEO,MAAMI,GAAW;AAAA,EAOtB,YAAYC,IAAiB,CAAC,GAAG,CAAC,GAAG;AACnC,SAAK,UAAUA,GACf,KAAK,aAAaA,GAElB,KAAK,kBAAkB,IACvB,KAAK,cAAc;AAAA,EACrB;AAAA,EAEA,cAAcC,GAAqB;AACjC,QAAI,KAAK,gBAAgB;AACvB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAGJ,gBAAK,UAAUA,GACf,KAAK,aAAaA,GACX;AAAA,EACT;AAAA,EAEU,YAAY5C,GAAkB;AACtC,QAAI6C,EAAW7C,EAAQ,YAAYA,EAAQ,SAAS;AAClD,YAAM,IAAI,MAAM,0BAA0BA,EAAQ,MAAM;AAGtD,QAAA,CAAC,KAAK;AACH,kBAAA,gBAAgB,KAAKA,CAAO,GAC1B;AAGH,UAAA8C,IAAkB,KAAK,gBAAgB,IAAI;AACjD,QAAI,CAACA;AAAuB,YAAA,IAAI,MAAM,oCAAoC;AAE1E,UAAMC,IACJ,KAAK,YAAY,SAAS,YAAYX,IAAkBH;AAE1D,gBAAK,gBAAgB;AAAA,MACnB,GAAGc,EAAWD,GAAiB9C,GAAS,KAAK,YAAY,MAAM;AAAA,IAAA,GAEjE,KAAK,cAAc,MACZ;AAAA,EACT;AAAA,EAEA,OAAO4C,GAAqB;AAC1B,UAAM5C,IAAU,IAAIE,EAAK,KAAK,SAAS0C,CAAK;AAC5C,gBAAK,UAAUA,GACR,KAAK,YAAY5C,CAAO;AAAA,EACjC;AAAA,EAEA,KAAKgD,GAAeC,GAAqB;AACvC,WAAO,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC,IAAID,GAAO,KAAK,QAAQ,CAAC,IAAIC,CAAK,CAAC;AAAA,EACvE;AAAA,EAEA,MAAMC,GAAwB;AACrB,WAAA,KAAK,KAAK,GAAGA,CAAQ;AAAA,EAC9B;AAAA,EAEA,MAAMA,GAAwB;AACrB,WAAA,KAAK,KAAKA,GAAU,CAAC;AAAA,EAC9B;AAAA,EAEA,QAAQC,GAAoB;AACnB,WAAA,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC,GAAGA,CAAI,CAAC;AAAA,EAC5C;AAAA,EAEA,QAAQC,GAAoB;AACnB,WAAA,KAAK,OAAO,CAACA,GAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,EAC5C;AAAA,EAEA,YAAY,CAACC,GAAGC,CAAK,GAAiB;AACpC,UAAMC,IAAcD,IAAQE,GACtBZ,IAAQa,EAAiBJ,GAAGE,CAAW;AACtC,WAAA,KAAK,OAAOX,CAAK;AAAA,EAC1B;AAAA,EAEA,UAAUM,GAAkBQ,GAAqB;AAC/C,UAAMH,IAAcG,IAAQF,GACtB,CAACG,GAAGC,CAAC,IAAIH,EAAiBP,GAAUK,CAAW;AAC9C,WAAA,KAAK,KAAKI,GAAGC,CAAC;AAAA,EACvB;AAAA,EAEA,YAAYV,GAAwB;AAClC,UAAMW,IAAgB,KAAK,gBAAgB,GAAG,EAAE;AAEhD,QAAI,CAACA;AACG,YAAA,IAAI,MAAM,sDAAsD;AAExE,UAAM,CAACC,GAAMC,CAAI,IAAIF,EAAc;AACnC,WAAO,KAAK,KAAKC,IAAOZ,GAAUa,IAAOb,CAAQ;AAAA,EACnD;AAAA,EAEA,iBAAiBc,GAAaC,GAAwB;AACpD,gBAAK,YAAYC,GAAe,KAAK,SAASD,GAAUD,CAAG,CAAC,GAC5D,KAAK,UAAUA,GACR;AAAA,EACT;AAAA,EAEA,eACEhB,GACAC,GACAkB,GACAC,GACM;AACN,UAAM,CAACC,GAAIC,CAAE,IAAI,KAAK;AACtB,WAAO,KAAK;AAAA,MACV,CAACD,IAAKrB,GAAOsB,IAAKrB,CAAK;AAAA,MACvB,CAACoB,IAAKF,GAAUG,IAAKF,CAAQ;AAAA,IAAA;AAAA,EAEjC;AAAA,EAEA,aAAaJ,GAAaO,GAAuB;AAC/C,QAAI,CAACA;AAAgB,aAAA,KAAK,OAAOP,CAAG;AACpC,UAAMQ,IAAQ,IAAItE,EAAK,KAAK,SAAS8D,CAAG,GAClCS,IAAO7D,EAAc4D,EAAM,mBAAmB,GAE9CE,IAAmBlE,EAAIgE,EAAM,UAAU/D,EAAegE,GAAMF,CAAO,CAAC;AAEnE,WAAA,KAAK,iBAAiBP,GAAKU,CAAQ;AAAA,EAC5C;AAAA,EAEA,WAAW1B,GAAeC,GAAesB,GAAuB;AAC9D,WAAO,KAAK;AAAA,MACV,CAACvB,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjDsB;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,YAAYrB,GAAkBqB,GAAuB;AACnD,WAAO,KAAK,WAAW,GAAGrB,GAAUqB,CAAO;AAAA,EAC7C;AAAA,EAEA,YAAYrB,GAAkBqB,GAAuB;AACnD,WAAO,KAAK,WAAWrB,GAAU,GAAGqB,CAAO;AAAA,EAC7C;AAAA,EAEA,WAAWP,GAAaW,GAAqB;AAC3C,QAAI,CAACA;AAAc,aAAA,KAAK,OAAOX,CAAG;AAClC,UAAMY,IAAY1B,EAAS,KAAK,SAASc,CAAG,IAAI,GAC1Ca,IAAiB,CAACF,IAAQC;AAEzB,WAAA,KAAK,aAAaZ,GAAKa,CAAc;AAAA,EAC9C;AAAA,EAEA,SAAS7B,GAAeC,GAAe0B,GAAqB;AAC1D,WAAO,KAAK;AAAA,MACV,CAAC3B,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjD0B;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,UAAUzB,GAAkByB,GAAqB;AAC/C,WAAO,KAAK,SAAS,GAAGzB,GAAUyB,CAAK;AAAA,EACzC;AAAA,EAEA,UAAUzB,GAAkByB,GAAqB;AAC/C,WAAO,KAAK,SAASzB,GAAU,GAAGyB,CAAK;AAAA,EACzC;AAAA,EAEA,aAAaX,GAAmB;AAC9B,UAAMH,IAAgB,KAAK,gBAAgB,GAAG,EAAE;AAEhD,QAAI,CAACA;AACG,YAAA,IAAI,MAAM,mDAAmD;AAEhE,gBAAA;AAAA,MACH1B,GAAW,KAAK,SAAS6B,GAAKH,EAAc,kBAAkB;AAAA,IAAA,GAGhE,KAAK,UAAUG,GACR;AAAA,EACT;AAAA,EAEA,WAAWhB,GAAeC,GAAqB;AAC7C,UAAM,CAACoB,GAAIC,CAAE,IAAI,KAAK;AACtB,WAAO,KAAK,aAAa,CAACtB,IAAQqB,GAAIpB,IAAQqB,CAAE,CAAC;AAAA,EACnD;AAAA,EAEA,aAAapD,GAAgB4D,IAA6B,UAAU;AAC9D,QAAA,CAAC,KAAK,gBAAgB;AAClB,YAAA,IAAI,MAAM,gDAAgD;AAE7D,gBAAA,cAAc,EAAE,MAAAA,GAAM,QAAA5D,EAAO,GAC3B;AAAA,EACT;AAAA,EAEU,2BACRA,GACA4D,IAA6B,UAC7B;AACA,QAAI,CAAC5D;AAAQ;AAEP,UAAA6D,IAAc,KAAK,gBAAgB,IAAI,GACvC/D,IAAe,KAAK,gBAAgB,MAAM;AAE5C,QAAA,CAAC+D,KAAe,CAAC/D;AACb,YAAA,IAAI,MAAM,uCAAuC;AAEnD,UAAA+B,IAAa+B,MAAS,YAAY1C,IAAkBH;AAE1D,SAAK,gBAAgB,KAAK,GAAGc,EAAWgC,GAAa/D,GAAcE,CAAM,CAAC;AAAA,EAC5E;AAAA,EAEA,QAAiB;AACX,QAAA,CAAC,KAAK,gBAAgB;AAAc,YAAA,IAAI,MAAM,sBAAsB;AAClE,UAAAF,IAAe,KAAK,gBAAgB,CAAC,GAErC+D,IAAc,KAAK,gBAAgB,GAAG,EAAE;AAE9C,WAAKlC,EAAW7B,EAAa,YAAY+D,EAAY,SAAS,KACvD,KAAA,OAAO/D,EAAa,UAAU,GAGjC,KAAK,gBAAgB,SAClB,KAAA;AAAA,MACH,KAAK,YAAY;AAAA,MACjB,KAAK,YAAY;AAAA,IAAA,GAEnB,KAAK,cAAc,OAGdqB,EAAuB,KAAK,eAAe;AAAA,EACpD;AAAA,EAEA,kBAA2B;AACrB,QAAA,CAAC,KAAK,gBAAgB;AAAc,YAAA,IAAI,MAAM,sBAAsB;AAElE,UAAArB,IAAe,KAAK,gBAAgB,CAAC,GAErC+D,IAAc,KAAK,gBAAgB,GAAG,EAAE,GAExCC,IAAeC;AAAA,MACnBF,EAAY;AAAA,MACZ/D,EAAa;AAAA,IAAA,GAETkE,IAAiB,IAAIC,GAAA,EAAuB;AAAA,MAChDH;AAAA,MACAhE,EAAa;AAAA,IAAA,GAGToE,IAAmB,KAAK,gBAAgB;AAAA,MAAI,CAACpF,MACjDA,EAAQ,UAAUkF,CAAc,EAAE,QAAQ;AAAA,IAAA;AAE5C,WAAAE,EAAiB,QAAQ,GAElB/C,EAAuB;AAAA,MAC5B,GAAG,KAAK;AAAA,MACR,GAAG+C;AAAA,IAAA,CACJ;AAAA,EACH;AACF;AAEO,SAASC,GAAK1C,IAAiB,CAAC,GAAG,CAAC,GAAe;AACjD,SAAA,IAAID,GAAWC,CAAM;AAC9B;AC1RO,SAAS2C,EAAcC,GAA0C;AACtE,MAAIA,aAAiB/C;AACnB,WAAO,CAAC+C,CAAK;AACf,MAAWA,aAAiB9C;AAC1B,WAAO,CAAC,IAAID,EAAO+C,CAAK,CAAC;AAC3B,MAAWA,aAAiBhD;AAC1B,WAAOgD,EAAM;AAET,QAAA,IAAI,MAAM,eAAe;AACjC;ACHgB,SAAAC,GACdzD,GACAC,GACS;AACT,SAAO,IAAIO;AAAA,IACTkD,GAAiBH,EAAcvD,CAAK,GAAGuD,EAActD,CAAM,CAAC;AAAA,EAAA;AAEhE;AAEO,SAAS0D,EAAQC,GAA8C;AACpE,SAAOA,EAAO;AAAA,IACZ,CAACC,GAAcL,MAAmCC,GAAKI,GAAKL,CAAK;AAAA,IACjE,IAAIhD,EAAQ;AAAA,EAAA;AAEhB;AAEgB,SAAAsD,GACd9D,GACAC,GACS;AACT,SAAO,IAAIO;AAAA,IACTuD,GAAgBR,EAAcvD,CAAK,GAAGuD,EAActD,CAAM,CAAC;AAAA,EAAA;AAE/D;AAEgB,SAAA+D,GACdhE,GACAC,GACS;AACT,SAAO,IAAIO;AAAA,IACTyD,GAAsBV,EAAcvD,CAAK,GAAGuD,EAActD,CAAM,CAAC;AAAA,EAAA;AAErE;ACtCA,SAASiE,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,WAAO7D,EAASsD,EAAM,YAAYC,EAAM,UAAU;AACzC,MAAAK,MAAkB,WAAWC,MAAmB;AACzD,WAAO7D,EAASsD,EAAM,WAAWC,EAAM,SAAS;AACvC,MAAAK,MAAkB,YAAYC,MAAmB;AAC1D,WAAO7D,EAASsD,EAAM,YAAYC,EAAM,SAAS;AACxC,MAAAK,MAAkB,WAAWC,MAAmB;AACzD,WAAO7D,EAASsD,EAAM,WAAWC,EAAM,UAAU;AAE3C,QAAA,IAAI,MAAM,kBAAkB;AAEtC;AC1CgB,SAAAO,EAAgB1G,GAAYI,GAAkB;AAG5D,MAAIuG,GAAoB3G,GAAMI,CAAG,EAAE,SAAS;AACnC,WAAA;AAGT,QAAMwG,IAAqBC,GAAmB7G,GAAMI,EAAI,MAAM;AAE1D,MAAAJ,EAAK,YAAY4G,CAAkB,GAAG;AACxC,UAAME,IAA2BlE,EAASgE,GAAoBxG,EAAI,MAAM;AAGxE,QAAI,KAAK,IAAI0G,IAA2B1G,EAAI,MAAM,IAAIJ,EAAK,aACrDI,EAAI,YAAYwG,CAAkB;AAC7B,aAAA;AAIX,QAAIE,IAA2B1G,EAAI,SAASJ,EAAK,WAAW;AAC1D,YAAM+G,IAAsBC;AAAA,QAC1BrC,EAASiC,GAAoBxG,EAAI,MAAM;AAAA,MAAA,GAGnC6G,IAAuB/G;AAAA,QAC3BE,EAAI;AAAA,QACJD,EAAe4G,GAAqB3G,EAAI,MAAM;AAAA,MAAA;AAG5C,UAAAA,EAAI,YAAY6G,CAAoB;AAC/B,eAAArE,EAASqE,GAAsBL,CAAkB;AAAA,IAE5D;AAAA,EACF;AAEA,SAAO,KAAK;AAAA,IACVxG,EAAI,aAAaJ,EAAK,UAAU;AAAA,IAChCI,EAAI,aAAaJ,EAAK,SAAS;AAAA,IAC/BA,EAAK,aAAaI,EAAI,UAAU;AAAA,IAChCJ,EAAK,aAAaI,EAAI,SAAS;AAAA,EAAA;AAEnC;AC5CA,MAAM8G,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,IAAkB7E,EAASuE,EAAK,QAAQC,EAAK,MAAM;AAErD,MAAAK,IAAkBN,EAAK,aACrBD,GAAkBC,GAAMC,CAAI;AAC9B,WAAO,KAAK,IAAID,EAAK,SAASC,EAAK,MAAM;AAI7C,QAAMM,IAAwBV,GAAUrC,EAASyC,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,IAEhD1E,EAASuE,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;ACjDgB,SAAAvE,GAASmF,GAAmBC,GAA2B;AACjE,MAAAD,aAAoBnI,KAAQoI,aAAoBpI;AAC3C,WAAAqG,GAAiB8B,GAAUC,CAAQ;AAGxC,MAAAD,aAAoBnI,KAAQoI,aAAoBlI;AAC3C,WAAA4G,EAAgBqB,GAAUC,CAAQ;AAGvC,MAAAD,aAAoBjI,KAAOkI,aAAoBpI;AAC1C,WAAA8G,EAAgBsB,GAAUD,CAAQ;AAGvC,MAAAA,aAAoBjI,KAAOkI,aAAoBlI;AAC1C,WAAAyH,GAAeQ,GAAUC,CAAQ;AAGpC,QAAA,IAAI,MAAM,iBAAiB;AACnC;ACxBe,MAAMC,GAAU;AAAA,EAE3B,cAAc;AACV,SAAK,MAAM,IACX,KAAK,SAAS,IACd,KAAK,SAAS;AAAA,EACjB;AAAA,EAED,QAAQ;AACJ,SAAK,SAAS;AAAA,EACjB;AAAA,EAED,KAAKC,GAAIC,GAAO;AACZ,QAAIC,IAAM,KAAK;AAEf,WAAOA,IAAM,KAAG;AACZ,YAAMC,IAAUD,IAAM,KAAM,GACtBE,IAAc,KAAK,OAAOD,CAAM;AACtC,UAAIF,KAASG;AAAa;AAC1B,WAAK,IAAIF,CAAG,IAAI,KAAK,IAAIC,CAAM,GAC/B,KAAK,OAAOD,CAAG,IAAIE,GACnBF,IAAMC;AAAA,IACT;AAED,SAAK,IAAID,CAAG,IAAIF,GAChB,KAAK,OAAOE,CAAG,IAAID;AAAA,EACtB;AAAA,EAED,MAAM;AACF,QAAI,KAAK,WAAW;AAAG;AAEvB,UAAMI,IAAM,KAAK,IAAI,CAAC;AAGtB,QAFA,KAAK,UAED,KAAK,SAAS,GAAG;AACjB,YAAML,IAAK,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,MAAM,GACvCC,IAAQ,KAAK,OAAO,CAAC,IAAI,KAAK,OAAO,KAAK,MAAM,GAChDK,IAAa,KAAK,UAAU;AAClC,UAAIJ,IAAM;AAEV,aAAOA,IAAMI,KAAY;AACrB,YAAIC,KAAQL,KAAO,KAAK;AACxB,cAAMM,IAAQD,IAAO;AACrB,YAAIE,IAAY,KAAK,IAAIF,CAAI,GACzBG,IAAY,KAAK,OAAOH,CAAI;AAChC,cAAMI,IAAa,KAAK,OAAOH,CAAK;AAOpC,YALIA,IAAQ,KAAK,UAAUG,IAAaD,MACpCH,IAAOC,GACPC,IAAY,KAAK,IAAID,CAAK,GAC1BE,IAAYC,IAEZD,KAAaT;AAAO;AAExB,aAAK,IAAIC,CAAG,IAAIO,GAChB,KAAK,OAAOP,CAAG,IAAIQ,GACnBR,IAAMK;AAAA,MACT;AAED,WAAK,IAAIL,CAAG,IAAIF,GAChB,KAAK,OAAOE,CAAG,IAAID;AAAA,IACtB;AAED,WAAOI;AAAA,EACV;AAAA,EAED,OAAO;AACH,QAAI,KAAK,WAAW;AACpB,aAAO,KAAK,IAAI,CAAC;AAAA,EACpB;AAAA,EAED,YAAY;AACR,QAAI,KAAK,WAAW;AACpB,aAAO,KAAK,OAAO,CAAC;AAAA,EACvB;AAAA,EAED,SAAS;AACL,SAAK,IAAI,SAAS,KAAK,OAAO,SAAS,KAAK;AAAA,EAC/C;AACL;AC9EA,MAAMO,IAAc;AAAA,EAChB;AAAA,EAAW;AAAA,EAAY;AAAA,EAAmB;AAAA,EAAY;AAAA,EACtD;AAAA,EAAY;AAAA,EAAa;AAAA,EAAc;AAC3C,GAEMC,IAAU;AAED,MAAMC,EAAS;AAAA,EAE1B,OAAO,KAAKC,GAAM;AACd,QAAI,CAACA,KAAQA,EAAK,eAAe,UAAaA,EAAK;AAC/C,YAAM,IAAI,MAAM,+DAA+D;AAEnF,UAAM,CAACC,GAAOC,CAAc,IAAI,IAAI,WAAWF,GAAM,GAAG,CAAC;AACzD,QAAIC,MAAU;AACV,YAAM,IAAI,MAAM,kDAAkD;AAEtE,QAAIC,KAAkB,MAAMJ;AACxB,YAAM,IAAI,MAAM,QAAQI,KAAkB,yBAAyBJ,IAAU;AAEjF,UAAM,CAACK,CAAQ,IAAI,IAAI,YAAYH,GAAM,GAAG,CAAC,GACvC,CAACI,CAAQ,IAAI,IAAI,YAAYJ,GAAM,GAAG,CAAC;AAE7C,WAAO,IAAID,EAASK,GAAUD,GAAUN,EAAYK,IAAiB,EAAI,GAAG,QAAWF,CAAI;AAAA,EAC9F;AAAA,EAED,YAAYI,GAAUD,IAAW,IAAIE,IAAY,cAAcC,IAAkB,aAAaN,GAAM;AAChG,QAAII,MAAa;AAAW,YAAM,IAAI,MAAM,sCAAsC;AAClF,QAAI,MAAMA,CAAQ,KAAKA,KAAY;AAAG,YAAM,IAAI,MAAM,8BAA8BA,IAAW;AAE/F,SAAK,WAAW,CAACA,GACjB,KAAK,WAAW,KAAK,IAAI,KAAK,IAAI,CAACD,GAAU,CAAC,GAAG,KAAK;AAItD,QAAII,IAAIH,GACJI,IAAWD;AACf,SAAK,eAAe,CAACA,IAAI,CAAC;AAC1B;AACI,MAAAA,IAAI,KAAK,KAAKA,IAAI,KAAK,QAAQ,GAC/BC,KAAYD,GACZ,KAAK,aAAa,KAAKC,IAAW,CAAC;AAAA,WAC9BD,MAAM;AAEf,SAAK,YAAYF,KAAa,cAC9B,KAAK,iBAAiBG,IAAW,QAAQ,cAAc;AAEvD,UAAMC,IAAiBZ,EAAY,QAAQ,KAAK,SAAS,GACnDa,IAAgBF,IAAW,IAAI,KAAK,UAAU;AAEpD,QAAIC,IAAiB;AACjB,YAAM,IAAI,MAAM,iCAAiCJ,IAAY;AAGjE,IAAIL,KAAQA,EAAK,eAAe,UAAa,CAACA,EAAK,UAC/C,KAAK,OAAOA,GACZ,KAAK,SAAS,IAAI,KAAK,UAAU,KAAK,MAAM,GAAGQ,IAAW,CAAC,GAC3D,KAAK,WAAW,IAAI,KAAK,eAAe,KAAK,MAAM,IAAIE,GAAeF,CAAQ,GAE9E,KAAK,OAAOA,IAAW,GACvB,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,CAAC,GACrC,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,CAAC,GACrC,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,CAAC,GACrC,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,CAAC,MAGrC,KAAK,OAAO,IAAIF,EAAgB,IAAII,IAAgBF,IAAW,KAAK,eAAe,iBAAiB,GACpG,KAAK,SAAS,IAAI,KAAK,UAAU,KAAK,MAAM,GAAGA,IAAW,CAAC,GAC3D,KAAK,WAAW,IAAI,KAAK,eAAe,KAAK,MAAM,IAAIE,GAAeF,CAAQ,GAC9E,KAAK,OAAO,GACZ,KAAK,OAAO,OACZ,KAAK,OAAO,OACZ,KAAK,OAAO,QACZ,KAAK,OAAO,QAEZ,IAAI,WAAW,KAAK,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAOV,KAAW,KAAKW,CAAc,CAAC,GAC3E,IAAI,YAAY,KAAK,MAAM,GAAG,CAAC,EAAE,CAAC,IAAIN,GACtC,IAAI,YAAY,KAAK,MAAM,GAAG,CAAC,EAAE,CAAC,IAAIC,IAI1C,KAAK,SAAS,IAAIpB;EACrB;AAAA,EAED,IAAI2B,GAAMC,GAAMC,GAAMC,GAAM;AACxB,UAAMC,IAAQ,KAAK,QAAQ,GACrBC,IAAQ,KAAK;AACnB,gBAAK,SAASD,CAAK,IAAIA,GACvBC,EAAM,KAAK,MAAM,IAAIL,GACrBK,EAAM,KAAK,MAAM,IAAIJ,GACrBI,EAAM,KAAK,MAAM,IAAIH,GACrBG,EAAM,KAAK,MAAM,IAAIF,GAEjBH,IAAO,KAAK,SAAM,KAAK,OAAOA,IAC9BC,IAAO,KAAK,SAAM,KAAK,OAAOA,IAC9BC,IAAO,KAAK,SAAM,KAAK,OAAOA,IAC9BC,IAAO,KAAK,SAAM,KAAK,OAAOA,IAE3BC;AAAA,EACV;AAAA,EAED,SAAS;AACL,QAAI,KAAK,QAAQ,MAAM,KAAK;AACxB,YAAM,IAAI,MAAM,SAAS,KAAK,QAAQ,yBAAyB,KAAK,WAAW;AAEnF,UAAMC,IAAQ,KAAK;AAEnB,QAAI,KAAK,YAAY,KAAK,UAAU;AAEhC,MAAAA,EAAM,KAAK,MAAM,IAAI,KAAK,MAC1BA,EAAM,KAAK,MAAM,IAAI,KAAK,MAC1BA,EAAM,KAAK,MAAM,IAAI,KAAK,MAC1BA,EAAM,KAAK,MAAM,IAAI,KAAK;AAC1B;AAAA,IACH;AAED,UAAMC,IAAS,KAAK,OAAO,KAAK,QAAS,GACnCC,IAAU,KAAK,OAAO,KAAK,QAAS,GACpCC,IAAgB,IAAI,YAAY,KAAK,QAAQ,GAC7CC,KAAc,KAAK,MAAM;AAG/B,aAASC,IAAI,GAAGlC,IAAM,GAAGkC,IAAI,KAAK,UAAUA,KAAK;AAC7C,YAAMV,IAAOK,EAAM7B,GAAK,GAClByB,IAAOI,EAAM7B,GAAK,GAClB0B,IAAOG,EAAM7B,GAAK,GAClB2B,IAAOE,EAAM7B,GAAK,GAClB/E,IAAI,KAAK,MAAMgH,MAAeT,IAAOE,KAAQ,IAAI,KAAK,QAAQI,CAAK,GACnE5G,IAAI,KAAK,MAAM+G,MAAeR,IAAOE,KAAQ,IAAI,KAAK,QAAQI,CAAM;AAC1E,MAAAC,EAAcE,CAAC,IAAIC,GAAQlH,GAAGC,CAAC;AAAA,IAClC;AAGD,IAAAkH,EAAKJ,GAAeH,GAAO,KAAK,UAAU,GAAG,KAAK,WAAW,GAAG,KAAK,QAAQ;AAG7E,aAASK,IAAI,GAAGlC,IAAM,GAAGkC,IAAI,KAAK,aAAa,SAAS,GAAGA,KAAK;AAC5D,YAAM5G,IAAM,KAAK,aAAa4G,CAAC;AAG/B,aAAOlC,IAAM1E,KAAK;AACd,cAAM+G,IAAYrC;AAGlB,YAAIsC,IAAWT,EAAM7B,GAAK,GACtBuC,IAAWV,EAAM7B,GAAK,GACtBwC,IAAWX,EAAM7B,GAAK,GACtByC,IAAWZ,EAAM7B,GAAK;AAC1B,iBAAS0C,IAAI,GAAGA,IAAI,KAAK,YAAY1C,IAAM1E,GAAKoH;AAC5C,UAAAJ,IAAW,KAAK,IAAIA,GAAUT,EAAM7B,GAAK,CAAC,GAC1CuC,IAAW,KAAK,IAAIA,GAAUV,EAAM7B,GAAK,CAAC,GAC1CwC,IAAW,KAAK,IAAIA,GAAUX,EAAM7B,GAAK,CAAC,GAC1CyC,IAAW,KAAK,IAAIA,GAAUZ,EAAM7B,GAAK,CAAC;AAI9C,aAAK,SAAS,KAAK,QAAQ,CAAC,IAAIqC,GAChCR,EAAM,KAAK,MAAM,IAAIS,GACrBT,EAAM,KAAK,MAAM,IAAIU,GACrBV,EAAM,KAAK,MAAM,IAAIW,GACrBX,EAAM,KAAK,MAAM,IAAIY;AAAA,MACxB;AAAA,IACJ;AAAA,EACJ;AAAA,EAED,OAAOjB,GAAMC,GAAMC,GAAMC,GAAMgB,GAAU;AACrC,QAAI,KAAK,SAAS,KAAK,OAAO;AAC1B,YAAM,IAAI,MAAM,6CAA6C;AAGjE,QAAIN,IAAY,KAAK,OAAO,SAAS;AACrC,UAAMO,IAAQ,CAAA,GACRC,IAAU,CAAA;AAEhB,WAAOR,MAAc,UAAW;AAE5B,YAAM/G,IAAM,KAAK,IAAI+G,IAAY,KAAK,WAAW,GAAGS,EAAWT,GAAW,KAAK,YAAY,CAAC;AAG5F,eAASrC,IAAMqC,GAAWrC,IAAM1E,GAAK0E,KAAO,GAAG;AAK3C,YAHI0B,IAAO,KAAK,OAAO1B,CAAG,KACtB2B,IAAO,KAAK,OAAO3B,IAAM,CAAC,KAC1BwB,IAAO,KAAK,OAAOxB,IAAM,CAAC,KAC1ByB,IAAO,KAAK,OAAOzB,IAAM,CAAC;AAAG;AAEjC,cAAM4B,IAAQ,KAAK,SAAS5B,KAAO,CAAC,IAAI;AAExC,QAAIqC,KAAa,KAAK,WAAW,IAC7BO,EAAM,KAAKhB,CAAK,KAETe,MAAa,UAAaA,EAASf,CAAK,MAC/CiB,EAAQ,KAAKjB,CAAK;AAAA,MAEzB;AAED,MAAAS,IAAYO,EAAM;IACrB;AAED,WAAOC;AAAA,EACV;AAAA,EAED,UAAU5H,GAAGC,GAAG6H,IAAa,OAAUC,IAAc,OAAUL,GAAU;AACrE,QAAI,KAAK,SAAS,KAAK,OAAO;AAC1B,YAAM,IAAI,MAAM,6CAA6C;AAGjE,QAAIN,IAAY,KAAK,OAAO,SAAS;AACrC,UAAMY,IAAI,KAAK,QACTJ,IAAU,CAAA,GACVK,IAAiBF,IAAcA;AAErC,WAAOX,MAAc,UAAW;AAE5B,YAAM/G,IAAM,KAAK,IAAI+G,IAAY,KAAK,WAAW,GAAGS,EAAWT,GAAW,KAAK,YAAY,CAAC;AAG5F,eAASrC,IAAMqC,GAAWrC,IAAM1E,GAAK0E,KAAO,GAAG;AAC3C,cAAM4B,IAAQ,KAAK,SAAS5B,KAAO,CAAC,IAAI,GAElCmD,IAAKC,EAASnI,GAAG,KAAK,OAAO+E,CAAG,GAAG,KAAK,OAAOA,IAAM,CAAC,CAAC,GACvDqD,IAAKD,EAASlI,GAAG,KAAK,OAAO8E,IAAM,CAAC,GAAG,KAAK,OAAOA,IAAM,CAAC,CAAC,GAC3DsD,IAAOH,IAAKA,IAAKE,IAAKA;AAE5B,QAAIhB,KAAa,KAAK,WAAW,IAC7BY,EAAE,KAAKrB,KAAS,GAAG0B,CAAI,KAEhBX,MAAa,UAAaA,EAASf,CAAK,MAC/CqB,EAAE,MAAMrB,KAAS,KAAK,GAAG0B,CAAI;AAAA,MAEpC;AAGD,aAAOL,EAAE,UAAWA,EAAE,KAAM,IAAG;AAQ3B,YAPaA,EAAE,cACJC,MAIXL,EAAQ,KAAKI,EAAE,IAAK,KAAI,CAAC,GAErBJ,EAAQ,WAAWE;AACnB,iBAAAE,EAAE,MAAK,GACAJ;AAIf,MAAAR,IAAYY,EAAE,IAAK,KAAI;AAAA,IAC1B;AAED,WAAAA,EAAE,MAAK,GACAJ;AAAA,EACV;AACL;AAEA,SAASO,EAASG,GAAGC,GAAKC,GAAK;AAC3B,SAAOF,IAAIC,IAAMA,IAAMD,IAAIA,KAAKE,IAAM,IAAIF,IAAIE;AAClD;AAGA,SAASX,EAAW/C,GAAO2D,GAAK;AAC5B,MAAIxB,IAAI,GACJQ,IAAIgB,EAAI,SAAS;AACrB,SAAOxB,IAAIQ,KAAG;AACV,UAAMiB,IAAKzB,IAAIQ,KAAM;AACrB,IAAIgB,EAAIC,CAAC,IAAI5D,IACT2C,IAAIiB,IAEJzB,IAAIyB,IAAI;AAAA,EAEf;AACD,SAAOD,EAAIxB,CAAC;AAChB;AAGA,SAASE,EAAKwB,GAAQ/B,GAAOgC,GAASxD,GAAMC,GAAOU,GAAU;AACzD,MAAI,KAAK,MAAMX,IAAOW,CAAQ,KAAK,KAAK,MAAMV,IAAQU,CAAQ;AAAG;AAEjE,QAAM8C,IAAQF,EAAQvD,IAAOC,KAAU,CAAC;AACxC,MAAI4B,IAAI7B,IAAO,GACXqC,IAAIpC,IAAQ;AAEhB,aAAa;AACT;AAAG,MAAA4B;AAAA,WAAY0B,EAAO1B,CAAC,IAAI4B;AAC3B;AAAG,MAAApB;AAAA,WAAYkB,EAAOlB,CAAC,IAAIoB;AAC3B,QAAI5B,KAAKQ;AAAG;AACZ,IAAAqB,GAAKH,GAAQ/B,GAAOgC,GAAS3B,GAAGQ,CAAC;AAAA,EACpC;AAED,EAAAN,EAAKwB,GAAQ/B,GAAOgC,GAASxD,GAAMqC,GAAG1B,CAAQ,GAC9CoB,EAAKwB,GAAQ/B,GAAOgC,GAASnB,IAAI,GAAGpC,GAAOU,CAAQ;AACvD;AAGA,SAAS+C,GAAKH,GAAQ/B,GAAOgC,GAAS,GAAGnB,GAAG;AACxC,QAAMsB,IAAOJ,EAAO,CAAC;AACrB,EAAAA,EAAO,CAAC,IAAIA,EAAOlB,CAAC,GACpBkB,EAAOlB,CAAC,IAAIsB;AAEZ,QAAMT,IAAI,IAAI,GACRI,IAAI,IAAIjB,GAERuB,IAAIpC,EAAM0B,CAAC,GACXW,IAAIrC,EAAM0B,IAAI,CAAC,GACf,IAAI1B,EAAM0B,IAAI,CAAC,GACfY,IAAItC,EAAM0B,IAAI,CAAC;AACrB,EAAA1B,EAAM0B,CAAC,IAAI1B,EAAM8B,CAAC,GAClB9B,EAAM0B,IAAI,CAAC,IAAI1B,EAAM8B,IAAI,CAAC,GAC1B9B,EAAM0B,IAAI,CAAC,IAAI1B,EAAM8B,IAAI,CAAC,GAC1B9B,EAAM0B,IAAI,CAAC,IAAI1B,EAAM8B,IAAI,CAAC,GAC1B9B,EAAM8B,CAAC,IAAIM,GACXpC,EAAM8B,IAAI,CAAC,IAAIO,GACfrC,EAAM8B,IAAI,CAAC,IAAI,GACf9B,EAAM8B,IAAI,CAAC,IAAIQ;AAEf,QAAMC,IAAIP,EAAQ,CAAC;AACnB,EAAAA,EAAQ,CAAC,IAAIA,EAAQnB,CAAC,GACtBmB,EAAQnB,CAAC,IAAI0B;AACjB;AAIA,SAASjC,GAAQlH,GAAGC,GAAG;AACnB,MAAI+I,IAAIhJ,IAAIC,GACRgJ,IAAI,QAASD,GACbI,IAAI,SAAUpJ,IAAIC,IAClBiJ,IAAIlJ,KAAKC,IAAI,QAEboJ,IAAIL,IAAKC,KAAK,GACdK,IAAKN,KAAK,IAAKA,GACfO,IAAMH,KAAK,IAAMH,IAAKC,KAAK,IAAOE,GAClCI,IAAMR,IAAKI,KAAK,IAAOF,KAAK,IAAMA;AAEtC,EAAAF,IAAIK,GAAGJ,IAAIK,GAAGF,IAAIG,GAAGL,IAAIM,GACzBH,IAAML,IAAKA,KAAK,IAAOC,IAAKA,KAAK,GACjCK,IAAMN,IAAKC,KAAK,IAAOA,KAAMD,IAAIC,MAAM,GACvCM,KAAOP,IAAKI,KAAK,IAAOH,IAAKC,KAAK,GAClCM,KAAOP,IAAKG,KAAK,KAAQJ,IAAIC,KAAMC,KAAK,GAExCF,IAAIK,GAAGJ,IAAIK,GAAGF,IAAIG,GAAGL,IAAIM,GACzBH,IAAML,IAAKA,KAAK,IAAOC,IAAKA,KAAK,GACjCK,IAAMN,IAAKC,KAAK,IAAOA,KAAMD,IAAIC,MAAM,GACvCM,KAAOP,IAAKI,KAAK,IAAOH,IAAKC,KAAK,GAClCM,KAAOP,IAAKG,KAAK,KAAQJ,IAAIC,KAAMC,KAAK,GAExCF,IAAIK,GAAGJ,IAAIK,GAAGF,IAAIG,GAAGL,IAAIM,GACzBD,KAAOP,IAAKI,KAAK,IAAOH,IAAKC,KAAK,GAClCM,KAAOP,IAAKG,KAAK,KAAQJ,IAAIC,KAAMC,KAAK,GAExCF,IAAIO,IAAKA,KAAK,GACdN,IAAIO,IAAKA,KAAK;AAEd,MAAIC,IAAKzJ,IAAIC,GACTyJ,IAAKT,IAAK,SAAUQ,IAAKT;AAE7B,SAAAS,KAAMA,IAAMA,KAAM,KAAM,UACxBA,KAAMA,IAAMA,KAAM,KAAM,WACxBA,KAAMA,IAAMA,KAAM,KAAM,WACxBA,KAAMA,IAAMA,KAAM,KAAM,YAExBC,KAAMA,IAAMA,KAAM,KAAM,UACxBA,KAAMA,IAAMA,KAAM,KAAM,WACxBA,KAAMA,IAAMA,KAAM,KAAM,WACxBA,KAAMA,IAAMA,KAAM,KAAM,aAEfA,KAAM,IAAKD,OAAQ;AAChC;AC7WgB,SAAAE,GACdhL,GACAiL,IAAY,MACC;AAEb,QAAMC,IAAc,IAAIlE,EAAShH,EAAS,MAAM;AACvC,EAAAA,EAAA,QAAQ,CAACyK,MAAM;AACtB,UAAM,CAACpJ,GAAGC,CAAC,IAAImJ,EAAE;AACL,IAAAS,EAAA,IAAI7J,IAAI4J,GAAW3J,IAAI2J,GAAW5J,IAAI4J,GAAW3J,IAAI2J,CAAS;AAAA,EAAA,CAC3E,GACDC,EAAY,OAAO;AAEnB,QAAMC,IAAgC,CAAA,GAChCC,wBAAc;AAEX,SAAApL,EAAA,QAAQ,CAACtC,GAASsK,MAAU;AAC/B,QAAAoD,EAAQ,IAAIpD,CAAK;AAAG;AAElB,UAAAqD,IAA+B,CAAC3N,CAAO;AAC7C,QAAI4N,IAAetD;AAEnB,IAAAoD,EAAQ,IAAIpD,CAAK;AAIjB,QAAIuD,IAAWvL,EAAS;AAExB,eAAa;AACX,UAAIuL,MAAa;AACT,cAAA,IAAI,MAAM,wBAAwB;AAG1C,YAAM/N,IACJ6N,EAAkBA,EAAkB,SAAS,CAAC,EAAE,WAE5C,CAAChK,GAAGC,CAAC,IAAI9D,GACTgO,IAAYN,EAAY;AAAA,QAC5B7J,IAAI4J;AAAA,QACJ3J,IAAI2J;AAAA,QACJ5J,IAAI4J;AAAA,QACJ3J,IAAI2J;AAAA,MAAA,GAGAQ,IAAgB,CAACC,MACrB,KAAK,KAAKJ,IAAeI,KAAc1L,EAAS,MAAM,GAClD2L,IAAwBH,EAC3B,OAAO,CAACI,MAAkB,CAACR,EAAQ,IAAIQ,CAAa,CAAC,EACrD,IAAI,CAACA,MAA6C;AAAA,QACjD5L,EAAS4L,CAAa;AAAA,QACtBA;AAAA,QACAH,EAAcG,CAAa;AAAA,MAC5B,CAAA,EACA,KAAK,CAAC,CAAK,EAAA,EAAAvB,CAAC,GAAG,CAAK,EAAA,EAAAC,CAAC,MAAMmB,EAAcpB,CAAC,IAAIoB,EAAcnB,CAAC,CAAC;AAE7D,UAAAqB,EAAsB,WAAW,GAAG;AAEtC,QAAAR,EAAiB,KAAKE,CAAiB;AACvC;AAAA,MACF;AAEA,YAAM,CAACQ,GAAaC,CAAgB,IAAIH,EAAsB,CAAC;AAE/D,MAAAN,EAAkB,KAAKQ,CAAW,GAClCT,EAAQ,IAAIU,CAAgB,GACbR,IAAAQ;AAAA,IACjB;AAAA,EAAA,CACD,GAEMX;AACT;ACtDA,MAAMY,IAAY;AAEF,SAAAC,GACdC,GACAtO,GACW;AACX,QAAMuO,IAAsCD,EAAiB,IAAI,CAACxB,OAAO;AAAA,IACvE,QAAQhN,EAAcgN,GAAG9M,CAAM;AAAA,IAC/B,UAAU8M;AAAA,EACV,EAAA,GAMI0B,IAA4B,CAAA;AAElC,MAAIC,IAA6C,MAE7C5L,IAAkB0L,EAAe,GAAG,EAAE;AAG1C,MAAI,CAAC1L;AAAiB,WAAO;AAC7B,MAAI2L,EAAe,WAAW;AAAU,WAAAA;AAElC,QAAAE,IAAgB,CAAC3O,MAA+B;AACpD,IAAK0O,IAEQ1O,EAAQ,kBAAkBJ,IAGpCiD,EAAW7C,EAAQ,OAAO,YAAYA,EAAQ,OAAO,SAAS,KAEhDyO,EAAA;AAAA,MACb,IAAIvO,EAAKF,EAAQ,OAAO,YAAYA,EAAQ,OAAO,SAAS;AAAA,IAAA,IAL/CyO,EAAA,KAAKzO,EAAQ,MAAM,IAFf0O,IAAA1O;AAAA,EASrB,GAEI4O,IAAwB,aAA2C;AACvE,eAAW5O,KAAWwO,EAAe,MAAM,GAAG,EAAE;AACxC,YAAAxO;AAGR,QAAI,CAAC0O;AAAwB,YAAA,IAAI,MAAM,6BAA6B;AAC9D,UAAAA;AAAA,EAAA;AAGG,aAAA1O,KAAW4O,KAAyB;AACvC,UAAAC,IAAoB/L,EAAgB,OAAO,WAC3CjD,IAAaG,EAAQ,OAAO;AAG9B,QAAA6C,EAAWgM,GAAmBhP,CAAU,GAAG;AAC7C,MAAA8O,EAAc7L,CAAe,GACXA,IAAA9C;AAClB;AAAA,IACF;AAEA,QAAI8O,IAA0B,CAAA;AAE9B,QACE,EAAEhM,EAAgB,kBAAkBlD,MACpC,EAAEI,EAAQ,kBAAkBJ,IAC5B;AAEA,YAAM,EAAE,eAAemP,GAAoB,UAAAC,EACzC,IAAAC;AAAA,QACEnM,EAAgB;AAAA,QAChB9C,EAAQ;AAAA,QACRqO,IAAY;AAAA,MAAA;AAEA,MAAAS,IAAA;AAAA,QACd,GAAGC;AAAA,QACH,GAAGC,EAAS,QAAQ,CAACjC,MAAM,CAACA,EAAE,YAAYA,EAAE,SAAS,CAAC;AAAA,MAAA;AAAA,IAE1D;AAEI,QAAA+B,EAAc,SAAS,GAAG;AACxB,UAAAI,IAAeJ,EAAc,CAAC;AAC9B,UAAAA,EAAc,SAAS,GAAG;AAKtB,cAAAK,IAAmBrM,KAAA,gBAAAA,EAAiB,SAAS,WAC7CsM,IAAYN,EAAc;AAAA,UAAI,CAAClE,OACnCyE,GAAezE,IAAGuE,CAAgB;AAAA,QAAA;AAErB,QAAAD,IAAAJ,EAAcM,EAAU,QAAQ,KAAK,IAAI,GAAGA,CAAS,CAAC,CAAC;AAAA,MACxE;AAKM,YAAAE,IAAwBxM,EAAgB,OAAmB,QAAQ;AAAA,QACvEoM;AAAA,MAAA,CACD,EAAE,CAAC,GACEK,IAAgBvP,EAAQ,OAC3B,QAAQ,CAACkP,CAAY,CAAC,EACtB,GAAG,EAAE;AAER,UAAI,CAACK;AAAoB,cAAA,IAAI,MAAM,qCAAqC;AAE1D,MAAAZ,EAAA;AAAA,QACZ,QAAQW;AAAA,QACR,UAAUxM,EAAgB;AAAA,MAAA,CAC3B,GACDA,IAAkB,EAAE,QAAQyM,GAAc,UAAUvP,EAAQ;AAC5D;AAAA,IACF;AAIM,UAAA0B,IAASoB,EAAgB,SAAS,WAClC0M,IACJpO;AAAA,MACE6D,EAASpF,GAAY6B,CAAM;AAAA,MAC3BuD,EAAS4J,GAAmBnN,CAAM;AAAA,IAChC,IAAA,GAEA+N,IAAS,IAAIrP,EAAIyO,GAAmBhP,GAAY6B,GAAQ8N,CAAS;AAEvE,IAAAb,EAAc7L,CAAe,GAC7B2L,EAAe,KAAKgB,CAAM,GACR3M,IAAA9C;AAAA,EACpB;AAEA,SAAA2O,EAAc7L,CAAe,GACtB2L;AACT;AAOgB,SAAAiB,EAAWC,GAAY1P,GAAyB;AAC9D,QAAM2P,IAAkBD,EAAK,YAAY1P,IAAS,CAACA,GAC7CwO,IAAiBH,GAAWqB,EAAK,UAAUC,CAAe;AAEhE,MAAInB,EAAe,SAAS;AAAG,WAAO,IAAIlM,EAAQ;AAK5C,QAAAsN,wBAA8C,OAC9CC,IAAsB,CAACxF,GAAeyF,MAAwB;AAClE,UAAMjB,IAAgBe,EAAiB,IAAIvF,CAAK,KAAK,CAAA;AACrD,IAAAuF,EAAiB,IAAIvF,GAAO,CAAC,GAAGwE,GAAe,GAAGiB,CAAS,CAAC;AAAA,EAAA;AAgC1D,MA7BWtB,EAAA,QAAQ,CAACzN,GAAcgP,MAAe;AACnD,IAAAvB,EACG,MAAMuB,IAAa,CAAC,EACpB,QAAQ,CAAC/O,GAAegP,MAAgB;AACjC,YAAA,EAAE,eAAeC,GAAkB,UAAAlB,EAAA,IACvCC,GAA6BjO,GAAcC,GAAeoN,CAAS,GAE/DS,IAAgB;AAAA,QACpB,GAAGoB;AAAA,QACH,GAAGlB,EAAS,QAAQ,CAACjC,MAAM,CAACA,EAAE,YAAYA,EAAE,SAAS,CAAC;AAAA,MAAA,EACtD,OAAO,CAACmC,MAAiB;AACnB,cAAAiB,IACJtN,EAAWqM,GAAclO,EAAa,UAAU,KAChD6B,EAAWqM,GAAclO,EAAa,SAAS,GAE3CoP,IACJvN,EAAWqM,GAAcjO,EAAc,UAAU,KACjD4B,EAAWqM,GAAcjO,EAAc,SAAS;AAElD,eAAO,EAAEkP,KAA2BC;AAAA,MAAA,CACrC;AAED,MAAKtB,EAAc,WAEnBgB,EAAoBE,GAAYlB,CAAa,GACzBgB,EAAAG,IAAcD,IAAa,GAAGlB,CAAa;AAAA,IAAA,CAChE;AAAA,EAAA,CACJ,GAEG,CAACe,EAAiB,MAAM;AACpB,UAAAQ,IAAgB,IAAI5N,EAAKgM,CAAc;AAC7C,WAAO,IAAIlM,EAAQ,CAAC,IAAIC,EAAO6N,CAAa,CAAC,CAAC;AAAA,EAMhD;AAWA,QAAMC,IATgB7B,EAAe,QAAQ,CAACzO,GAASsK,MAAU;AAC3D,QAAA,CAACuF,EAAiB,IAAIvF,CAAK;AAAU,aAAAtK;AAEzC,UAAM8O,IAAgBe,EAAiB,IAAIvF,CAAK,KAAK,CAAA;AAE9CiG,WADevQ,EAAQ,QAAQ8O,CAAa;AAAA,EAC5C,CACR,EAGoC,OAAO,CAAC9O,MAIpC,CAHc2P,EAAK,SAAS,KAAK,CAAC5C,MAChC7J,GAAS6J,GAAG/M,CAAO,IAAI,KAAK,IAAIC,CAAM,IAAIoO,CAClD,CAEF;AAED,MAAI,CAACiC,EAAe;AAAQ,WAAO,IAAI/N,EAAQ;AAI/C,QAAMiO,IAFkBlD,GAAegD,CAAc,EAGlD,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,OAAO,CAAC,MAAMzN,EAAW,EAAE,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,EAAG,SAAS,CAAC,EAC9D,IAAI,CAAC,MAAM,IAAIJ,EAAK,CAAC,CAAC;AAEzB,SAAK+N,EAAS,SACP,IAAIjO,EAAQiO,EAAS,IAAI,CAACC,MAAM,IAAIjO,EAAOiO,CAAC,CAAC,CAAC,IADxB,IAAIlO,EAAQ;AAE3C;ACtOwB,SAAAmO,GACtBC,GACAC,GACS;AACT,QAAMF,IAAgBC,EAAQ,IAAI,CAACE,MAAW;AAC5C,UAAMC,IAAapL;AAAA,MACjBmL,EAAO,MAAM,IAAI,CAACJ,MAAMf,EAAWe,GAAGG,CAAc,CAAC;AAAA,IAAA;AAEvD,WAAO/K,GAAI6J,EAAWmB,EAAO,SAASD,CAAc,GAAGE,CAAU;AAAA,EAAA,CAClE;AAED,SAAOpL,EAAQgL,CAAa;AAC9B;ACXgB,SAAAzQ,GACdsF,GACAqL,GACS;AACT,SAAOF,GAAcpL,EAAcC,CAAK,GAAGqL,CAAc;AAC3D;ACPO,SAASG,GAAiB/Q,GAAkB;AACjD,MAAIA,aAAmBE;AACrB,WAAO,KAAKF,EAAQ,UAAU,KAAK,GAAG;AAExC,MAAIA,aAAmBI;AACrB,WAAO,KAAKJ,EAAQ,UAAUA,EAAQ,YACpCA,EAAQ,gBAAgB,KAAK,KAAK,MAAM,OACtCA,EAAQ,YAAY,MAAM,OAAOA,EAAQ,UAAU,KAAK,GAAG;AAG3D,QAAA,IAAI,MAAM,sBAAsB;AACxC;ACZO,SAASgR,GAAQrB,GAAY;AAClC,QAAMsB,IAAQ,KAAKtB,EAAK,WAAW,KAAK,GAAG,KACrCrN,IAAWqN,EAAK,SAAS,IAAIoB,EAAgB,EAAE,KAAK,GAAG;AAC7D,SAAO,GAAGE,KAAS3O;AACrB;ACJO,SAAS4O,GAAUL,GAAgB;AAExC,SAAO,YADMA,EAAO,SAAS,IAAIG,EAAO,EAAE,KAAK,GAAG;AAEpD;ACHO,SAASG,GAAWC,GAAkB;AACpC,SAAA;AAAA,IACLA,EAAQ,QAAQ,IAAIF,EAAS,EAAE,KAAK;AAAA,CAAI;AAAA;AAE5C;ACLgB,SAAAG,GAAWC,GAAmBC,IAAS,GAAG;AAClD,QAAArH,IAAOoH,EAAK,OAAOC,GACnBpH,IAAOmH,EAAK,OAAOC;AAElB,SAAA,GAAGrH,KAAQC,KAAQmH,EAAK,QAAQ,IAAIC,KACzCD,EAAK,SAAS,IAAIC;AAEtB;AAEO,SAASC,EAAQC,GAAcC,GAA0BH,IAAS,GAAG;AAEnE,SAAA;AAAA,iEADMF,GAAWK,GAAaH,CAAM;AAAA,MAGvCE;AAAA;AAEN;ACJO,SAASE,EAAQpM,GAAc;AACpC,MAAIA,aAAiBhD;AACnB,WAAO4O,GAAW5L,CAAK;AACzB,MAAWA,aAAiB/C;AAC1B,WAAO0O,GAAU3L,CAAK;AACxB,MAAWA,aAAiB9C;AACnB,WAAA,YAAYuO,GAAQzL,CAAK;AACvB,MAAAA,aAAiBnF,KAAOmF,aAAiBrF;AAClD,WAAO,YAAY,KAAKqF,EAAM,WAAW,KAAK,GAAG,OAAOwL;AAAA,MACtDxL;AAAA,IACF;AAEM,QAAA,IAAI,MAAM,oBAAoB;AAExC;AAEgB,SAAAqM,GAAUrM,GAAwBgM,IAAS,GAAG;AACxD,MAAA,MAAM,QAAQhM,CAAK,GAAG;AACxB,UAAMsM,IAAUtM,EAAM,IAAI,CAACuM,MAAMA,EAAE,QAAQ,GACrCL,IAAOI,EAAQ,IAAI,CAACC,MAAMH,EAAQG,CAAC,CAAC,EAAE,KAAK;AAAA,CAAI,GAC/CR,IAAOO,EACV,MAAM,CAAC,EACP,OAAO,CAACP,GAAMQ,MAAMR,EAAK,MAAMQ,EAAE,WAAW,GAAGD,EAAQ,CAAC,EAAE,WAAW;AAEjE,WAAAL,EAAQC,GAAMH,CAAI;AAAA,EAC3B;AACM,QAAAO,IAAUtM,EAAM;AACtB,SAAOiM,EAAQG,EAAQE,CAAO,GAAGA,EAAQ,aAAaN,CAAM;AAC9D;ACnCA,MAAMQ,KAAgB,CAACC,MAAc;AAC/B,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAI9R,EAAK8R,EAAK,YAAYA,EAAK,SAAS;AAE7C,MAAAA,EAAK,SAAS;AAChB,WAAO,IAAI5R;AAAA,MACT4R,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,MACLA,EAAK;AAAA,IAAA;AAGH,QAAA,IAAI,MAAM,sBAAsB;AACxC,GAEMC,IAAa,CAACD,MAAc;AAChC,QAAM1P,IAAW0P,EAAK,SAAS,IAAID,EAAa;AACzC,SAAA,IAAItP,EAAKH,CAAQ;AAC1B,GAEM4P,KAAe,CAACF,MAAc;AAC5B,QAAAG,IAAUF,EAAWD,EAAK,OAAO,GACjCI,IAAQJ,EAAK,MAAM,IAAIC,CAAU;AAChC,SAAA,IAAIzP,EAAO2P,GAASC,CAAK;AAClC,GAEMC,KAAgB,CAACL,MAAc;AACnC,QAAMrB,IAAUqB,EAAK,QAAQ,IAAIE,EAAY;AACtC,SAAA,IAAI3P,EAAQoO,CAAO;AAC5B;AAEO,SAAS2B,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;AAExB,MAAIA,EAAK,SAAS,UAAUA,EAAK,SAAS;AACxC,WAAOD,GAAcC,CAAI;AAErB,QAAA,IAAI,MAAM,oBAAoB;AACtC;AChDa,MAAAxO,KAAU,KAAK,KAAK,KACpB+O,KAAU,MAAM,KAAK;AAElB,SAAA9O,GAAiBJ,GAAWC,GAAuB;AACjE,QAAMK,IAAI,KAAK,IAAIL,IAAQE,EAAO,IAAIH,GAChCO,IAAI,KAAK,IAAIN,IAAQE,EAAO,IAAIH;AAC/B,SAAA,CAACM,GAAGC,CAAC;AACd;AAEO,SAAS4O,GAAiB,CAAC7O,GAAGC,CAAC,GAA6B;AACjE,QAAMP,IAAI,KAAK,KAAKM,IAAIA,IAAIC,IAAIA,CAAC,GAC3BN,IAAQ,KAAK,MAAMM,GAAGD,CAAC,IAAI4O;AAC1B,SAAA,CAAClP,GAAGC,CAAK;AAClB;","x_google_ignoreList":[9,10]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantograph2d",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Pantograph, the pure JS 2D CAD library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/pantograph.cjs",
|
|
@@ -44,5 +44,10 @@
|
|
|
44
44
|
"vite-plugin-dts": "^2.2.0",
|
|
45
45
|
"vitest": "^0.29.2"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "46ec6506931df9c9e0b4de3e8045248715fd17d5",
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"-": "^0.0.1",
|
|
50
|
+
"@types/flatbush": "^3.3.0",
|
|
51
|
+
"flatbush": "^4.1.0"
|
|
52
|
+
}
|
|
48
53
|
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
"use strict";function T(e,t,n,r){return e<=r&&t>=n}class F{constructor(t=1/0,n=1/0,r=-1/0,s=-1/0){this.xMin=t,this.yMin=n,this.xMax=r,this.yMax=s}get width(){return this.xMax-this.xMin}get height(){return this.yMax-this.yMin}contains(t){const[n,r]=t;return T(this.xMin,this.xMax,n,n)&&T(this.yMin,this.yMax,r,r)}overlaps(t){return T(this.xMin,this.xMax,t.xMin,t.xMax)&&T(this.yMin,this.yMax,t.yMin,t.yMax)}addPoint(t){const[n,r]=t;return new F(Math.min(this.xMin,n),Math.min(this.yMin,r),Math.max(this.xMax,n),Math.max(this.yMax,r))}merge(t){return new F(Math.min(this.xMin,t.xMin),Math.min(this.yMin,t.yMin),Math.max(this.xMax,t.xMax),Math.max(this.yMax,t.yMax))}}function ut(e){const t=[];for(let n=0;n<e;n++)for(let r=0;r<=n;r++)t.push([n,r]);return t}function*H(e){for(const[t,n]of ut(e.length))t!==n&&(yield[e[t],e[n]])}const at=Math.PI/180,$=e=>`[${e[0]}, ${e[1]}]`,c=([e,t],[n,r],s=1e-9)=>Math.abs(e-n)<=s&&Math.abs(t-r)<=s,K=([e,t],[n,r])=>[e+n,t+r],L=([e,t],[n,r])=>[e-n,t-r],_=([e,t])=>e*e+t*t,Q=([e,t],n)=>[e*n,t*n],lt=([e,t],[n,r]=[0,0])=>(e-n)**2+(t-r)**2,k=(e,t=[0,0])=>Math.sqrt(lt(e,t));function q([e,t],[n,r]){return e*r-t*n}function Z([e,t],[n,r]){return e*n+t*r}function W([e,t]){const n=k([e,t]);return[e/n,t/n]}function xt(e,t){const n=Math.cos(t)*e,r=Math.sin(t)*e;return[n,r]}function ct(e,t,n=1e-9){const r=q(e,t),s=_(e),i=_(t);return r*r<s*i*n*n}const V=(e,t)=>{const[n,r,s,i,o,u,a,l,h]=e,[m,f,g,P,x,M,C,v,I]=t;return[n*m+r*P+s*C,n*f+r*x+s*v,n*g+r*M+s*I,i*m+o*P+u*C,i*f+o*x+u*v,i*g+o*M+u*I,a*m+l*P+h*C,a*f+l*x+h*v,a*g+l*M+h*I]};class y{constructor(){this._matrix=[1,0,0,0,1,0,0,0,1]}translate(t,n){return this._matrix=V(this._matrix,[1,0,t,0,1,n,0,0,1]),this}rotate(t,n){const r=Math.cos(t),s=Math.sin(t),i=[r,-s,0,s,r,0,0,0,1];return n&&this.translate(n[0],n[1]),this._matrix=V(this._matrix,i),n&&this.translate(-n[0],-n[1]),this}mirrorX(){return this._matrix=V(this._matrix,[1,0,0,0,-1,0,0,0,1]),this}mirrorY(){return this._matrix=V(this._matrix,[-1,0,0,0,1,0,0,0,1]),this}mirrorLine(t,n){const[r,s]=t,i=Math.atan2(s,r);return n&&this.translate(n[0],n[1]),this.rotate(i),this.mirrorX(),this.rotate(-i),n&&this.translate(-n[0],-n[1]),this}mirrorCenter(t){return t&&this.translate(t[0],t[1]),this._matrix=V(this._matrix,[-1,0,0,0,-1,0,0,0,1]),t&&this.translate(-t[0],-t[1]),this}scale(t,n){return n&&this.translate(n[0],n[1]),this._matrix=V(this._matrix,[t,0,0,0,t,0,0,0,1]),n&&this.translate(-n[0],-n[1]),this}transform(t){const[n,r]=t,[s,i,o,u,a,l]=this._matrix;return[s*n+i*r+o,u*n+a*r+l]}}class G{translateX(t){const n=new y().translate(t,0);return this.transform(n)}translateY(t){const n=new y().translate(0,t);return this.transform(n)}translate(t,n){const r=new y().translate(t,n);return this.transform(r)}translateTo([t,n]){const r=new y().translate(t,n);return this.transform(r)}rotate(t,n){const r=new y().rotate(t*at,n);return this.transform(r)}scale(t,n){const r=new y().scale(t,n);return this.transform(r)}mirrorCenter(t){const n=new y().mirrorCenter(t);return this.transform(n)}mirror(t="x",n){const r=new y;return t==="x"?r.mirrorX():t==="y"?r.mirrorY():r.mirrorLine(t,n),this.transform(r)}}class w extends G{constructor(t,n=[],{ignoreChecks:r=!1}={}){super(),r||dt(t,n),this.contour=t,this.holes=n}get boundingBox(){return this.contour.boundingBox}get isFull(){return this.holes.length===0}get allLoops(){return[this.contour,...this.holes]}clone(){return new w(this.contour.clone(),this.holes.map(t=>t.clone()))}transform(t){return new w(this.contour.transform(t),this.holes.map(n=>n.transform(t)))}contains(t){return this.contour.contains(t)&&!this.holes.some(n=>n.contains(t))}intersects(t){return this.allLoops.some(n=>t.allLoops.some(r=>n.intersects(r)))}}function dt(e,t=[]){if(!e)throw new Error("Figure must have a contour");for(const[n,r]of H([e,...t]))if(n.intersects(r))throw new Error("Loops in a figure must not intersect");if(t.some(n=>!e.contains(n.firstPoint)))throw new Error("Holes must be inside the contour");for(const[n,r]of H(t))if(n.contains(r.firstPoint))throw new Error("Holes must not be inside other holes")}const wt=e=>{const t=e.map((s,i)=>e.slice(i+1).map((o,u)=>[u+i+1,o]).filter(([,o])=>s.boundingBox.overlaps(o.boundingBox)).map(([o])=>o)),n=[],r=Array(t.length);return t.forEach((s,i)=>{let o=r[i];o||(o=[],n.push(o)),o.push(e[i]),s.length&&s.forEach(u=>{r[u]=o})}),n},ht=e=>e.map((t,n)=>{const s=t.segments[0].midPoint,i=e.filter((o,u)=>n===u?!1:o.contains(s));return{loop:t,isIn:i}}),Mt=(e,t)=>e.flatMap(({loop:n})=>Y(t.filter(({loop:r,isIn:s})=>r===n||s.indexOf(n)!==-1))),yt=(e,t)=>{const n=t.filter(({isIn:s})=>s.length<=1),r=Y(ht(e.map(({loop:s})=>s)));return[n,...r]},Y=e=>{if(!e.length)return[];const t=e.filter(({isIn:r})=>!r.length),n=e.filter(({isIn:r})=>r.length>1);return t.length===1&&n.length===0?[e]:t.length>1?Mt(t,e):yt(n,e)};function O(e){return wt(e).map(ht).flatMap(Y).map(n=>{if(n.length===1)return new w(n[0].loop);n.sort((i,o)=>i.isIn.length-o.isIn.length);const[r,...s]=n.map(({loop:i})=>i);return new w(r,s)})}function vt(e,t){const n=[];for(const r of e)for(const s of t)n.push([r,s]);return n}function St(e){return Array.from(Array(e).keys())}function E(e){const t=Math.min(...e.map(n=>n.length));return St(t).map(n=>e.map(r=>r[n]))}const tt=(e,t=1e-9)=>{let n=e;return Math.abs(e)<t&&(n=0),n.toFixed(-Math.log10(t))};function z(e,t=1e-9){return Array.from(new Map(e.map(([n,r])=>[`[${tt(n,t)},${tt(r,t)}]`,[n,r]])).values())}class bt extends G{constructor(t,n){super(),this.firstPoint=t,this.lastPoint=n,this.precision=1e-9,this.firstPoint=t,this.lastPoint=n}get repr(){return`${this.segmentType} ${$(this.firstPoint)} - ${$(this.lastPoint)}`}[Symbol.for("nodejs.util.inspect.custom")](){return this.repr}}class p extends bt{constructor(){super(...arguments),this.segmentType="LINE",this._V=null,this._boundingBox=null}isValidParameter(t){const n=this.length*this.precision;return t>=-n&&1-t>=-n}paramPoint(t){return K(this.firstPoint,Q(this.V,t))}get length(){return k(this.firstPoint,this.lastPoint)}get squareLength(){return lt(this.firstPoint,this.lastPoint)}get V(){return this._V===null&&(this._V=L(this.lastPoint,this.firstPoint)),this._V}get midPoint(){return K(this.firstPoint,Q(this.V,.5))}isSame(t){return t instanceof p?c(this.firstPoint,t.firstPoint)&&c(this.lastPoint,t.lastPoint)||c(this.lastPoint,t.firstPoint)&&c(this.firstPoint,t.lastPoint):!1}clone(){return new p(this.firstPoint,this.lastPoint)}reverse(){return new p(this.lastPoint,this.firstPoint)}get boundingBox(){return this._boundingBox===null&&(this._boundingBox=new F(Math.min(this.firstPoint[0],this.lastPoint[0])-this.precision,Math.min(this.firstPoint[1],this.lastPoint[1])-this.precision,Math.max(this.firstPoint[0],this.lastPoint[0])+this.precision,Math.max(this.firstPoint[1],this.lastPoint[1])+this.precision)),this._boundingBox}distanceFrom(t){const n=L(t,this.firstPoint),r=Z(n,this.V)/this.squareLength;if(r<0)return k(t,this.firstPoint);if(r>1)return k(t,this.lastPoint);const s=this.paramPoint(r);return k(t,s)}isOnSegment(t){if(c(t,this.firstPoint,this.precision))return!0;const n=L(t,this.firstPoint);if(!ct(this.V,n))return!1;const r=Z(n,this.V)/this.squareLength;return this.isValidParameter(r)}tangentAt(t){if(!this.isOnSegment(t))throw new Error("Point is not on segment");return W(this.V)}get tangentAtFirstPoint(){return W(this.V)}get tangentAtLastPoint(){return W(this.V)}splitAt(t){let n;if(Array.isArray(t)&&t.length===0)return[this];Array.isArray(t[0])?n=t:n=[t],n.forEach(a=>{if(!this.isOnSegment(a))throw new Error(`Point ${$(a)} is not on segment ${this.repr}`)});const r=[this.firstPoint,...n,this.lastPoint],s=z(r),i=this.lastPoint[0]-this.firstPoint[0];let o=Math.sign(i),u=0;return Math.abs(i)<this.precision&&(o=Math.sign(this.lastPoint[1]-this.firstPoint[1]),u=1),s.sort((a,l)=>o*(a[u]-l[u])),s.flatMap((a,l)=>l===s.length-1?[]:new p(a,s[l+1]))}transform(t){return new p(t.transform(this.firstPoint),t.transform(this.lastPoint))}}const ft=(e,t,n)=>{const r=q(e.V,t.V),s=_(e.V),i=_(t.V),o=n?n*n:e.precision*t.precision;if(r*r<s*i*o)return"parallel";const u=L(t.firstPoint,e.firstPoint),a=q(u,t.V)/r,l=q(u,e.V)/r;return{intersectionParam1:a,intersectionParam2:l}};function Ct(e,t,n=!1,r){const s=ft(e,t,r);if(s==="parallel"){if(!n)return null;if(e.isSame(t))return e;const u=z([t.isOnSegment(e.firstPoint)?e.firstPoint:null,t.isOnSegment(e.lastPoint)?e.lastPoint:null,e.isOnSegment(t.firstPoint)?t.firstPoint:null,e.isOnSegment(t.lastPoint)?t.lastPoint:null].filter(a=>a!==null)).sort((a,l)=>a[0]-l[0]);if(u.length===0)return null;if(u.length===1)return null;if(u.length===2)return new p(u[0],u[1]);throw console.error(u),new Error("Unexpected number of points while intersecting parallel lines")}const{intersectionParam1:i,intersectionParam2:o}=s;return!e.isValidParameter(i)||!t.isValidParameter(o)?null:e.paramPoint(i)}function R(e,t,n){if(e instanceof p&&t instanceof p){const r=Ct(e,t,!0,n);return r===null?{intersections:[],overlaps:[],count:0}:r instanceof p?{intersections:[],overlaps:[r],count:1}:{intersections:[r],overlaps:[],count:1}}throw new Error("Not implemented")}class mt extends G{constructor(t,{ignoreChecks:n=!1}={}){super(),this._boundingBox=null,n||gt(t),this.segments=t}get repr(){return this.segments.map(t=>t.repr).join(`
|
|
2
|
-
`)+`
|
|
3
|
-
`}get firstPoint(){return this.segments[0].firstPoint}get lastPoint(){return this.segments[this.segments.length-1].lastPoint}get segmentsCount(){return this.segments.length}onStroke(t){return this.segments.some(n=>n.isOnSegment(t))}intersects(t){return this.boundingBox.overlaps(t.boundingBox)?this.segments.some(n=>t.segments.some(r=>R(n,r).count>0)):!1}get boundingBox(){if(this._boundingBox===null){let t=this.segments[0].boundingBox;this.segments.slice(1).forEach(n=>{t=t.merge(n.boundingBox)}),this._boundingBox=t}return this._boundingBox}[Symbol.for("nodejs.util.inspect.custom")](){return this.repr}}function It(e,t="Stroke"){ut(e.length).forEach(([n,r])=>{if(n===r)return;const s=e[n],i=e[r],o=R(s,i);if(o.count!==0){if(o.count===1&&!o.overlaps.length){const u=n-r,a=o.intersections[0];if(u===1&&c(s.firstPoint,a)||u===-1&&c(s.lastPoint,a)||u===e.length-1&&c(s.lastPoint,a)&&c(i.firstPoint,a)||-u===e.length-1&&c(s.firstPoint,a)&&c(i.lastPoint,a))return}throw new Error(`${t} segments must not intersect, but segments ${s.repr} and ${i.repr} do`)}})}function gt(e,t="Stroke"){if(e.length===0)throw new Error(`${t} must have at least one segment`);E([e.slice(0,-1),e.slice(1)]).forEach(([n,r])=>{if(!c(n.lastPoint,r.firstPoint))throw new Error(`${t} segments must be connected, but ${n.repr} and ${r.repr} are not`)}),It(e,t)}function nt(e,t){return!!(e instanceof p&&t instanceof p&&ct(e.V,t.V))}function et(e,t){if(e instanceof p&&t instanceof p)return new p(e.firstPoint,t.lastPoint);throw new Error("Not implemented")}function pt(e){let t=!1;const n=[];for(const r of e.segments){if(n.length===0){n.push(r);continue}const s=n[n.length-1];nt(s,r)?(t=!0,n.pop(),n.push(et(s,r))):n.push(r)}if(c(e.firstPoint,e.lastPoint)&&nt(n[0],n[n.length-1])){t=!0;const r=n.pop();n[0]=et(r,n[0])}return t?n:null}class d extends mt{reverse(){const t=this.segments.map(n=>n.reverse());return t.reverse(),new d(t,{ignoreChecks:!0})}clone(){return new d(this.segments.map(t=>t.clone()),{ignoreChecks:!0})}extend(t){if(!c(this.lastPoint,t.firstPoint))throw console.error(this.repr,t.repr),new Error("Cannot extend strand: connection point is not the same");return new d([...this.segments,...t.segments])}simplify(){const t=pt(this);return t?new d(t,{ignoreChecks:!0}):this}transform(t){return new d(this.segments.map(n=>n.transform(t)),{ignoreChecks:!0})}}const Vt=(e,t)=>{const n=ft(t,{V:[1,0],firstPoint:e,precision:t.precision});if(n==="parallel")return 0;const{intersectionParam1:r,intersectionParam2:s}=n;if(!t.isValidParameter(r)||s<=-t.precision)return 0;if(Math.abs(r)<t.precision||Math.abs(r-1)<t.precision){const[,i]=t.midPoint;return e[1]-i<0?1:0}return 1};function Et(e,t){if(t instanceof p)return Vt(e,t);throw new Error("Not implemented")}class b extends mt{constructor(t,{ignoreChecks:n=!1}={}){super(t,{ignoreChecks:!0}),n||Ft(t)}clone(){return new b(this.segments.map(t=>t.clone()),{ignoreChecks:!0})}reverse(){const t=this.segments.map(n=>n.reverse());return t.reverse(),new b(t,{ignoreChecks:!0})}transform(t){return new b(this.segments.map(n=>n.transform(t)),{ignoreChecks:!0})}contains(t){return this.onStroke(t)?!1:this.segments.reduce((r,s)=>r+Et(t,s),0)%2===1}simplify(){const t=pt(this);return t?new b(t,{ignoreChecks:!0}):this}}function Ft(e){if(gt(e,"Loop"),!c(e[0].firstPoint,e[e.length-1].lastPoint))throw new Error("Loop segment must be closed")}const rt=(e,t)=>{const n=e.findIndex(i=>c(t,i.firstPoint)),r=e.slice(0,n);return e.slice(n).concat(r)},st=(e,t)=>{let n=e;const r=u=>c(u.firstPoint,t.firstPoint)&&c(u.lastPoint,t.lastPoint);let s=e.findIndex(r);if(s===-1){const u=e.map(a=>a.reverse());if(u.reverse(),s=u.findIndex(r),s===-1)throw console.error(u.map(a=>a.repr),t.repr),new Error("Failed to rotate to segment start");n=u}const i=n.slice(0,s);return n.slice(s).concat(i)};function*it(e,t,n){const r=o=>t.some(u=>c(u,o.lastPoint)),s=o=>n.some(u=>o.isSame(u));let i=[];for(const o of e)r(o)?(i.push(o),yield new d(i,{ignoreChecks:!0}),i=[]):s(o)?(i.length&&(yield new d(i,{ignoreChecks:!0}),i=[]),yield new d([o],{ignoreChecks:!0})):i.push(o);i.length&&(yield new d(i,{ignoreChecks:!0}))}function At(e,t,n){return e.filter(r=>{const s=t.filter(u=>c(u.firstPoint,r)||c(u.lastPoint,r));if(s.length%2)throw new Error("Bug in the intersection algo on non crossing point");const i=s.map(u=>n.contains(u.midPoint));return!(i.every(u=>u)||!i.some(u=>u))})}function Bt(e,t,n){let r=[];const s=[],i=new Array(e.segments.length).fill(0).map(()=>[]),o=new Array(t.segments.length).fill(0).map(()=>[]);if(e.segments.forEach((f,g)=>{t.segments.forEach((P,x)=>{const{intersections:M,overlaps:C}=R(f,P,n);r.push(...M),i[g].push(...M),o[x].push(...M),s.push(...C);const v=C.flatMap(I=>[I.firstPoint,I.lastPoint]);r.push(...v),i[g].push(...v),o[x].push(...v)})}),r=z(r,n),!r.length||r.length===1)return null;const u=([f,g])=>g.length?f.splitAt(g):[f];let a=E([e.segments,i]).flatMap(u),l=E([t.segments,o]).flatMap(u);if(r=At(r,a,t),!r.length&&!s.length)return null;if(s.length){const f=s[0];a=st(a,f),l=st(l,f)}else{const f=r[0];a=rt(a,f),l=rt(l,f)}const h=Array.from(it(a,r,s));let m=Array.from(it(l,r,s));return(!c(m[0].lastPoint,h[0].lastPoint)||s.length>0&&m[0].segmentsCount!==1)&&(m=m.reverse().map(f=>f.reverse())),E([h,m]).map(([f,g])=>f.segmentsCount===1&&s.some(P=>f.segments[0].isSame(P))?[f,"same"]:[f,g])}function X(e){let t=e[0];for(const n of e.slice(1))t=t.extend(n);if(!c(t.firstPoint,t.lastPoint))throw console.error($(t.firstPoint),$(t.lastPoint)),new Error("Bug in the intersection algo on non closing strand");return new b(t.segments)}function kt(e){if(!e.length)return[];const t=e.map(o=>o.firstPoint);let n=e.map(o=>o.lastPoint);n=n.slice(-1).concat(n.slice(0,-1));const r=E([t,n]).flatMap(([o,u],a)=>c(o,u)?[]:a);if(!r.length)return[X(e)];const s=E([r.slice(0,-1),r.slice(1)]).map(([o,u])=>X(e.slice(o,u)));let i=e.slice(r[r.length-1]);return r[0]!==0&&(i=i.concat(e.slice(0,r[0]))),s.push(X(i)),s}const ot=(e,t)=>{if(e.length===0)return[t];const n=e.at(-1);return c(n.lastPoint,t.firstPoint)?e.slice(0,-1).concat([n.extend(t)]):c(n.lastPoint,t.lastPoint)?e.slice(0,-1).concat([n.extend(t.reverse())]):e.concat([t])},Lt=(e,t)=>e.length===0?[t]:c(e[0].firstPoint,t.lastPoint)?[t.extend(e[0])].concat(e.slice(1)):[t].concat(e);function U(e,t,{firstInside:n,secondInside:r}){const s=Bt(e,t);if(!s){const a=e.segments[0].midPoint,l=t.contains(a),h=t.segments[0].midPoint,m=e.contains(h);return{identical:!1,firstCurveInSecond:l,secondCurveInFirst:m}}if(s.every(([,a])=>a==="same"))return{identical:!0};let i=null,o=null;const u=s.flatMap(([a,l])=>{let h=[],m=0;if(l==="same")return o===1?(o=1,a):o===2||o===0?(o=null,[]):o===null?(i?i=i.extend(a):i=a,[]):(console.error("weird situation"),[]);const f=a.segments[0].midPoint,g=t.contains(f);(n==="keep"&&g||n==="remove"&&!g)&&(m+=1,h=ot(h,a));const P=l.segments[0].midPoint,x=e.contains(P);if(r==="keep"&&x||r==="remove"&&!x){const M=l;m+=1,m===2&&h.length?(h=ot(h,M),i=null):h=[M]}return o===null&&m===1&&i&&(h=Lt(h,i)),m===1&&(o=m,i=null),h.length?h:(i=null,[])});return kt(u)}const Ot=(e,t)=>{const n=U(e,t,{firstInside:"remove",secondInside:"remove"});return Array.isArray(n)?n:n.identical?[e]:n.firstCurveInSecond?[t]:n.secondCurveInFirst?[e]:[e,t]},j=(e,t)=>{const n=U(e,t,{firstInside:"remove",secondInside:"keep"});return Array.isArray(n)?n:n.identical?[]:n.firstCurveInSecond?[]:n.secondCurveInFirst?[e,t]:[e]},J=(e,t)=>{const n=U(e,t,{firstInside:"keep",secondInside:"keep"});return Array.isArray(n)?n:n.identical?[e]:n.firstCurveInSecond?[e]:n.secondCurveInFirst?[t]:[]};function $t(e){const t=new Map,n=[];return e.forEach((r,s)=>{let i;t.has(s)?i=t.get(s):(i={current:[r],fusedWith:new Set([s])},n.push(i)),e.slice(s+1).forEach((o,u)=>{const a=i.current,l=s+u+1;if(i.fusedWith.has(l))return;let h=[o],m=!1;if(t.has(l)&&(h=t.get(l).current,m=!0),!a.some(P=>h.some(x=>P.intersects(x))))return;let g;a.length>1||h.length>1?g=A(a,h):g=Pt(a[0],h[0]),i.fusedWith.add(l),i.current=g,m||t.set(l,i)})}),n.flatMap(({current:r})=>r)}function Pt(e,t){const n=Ot(e.contour,t.contour),r=t.holes.flatMap(o=>j(o,e.contour)),s=e.holes.flatMap(o=>j(o,t.contour)),i=vt(e.holes,t.holes).flatMap(([o,u])=>J(o,u));return O([...n,...r,...s,...i])}function D(e,t){if(e.isFull&&t.isFull)return O(j(e.contour,t.contour));if(e.isFull){const r=j(e.contour,t.contour),s=t.holes.flatMap(i=>J(i,e.contour));return O([...r,...s])}else if(t.isFull&&!e.contour.intersects(t.contour))if(e.contour.contains(t.contour.firstPoint)){const r=A(e.holes.map(s=>new w(s)),[t]);return O([e.contour,...r.flatMap(s=>s.allLoops)])}else return[e];let n=D(new w(e.contour),t);return e.holes.forEach(r=>{n=n.flatMap(s=>D(s,new w(r)))}),n}function Tt(e,t){const n=J(e.contour,t.contour);if(!n.length)return[];let r=O(n);return r=B(r,e.holes.map(s=>new w(s))),B(r,t.holes.map(s=>new w(s)))}function A(e,t){if(!e.length)return t;if(!t.length)return e;if(e.length===1&&t.length>1||t.length===1&&e.length>1)return $t([...e,...t]);if(e.length>1&&t.length>1){let n=A([e[0]],t);return e.slice(1).forEach(r=>{n=A([r],n)}),n}return e.length===1&&t.length===1?Pt(e[0],t[0]):[]}function B(e,t){if(!e.length)return[];if(!t.length)return e;if(e.length===1&&t.length===1)return D(e[0],t[0]);if(e.length>1)return e.flatMap(r=>B([r],t));let n=D(e[0],t[0]);return t.slice(1).forEach(r=>{n=B(n,[r])}),n}function N(e,t){return!e.length||!t.length?[]:e.length===1&&t.length===1?Tt(e[0],t[0]):e.length>1?e.flatMap(n=>N([n],t)):t.flatMap(n=>N(e,[n]))}class S extends G{constructor(t=[],{ignoreChecks:n=!1}={}){super(),this._boundingBox=null,n||qt(t),this.figures=t}get isEmpty(){return this.figures.length===0}get boundingBox(){if(this.isEmpty)return new F;if(this._boundingBox===null){let t=this.figures[0].boundingBox;for(const n of this.figures.slice(1))t=t.merge(n.boundingBox);this._boundingBox=t}return this._boundingBox}clone(){return new S(this.figures.map(t=>t.clone()))}transform(t){return new S(this.figures.map(n=>n.transform(t)))}contains(t){return this.figures.some(n=>n.contains(t))}intersects(t){return this.figures.some(n=>t.figures.some(r=>n.intersects(r)))}fuse(t){return new S(A(this.figures,t.figures))}cut(t){return new S(B(this.figures,t.figures))}intersect(t){return new S(N(this.figures,t.figures))}}function qt(e){for(const[t,n]of H(e))if(t.intersects(n))throw new Error("Diagram figures must not intersect")}exports.BoundingBox=F;exports.DEG2RAD=at;exports.Diagram=S;exports.Figure=w;exports.Line=p;exports.Loop=b;exports.Strand=d;exports.TransformationMatrix=y;exports.cutFiguresLists=B;exports.fuseFiguresLists=A;exports.intersectFiguresLists=N;exports.polarToCartesian=xt;exports.sameVector=c;exports.subtract=L;
|
|
4
|
-
//# sourceMappingURL=Diagram-81a7df15.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Diagram-81a7df15.cjs","sources":["../src/models/BoundingBox.ts","../src/utils/allCombinations.ts","../src/vectorOperations.ts","../src/models/TransformationMatrix.ts","../src/models/utils/Transformable.ts","../src/models/Figure.ts","../src/algorithms/organiseLoops.ts","../src/utils/allPairs.ts","../src/utils/range.ts","../src/utils/zip.ts","../src/utils/removeDuplicatePoints.ts","../src/models/segments/Segment.ts","../src/models/segments/Line.ts","../src/algorithms/intersections.ts","../src/models/Stroke.ts","../src/algorithms/simplify.ts","../src/models/Strand.ts","../src/algorithms/rayIntersections.ts","../src/models/Loop.ts","../src/algorithms/boolean/loopBooleans.ts","../src/algorithms/boolean/figureBooleans.ts","../src/models/Diagram.ts"],"sourcesContent":["import { Vector } from \"../definitions\";\n\nfunction overlap1D(\n min1: number,\n max1: number,\n min2: number,\n max2: number\n): boolean {\n return min1 <= max2 && max1 >= min2;\n}\n\nexport class BoundingBox {\n readonly xMin: number;\n readonly yMin: number;\n\n readonly xMax: number;\n readonly yMax: number;\n\n constructor(\n xMin = Infinity,\n yMin = Infinity,\n xMax = -Infinity,\n yMax = -Infinity\n ) {\n this.xMin = xMin;\n this.yMin = yMin;\n this.xMax = xMax;\n this.yMax = yMax;\n }\n\n get width(): number {\n return this.xMax - this.xMin;\n }\n\n get height(): number {\n return this.yMax - this.yMin;\n }\n\n contains(point: Vector): boolean {\n const [x, y] = point;\n return (\n overlap1D(this.xMin, this.xMax, x, x) &&\n overlap1D(this.yMin, this.yMax, y, y)\n );\n }\n\n overlaps(other: BoundingBox): boolean {\n return (\n overlap1D(this.xMin, this.xMax, other.xMin, other.xMax) &&\n overlap1D(this.yMin, this.yMax, other.yMin, other.yMax)\n );\n }\n\n addPoint(point: Vector): BoundingBox {\n const [x, y] = point;\n return new BoundingBox(\n Math.min(this.xMin, x),\n Math.min(this.yMin, y),\n\n Math.max(this.xMax, x),\n Math.max(this.yMax, y)\n );\n }\n\n merge(other: BoundingBox): BoundingBox {\n return new BoundingBox(\n Math.min(this.xMin, other.xMin),\n Math.min(this.yMin, other.yMin),\n Math.max(this.xMax, other.xMax),\n Math.max(this.yMax, other.yMax)\n );\n }\n}\n","export function allCombinations(count: number): [number, number][] {\n const result: [number, number][] = [];\n\n for (let i = 0; i < count; i++) {\n for (let j = 0; j <= i; j++) {\n result.push([i, j]);\n }\n }\n\n return result;\n}\n\nexport function* combineDifferentValues<T>(array: T[]): Generator<[T, T]> {\n for (const [i, j] of allCombinations(array.length)) {\n if (i === j) continue;\n yield [array[i], array[j]];\n }\n}\n","import type { Vector } from \"./definitions\";\n\nexport const DEG2RAD = Math.PI / 180;\n\nexport const reprVector = (vector: Vector): string => {\n return `[${vector[0]}, ${vector[1]}]`;\n};\n\nexport const sameVector = (\n [x0, y0]: Vector,\n [x1, y1]: Vector,\n precision = 1e-9\n): boolean => {\n return Math.abs(x0 - x1) <= precision && Math.abs(y0 - y1) <= precision;\n};\n\nexport const add = ([x0, y0]: Vector, [x1, y1]: Vector): Vector => {\n return [x0 + x1, y0 + y1];\n};\n\nexport const subtract = ([x0, y0]: Vector, [x1, y1]: Vector): Vector => {\n return [x0 - x1, y0 - y1];\n};\n\nexport const squareLength = ([x, y]: Vector): number => {\n return x * x + y * y;\n};\n\nexport const length = ([x, y]: Vector): number => {\n return Math.sqrt(squareLength([x, y]));\n};\n\nexport const scalarMultiply = ([x0, y0]: Vector, scalar: number): Vector => {\n return [x0 * scalar, y0 * scalar];\n};\n\nexport const squareDistance = (\n [x0, y0]: Vector,\n [x1, y1]: Vector = [0, 0]\n): number => {\n return (x0 - x1) ** 2 + (y0 - y1) ** 2;\n};\n\nexport const distance = (p0: Vector, p1: Vector = [0, 0]): number => {\n return Math.sqrt(squareDistance(p0, p1));\n};\n\nexport function crossProduct([x0, y0]: Vector, [x1, y1]: Vector): number {\n return x0 * y1 - y0 * x1;\n}\n\nexport function dotProduct([x0, y0]: Vector, [x1, y1]: Vector): number {\n return x0 * x1 + y0 * y1;\n}\n\nexport const angle = ([x0, y0]: Vector, [x1, y1]: Vector = [0, 0]): number => {\n return Math.atan2(y1 * x0 - y0 * x1, x0 * x1 + y0 * y1);\n};\n\nexport function normalize([x0, y0]: Vector): Vector {\n const l = distance([x0, y0]);\n return [x0 / l, y0 / l];\n}\n\nexport function polarToCartesian(r: number, theta: number): Vector {\n const x = Math.cos(theta) * r;\n const y = Math.sin(theta) * r;\n return [x, y];\n}\n\nexport function cartesianToPolar([x, y]: Vector): [number, number] {\n const r = distance([x, y]);\n const theta = Math.atan2(y, x);\n\n return [r, theta];\n}\n\nexport function parallel(v1: Vector, v2: Vector, precision = 1e-9): boolean {\n const V1xV2 = crossProduct(v1, v2);\n\n const xLength = squareLength(v1);\n const yLength = squareLength(v2);\n\n return V1xV2 * V1xV2 < xLength * yLength * precision * precision;\n}\n","import { Vector } from \"../definitions\";\n\ntype Matrix = [\n number,\n number,\n number,\n number,\n number,\n number,\n number,\n number,\n number\n];\n\nconst matMult = (m1: Matrix, m2: Matrix): Matrix => {\n const [a, b, c, d, e, f, g, h, i] = m1;\n const [j, k, l, m, n, o, p, q, r] = m2;\n return [\n a * j + b * m + c * p,\n a * k + b * n + c * q,\n a * l + b * o + c * r,\n d * j + e * m + f * p,\n d * k + e * n + f * q,\n d * l + e * o + f * r,\n g * j + h * m + i * p,\n g * k + h * n + i * q,\n g * l + h * o + i * r,\n ];\n};\n\nexport class TransformationMatrix {\n private _matrix: Matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];\n\n translate(x: number, y: number): TransformationMatrix {\n this._matrix = matMult(this._matrix, [1, 0, x, 0, 1, y, 0, 0, 1]);\n return this;\n }\n\n rotate(angle: number, center?: Vector): TransformationMatrix {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n const rotationMatrix: Matrix = [cos, -sin, 0, sin, cos, 0, 0, 0, 1];\n\n if (center) this.translate(center[0], center[1]);\n this._matrix = matMult(this._matrix, rotationMatrix);\n if (center) this.translate(-center[0], -center[1]);\n\n return this;\n }\n\n mirrorX(): TransformationMatrix {\n this._matrix = matMult(this._matrix, [1, 0, 0, 0, -1, 0, 0, 0, 1]);\n return this;\n }\n\n mirrorY(): TransformationMatrix {\n this._matrix = matMult(this._matrix, [-1, 0, 0, 0, 1, 0, 0, 0, 1]);\n return this;\n }\n\n mirrorLine(normal: Vector, point?: Vector): TransformationMatrix {\n const [a, b] = normal;\n\n const angle = Math.atan2(b, a);\n\n if (point) this.translate(point[0], point[1]);\n this.rotate(angle);\n this.mirrorX();\n this.rotate(-angle);\n if (point) this.translate(-point[0], -point[1]);\n return this;\n }\n\n mirrorCenter(center?: Vector): TransformationMatrix {\n if (center) this.translate(center[0], center[1]);\n this._matrix = matMult(this._matrix, [-1, 0, 0, 0, -1, 0, 0, 0, 1]);\n if (center) this.translate(-center[0], -center[1]);\n return this;\n }\n\n scale(scalar: number, center?: Vector): TransformationMatrix {\n if (center) this.translate(center[0], center[1]);\n this._matrix = matMult(this._matrix, [scalar, 0, 0, 0, scalar, 0, 0, 0, 1]);\n if (center) this.translate(-center[0], -center[1]);\n\n return this;\n }\n\n transform(point: Vector): Vector {\n const [x, y] = point;\n const [a, b, c, d, e, f] = this._matrix;\n return [a * x + b * y + c, d * x + e * y + f];\n }\n}\n","import { Vector } from \"../../definitions\";\nimport { DEG2RAD } from \"../../vectorOperations\";\nimport { TransformationMatrix } from \"../TransformationMatrix\";\n\nexport abstract class Transformable<T> {\n abstract transform(matrix: TransformationMatrix): T;\n translateX(x: number): T {\n const transform = new TransformationMatrix().translate(x, 0);\n return this.transform(transform);\n }\n\n translateY(y: number): T {\n const transform = new TransformationMatrix().translate(0, y);\n return this.transform(transform);\n }\n\n translate(x: number, y: number): T {\n const transform = new TransformationMatrix().translate(x, y);\n return this.transform(transform);\n }\n\n translateTo([x, y]: Vector): T {\n const transform = new TransformationMatrix().translate(x, y);\n return this.transform(transform);\n }\n\n rotate(angle: number, center?: Vector): T {\n const transform = new TransformationMatrix().rotate(\n angle * DEG2RAD,\n center\n );\n return this.transform(transform);\n }\n\n scale(factor: number, center?: Vector): T {\n const transform = new TransformationMatrix().scale(factor, center);\n return this.transform(transform);\n }\n\n mirrorCenter(center?: Vector): T {\n const transform = new TransformationMatrix().mirrorCenter(center);\n return this.transform(transform);\n }\n\n mirror(axis?: \"x\" | \"y\"): T;\n mirror(direction: Vector, center?: Vector): T;\n mirror(axisOrDirection: \"x\" | \"y\" | Vector = \"x\", center?: Vector): T {\n const transform = new TransformationMatrix();\n if (axisOrDirection === \"x\") {\n transform.mirrorX();\n } else if (axisOrDirection === \"y\") {\n transform.mirrorY();\n } else {\n transform.mirrorLine(axisOrDirection, center);\n }\n return this.transform(transform);\n }\n}\n","import { Vector } from \"../definitions\";\nimport { TransformationMatrix } from \"./TransformationMatrix\";\nimport type { BoundingBox } from \"./BoundingBox\";\nimport { Loop } from \"./Loop\";\nimport { combineDifferentValues } from \"../utils/allCombinations\";\nimport { Transformable } from \"./utils/Transformable\";\n\nexport class Figure extends Transformable<Figure> {\n readonly contour: Loop;\n readonly holes: Loop[];\n\n constructor(\n contour: Loop,\n holes: Loop[] = [],\n { ignoreChecks = false } = {}\n ) {\n super();\n if (!ignoreChecks) checkIsValidFigure(contour, holes);\n this.contour = contour;\n this.holes = holes;\n }\n\n get boundingBox(): BoundingBox {\n return this.contour.boundingBox;\n }\n\n get isFull(): boolean {\n return this.holes.length === 0;\n }\n\n get allLoops(): Loop[] {\n return [this.contour, ...this.holes];\n }\n\n clone(): Figure {\n return new Figure(\n this.contour.clone(),\n this.holes.map((hole) => hole.clone())\n );\n }\n\n transform(matrix: TransformationMatrix): Figure {\n return new Figure(\n this.contour.transform(matrix),\n this.holes.map((hole) => hole.transform(matrix))\n );\n }\n\n contains(point: Vector): boolean {\n return (\n this.contour.contains(point) &&\n !this.holes.some((hole) => hole.contains(point))\n );\n }\n\n intersects(other: Figure): boolean {\n return this.allLoops.some((loop) =>\n other.allLoops.some((otherLoop) => loop.intersects(otherLoop))\n );\n }\n}\n\nexport function checkIsValidFigure(contour?: Loop, holes: Loop[] = []): void {\n if (!contour) throw new Error(\"Figure must have a contour\");\n for (const [loop1, loop2] of combineDifferentValues([contour, ...holes])) {\n if (loop1.intersects(loop2)) {\n throw new Error(\"Loops in a figure must not intersect\");\n }\n }\n\n if (holes.some((hole) => !contour.contains(hole.firstPoint))) {\n throw new Error(\"Holes must be inside the contour\");\n }\n\n for (const [hole1, hole2] of combineDifferentValues(holes)) {\n if (hole1.contains(hole2.firstPoint)) {\n throw new Error(\"Holes must not be inside other holes\");\n }\n }\n}\n","import { Figure } from \"../models/Figure\";\nimport { Loop } from \"../models/Loop\";\n\nconst groupByBoundingBoxOverlap = (loops: Loop[]): Loop[][] => {\n const overlaps = loops.map((loop, i) => {\n return loops\n .slice(i + 1)\n .map((v, j): [number, Loop] => [j + i + 1, v])\n .filter(([, other]) => loop.boundingBox.overlaps(other.boundingBox))\n .map(([index]) => index);\n });\n const groups: Loop[][] = [];\n const groupsInOverlaps = Array(overlaps.length);\n\n overlaps.forEach((indices, i) => {\n let myGroup = groupsInOverlaps[i];\n if (!myGroup) {\n myGroup = [];\n groups.push(myGroup);\n }\n\n myGroup.push(loops[i]);\n\n if (indices.length) {\n indices.forEach((index) => {\n groupsInOverlaps[index] = myGroup;\n });\n }\n });\n\n return groups;\n};\n\ninterface ContainedLoop {\n loop: Loop;\n isIn: Loop[];\n}\n\nconst addContainmentInfo = (groupedLoops: Loop[]): ContainedLoop[] => {\n return groupedLoops.map((loop, index) => {\n const firstCurve = loop.segments[0];\n const point = firstCurve.midPoint;\n\n const isIn = groupedLoops.filter((potentialOuterLoop, j) => {\n if (index === j) return false;\n return potentialOuterLoop.contains(point);\n });\n\n return {\n loop,\n isIn,\n };\n });\n};\n\nconst splitMultipleOuterLoops = (\n outerLoops: ContainedLoop[],\n allLoops: ContainedLoop[]\n): ContainedLoop[][] => {\n return outerLoops.flatMap(({ loop: outerLoop }) => {\n return cleanEdgeCases(\n allLoops.filter(\n ({ loop, isIn }) => loop === outerLoop || isIn.indexOf(outerLoop) !== -1\n )\n );\n });\n};\n\nconst handleNestedLoops = (\n nestedLoops: ContainedLoop[],\n allLoops: ContainedLoop[]\n): ContainedLoop[][] => {\n const firstLevelOuterLoops = allLoops.filter(({ isIn }) => isIn.length <= 1);\n\n const innerLevelsLoops = cleanEdgeCases(\n addContainmentInfo(nestedLoops.map(({ loop }) => loop))\n );\n return [firstLevelOuterLoops, ...innerLevelsLoops];\n};\n\nconst cleanEdgeCases = (groupedLoops: ContainedLoop[]): ContainedLoop[][] => {\n if (!groupedLoops.length) return [];\n\n const outerLoops = groupedLoops.filter(({ isIn }) => !isIn.length);\n const nestedLoops = groupedLoops.filter(({ isIn }) => isIn.length > 1);\n\n if (outerLoops.length === 1 && nestedLoops.length === 0) {\n return [groupedLoops];\n } else if (outerLoops.length > 1) {\n return splitMultipleOuterLoops(outerLoops, groupedLoops);\n } else {\n return handleNestedLoops(nestedLoops, groupedLoops);\n }\n};\n\n/**\n * Groups an array of loops such that loops that correspond to holes\n * in other loops are set in a Figure\n *\n * This algorithm assumes non intersecting loops.\n */\nexport function organiseLoops(loops: Loop[]): Figure[] {\n const basicGrouping =\n groupByBoundingBoxOverlap(loops).map(addContainmentInfo);\n return basicGrouping.flatMap(cleanEdgeCases).map((compounds) => {\n if (compounds.length === 1) return new Figure(compounds[0].loop);\n\n compounds.sort((a, b) => a.isIn.length - b.isIn.length);\n const [contour, ...holes] = compounds.map(({ loop }) => loop);\n return new Figure(contour, holes);\n });\n}\n","export function allPairs<S, T>(list1: T[], list2: S[]): [T, S][] {\n const result: [T, S][] = [];\n\n for (const l1 of list1) {\n for (const l2 of list2) {\n result.push([l1, l2]);\n }\n }\n\n return result;\n}\n","export default function range(len: number): number[] {\n return Array.from(Array(len).keys());\n}\n","import range from \"./range\";\n\nexport default function zip<T extends unknown[][]>(\n arrays: T\n): { [K in keyof T]: T[K] extends (infer V)[] ? V : never }[] {\n const minLength = Math.min(...arrays.map((arr) => arr.length));\n // @ts-expect-error This is too much for ts\n return range(minLength).map((i) => arrays.map((arr) => arr[i]));\n}\n","import type { Vector } from \"../definitions\";\n\nconst asFixed = (p: number, precision = 1e-9): string => {\n let num = p;\n if (Math.abs(p) < precision) num = 0;\n return num.toFixed(-Math.log10(precision));\n};\nexport default function removeDuplicatePoints(\n points: Vector[],\n precision = 1e-9\n): Vector[] {\n return Array.from(\n new Map(\n points.map(([p0, p1]) => [\n `[${asFixed(p0, precision)},${asFixed(p1, precision)}]`,\n [p0, p1] as Vector,\n ])\n ).values()\n );\n}\n","import type { Vector } from \"../../definitions\";\nimport { BoundingBox } from \"../BoundingBox\";\nimport type { TransformationMatrix } from \"../TransformationMatrix\";\nimport { reprVector } from \"../../vectorOperations\";\nimport { Transformable } from \"../utils/Transformable\";\n\nexport type Segment = AbstractSegment<any>;\n\nexport abstract class AbstractSegment<\n T extends AbstractSegment<T>\n> extends Transformable<T> {\n constructor(public firstPoint: Vector, public lastPoint: Vector) {\n super();\n this.firstPoint = firstPoint;\n this.lastPoint = lastPoint;\n }\n\n readonly precision: number = 1e-9;\n\n abstract segmentType: string;\n\n get repr() {\n return `${this.segmentType} ${reprVector(this.firstPoint)} - ${reprVector(\n this.lastPoint\n )}`;\n }\n\n abstract get midPoint(): Vector;\n\n abstract get boundingBox(): BoundingBox;\n\n abstract clone(): T;\n\n abstract reverse(): T;\n\n abstract isSame(other: AbstractSegment<any>): boolean;\n\n abstract distanceFrom(element: Vector): number;\n\n abstract isOnSegment(point: Vector): boolean;\n\n abstract tangentAt(point: Vector): Vector;\n\n abstract get tangentAtFirstPoint(): Vector;\n abstract get tangentAtLastPoint(): Vector;\n\n abstract splitAt(points: Vector[] | number[]): T[];\n\n abstract transform(matrix: TransformationMatrix): T;\n\n [Symbol.for(\"nodejs.util.inspect.custom\")]() {\n return this.repr;\n }\n}\n","import { BoundingBox } from \"../BoundingBox\";\nimport { Vector } from \"../../definitions\";\nimport { TransformationMatrix } from \"../TransformationMatrix\";\nimport removeDuplicatePoints from \"../../utils/removeDuplicatePoints\";\nimport {\n add,\n distance,\n dotProduct,\n normalize,\n parallel,\n reprVector,\n sameVector,\n scalarMultiply,\n squareDistance,\n subtract,\n} from \"../../vectorOperations\";\nimport { Segment, AbstractSegment } from \"./Segment\";\n\nexport class Line extends AbstractSegment<Line> {\n segmentType = \"LINE\";\n isValidParameter(t: number): boolean {\n const linearPrecision = this.length * this.precision;\n return t >= -linearPrecision && 1 - t >= -linearPrecision;\n }\n\n paramPoint(t: number): Vector {\n return add(this.firstPoint, scalarMultiply(this.V, t));\n }\n\n get length(): number {\n return distance(this.firstPoint, this.lastPoint);\n }\n\n get squareLength(): number {\n return squareDistance(this.firstPoint, this.lastPoint);\n }\n\n private _V: Vector | null = null;\n get V(): Vector {\n if (this._V === null) {\n this._V = subtract(this.lastPoint, this.firstPoint);\n }\n return this._V;\n }\n\n get midPoint(): Vector {\n return add(this.firstPoint, scalarMultiply(this.V, 0.5));\n }\n\n isSame(other: Segment): boolean {\n if (!(other instanceof Line)) return false;\n return (\n (sameVector(this.firstPoint, other.firstPoint) &&\n sameVector(this.lastPoint, other.lastPoint)) ||\n (sameVector(this.lastPoint, other.firstPoint) &&\n sameVector(this.firstPoint, other.lastPoint))\n );\n }\n\n clone(): Line {\n return new Line(this.firstPoint, this.lastPoint);\n }\n\n reverse(): Line {\n return new Line(this.lastPoint, this.firstPoint);\n }\n\n private _boundingBox: BoundingBox | null = null;\n get boundingBox(): BoundingBox {\n if (this._boundingBox === null) {\n this._boundingBox = new BoundingBox(\n Math.min(this.firstPoint[0], this.lastPoint[0]) - this.precision,\n Math.min(this.firstPoint[1], this.lastPoint[1]) - this.precision,\n Math.max(this.firstPoint[0], this.lastPoint[0]) + this.precision,\n Math.max(this.firstPoint[1], this.lastPoint[1]) + this.precision\n );\n }\n return this._boundingBox;\n }\n\n distanceFrom(point: Vector): number {\n const delta = subtract(point, this.firstPoint);\n const u = dotProduct(delta, this.V) / this.squareLength;\n\n if (u < 0) {\n return distance(point, this.firstPoint);\n }\n\n if (u > 1) {\n return distance(point, this.lastPoint);\n }\n\n const intersection = this.paramPoint(u);\n return distance(point, intersection);\n }\n isOnSegment(point: Vector): boolean {\n if (sameVector(point, this.firstPoint, this.precision)) return true;\n const pointVec = subtract(point, this.firstPoint);\n\n if (!parallel(this.V, pointVec)) return false;\n\n const u = dotProduct(pointVec, this.V) / this.squareLength;\n return this.isValidParameter(u);\n }\n\n tangentAt(point: Vector): Vector {\n if (!this.isOnSegment(point)) throw new Error(\"Point is not on segment\");\n return normalize(this.V);\n }\n\n get tangentAtFirstPoint(): Vector {\n return normalize(this.V);\n }\n\n get tangentAtLastPoint(): Vector {\n return normalize(this.V);\n }\n\n splitAt(points: Vector | Vector[]): Line[] {\n let splitPoints: Vector[];\n if (Array.isArray(points) && points.length === 0) {\n return [this];\n }\n if (!Array.isArray(points[0])) {\n splitPoints = [points as Vector];\n } else {\n splitPoints = points as Vector[];\n }\n\n // Check that all points are on the segment\n splitPoints.forEach((point) => {\n if (!this.isOnSegment(point))\n throw new Error(\n `Point ${reprVector(point)} is not on segment ${this.repr}`\n );\n });\n\n const allPoints = [this.firstPoint, ...splitPoints, this.lastPoint];\n const uniquePoints = removeDuplicatePoints(allPoints);\n\n // Sort the points to make sure they go from the first point to the last\n const xChange = this.lastPoint[0] - this.firstPoint[0];\n let defaultDir = Math.sign(xChange);\n let comparisonAxis = 0;\n\n if (Math.abs(xChange) < this.precision) {\n defaultDir = Math.sign(this.lastPoint[1] - this.firstPoint[1]);\n comparisonAxis = 1;\n }\n\n uniquePoints.sort(\n (a, b) => defaultDir * (a[comparisonAxis] - b[comparisonAxis])\n );\n\n return uniquePoints.flatMap((point, index) => {\n if (index === uniquePoints.length - 1) return [];\n return new Line(point, uniquePoints[index + 1]);\n });\n }\n\n transform(matrix: TransformationMatrix): Line {\n return new Line(\n matrix.transform(this.firstPoint),\n matrix.transform(this.lastPoint)\n );\n }\n}\n","import { crossProduct, squareLength, subtract } from \"../vectorOperations\";\nimport { Line } from \"../models/segments/Line\";\n\nimport type { Vector } from \"../definitions\";\nimport { Segment } from \"../models/segments/Segment\";\nimport removeDuplicatePoints from \"../utils/removeDuplicatePoints\";\n\nexport const lineLineParams = (\n line1: { V: Vector; firstPoint: Vector; precision: number },\n line2: { V: Vector; firstPoint: Vector; precision: number },\n precision?: number\n):\n | \"parallel\"\n | {\n intersectionParam1: number;\n intersectionParam2: number;\n } => {\n const V1xV2 = crossProduct(line1.V, line2.V);\n\n const xLength = squareLength(line1.V);\n const yLength = squareLength(line2.V);\n\n const squarePrecision = precision\n ? precision * precision\n : line1.precision * line2.precision;\n\n if (V1xV2 * V1xV2 < xLength * yLength * squarePrecision) {\n return \"parallel\";\n }\n\n const diffPoint = subtract(line2.firstPoint, line1.firstPoint);\n\n const intersectionParam1 = crossProduct(diffPoint, line2.V) / V1xV2;\n const intersectionParam2 = crossProduct(diffPoint, line1.V) / V1xV2;\n\n return {\n intersectionParam1,\n intersectionParam2,\n };\n};\n\n/**\n * Returns the intersection point between two segment of lines\n *\n * Note that collinear segments are not considered to intersect at all.\n * Additionally, if the segments intersect at a start or end point of one of the\n * segments, the intersection point is considered to be an intersection.\n *\n * @param line1\n * @param line2\n * @returns {Vector} the intersection point or null if the segments do not\n * intersect\n *\n **/\nexport function lineLineIntersection(\n line1: Line,\n line2: Line,\n includeOverlaps = false,\n precision?: number\n): null | Vector | Line {\n const intersectionParams = lineLineParams(line1, line2, precision);\n if (intersectionParams === \"parallel\") {\n if (!includeOverlaps) return null;\n if (line1.isSame(line2)) return line1;\n\n const points = removeDuplicatePoints(\n [\n line2.isOnSegment(line1.firstPoint) ? line1.firstPoint : null,\n line2.isOnSegment(line1.lastPoint) ? line1.lastPoint : null,\n line1.isOnSegment(line2.firstPoint) ? line2.firstPoint : null,\n line1.isOnSegment(line2.lastPoint) ? line2.lastPoint : null,\n ].filter((p) => p !== null) as Vector[]\n ).sort((a, b) => a[0] - b[0]);\n\n if (points.length === 0) return null;\n // We consider the case when the lines are collinear and touch only on\n // the last point. We consider that they do not overlap there\n else if (points.length === 1) return null;\n else if (points.length === 2) return new Line(points[0], points[1]);\n else {\n console.error(points);\n throw new Error(\n \"Unexpected number of points while intersecting parallel lines\"\n );\n }\n }\n\n const { intersectionParam1, intersectionParam2 } = intersectionParams;\n if (!line1.isValidParameter(intersectionParam1)) return null;\n if (!line2.isValidParameter(intersectionParam2)) return null;\n\n return line1.paramPoint(intersectionParam1);\n}\n\nexport function findIntersections(\n segment1: Segment,\n segment2: Segment,\n precision?: number\n): Vector[] {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n const intersection = lineLineIntersection(\n segment1,\n segment2,\n false,\n precision\n );\n if (intersection === null) return [];\n return [intersection as Vector];\n }\n throw new Error(\"Not implemented\");\n}\n\nexport function findIntersectionsAndOverlaps(\n segment1: Segment,\n segment2: Segment,\n precision?: number\n): { intersections: Vector[]; overlaps: Segment[]; count: number } {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n const intersection = lineLineIntersection(\n segment1,\n segment2,\n true,\n precision\n );\n if (intersection === null)\n return { intersections: [], overlaps: [], count: 0 };\n if (intersection instanceof Line)\n return { intersections: [], overlaps: [intersection], count: 1 };\n return { intersections: [intersection], overlaps: [], count: 1 };\n }\n throw new Error(\"Not implemented\");\n}\n","import { BoundingBox } from \"./BoundingBox\";\nimport { Vector } from \"../definitions\";\nimport { findIntersectionsAndOverlaps } from \"../algorithms/intersections\";\nimport { Segment } from \"./segments/Segment\";\nimport { TransformationMatrix } from \"./TransformationMatrix\";\nimport { allCombinations } from \"../utils/allCombinations\";\nimport zip from \"../utils/zip\";\nimport { sameVector } from \"../vectorOperations\";\nimport { Transformable } from \"./utils/Transformable\";\n\nexport type Stroke = AbstractStroke<any>;\n\nexport abstract class AbstractStroke<\n T extends AbstractStroke<T>\n> extends Transformable<T> {\n readonly segments: Segment[];\n\n get repr(): string {\n return this.segments.map((segment) => segment.repr).join(\"\\n\") + \"\\n\";\n }\n constructor(segments: Segment[], { ignoreChecks = false } = {}) {\n super();\n if (!ignoreChecks) checkValidStroke(segments);\n this.segments = segments;\n }\n\n get firstPoint(): Vector {\n return this.segments[0].firstPoint;\n }\n\n get lastPoint(): Vector {\n return this.segments[this.segments.length - 1].lastPoint;\n }\n\n get segmentsCount(): number {\n return this.segments.length;\n }\n\n onStroke(point: Vector): boolean {\n return this.segments.some((segment) => segment.isOnSegment(point));\n }\n\n intersects(other: Stroke): boolean {\n if (!this.boundingBox.overlaps(other.boundingBox)) return false;\n return this.segments.some((segment) =>\n other.segments.some(\n (otherSegment) =>\n findIntersectionsAndOverlaps(segment, otherSegment).count > 0\n )\n );\n }\n\n private _boundingBox: BoundingBox | null = null;\n get boundingBox(): BoundingBox {\n if (this._boundingBox === null) {\n let bbox = this.segments[0].boundingBox;\n\n this.segments.slice(1).forEach((segment) => {\n bbox = bbox.merge(segment.boundingBox);\n });\n this._boundingBox = bbox;\n }\n return this._boundingBox;\n }\n\n abstract reverse(): T;\n\n abstract clone(): T;\n\n abstract transform(matrix: TransformationMatrix): T;\n\n abstract simplify(): T;\n\n [Symbol.for(\"nodejs.util.inspect.custom\")]() {\n return this.repr;\n }\n}\n\nexport function checkSelfIntersections(\n segments: Segment[],\n type = \"Stroke\"\n): void {\n allCombinations(segments.length).forEach(\n ([segmentIndex, otherSegmentIndex]) => {\n if (segmentIndex === otherSegmentIndex) return;\n const segment = segments[segmentIndex];\n const otherSegment = segments[otherSegmentIndex];\n\n const intersections = findIntersectionsAndOverlaps(segment, otherSegment);\n if (intersections.count === 0) return;\n if (intersections.count === 1 && !intersections.overlaps.length) {\n const distance = segmentIndex - otherSegmentIndex;\n\n const intersection = intersections.intersections[0];\n\n if (distance === 1) {\n if (sameVector(segment.firstPoint, intersection)) return;\n }\n if (distance === -1) {\n if (sameVector(segment.lastPoint, intersection)) return;\n }\n if (distance === segments.length - 1) {\n if (\n sameVector(segment.lastPoint, intersection) &&\n sameVector(otherSegment.firstPoint, intersection)\n )\n return;\n }\n if (-distance === segments.length - 1) {\n if (\n sameVector(segment.firstPoint, intersection) &&\n sameVector(otherSegment.lastPoint, intersection)\n )\n return;\n }\n }\n throw new Error(\n `${type} segments must not intersect, but segments ${segment.repr} and ${otherSegment.repr} do`\n );\n }\n );\n}\n\nexport function checkValidStroke(segments: Segment[], type = \"Stroke\"): void {\n if (segments.length === 0)\n throw new Error(`${type} must have at least one segment`);\n\n zip([segments.slice(0, -1), segments.slice(1)]).forEach(\n ([segment, nextSegment]) => {\n if (!sameVector(segment.lastPoint, nextSegment.firstPoint))\n throw new Error(\n `${type} segments must be connected, but ${segment.repr} and ${nextSegment.repr} are not`\n );\n }\n );\n\n checkSelfIntersections(segments, type);\n}\n","import type { Stroke } from \"../models/Stroke\";\nimport { Line } from \"../models/segments/Line\";\nimport { Segment } from \"../models/segments/Segment\";\nimport { parallel, sameVector } from \"../vectorOperations\";\n\nfunction canExtendSegment(segment1: Segment, segment2: Segment): boolean {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n if (parallel(segment1.V, segment2.V)) {\n return true;\n }\n }\n return false;\n}\n\nfunction extendSegment(segment1: Segment, segment2: Segment): Segment {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n return new Line(segment1.firstPoint, segment2.lastPoint);\n }\n throw new Error(\"Not implemented\");\n}\n\nexport function simplifySegments(stroke: Stroke): Segment[] | null {\n let foundSimplification = false;\n const simplifiedSegments: Segment[] = [];\n\n for (const segment of stroke.segments) {\n if (simplifiedSegments.length === 0) {\n simplifiedSegments.push(segment);\n continue;\n }\n\n const lastSegment = simplifiedSegments[simplifiedSegments.length - 1];\n if (canExtendSegment(lastSegment, segment)) {\n foundSimplification = true;\n simplifiedSegments.pop();\n simplifiedSegments.push(extendSegment(lastSegment, segment));\n } else {\n simplifiedSegments.push(segment);\n }\n }\n\n if (sameVector(stroke.firstPoint, stroke.lastPoint)) {\n if (\n canExtendSegment(\n simplifiedSegments[0],\n simplifiedSegments[simplifiedSegments.length - 1]\n )\n ) {\n foundSimplification = true;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = simplifiedSegments.pop()!;\n simplifiedSegments[0] = extendSegment(lastSegment, simplifiedSegments[0]);\n }\n }\n\n if (!foundSimplification) return null;\n return simplifiedSegments;\n}\n","import { AbstractStroke } from \"./Stroke\";\n\nimport { TransformationMatrix } from \"./TransformationMatrix\";\nimport { sameVector } from \"../vectorOperations\";\nimport { simplifySegments } from \"../algorithms/simplify\";\n\nexport class Strand extends AbstractStroke<Strand> {\n reverse(): Strand {\n const reversedSegments = this.segments.map((segment) => segment.reverse());\n reversedSegments.reverse();\n return new Strand(reversedSegments, { ignoreChecks: true });\n }\n\n clone(): Strand {\n return new Strand(\n this.segments.map((segment) => segment.clone()),\n { ignoreChecks: true }\n );\n }\n\n extend(strand: Strand): Strand {\n if (!sameVector(this.lastPoint, strand.firstPoint)) {\n console.error(this.repr, strand.repr);\n throw new Error(\"Cannot extend strand: connection point is not the same\");\n }\n return new Strand([...this.segments, ...strand.segments]);\n }\n\n simplify(): Strand {\n const newSegments = simplifySegments(this);\n if (!newSegments) return this;\n return new Strand(newSegments, { ignoreChecks: true });\n }\n\n transform(matrix: TransformationMatrix): Strand {\n return new Strand(\n this.segments.map((segment) => segment.transform(matrix)),\n { ignoreChecks: true }\n );\n }\n}\n","import { Line } from \"../models/segments/Line\";\nimport { lineLineParams } from \"./intersections\";\nimport type { Vector } from \"../definitions\";\nimport { Segment } from \"../models/segments/Segment\";\n\nconst rayLineIntersectionsCount = (point: Vector, line: Line) => {\n const intersectionParams = lineLineParams(line, {\n V: [1, 0],\n firstPoint: point,\n precision: line.precision,\n });\n if (intersectionParams === \"parallel\") {\n // When the ray is parallel with the line, we can ignore its extremities.\n // They will be handled by the segments getting into and out of this one.\n return 0;\n }\n\n const { intersectionParam1, intersectionParam2 } = intersectionParams;\n\n if (!line.isValidParameter(intersectionParam1)) return 0;\n // With the ray we only check one side of the parameter\n if (intersectionParam2 <= -line.precision) return 0;\n\n // We need to check if the ray intersects the line segment at the extremities\n // In that case we considers that it crosses the segment if its midpoint is\n // above the line.\n\n if (\n Math.abs(intersectionParam1) < line.precision ||\n Math.abs(intersectionParam1 - 1) < line.precision\n ) {\n const [, y] = line.midPoint;\n return point[1] - y < 0 ? 1 : 0;\n }\n\n return 1;\n};\n\nexport function rayIntersectionsCount(point: Vector, segment: Segment): number {\n if (segment instanceof Line) {\n return rayLineIntersectionsCount(point, segment);\n }\n\n throw new Error(\"Not implemented\");\n}\n","import type { Vector } from \"../definitions\";\nimport { rayIntersectionsCount } from \"../algorithms/rayIntersections\";\nimport { AbstractStroke, checkValidStroke } from \"./Stroke\";\nimport type { TransformationMatrix } from \"./TransformationMatrix\";\nimport { simplifySegments } from \"../algorithms/simplify\";\nimport { Segment } from \"./segments/Segment\";\nimport { sameVector } from \"../vectorOperations\";\n\nexport class Loop extends AbstractStroke<Loop> {\n constructor(segments: Segment[], { ignoreChecks = false } = {}) {\n super(segments, { ignoreChecks: true });\n if (!ignoreChecks) checkValidLoop(segments);\n }\n\n clone(): Loop {\n return new Loop(\n this.segments.map((segment) => segment.clone()),\n { ignoreChecks: true }\n );\n }\n\n reverse(): Loop {\n const reversedSegments = this.segments.map((segment) => segment.reverse());\n reversedSegments.reverse();\n return new Loop(reversedSegments, { ignoreChecks: true });\n }\n\n transform(matrix: TransformationMatrix): Loop {\n return new Loop(\n this.segments.map((segment) => segment.transform(matrix)),\n { ignoreChecks: true }\n );\n }\n\n contains(point: Vector): boolean {\n if (this.onStroke(point)) return false;\n\n const intersections = this.segments.reduce((acc, segment) => {\n return acc + rayIntersectionsCount(point, segment);\n }, 0);\n\n return intersections % 2 === 1;\n }\n\n simplify(): Loop {\n const newSegments = simplifySegments(this);\n if (!newSegments) return this;\n return new Loop(newSegments, { ignoreChecks: true });\n }\n}\n\nexport function checkValidLoop(segments: Segment[]): void {\n checkValidStroke(segments, \"Loop\");\n if (\n !sameVector(segments[0].firstPoint, segments[segments.length - 1].lastPoint)\n )\n throw new Error(\"Loop segment must be closed\");\n}\n","import { Vector } from \"../../definitions\";\nimport zip from \"../../utils/zip\";\n\nimport { Segment } from \"../../models/segments/Segment\";\nimport { Strand } from \"../../models/Strand\";\nimport { reprVector, sameVector } from \"../../vectorOperations\";\nimport { Loop } from \"../../models/Loop\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport removeDuplicatePoints from \"../../utils/removeDuplicatePoints\";\n\nconst rotateToStartAt = (segments: Segment[], point: Vector) => {\n const startIndex = segments.findIndex((segment: Segment) => {\n return sameVector(point, segment.firstPoint);\n });\n\n const start = segments.slice(0, startIndex);\n const end = segments.slice(startIndex);\n\n return end.concat(start);\n};\n\nconst rotateToStartAtSegment = (segments: Segment[], segment: Segment) => {\n let usedSegments = segments;\n\n const onSegment = (seg: Segment) => {\n return (\n sameVector(seg.firstPoint, segment.firstPoint) &&\n sameVector(seg.lastPoint, segment.lastPoint)\n );\n };\n\n let startIndex = segments.findIndex(onSegment);\n\n // it is also possible that the segment is oriented the other way. We still\n // need to align a start point\n if (startIndex === -1) {\n const reversedSegments = segments.map((s) => s.reverse());\n reversedSegments.reverse();\n startIndex = reversedSegments.findIndex(onSegment);\n if (startIndex === -1) {\n console.error(\n reversedSegments.map((c) => c.repr),\n segment.repr\n );\n throw new Error(\"Failed to rotate to segment start\");\n }\n usedSegments = reversedSegments;\n }\n\n const start = usedSegments.slice(0, startIndex);\n const end = usedSegments.slice(startIndex);\n\n return end.concat(start);\n};\n\nfunction* strandsBetweenIntersections(\n segments: Segment[],\n allIntersections: Vector[],\n allCommonSegments: Segment[]\n): Generator<Strand> {\n const endsAtIntersection = (segment: Segment) => {\n return allIntersections.some((intersection) => {\n return sameVector(intersection, segment.lastPoint);\n });\n };\n\n const isCommonSegment = (commonSegment: Segment) => {\n return allCommonSegments.some((segment) => {\n return commonSegment.isSame(segment);\n });\n };\n\n let currentCurves: Segment[] = [];\n for (const segment of segments) {\n // We ignore the checks at strand creation as these strands are part of\n // a loop and can be trusted to be valid\n if (endsAtIntersection(segment)) {\n currentCurves.push(segment);\n yield new Strand(currentCurves, { ignoreChecks: true });\n currentCurves = [];\n } else if (isCommonSegment(segment)) {\n if (currentCurves.length) {\n yield new Strand(currentCurves, { ignoreChecks: true });\n currentCurves = [];\n }\n yield new Strand([segment], { ignoreChecks: true });\n } else {\n currentCurves.push(segment);\n }\n }\n if (currentCurves.length) {\n yield new Strand(currentCurves, { ignoreChecks: true });\n }\n}\n\ntype IntersectionStrand = [Strand, Strand | \"same\"];\n\nfunction removeNonCrossingPoint(\n allIntersections: Vector[],\n segmentedCurve: Segment[],\n loopToCheck: Loop\n) {\n return allIntersections.filter((intersection: Vector) => {\n const segmentsOfIntersection = segmentedCurve.filter((s) => {\n return (\n sameVector(s.firstPoint, intersection) ||\n sameVector(s.lastPoint, intersection)\n );\n });\n if (segmentsOfIntersection.length % 2) {\n throw new Error(\"Bug in the intersection algo on non crossing point\");\n }\n\n const isInside = segmentsOfIntersection.map((segment: Segment): boolean => {\n return loopToCheck.contains(segment.midPoint);\n });\n\n // Either they are all inside or outside\n const segmentsOnTheSameSide =\n isInside.every((i) => i) || !isInside.some((i) => i);\n\n return !segmentsOnTheSameSide;\n });\n}\n\n/* When two shape intersect we cut them into segments between the intersection\n * points.\n *\n * This function returns the list of segments that have the same start and end\n * at the same intersection points or null if there is no intersection.\n */\nfunction loopIntersectionStrands(\n first: Loop,\n second: Loop,\n precision?: number\n): IntersectionStrand[] | null {\n // For each segment of each blueprint we figure out where the intersection\n // points are.\n let allIntersections: Vector[] = [];\n const allCommonSegments: Segment[] = [];\n\n const firstCurvePoints: Vector[][] = new Array(first.segments.length)\n .fill(0)\n .map(() => []);\n const secondCurvePoints: Vector[][] = new Array(second.segments.length)\n .fill(0)\n .map(() => []);\n\n first.segments.forEach((thisSegments, firstIndex) => {\n second.segments.forEach((otherSegments, secondIndex) => {\n const { intersections, overlaps } = findIntersectionsAndOverlaps(\n thisSegments,\n otherSegments,\n precision\n );\n\n allIntersections.push(...intersections);\n firstCurvePoints[firstIndex].push(...intersections);\n secondCurvePoints[secondIndex].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 firstCurvePoints[firstIndex].push(...commonSegmentsPoints);\n secondCurvePoints[secondIndex].push(...commonSegmentsPoints);\n });\n });\n\n allIntersections = removeDuplicatePoints(allIntersections, precision);\n\n // If there is only one intersection point we consider that the loops\n // are not intersecting\n if (!allIntersections.length || allIntersections.length === 1) return null;\n\n // We further split the segments at the intersections\n const cutCurve = ([segment, intersections]: [\n Segment,\n Vector[]\n ]): Segment[] => {\n if (!intersections.length) return [segment];\n return segment.splitAt(intersections);\n };\n let firstCurveSegments = zip([first.segments, firstCurvePoints] as [\n Segment[],\n Vector[][]\n ]).flatMap(cutCurve);\n\n let secondCurveSegments = zip([second.segments, secondCurvePoints] as [\n Segment[],\n Vector[][]\n ]).flatMap(cutCurve);\n\n // We need to remove intersection points that are not crossing into each\n // other (i.e. the two blueprints are only touching in one point and not\n // intersecting there.)\n allIntersections = removeNonCrossingPoint(\n allIntersections,\n firstCurveSegments,\n second\n );\n\n if (!allIntersections.length && !allCommonSegments.length) return null;\n\n // We align the beginning of the segments\n if (!allCommonSegments.length) {\n const startAt = allIntersections[0];\n firstCurveSegments = rotateToStartAt(firstCurveSegments, startAt);\n secondCurveSegments = rotateToStartAt(secondCurveSegments, startAt);\n } else {\n // When there are common segments we always start on one\n const startSegment = allCommonSegments[0];\n firstCurveSegments = rotateToStartAtSegment(\n firstCurveSegments,\n startSegment\n );\n secondCurveSegments = rotateToStartAtSegment(\n secondCurveSegments,\n startSegment\n );\n }\n\n // We group segments between intersections in strands\n const strandsFromFirst = Array.from(\n strandsBetweenIntersections(\n firstCurveSegments,\n allIntersections,\n allCommonSegments\n )\n );\n\n let strandsFromSecond = Array.from(\n strandsBetweenIntersections(\n secondCurveSegments,\n allIntersections,\n allCommonSegments\n )\n );\n\n if (\n !sameVector(\n strandsFromSecond[0].lastPoint,\n strandsFromFirst[0].lastPoint\n ) ||\n (allCommonSegments.length > 0 && strandsFromSecond[0].segmentsCount !== 1)\n ) {\n strandsFromSecond = strandsFromSecond.reverse().map((s) => s.reverse());\n }\n\n return zip([strandsFromFirst, strandsFromSecond]).map(([first, second]) => {\n if (\n first.segmentsCount === 1 &&\n allCommonSegments.some((commonSegment) => {\n return first.segments[0].isSame(commonSegment);\n })\n ) {\n return [first, \"same\"];\n }\n return [first, second];\n });\n}\n\nfunction mergeStrandsAsLoop(strands: Strand[]) {\n let outStrand = strands[0];\n\n for (const strand of strands.slice(1)) {\n outStrand = outStrand.extend(strand);\n }\n\n if (!sameVector(outStrand.firstPoint, outStrand.lastPoint)) {\n console.error(\n reprVector(outStrand.firstPoint),\n reprVector(outStrand.lastPoint)\n );\n throw new Error(\"Bug in the intersection algo on non closing strand\");\n }\n\n return new Loop(outStrand.segments);\n}\n\nfunction groupLoops(inputStrands: Strand[]): Loop[] {\n if (!inputStrands.length) return [];\n\n const startPoints = inputStrands.map((c) => c.firstPoint);\n let endPoints = inputStrands.map((c) => c.lastPoint);\n endPoints = endPoints.slice(-1).concat(endPoints.slice(0, -1));\n\n const discontinuities = zip([startPoints, endPoints]).flatMap(\n ([startPoint, endPoint], index) => {\n if (!sameVector(startPoint, endPoint)) {\n return index;\n }\n return [];\n }\n );\n\n if (!discontinuities.length) return [mergeStrandsAsLoop(inputStrands)];\n\n const strands = zip([\n discontinuities.slice(0, -1),\n discontinuities.slice(1),\n ]).map(([start, end]) => {\n return mergeStrandsAsLoop(inputStrands.slice(start, end));\n });\n\n let lastStrand = inputStrands.slice(\n discontinuities[discontinuities.length - 1]\n );\n if (discontinuities[0] !== 0) {\n lastStrand = lastStrand.concat(inputStrands.slice(0, discontinuities[0]));\n }\n strands.push(mergeStrandsAsLoop(lastStrand));\n\n return strands;\n}\n\nconst extendStrandList = (strandList: Strand[], strand: Strand) => {\n if (strandList.length === 0) return [strand];\n const lastStrand = strandList.at(-1)!;\n if (sameVector(lastStrand.lastPoint, strand.firstPoint)) {\n return strandList.slice(0, -1).concat([lastStrand.extend(strand)]);\n } else if (sameVector(lastStrand.lastPoint, strand.lastPoint)) {\n return strandList\n .slice(0, -1)\n .concat([lastStrand.extend(strand.reverse())]);\n } else {\n return strandList.concat([strand]);\n }\n};\n\nconst prependStrandList = (strandList: Strand[], strand: Strand) => {\n if (strandList.length === 0) return [strand];\n if (sameVector(strandList[0].firstPoint, strand.lastPoint)) {\n return [strand.extend(strandList[0])].concat(strandList.slice(1));\n } else {\n return [strand].concat(strandList);\n }\n};\n\nexport function loopBooleanOperation(\n first: Loop,\n second: Loop,\n {\n firstInside,\n secondInside,\n }: {\n firstInside: \"keep\" | \"remove\";\n secondInside: \"keep\" | \"remove\";\n }\n):\n | Loop[]\n | { identical: true }\n | {\n firstCurveInSecond: boolean;\n secondCurveInFirst: boolean;\n identical: false;\n } {\n const strands = loopIntersectionStrands(first, second);\n\n // The case where we have no intersections\n if (!strands) {\n const firstStrandPoint = first.segments[0].midPoint;\n const firstCurveInSecond = second.contains(firstStrandPoint);\n\n const secondStrandPoint = second.segments[0].midPoint;\n const secondCurveInFirst = first.contains(secondStrandPoint);\n\n return {\n identical: false,\n firstCurveInSecond,\n secondCurveInFirst,\n };\n }\n\n if (strands.every(([, secondStrand]) => secondStrand === \"same\")) {\n return { identical: true };\n }\n\n let lastWasSame: null | Strand = null;\n let strandsIn: number | null = null;\n\n const s = strands.flatMap(([firstStrand, secondStrand]) => {\n let mergedStrands: Strand[] = [];\n let strandsOut = 0;\n\n // When two strands are on top of each other we base our decision on the\n // fact that every point should have one strand entering, and one going\n // out.\n if (secondStrand === \"same\") {\n if (strandsIn === 1) {\n strandsIn = 1;\n return firstStrand;\n }\n\n if (strandsIn === 2 || strandsIn === 0) {\n strandsIn = null;\n return [];\n }\n\n if (strandsIn === null) {\n if (!lastWasSame) lastWasSame = firstStrand;\n else lastWasSame = lastWasSame.extend(firstStrand);\n return [];\n }\n\n console.error(\"weird situation\");\n return [];\n }\n\n // Every strand is kept or removed according to the fact that it is within\n // or not of the other closed loop\n\n const firstSegmentPoint = firstStrand.segments[0].midPoint;\n const firstSegmentInSecondShape = second.contains(firstSegmentPoint);\n\n if (\n (firstInside === \"keep\" && firstSegmentInSecondShape) ||\n (firstInside === \"remove\" && !firstSegmentInSecondShape)\n ) {\n strandsOut += 1;\n mergedStrands = extendStrandList(mergedStrands, firstStrand);\n }\n\n const secondSegmentPoint = secondStrand.segments[0].midPoint;\n const secondSegmentInFirstShape = first.contains(secondSegmentPoint);\n\n if (\n (secondInside === \"keep\" && secondSegmentInFirstShape) ||\n (secondInside === \"remove\" && !secondSegmentInFirstShape)\n ) {\n const strandToAdd = secondStrand;\n\n strandsOut += 1;\n\n if (strandsOut === 2 && mergedStrands.length) {\n mergedStrands = extendStrandList(mergedStrands, strandToAdd);\n lastWasSame = null;\n } else {\n mergedStrands = [strandToAdd];\n }\n }\n\n // This is the case where the information about the strands entering the\n // previous node where not known and no strand was selected\n if (strandsIn === null && strandsOut === 1 && lastWasSame) {\n mergedStrands = prependStrandList(mergedStrands, lastWasSame);\n }\n\n if (strandsOut === 1) {\n strandsIn = strandsOut;\n lastWasSame = null;\n }\n if (!mergedStrands.length) {\n lastWasSame = null;\n return [];\n }\n return mergedStrands;\n });\n\n // We now have a bunch of strands, we need to group them into loops\n return groupLoops(s);\n}\n\nexport const fuseLoops = (first: Loop, second: Loop): Loop[] => {\n const result = loopBooleanOperation(first, second, {\n firstInside: \"remove\",\n secondInside: \"remove\",\n });\n\n if (Array.isArray(result)) return result;\n\n if (result.identical) {\n return [first];\n }\n\n if (result.firstCurveInSecond) {\n return [second];\n }\n\n if (result.secondCurveInFirst) {\n return [first];\n }\n\n return [first, second];\n};\n\nexport const cutLoops = (first: Loop, second: Loop): Loop[] => {\n const result = loopBooleanOperation(first, second, {\n firstInside: \"remove\",\n secondInside: \"keep\",\n });\n\n if (Array.isArray(result)) return result;\n\n if (result.identical) {\n return [];\n }\n\n if (result.firstCurveInSecond) {\n return [];\n }\n\n if (result.secondCurveInFirst) {\n return [first, second];\n }\n\n return [first];\n};\n\nexport const intersectLoops = (first: Loop, second: Loop): Loop[] => {\n const result = loopBooleanOperation(first, second, {\n firstInside: \"keep\",\n secondInside: \"keep\",\n });\n\n if (Array.isArray(result)) return result;\n\n if (result.identical) {\n return [first];\n }\n\n if (result.firstCurveInSecond) {\n return [first];\n }\n\n if (result.secondCurveInFirst) {\n return [second];\n }\n\n return [];\n};\n","import { Figure } from \"../../models/Figure\";\nimport { organiseLoops } from \"../organiseLoops\";\nimport { allPairs } from \"../../utils/allPairs\";\nimport { cutLoops, fuseLoops, intersectLoops } from \"./loopBooleans\";\n\nexport function fuseIntersectingFigures(figures: Figure[]) {\n const fused = new Map();\n\n const output: { current: Figure[] }[] = [];\n\n figures.forEach((inputFigure, i) => {\n let savedFigures: {\n current: Figure[];\n fusedWith: Set<number>;\n };\n\n if (fused.has(i)) {\n savedFigures = fused.get(i);\n } else {\n savedFigures = { current: [inputFigure], fusedWith: new Set([i]) };\n output.push(savedFigures);\n }\n\n figures.slice(i + 1).forEach((inputOtherFigure, j) => {\n const figure = savedFigures.current;\n\n const currentIndex = i + j + 1;\n\n if (savedFigures.fusedWith.has(currentIndex)) return;\n\n let otherFigure = [inputOtherFigure];\n let otherIsFused = false;\n\n if (fused.has(currentIndex)) {\n otherFigure = fused.get(currentIndex).current;\n otherIsFused = true;\n }\n\n const doListIntersect = figure.some((f) =>\n otherFigure.some((s) => f.intersects(s))\n );\n if (!doListIntersect) return;\n\n let newFused: Figure[];\n if (figure.length > 1 || otherFigure.length > 1) {\n newFused = fuseFiguresLists(figure, otherFigure);\n } else {\n newFused = fuseFigures(figure[0], otherFigure[0]);\n }\n\n savedFigures.fusedWith.add(currentIndex);\n savedFigures.current = newFused;\n if (!otherIsFused) fused.set(currentIndex, savedFigures);\n });\n });\n\n return output.flatMap(({ current }) => current);\n}\n\nexport function fuseFigures(first: Figure, second: Figure) {\n const outerFused = fuseLoops(first.contour, second.contour);\n\n const inner1Fused = second.holes.flatMap((c) => cutLoops(c, first.contour));\n const inner2Fused = first.holes.flatMap((c) => cutLoops(c, second.contour));\n\n const innerIntersections = allPairs(first.holes, second.holes).flatMap(\n ([first, second]) => intersectLoops(first, second)\n );\n\n return organiseLoops([\n ...outerFused,\n ...inner1Fused,\n ...inner2Fused,\n ...innerIntersections,\n ]);\n}\n\nexport function cutFigures(first: Figure, second: Figure): Figure[] {\n if (first.isFull && second.isFull) {\n return organiseLoops(cutLoops(first.contour, second.contour));\n }\n\n if (first.isFull) {\n const cutContour = cutLoops(first.contour, second.contour);\n const cutHoles = second.holes.flatMap((c) =>\n intersectLoops(c, first.contour)\n );\n // We might be able to assume that the contour and the holes are already\n // distinct figures.\n return organiseLoops([...cutContour, ...cutHoles]);\n } else if (second.isFull) {\n if (!first.contour.intersects(second.contour)) {\n if (!first.contour.contains(second.contour.firstPoint)) {\n // nothing to do here, the second figure is outside the first\n return [first];\n } else {\n const fusedCuts = fuseFiguresLists(\n first.holes.map((h) => new Figure(h)),\n [second]\n );\n\n return organiseLoops([\n first.contour,\n ...fusedCuts.flatMap((f) => f.allLoops),\n ]);\n }\n }\n }\n\n // We turn the last case in one where the second is full\n let newFigures = cutFigures(new Figure(first.contour), second);\n first.holes.forEach((cut) => {\n newFigures = newFigures.flatMap((c) => cutFigures(c, new Figure(cut)));\n });\n\n return newFigures;\n}\n\nexport function intersectFigures(first: Figure, second: Figure): Figure[] {\n const outerIntersection = intersectLoops(first.contour, second.contour);\n if (!outerIntersection.length) return [];\n\n let out = organiseLoops(outerIntersection);\n out = cutFiguresLists(\n out,\n first.holes.map((h) => new Figure(h))\n );\n\n // Here we need to do the cut in two steps, because the holes might intersect\n return cutFiguresLists(\n out,\n second.holes.map((h) => new Figure(h))\n );\n}\n\nexport function fuseFiguresLists(first: Figure[], second: Figure[]): Figure[] {\n if (!first.length) return second;\n if (!second.length) return first;\n\n if (\n (first.length === 1 && second.length > 1) ||\n (second.length === 1 && first.length > 1)\n ) {\n return fuseIntersectingFigures([...first, ...second]);\n }\n\n if (first.length > 1 && second.length > 1) {\n let out = fuseFiguresLists([first[0]], second);\n\n first.slice(1).forEach((fig) => {\n out = fuseFiguresLists([fig], out);\n });\n return out;\n }\n\n if (first.length === 1 && second.length === 1) {\n return fuseFigures(first[0], second[0]);\n }\n\n return [];\n}\n\nexport function cutFiguresLists(first: Figure[], second: Figure[]): Figure[] {\n if (!first.length) return [];\n if (!second.length) return first;\n\n // The easy case\n if (first.length === 1 && second.length === 1) {\n return cutFigures(first[0], second[0]);\n }\n\n if (first.length > 1) {\n // All the figures here are independant, so we can cut them independently\n return first.flatMap((fig) => cutFiguresLists([fig], second));\n }\n\n // We are now in the case where there is only one figure in the first list\n // and multiple figures in the second list\n //\n // We turn it in the case with (potentially) multiple figures in the first list\n // and one figure in the second list\n\n let out = cutFigures(first[0], second[0]);\n second.slice(1).forEach((fig) => {\n out = cutFiguresLists(out, [fig]);\n });\n return out;\n}\n\nexport function intersectFiguresLists(\n first: Figure[],\n second: Figure[]\n): Figure[] {\n if (!first.length || !second.length) {\n return [];\n }\n\n if (first.length === 1 && second.length === 1) {\n return intersectFigures(first[0], second[0]);\n }\n\n if (first.length > 1) {\n return first.flatMap((fig) => intersectFiguresLists([fig], second));\n }\n\n return second.flatMap((fig) => intersectFiguresLists(first, [fig]));\n}\n","import type { Vector } from \"../definitions\";\nimport { BoundingBox } from \"./BoundingBox\";\nimport type { Figure } from \"./Figure\";\nimport type { TransformationMatrix } from \"./TransformationMatrix\";\n\nimport {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"../algorithms/boolean/figureBooleans\";\nimport { combineDifferentValues } from \"../utils/allCombinations\";\nimport { Transformable } from \"./utils/Transformable\";\n\nexport class Diagram extends Transformable<Diagram> {\n figures: Figure[];\n\n constructor(figures: Figure[] = [], { ignoreChecks = false } = {}) {\n super();\n if (!ignoreChecks) checkIsValidDiagram(figures);\n this.figures = figures;\n }\n\n private _boundingBox: BoundingBox | null = null;\n\n get isEmpty(): boolean {\n return this.figures.length === 0;\n }\n\n get boundingBox(): BoundingBox {\n if (this.isEmpty) return new BoundingBox();\n if (this._boundingBox === null) {\n let boundingBox = this.figures[0].boundingBox;\n for (const figure of this.figures.slice(1)) {\n boundingBox = boundingBox.merge(figure.boundingBox);\n }\n this._boundingBox = boundingBox;\n }\n return this._boundingBox;\n }\n\n clone(): Diagram {\n return new Diagram(this.figures.map((figure) => figure.clone()));\n }\n\n transform(matrix: TransformationMatrix): Diagram {\n return new Diagram(this.figures.map((figure) => figure.transform(matrix)));\n }\n\n contains(point: Vector): boolean {\n return this.figures.some((figure) => figure.contains(point));\n }\n\n intersects(other: Diagram): boolean {\n return this.figures.some((figure) =>\n other.figures.some((otherFigure) => figure.intersects(otherFigure))\n );\n }\n\n fuse(other: Diagram): Diagram {\n return new Diagram(fuseFiguresLists(this.figures, other.figures));\n }\n\n cut(other: Diagram): Diagram {\n return new Diagram(cutFiguresLists(this.figures, other.figures));\n }\n\n intersect(other: Diagram): Diagram {\n return new Diagram(intersectFiguresLists(this.figures, other.figures));\n }\n}\n\nexport function checkIsValidDiagram(figures: Figure[]): void {\n for (const [figure, otherFigure] of combineDifferentValues(figures)) {\n if (figure.intersects(otherFigure)) {\n throw new Error(\"Diagram figures must not intersect\");\n }\n }\n}\n"],"names":["overlap1D","min1","max1","min2","max2","BoundingBox","xMin","yMin","xMax","yMax","point","x","y","other","allCombinations","count","result","i","j","combineDifferentValues","array","DEG2RAD","reprVector","vector","sameVector","x0","y0","x1","y1","precision","add","subtract","squareLength","scalarMultiply","scalar","squareDistance","distance","p0","p1","crossProduct","dotProduct","normalize","l","polarToCartesian","r","theta","parallel","v1","v2","V1xV2","xLength","yLength","matMult","m1","m2","a","b","c","d","e","f","g","h","k","m","n","o","p","q","TransformationMatrix","angle","center","cos","sin","rotationMatrix","normal","Transformable","transform","factor","axisOrDirection","Figure","contour","holes","ignoreChecks","checkIsValidFigure","hole","matrix","loop","otherLoop","loop1","loop2","hole1","hole2","groupByBoundingBoxOverlap","loops","overlaps","v","index","groups","groupsInOverlaps","indices","myGroup","addContainmentInfo","groupedLoops","isIn","potentialOuterLoop","splitMultipleOuterLoops","outerLoops","allLoops","outerLoop","cleanEdgeCases","handleNestedLoops","nestedLoops","firstLevelOuterLoops","innerLevelsLoops","organiseLoops","compounds","allPairs","list1","list2","l1","l2","range","len","zip","arrays","minLength","arr","asFixed","num","removeDuplicatePoints","points","AbstractSegment","firstPoint","lastPoint","Line","linearPrecision","delta","u","intersection","pointVec","splitPoints","allPoints","uniquePoints","xChange","defaultDir","comparisonAxis","lineLineParams","line1","line2","squarePrecision","diffPoint","intersectionParam1","intersectionParam2","lineLineIntersection","includeOverlaps","intersectionParams","findIntersectionsAndOverlaps","segment1","segment2","AbstractStroke","segments","checkValidStroke","segment","otherSegment","bbox","checkSelfIntersections","type","segmentIndex","otherSegmentIndex","intersections","nextSegment","canExtendSegment","extendSegment","simplifySegments","stroke","foundSimplification","simplifiedSegments","lastSegment","Strand","reversedSegments","strand","newSegments","rayLineIntersectionsCount","line","rayIntersectionsCount","Loop","checkValidLoop","acc","rotateToStartAt","startIndex","start","rotateToStartAtSegment","usedSegments","onSegment","seg","s","strandsBetweenIntersections","allIntersections","allCommonSegments","endsAtIntersection","isCommonSegment","commonSegment","currentCurves","removeNonCrossingPoint","segmentedCurve","loopToCheck","segmentsOfIntersection","isInside","loopIntersectionStrands","first","second","firstCurvePoints","secondCurvePoints","thisSegments","firstIndex","otherSegments","secondIndex","commonSegmentsPoints","cutCurve","firstCurveSegments","secondCurveSegments","startSegment","startAt","strandsFromFirst","strandsFromSecond","mergeStrandsAsLoop","strands","outStrand","groupLoops","inputStrands","startPoints","endPoints","discontinuities","startPoint","endPoint","end","lastStrand","extendStrandList","strandList","prependStrandList","loopBooleanOperation","firstInside","secondInside","firstStrandPoint","firstCurveInSecond","secondStrandPoint","secondCurveInFirst","secondStrand","lastWasSame","strandsIn","firstStrand","mergedStrands","strandsOut","firstSegmentPoint","firstSegmentInSecondShape","secondSegmentPoint","secondSegmentInFirstShape","strandToAdd","fuseLoops","cutLoops","intersectLoops","fuseIntersectingFigures","figures","fused","output","inputFigure","savedFigures","inputOtherFigure","figure","currentIndex","otherFigure","otherIsFused","newFused","fuseFiguresLists","fuseFigures","current","outerFused","inner1Fused","inner2Fused","innerIntersections","cutFigures","cutContour","cutHoles","fusedCuts","newFigures","cut","intersectFigures","outerIntersection","out","cutFiguresLists","fig","intersectFiguresLists","Diagram","checkIsValidDiagram","boundingBox"],"mappings":"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"}
|