pantograph2d 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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/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","../src/import/json/importJSON.ts","../src/main.ts"],"sourcesContent":["import { 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 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 if (sameVector(segment.firstPoint, segment.lastPoint)) {\n throw new Error(`Segment has no length, ${segment.repr}`);\n }\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 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 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 { 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 } 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":["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","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","perpendicular","sagPoint","add","scalarMultiply","bulge","halfChord","bulgeAsSagitta","tangentArc","mirrorVector","subtract","mirrorTranform","TransformationMatrix","mirroredSegments","draw","listOfFigures","shape","fuse","first","second","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","svgSegmentToPath","Arc","svgLoop","loop","start","svgFigure","figure","svgDiagram","diagram","SVGViewbox","bbox","margin","minX","minY","wrapSVG","body","boundingBox","svgBody","exportSVG","flipped","s","importSegment","json","importLoop","importFigure","contour","holes","importDiagram","figures","importJSON","RAD2DEG","cartesianToPolar"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pantograph2d",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Pantograph, the pure JS 2D CAD library",
5
5
  "type": "module",
6
6
  "main": "./dist/pantograph.cjs",
@@ -44,5 +44,5 @@
44
44
  "vite-plugin-dts": "^2.2.0",
45
45
  "vitest": "^0.29.2"
46
46
  },
47
- "gitHead": "a2b9db5c938cdbd7452e96175b403fac8f4caf5b"
47
+ "gitHead": "1be6def26c11010bfaa76554e517ffad261ba966"
48
48
  }
@@ -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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"}