pantograph2d 0.1.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.
@@ -0,0 +1,196 @@
1
+ declare abstract class AbstractSegment<T extends AbstractSegment<T>> extends Transformable<T> {
2
+ firstPoint: Vector;
3
+ lastPoint: Vector;
4
+ constructor(firstPoint: Vector, lastPoint: Vector);
5
+ readonly precision: number;
6
+ abstract segmentType: string;
7
+ get repr(): string;
8
+ abstract get midPoint(): Vector;
9
+ abstract get boundingBox(): BoundingBox;
10
+ abstract clone(): T;
11
+ abstract reverse(): T;
12
+ abstract isSame(other: AbstractSegment<any>): boolean;
13
+ abstract distanceFrom(element: Vector): number;
14
+ abstract isOnSegment(point: Vector): boolean;
15
+ abstract tangentAt(point: Vector): Vector;
16
+ abstract get tangentAtFirstPoint(): Vector;
17
+ abstract get tangentAtLastPoint(): Vector;
18
+ abstract splitAt(points: Vector[] | number[]): T[];
19
+ abstract transform(matrix: TransformationMatrix): T;
20
+ }
21
+
22
+ declare abstract class AbstractStroke<T extends AbstractStroke<T>> extends Transformable<T> {
23
+ readonly segments: Segment[];
24
+ get repr(): string;
25
+ constructor(segments: Segment[], { ignoreChecks }?: {
26
+ ignoreChecks?: boolean | undefined;
27
+ });
28
+ get firstPoint(): Vector;
29
+ get lastPoint(): Vector;
30
+ get segmentsCount(): number;
31
+ onStroke(point: Vector): boolean;
32
+ intersects(other: Stroke): boolean;
33
+ private _boundingBox;
34
+ get boundingBox(): BoundingBox;
35
+ abstract reverse(): T;
36
+ abstract clone(): T;
37
+ abstract transform(matrix: TransformationMatrix): T;
38
+ abstract simplify(): T;
39
+ }
40
+
41
+ export declare class BoundingBox {
42
+ readonly xMin: number;
43
+ readonly yMin: number;
44
+ readonly xMax: number;
45
+ readonly yMax: number;
46
+ constructor(xMin?: number, yMin?: number, xMax?: number, yMax?: number);
47
+ get width(): number;
48
+ get height(): number;
49
+ contains(point: Vector): boolean;
50
+ overlaps(other: BoundingBox): boolean;
51
+ addPoint(point: Vector): BoundingBox;
52
+ merge(other: BoundingBox): BoundingBox;
53
+ }
54
+
55
+ export declare function cut(first: Diagram | Figure | Loop, second: Diagram | Figure | Loop): Diagram;
56
+
57
+ export declare class Diagram extends Transformable<Diagram> {
58
+ figures: Figure[];
59
+ constructor(figures?: Figure[], { ignoreChecks }?: {
60
+ ignoreChecks?: boolean | undefined;
61
+ });
62
+ private _boundingBox;
63
+ get isEmpty(): boolean;
64
+ get boundingBox(): BoundingBox;
65
+ clone(): Diagram;
66
+ transform(matrix: TransformationMatrix): Diagram;
67
+ contains(point: Vector): boolean;
68
+ intersects(other: Diagram): boolean;
69
+ fuse(other: Diagram): Diagram;
70
+ cut(other: Diagram): Diagram;
71
+ intersect(other: Diagram): Diagram;
72
+ }
73
+
74
+ export declare function draw(origin?: Vector): DrawingPen;
75
+
76
+ declare class DrawingPen {
77
+ protected pointer: Vector;
78
+ protected firstPoint: Vector;
79
+ protected pendingSegments: Segment[];
80
+ constructor(origin?: Vector);
81
+ movePointerTo(point: Vector): this;
82
+ protected saveSegment(segment: Segment): this;
83
+ lineTo(point: Vector): this;
84
+ line(xDist: number, yDist: number): this;
85
+ vLine(distance: number): this;
86
+ hLine(distance: number): this;
87
+ vLineTo(yPos: number): this;
88
+ hLineTo(xPos: number): this;
89
+ polarLineTo([r, theta]: Vector): this;
90
+ polarLine(distance: number, angle: number): this;
91
+ tangentLine(distance: number): this;
92
+ close(): Diagram;
93
+ closeWithMirror(): Diagram;
94
+ }
95
+
96
+ export declare function exportSVG(shape: Shape | Shape[], margin?: number): string;
97
+
98
+ export declare class Figure extends Transformable<Figure> {
99
+ readonly contour: Loop;
100
+ readonly holes: Loop[];
101
+ constructor(contour: Loop, holes?: Loop[], { ignoreChecks }?: {
102
+ ignoreChecks?: boolean | undefined;
103
+ });
104
+ get boundingBox(): BoundingBox;
105
+ get isFull(): boolean;
106
+ get allLoops(): Loop[];
107
+ clone(): Figure;
108
+ transform(matrix: TransformationMatrix): Figure;
109
+ contains(point: Vector): boolean;
110
+ intersects(other: Figure): boolean;
111
+ }
112
+
113
+ export declare function fuse(first: Diagram | Figure | Loop, second: Diagram | Figure | Loop): Diagram;
114
+
115
+ export declare function fuseAll(shapes: (Diagram | Figure | Loop)[]): Diagram;
116
+
117
+ export declare function intersect(first: Diagram | Figure | Loop, second: Diagram | Figure | Loop): Diagram;
118
+
119
+ export declare class Line extends AbstractSegment<Line> {
120
+ segmentType: string;
121
+ isValidParameter(t: number): boolean;
122
+ paramPoint(t: number): Vector;
123
+ get length(): number;
124
+ get squareLength(): number;
125
+ private _V;
126
+ get V(): Vector;
127
+ get midPoint(): Vector;
128
+ isSame(other: Segment): boolean;
129
+ clone(): Line;
130
+ reverse(): Line;
131
+ private _boundingBox;
132
+ get boundingBox(): BoundingBox;
133
+ distanceFrom(point: Vector): number;
134
+ isOnSegment(point: Vector): boolean;
135
+ tangentAt(point: Vector): Vector;
136
+ get tangentAtFirstPoint(): Vector;
137
+ get tangentAtLastPoint(): Vector;
138
+ splitAt(points: Vector | Vector[]): Line[];
139
+ transform(matrix: TransformationMatrix): Line;
140
+ }
141
+
142
+ export declare class Loop extends AbstractStroke<Loop> {
143
+ constructor(segments: Segment[], { ignoreChecks }?: {
144
+ ignoreChecks?: boolean | undefined;
145
+ });
146
+ clone(): Loop;
147
+ reverse(): Loop;
148
+ transform(matrix: TransformationMatrix): Loop;
149
+ contains(point: Vector): boolean;
150
+ simplify(): Loop;
151
+ }
152
+
153
+ export declare type Segment = AbstractSegment<any>;
154
+
155
+ declare type Shape = Loop | Figure | Diagram;
156
+
157
+ export declare class Strand extends AbstractStroke<Strand> {
158
+ reverse(): Strand;
159
+ clone(): Strand;
160
+ extend(strand: Strand): Strand;
161
+ simplify(): Strand;
162
+ transform(matrix: TransformationMatrix): Strand;
163
+ }
164
+
165
+ export declare type Stroke = AbstractStroke<any>;
166
+
167
+ export declare function svgBody(shape: Shape): string;
168
+
169
+ declare abstract class Transformable<T> {
170
+ abstract transform(matrix: TransformationMatrix): T;
171
+ translateX(x: number): T;
172
+ translateY(y: number): T;
173
+ translate(x: number, y: number): T;
174
+ translateTo([x, y]: Vector): T;
175
+ rotate(angle: number, center?: Vector): T;
176
+ scale(factor: number, center?: Vector): T;
177
+ mirrorCenter(center?: Vector): T;
178
+ mirror(axis?: "x" | "y"): T;
179
+ mirror(direction: Vector, center?: Vector): T;
180
+ }
181
+
182
+ export declare class TransformationMatrix {
183
+ private _matrix;
184
+ translate(x: number, y: number): TransformationMatrix;
185
+ rotate(angle: number, center?: Vector): TransformationMatrix;
186
+ mirrorX(): TransformationMatrix;
187
+ mirrorY(): TransformationMatrix;
188
+ mirrorLine(normal: Vector, point?: Vector): TransformationMatrix;
189
+ mirrorCenter(center?: Vector): TransformationMatrix;
190
+ scale(scalar: number, center?: Vector): TransformationMatrix;
191
+ transform(point: Vector): Vector;
192
+ }
193
+
194
+ declare type Vector = [number, number];
195
+
196
+ export { }
@@ -0,0 +1,172 @@
1
+ import { L as g, s as L, T, a as P, D as s, F as a, b as f, p as l, c as m, f as x, d as $, i as y } from "./Diagram-8b41118e.js";
2
+ function D(t) {
3
+ if (!t.length)
4
+ throw new Error("No segments to close");
5
+ const n = t[0], e = t.at(-1);
6
+ return P(n.firstPoint, e.lastPoint) ? t : [
7
+ ...t,
8
+ new g(e.lastPoint, n.firstPoint)
9
+ ];
10
+ }
11
+ function h(t) {
12
+ return new s([new a(new f(t))]);
13
+ }
14
+ class k {
15
+ constructor(n = [0, 0]) {
16
+ this.pointer = n, this.firstPoint = n, this.pendingSegments = [];
17
+ }
18
+ movePointerTo(n) {
19
+ if (this.pendingSegments.length)
20
+ throw new Error(
21
+ "You can only move the pointer if there is no segment defined"
22
+ );
23
+ return this.pointer = n, this.firstPoint = n, this;
24
+ }
25
+ saveSegment(n) {
26
+ return this.pendingSegments.push(n), this;
27
+ }
28
+ lineTo(n) {
29
+ const e = new g(this.pointer, n);
30
+ return this.pointer = n, this.saveSegment(e);
31
+ }
32
+ line(n, e) {
33
+ return this.lineTo([this.pointer[0] + n, this.pointer[1] + e]);
34
+ }
35
+ vLine(n) {
36
+ return this.line(0, n);
37
+ }
38
+ hLine(n) {
39
+ return this.line(n, 0);
40
+ }
41
+ vLineTo(n) {
42
+ return this.lineTo([this.pointer[0], n]);
43
+ }
44
+ hLineTo(n) {
45
+ return this.lineTo([n, this.pointer[1]]);
46
+ }
47
+ polarLineTo([n, e]) {
48
+ const r = e * m, i = l(n, r);
49
+ return this.lineTo(i);
50
+ }
51
+ polarLine(n, e) {
52
+ const r = e * m, [i, u] = l(n, r);
53
+ return this.line(i, u);
54
+ }
55
+ tangentLine(n) {
56
+ const e = this.pendingSegments.at(-1);
57
+ if (!e)
58
+ throw new Error("You need a previous segment to sketch a tangent line");
59
+ const [r, i] = e.tangentAtLastPoint;
60
+ return this.line(r * n, i * n);
61
+ }
62
+ close() {
63
+ const n = D(this.pendingSegments);
64
+ return h(n);
65
+ }
66
+ closeWithMirror() {
67
+ if (!this.pendingSegments.length)
68
+ throw new Error("No segments to close");
69
+ const n = this.pendingSegments[0], e = this.pendingSegments.at(-1), r = L(
70
+ e.lastPoint,
71
+ n.firstPoint
72
+ ), i = new T().mirrorLine(
73
+ r,
74
+ n.firstPoint
75
+ ), u = this.pendingSegments.map(
76
+ (o) => o.transform(i).reverse()
77
+ );
78
+ return u.reverse(), h([
79
+ ...this.pendingSegments,
80
+ ...u
81
+ ]);
82
+ }
83
+ }
84
+ function A(t = [0, 0]) {
85
+ return new k(t);
86
+ }
87
+ function c(t) {
88
+ if (t instanceof a)
89
+ return [t];
90
+ if (t instanceof f)
91
+ return [new a(t)];
92
+ if (t instanceof s)
93
+ return t.figures;
94
+ throw new Error("Unknown shape");
95
+ }
96
+ function E(t, n) {
97
+ return new s(
98
+ x(c(t), c(n))
99
+ );
100
+ }
101
+ function B(t) {
102
+ return t.reduce(
103
+ (n, e) => E(n, e),
104
+ new s()
105
+ );
106
+ }
107
+ function M(t, n) {
108
+ return new s(
109
+ $(c(t), c(n))
110
+ );
111
+ }
112
+ function G(t, n) {
113
+ return new s(
114
+ y(c(t), c(n))
115
+ );
116
+ }
117
+ function F(t) {
118
+ if (t instanceof g)
119
+ return `L ${t.lastPoint.join(" ")}`;
120
+ throw new Error("Unknown segment type");
121
+ }
122
+ function d(t) {
123
+ const n = `M ${t.firstPoint.join(" ")}`, e = t.segments.map(F).join(" ");
124
+ return `${n} ${e} Z`;
125
+ }
126
+ function v(t) {
127
+ return `<path d="${t.allLoops.map(d).join(" ")}" />`;
128
+ }
129
+ function b(t) {
130
+ return `<g>
131
+ ${t.figures.map(v).join(`
132
+ `)}
133
+ </g>`;
134
+ }
135
+ function j(t, n = 1) {
136
+ const e = t.xMin - n, r = t.yMin - n;
137
+ return `${e} ${r} ${t.width + 2 * n} ${t.height + 2 * n}`;
138
+ }
139
+ function w(t, n, e = 1) {
140
+ return `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
141
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="${j(n, e)}" fill="none" stroke="black" stroke-width="0.2%" vector-effect="non-scaling-stroke">
142
+ ${t}
143
+ </svg>`;
144
+ }
145
+ function p(t) {
146
+ if (t instanceof s)
147
+ return b(t);
148
+ if (t instanceof a)
149
+ return v(t);
150
+ if (t instanceof f)
151
+ return `<path d="${d(t)}" />`;
152
+ throw new Error("Unknown shape type");
153
+ }
154
+ function U(t, n = 1) {
155
+ if (Array.isArray(t)) {
156
+ const r = t.map((o) => o.mirror()), i = r.map((o) => p(o)).join(`
157
+ `), u = r.slice(1).reduce((o, S) => o.merge(S.boundingBox), r[0].boundingBox);
158
+ return w(i, u);
159
+ }
160
+ const e = t.mirror();
161
+ return w(p(e), e.boundingBox, n);
162
+ }
163
+ export {
164
+ M as cut,
165
+ A as draw,
166
+ U as exportSVG,
167
+ E as fuse,
168
+ B as fuseAll,
169
+ G as intersect,
170
+ p as svgBody
171
+ };
172
+ //# sourceMappingURL=pantograph.js.map
@@ -0,0 +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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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "pantograph2d",
3
+ "version": "0.1.0",
4
+ "description": "Pantograph, the pure JS 2D CAD library",
5
+ "type": "module",
6
+ "main": "./dist/pantograph.cjs",
7
+ "module": "./dist/pantograph.js",
8
+ "types": "./dist/pantograph.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/pantograph.js",
15
+ "require": "./dist/pantograph.cjs"
16
+ },
17
+ "./models": {
18
+ "import": "./dist/pantograph/models.js",
19
+ "require": "./dist/pantograph/models.cjs"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "start": "vite",
24
+ "build": "vite build",
25
+ "test": "vitest"
26
+ },
27
+ "keywords": [
28
+ "2d",
29
+ "graphics",
30
+ "cad",
31
+ "svg"
32
+ ],
33
+ "author": "Steve Genoud",
34
+ "license": "AGPL",
35
+ "devDependencies": {
36
+ "@types/node": "^18.15.5",
37
+ "@typescript-eslint/eslint-plugin": "^5.55.0",
38
+ "@typescript-eslint/parser": "^5.55.0",
39
+ "eslint": "^8.36.0",
40
+ "prettier": "^2.8.4",
41
+ "terminal-image": "^2.0.0",
42
+ "typescript": "^5.0.2",
43
+ "vite": "^4.1.4",
44
+ "vite-plugin-dts": "^2.2.0",
45
+ "vitest": "^0.29.2"
46
+ },
47
+ "gitHead": "a2b9db5c938cdbd7452e96175b403fac8f4caf5b"
48
+ }