pantograph2d 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{exportJSON-26bb92ef.js → Diagram-1c56996e.js} +544 -515
- package/dist/Diagram-1c56996e.js.map +1 -0
- package/dist/Diagram-4fa55d2b.cjs +4 -0
- package/dist/Diagram-4fa55d2b.cjs.map +1 -0
- package/dist/draw-44dd36a9.js +256 -0
- package/dist/draw-44dd36a9.js.map +1 -0
- package/dist/draw-8c69c65f.cjs +2 -0
- package/dist/draw-8c69c65f.cjs.map +1 -0
- package/dist/drawShape.d.ts +153 -0
- package/dist/models.d.ts +7 -1
- package/dist/pantograph/drawShape.cjs +2 -0
- package/dist/pantograph/drawShape.cjs.map +1 -0
- package/dist/pantograph/drawShape.d.ts +1 -0
- package/dist/pantograph/drawShape.js +24 -0
- package/dist/pantograph/drawShape.js.map +1 -0
- package/dist/pantograph/models.cjs +1 -1
- package/dist/pantograph/models.js +7 -6
- package/dist/pantograph.cjs +5 -5
- package/dist/pantograph.cjs.map +1 -1
- package/dist/pantograph.d.ts +13 -2
- package/dist/pantograph.js +292 -449
- package/dist/pantograph.js.map +1 -1
- package/package.json +6 -2
- package/dist/exportJSON-26bb92ef.js.map +0 -1
- package/dist/exportJSON-3b325312.cjs +0 -4
- package/dist/exportJSON-3b325312.cjs.map +0 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { A as s,
|
|
1
|
+
import { A as s, B as o, D as n, F as i, m, L as e, S as t, w as f, T as g } from "../Diagram-1c56996e.js";
|
|
2
2
|
export {
|
|
3
3
|
s as Arc,
|
|
4
4
|
o as BoundingBox,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
n as Diagram,
|
|
6
|
+
i as Figure,
|
|
7
|
+
m as Line,
|
|
8
8
|
e as Loop,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
t as Strand,
|
|
10
|
+
f as Transformable,
|
|
11
|
+
g as TransformationMatrix
|
|
11
12
|
};
|
|
12
13
|
//# sourceMappingURL=models.js.map
|
package/dist/pantograph.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./exportJSON-3b325312.cjs");class A{constructor(n,r){this.firstPoint=n,this.lastPoint=r}}function D(t,n){if(t instanceof e.Line)return Z(t,n);if(t instanceof e.Arc)return H(t,n);throw new Error("Not implemented")}function Z(t,n){const{firstPoint:r,lastPoint:i}=t,s=t.normalVector;return new e.Line(e.add(r,e.scalarMultiply(s,n)),e.add(i,e.scalarMultiply(s,n)))}function H(t,n){const r=e.add(t.firstPoint,e.scalarMultiply(e.perpendicular(t.tangentAtFirstPoint),n)),i=e.add(t.lastPoint,e.scalarMultiply(e.perpendicular(t.tangentAtLastPoint),n)),s=n*(t.clockwise?1:-1);return t.radius+s<t.precision?new A(r,i):new e.Arc(r,i,t.center,t.clockwise)}function _(t,n,r){const i=e.crossProduct(t.tangentAtLastPoint,n.tangentAtFirstPoint);if(Math.abs(i)<1e-10)return null;const s=i>0?1:-1,o=Math.abs(r)*s,a=D(t,o),l=D(n,o);if(a instanceof A||l instanceof A)return null;let f;try{f=e.findIntersections(a,l,1e-9).at(-1)}catch{return null}if(!f)return null;const p=f,c=(P,S)=>{const m=S.tangentAt(p),d=e.perpendicularClockwise(m),h=e.add(p,e.scalarMultiply(d,o));return P.splitAt(h)},[u]=c(t,a),[,g]=c(n,l);return{first:u,second:g,center:p}}function E(t,n,r){const i=_(t,n,r);if(!i)return console.warn("Cannot fillet between segments",t.repr,n.repr),[t,n];const{first:s,second:o}=i;return[s,e.tangentArc(s.lastPoint,o.firstPoint,s.tangentAtLastPoint),o]}function $(t,n,r){const i=_(t,n,r);if(!i)return console.warn("Cannot chamfer between segments",t.repr,n.repr),[t,n];const{first:s,second:o}=i;return[s,new e.Line(s.lastPoint,o.firstPoint),o]}function x(t){return new e.Diagram([new e.Figure(new e.Loop(t))])}class K{constructor(n=[0,0]){this.pointer=n,this.firstPoint=n,this.pendingSegments=[],this._nextCorner=null}movePointerTo(n){if(this.pendingSegments.length)throw new Error("You can only move the pointer if there is no segment defined");return this.pointer=n,this.firstPoint=n,this}saveSegment(n){if(e.sameVector(n.firstPoint,n.lastPoint))throw new Error(`Segment has no length, ${n.repr}`);if(!this._nextCorner)return this.pendingSegments.push(n),this;const r=this.pendingSegments.pop();if(!r)throw new Error("bug in the custom corner algorithm");const i=this._nextCorner.mode==="chamfer"?$:E;return this.pendingSegments.push(...i(r,n,this._nextCorner.radius)),this._nextCorner=null,this}lineTo(n){const r=new e.Line(this.pointer,n);return this.pointer=n,this.saveSegment(r)}line(n,r){return this.lineTo([this.pointer[0]+n,this.pointer[1]+r])}vLine(n){return this.line(0,n)}hLine(n){return this.line(n,0)}vLineTo(n){return this.lineTo([this.pointer[0],n])}hLineTo(n){return this.lineTo([n,this.pointer[1]])}polarLineTo([n,r]){const i=r*e.DEG2RAD,s=e.polarToCartesian(n,i);return this.lineTo(s)}polarLine(n,r){const i=r*e.DEG2RAD,[s,o]=e.polarToCartesian(n,i);return this.line(s,o)}tangentLine(n){const r=this.pendingSegments.at(-1);if(!r)throw new Error("You need a previous segment to sketch a tangent line");const[i,s]=r.tangentAtLastPoint;return this.line(i*n,s*n)}threePointsArcTo(n,r){return this.saveSegment(e.threePointsArc(this.pointer,r,n)),this.pointer=n,this}threePointsArc(n,r,i,s){const[o,a]=this.pointer;return this.threePointsArcTo([o+n,a+r],[o+i,a+s])}sagittaArcTo(n,r){if(!r)return this.lineTo(n);const i=new e.Line(this.pointer,n),s=e.perpendicular(i.tangentAtFirstPoint),o=e.add(i.midPoint,e.scalarMultiply(s,r));return this.threePointsArcTo(n,o)}sagittaArc(n,r,i){return this.sagittaArcTo([n+this.pointer[0],r+this.pointer[1]],i)}vSagittaArc(n,r){return this.sagittaArc(0,n,r)}hSagittaArc(n,r){return this.sagittaArc(n,0,r)}bulgeArcTo(n,r){if(!r)return this.lineTo(n);const i=e.distance(this.pointer,n)/2,s=-r*i;return this.sagittaArcTo(n,s)}bulgeArc(n,r,i){return this.bulgeArcTo([n+this.pointer[0],r+this.pointer[1]],i)}vBulgeArc(n,r){return this.bulgeArc(0,n,r)}hBulgeArc(n,r){return this.bulgeArc(n,0,r)}tangentArcTo(n){const r=this.pendingSegments.at(-1);if(!r)throw new Error("You need a previous curve to sketch a tangent arc");return this.saveSegment(e.tangentArc(this.pointer,n,r.tangentAtLastPoint)),this.pointer=n,this}tangentArc(n,r){const[i,s]=this.pointer;return this.tangentArcTo([n+i,r+s])}customCorner(n,r="fillet"){if(!this.pendingSegments.length)throw new Error("You need a segment defined to fillet the angle");return this._nextCorner={mode:r,radius:n},this}_customCornerLastWithFirst(n,r="fillet"){if(!n)return;const i=this.pendingSegments.pop(),s=this.pendingSegments.shift();if(!i||!s)throw new Error("Not enough curves to close and fillet");const o=r==="chamfer"?$:E;this.pendingSegments.push(...o(i,s,n))}close(){if(!this.pendingSegments.length)throw new Error("No segments to close");const n=this.pendingSegments[0],r=this.pendingSegments.at(-1);return e.sameVector(n.firstPoint,r.lastPoint)||this.lineTo(n.firstPoint),this._nextCorner!==null&&(this._customCornerLastWithFirst(this._nextCorner.radius,this._nextCorner.mode),this._nextCorner=null),x(this.pendingSegments)}closeWithMirror(){if(!this.pendingSegments.length)throw new Error("No segments to close");const n=this.pendingSegments[0],r=this.pendingSegments.at(-1),i=e.subtract(r.lastPoint,n.firstPoint),s=new e.TransformationMatrix().mirrorLine(i,n.firstPoint),o=this.pendingSegments.map(a=>a.transform(s).reverse());return o.reverse(),x([...this.pendingSegments,...o])}}function Q(t=[0,0]){return new K(t)}function w(t){if(t instanceof e.Figure)return[t];if(t instanceof e.Loop)return[new e.Figure(t)];if(t instanceof e.Diagram)return t.figures;throw new Error("Unknown shape")}function B(t,n){return new e.Diagram(e.fuseFiguresLists(w(t),w(n)))}function M(t){return t.reduce((n,r)=>B(n,r),new e.Diagram)}function U(t,n){return new e.Diagram(e.cutFiguresLists(w(t),w(n)))}function j(t,n){return new e.Diagram(e.intersectFiguresLists(w(t),w(n)))}function O(t){return t<0?"before":t>1?"after":"between"}const I=(t,n,r)=>{if(r==="before")return t.distanceFrom(n.firstPoint);if(r==="after")return t.distanceFrom(n.lastPoint);throw new Error("Invalid position")};function tt(t,n){const r=e.lineLineParams(t,n);if(r==="parallel")return Math.min(t.distanceFrom(n.firstPoint),t.distanceFrom(n.lastPoint));const{intersectionParam1:i,intersectionParam2:s}=r,o=O(i),a=O(s);if(o==="between"&&a==="between")return 0;if(o==="between"&&a!=="between")return I(t,n,a);if(a==="between"&&o!=="between")return I(n,t,o);if(o==="before"&&a==="before")return e.distance(t.firstPoint,n.firstPoint);if(o==="after"&&a==="after")return e.distance(t.lastPoint,n.lastPoint);if(o==="before"&&a==="after")return e.distance(t.firstPoint,n.lastPoint);if(o==="after"&&a==="before")return e.distance(t.lastPoint,n.firstPoint);throw new Error("Invalid position")}function k(t,n){if(e.lineArcIntersection(t,n).length>0)return 0;const r=e.projectPointOnLine(t,n.center);if(t.isOnSegment(r)){const i=e.distance(r,n.center);if(Math.abs(i-n.radius)<t.precision&&n.isOnSegment(r))return 0;if(i-n.radius>t.precision){const s=e.normalize(e.subtract(r,n.center)),o=e.add(n.center,e.scalarMultiply(s,n.radius));if(n.isOnSegment(o))return e.distance(o,r)}}return Math.min(n.distanceFrom(t.firstPoint),n.distanceFrom(t.lastPoint),t.distanceFrom(n.firstPoint),t.distanceFrom(n.lastPoint))}const nt=(t,n)=>{const r=t.angleToParam(n.firstAngle);if(t.isValidParameter(r))return!0;const i=t.angleToParam(n.lastAngle);return!!t.isValidParameter(i)};function et(t,n){if(e.arcArcIntersection(t,n,!0).length>0)return 0;const r=e.distance(t.center,n.center);if(r<t.precision&&nt(t,n))return Math.abs(t.radius-n.radius);const i=e.normalize(e.subtract(n.center,t.center)),s=r-Math.abs(t.radius-n.radius)<t.precision;let o=e.polarAngle(i);s&&n.radius>t.radius&&(o+=Math.PI);const a=s?o:o+Math.PI,l=t.angleToParam(o),f=n.angleToParam(a);return t.isValidParameter(l)&&n.isValidParameter(f)?e.distance(t.paramPoint(l),n.paramPoint(f)):Math.min(t.distanceFrom(n.firstPoint),t.distanceFrom(n.lastPoint),n.distanceFrom(t.firstPoint),n.distanceFrom(t.lastPoint))}function rt(t,n){if(t instanceof e.Line&&n instanceof e.Line)return tt(t,n);if(t instanceof e.Line&&n instanceof e.Arc)return k(t,n);if(t instanceof e.Arc&&n instanceof e.Line)return k(n,t);if(t instanceof e.Arc&&n instanceof e.Arc)return et(t,n);throw new Error("Not implemented")}const C=1e-8;function it(t,n){const r=t.map(f=>({offset:D(f,n),original:f})),i=[];let s=null,o=r.at(-1);if(!o)return[];if(i.length===1)return i;const a=f=>{s?f.offset instanceof A?e.sameVector(f.offset.firstPoint,f.offset.lastPoint)||i.push(new e.Line(f.offset.firstPoint,f.offset.lastPoint)):i.push(f.offset):s=f},l=function*(){for(const f of r.slice(0,-1))yield f;if(!s)throw new Error("Bug in the offset algorithm");yield s};for(const f of l()){const p=o.offset.lastPoint,c=f.offset.firstPoint;if(e.sameVector(p,c)){a(o),o=f;continue}let u=[];if(!(o.offset instanceof A)&&!(f.offset instanceof A)){const{intersections:m,overlaps:d}=e.findIntersectionsAndOverlaps(o.offset,f.offset,C/100);u=[...m,...d.flatMap(h=>[h.firstPoint,h.lastPoint])]}if(u.length>0){let m=u[0];if(u.length>1){const v=o==null?void 0:o.original.lastPoint,L=u.map(X=>e.squareDistance(X,v));m=u[L.indexOf(Math.min(...L))]}const d=o.offset.splitAt([m])[0],h=f.offset.splitAt([m]).at(-1);if(!h)throw new Error("Bug in the splitting algo in offset");a({offset:d,original:o.original}),o={offset:h,original:f.original};continue}const g=o.original.lastPoint,P=e.crossProduct(e.subtract(c,g),e.subtract(p,g))>0,S=new e.Arc(p,c,g,P);a(o),i.push(S),o=f}return a(o),i}function V(t,n){const r=t.clockwise?n:-n,i=it(t.segments,r);if(i.length<2)return new e.Diagram;const s=new Map,o=(c,u)=>{const g=s.get(c)||[];s.set(c,[...g,...u])};if(i.forEach((c,u)=>{i.slice(u+1).forEach((g,P)=>{const{intersections:S,overlaps:m}=e.findIntersectionsAndOverlaps(c,g,C),d=[...S,...m.flatMap(h=>[h.firstPoint,h.lastPoint])].filter(h=>{const v=e.sameVector(h,c.firstPoint)||e.sameVector(h,c.lastPoint),L=e.sameVector(h,g.firstPoint)||e.sameVector(h,g.lastPoint);return!(v&&L)});d.length&&(o(u,d),o(P+u+1,d))})}),!s.size){const c=new e.Loop(i);return new e.Diagram([new e.Figure(c)])}const l=i.flatMap((c,u)=>{if(!s.has(u))return c;const g=s.get(u)||[];return c.splitAt(g)}).filter(c=>!t.segments.some(g=>rt(g,c)<Math.abs(n)-C));if(!l.length)return new e.Diagram;const p=e.stitchSegments(l).filter(c=>c.length>1).filter(c=>e.sameVector(c[0].firstPoint,c.at(-1).lastPoint)).map(c=>new e.Loop(c));return p.length?new e.Diagram(p.map(c=>new e.Figure(c))):new e.Diagram}function ot(t,n){const r=t.map(i=>{const s=M(i.holes.map(o=>V(o,n)));return U(V(i.contour,n),s)});return M(r)}function st(t,n){return ot(w(t),n)}function y(t){if(t instanceof e.Line)return`L ${t.lastPoint.join(" ")}`;if(t instanceof e.Arc)return`A ${t.radius} ${t.radius} 0 ${t.angularLength>Math.PI?"1":"0"} ${t.clockwise?"0":"1"} ${t.lastPoint.join(" ")}`;throw new Error("Unknown segment type")}function J(t){const n=`M ${t.firstPoint.join(" ")}`,r=t.segments.map(y).join(" ");return`${n} ${r} Z`}function Y(t){return`<path d="${t.allLoops.map(J).join(" ")}" />`}function at(t){return`<g>
|
|
2
|
-
${t.figures.map(
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("./draw-8c69c65f.cjs"),e=require("./Diagram-4fa55d2b.cjs");function h(t){if(t instanceof e.Figure)return[t];if(t instanceof e.Loop)return[new e.Figure(t)];if(t instanceof e.Diagram)return t.figures;throw new Error("Unknown shape")}function U(t,n,r=1e-9){let o=[];const s=[],i=new Array(n.segments.length).fill(0).map(()=>[]);n.segments.forEach((l,f)=>{t.segments.forEach(m=>{const{intersections:a,overlaps:u}=e.findIntersectionsAndOverlaps(l,m,r);o.push(...a),i[f].push(...a),s.push(...u);const p=u.flatMap(d=>[d.firstPoint,d.lastPoint]);o.push(...p),i[f].push(...p)})}),o=e.removeDuplicatePoints(o,r);const c=e.zip([n.segments,i]).flatMap(([l,f])=>f.length?l.splitAt(f):[l]);return Array.from(e.strandsBetweenIntersections(c,o,s))}function b(t,n,r=!1){return U(n,t).filter(s=>{const i=s.segments[0].midPoint;return n.onStroke(i)?!r:!n.contains(i)})}function y(t,n,r=!1){return U(n,t).filter(s=>{const i=s.segments[0].midPoint;return n.onStroke(i)?!r:n.contains(i)})}function O(t,n,r=!1){const o=b(t,n.contour,r),s=n.holes.flatMap(i=>y(t,i,r));return[...o,...s]}function k(t,n,r=!1){let o=y(t,n.contour,r);return n.holes.forEach(s=>{o=o.flatMap(i=>b(i,s,r))}),o}function q(t,n){return new e.Diagram(e.fuseFiguresLists(h(t),h(n)))}function M(t){return t.reduce((n,r)=>q(n,r),new e.Diagram)}function z(t,n){return new e.Diagram(e.cutFiguresLists(h(t),h(n)))}function H(t,n){return new e.Diagram(e.intersectFiguresLists(h(t),h(n)))}function K(t,n,r=!0){if(n instanceof e.Loop)return b(t,n,r);if(n instanceof e.Figure)return O(t,n,r);let o=[t];return n.figures.forEach(s=>{o=o.flatMap(i=>O(i,s,r))}),o}function Q(t,n,r=!1){if(n instanceof e.Loop)return y(t,n,r);if(n instanceof e.Figure)return k(t,n,r);let o=[t];return n.figures.forEach(s=>{o=o.flatMap(i=>k(i,s,r))}),o}function V(t){return t<0?"before":t>1?"after":"between"}const C=(t,n,r)=>{if(r==="before")return t.distanceFrom(n.firstPoint);if(r==="after")return t.distanceFrom(n.lastPoint);throw new Error("Invalid position")};function _(t,n){const r=e.lineLineParams(t,n);if(r==="parallel")return Math.min(t.distanceFrom(n.firstPoint),t.distanceFrom(n.lastPoint));const{intersectionParam1:o,intersectionParam2:s}=r,i=V(o),c=V(s);if(i==="between"&&c==="between")return 0;if(i==="between"&&c!=="between")return C(t,n,c);if(c==="between"&&i!=="between")return C(n,t,i);if(i==="before"&&c==="before")return e.distance(t.firstPoint,n.firstPoint);if(i==="after"&&c==="after")return e.distance(t.lastPoint,n.lastPoint);if(i==="before"&&c==="after")return e.distance(t.firstPoint,n.lastPoint);if(i==="after"&&c==="before")return e.distance(t.lastPoint,n.firstPoint);throw new Error("Invalid position")}function G(t,n){if(e.lineArcIntersection(t,n).length>0)return 0;const r=e.projectPointOnLine(t,n.center);if(t.isOnSegment(r)){const o=e.distance(r,n.center);if(Math.abs(o-n.radius)<t.precision&&n.isOnSegment(r))return 0;if(o-n.radius>t.precision){const s=e.normalize(e.subtract(r,n.center)),i=e.add(n.center,e.scalarMultiply(s,n.radius));if(n.isOnSegment(i))return e.distance(i,r)}}return Math.min(n.distanceFrom(t.firstPoint),n.distanceFrom(t.lastPoint),t.distanceFrom(n.firstPoint),t.distanceFrom(n.lastPoint))}const j=(t,n)=>{const r=t.angleToParam(n.firstAngle);if(t.isValidParameter(r))return!0;const o=t.angleToParam(n.lastAngle);return!!t.isValidParameter(o)};function tt(t,n){if(e.arcArcIntersection(t,n,!0).length>0)return 0;const r=e.distance(t.center,n.center);if(r<t.precision&&j(t,n))return Math.abs(t.radius-n.radius);const o=e.normalize(e.subtract(n.center,t.center)),s=r-Math.abs(t.radius-n.radius)<t.precision;let i=e.polarAngle(o);s&&n.radius>t.radius&&(i+=Math.PI);const c=s?i:i+Math.PI,l=t.angleToParam(i),f=n.angleToParam(c);return t.isValidParameter(l)&&n.isValidParameter(f)?e.distance(t.paramPoint(l),n.paramPoint(f)):Math.min(t.distanceFrom(n.firstPoint),t.distanceFrom(n.lastPoint),n.distanceFrom(t.firstPoint),n.distanceFrom(t.lastPoint))}function nt(t,n){if(t instanceof e.Line&&n instanceof e.Line)return _(t,n);if(t instanceof e.Line&&n instanceof e.Arc)return G(t,n);if(t instanceof e.Arc&&n instanceof e.Line)return G(n,t);if(t instanceof e.Arc&&n instanceof e.Arc)return tt(t,n);throw new Error("Not implemented")}const F=1e-8;function et(t,n){const r=t.map(f=>({offset:S.offsetSegment(f,n),original:f})),o=[];let s=null,i=r.at(-1);if(!i)return[];if(o.length===1)return o;const c=f=>{s?f.offset instanceof S.DegenerateSegment?e.sameVector(f.offset.firstPoint,f.offset.lastPoint)||o.push(new e.Line(f.offset.firstPoint,f.offset.lastPoint)):o.push(f.offset):s=f},l=function*(){for(const f of r.slice(0,-1))yield f;if(!s)throw new Error("Bug in the offset algorithm");yield s};for(const f of l()){const m=i.offset.lastPoint,a=f.offset.firstPoint;if(e.sameVector(m,a)){c(i),i=f;continue}let u=[];if(!(i.offset instanceof S.DegenerateSegment)&&!(f.offset instanceof S.DegenerateSegment)){const{intersections:P,overlaps:w}=e.findIntersectionsAndOverlaps(i.offset,f.offset,F/100);u=[...P,...w.flatMap(g=>[g.firstPoint,g.lastPoint])]}if(u.length>0){let P=u[0];if(u.length>1){const D=i==null?void 0:i.original.lastPoint,A=u.map(Z=>e.squareDistance(Z,D));P=u[A.indexOf(Math.min(...A))]}const w=i.offset.splitAt([P])[0],g=f.offset.splitAt([P]).at(-1);if(!g)throw new Error("Bug in the splitting algo in offset");c({offset:w,original:i.original}),i={offset:g,original:f.original};continue}const p=i.original.lastPoint,d=e.crossProduct(e.subtract(a,p),e.subtract(m,p))>0,L=new e.Arc(m,a,p,d);c(i),o.push(L),i=f}return c(i),o}function T(t,n){const r=t.clockwise?n:-n,o=et(t.segments,r);if(o.length<2)return new e.Diagram;const s=new Map,i=(a,u)=>{const p=s.get(a)||[];s.set(a,[...p,...u])};if(o.forEach((a,u)=>{o.slice(u+1).forEach((p,d)=>{const{intersections:L,overlaps:P}=e.findIntersectionsAndOverlaps(a,p,F),w=[...L,...P.flatMap(g=>[g.firstPoint,g.lastPoint])].filter(g=>{const D=e.sameVector(g,a.firstPoint)||e.sameVector(g,a.lastPoint),A=e.sameVector(g,p.firstPoint)||e.sameVector(g,p.lastPoint);return!(D&&A)});w.length&&(i(u,w),i(d+u+1,w))})}),!s.size){const a=new e.Loop(o);return new e.Diagram([new e.Figure(a)])}const l=o.flatMap((a,u)=>{if(!s.has(u))return a;const p=s.get(u)||[];return a.splitAt(p)}).filter(a=>!t.segments.some(p=>nt(p,a)<Math.abs(n)-F));if(!l.length)return new e.Diagram;const m=e.stitchSegments(l).filter(a=>a.length>1).filter(a=>e.sameVector(a[0].firstPoint,a.at(-1).lastPoint)).map(a=>new e.Loop(a));return m.length?new e.Diagram(m.map(a=>new e.Figure(a))):new e.Diagram}function rt(t,n){const r=t.map(o=>{const s=M(o.holes.map(i=>T(i,n)));return z(T(o.contour,n),s)});return M(r)}function it(t,n){return rt(h(t),n)}function I(t){if(t instanceof e.Line)return`L ${t.lastPoint.join(" ")}`;if(t instanceof e.Arc)return`A ${t.radius} ${t.radius} 0 ${t.angularLength>Math.PI?"1":"0"} ${t.clockwise?"0":"1"} ${t.lastPoint.join(" ")}`;throw new Error("Unknown segment type")}function J(t){const n=`M ${t.firstPoint.join(" ")}`,r=t.segments.map(I).join(" ");return`${n} ${r} Z`}function B(t){return`<path d="${t.allLoops.map(J).join(" ")}" />`}function ot(t){return`<g>
|
|
2
|
+
${t.figures.map(B).join(`
|
|
3
3
|
`)}
|
|
4
|
-
</g>`}function
|
|
4
|
+
</g>`}function st(t){const n=`M ${t.firstPoint.join(" ")}`,r=t.segments.map(I).join(" ");return`${n} ${r}`}function ft(t,n=1){const r=t.xMin-n,o=t.yMin-n;return`${r} ${o} ${t.width+2*n} ${t.height+2*n}`}function x(t,n,r=1){return`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
5
5
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="${ft(n,r)}" fill="none" stroke="black" stroke-width="0.2%" vector-effect="non-scaling-stroke">
|
|
6
6
|
${t}
|
|
7
|
-
</svg>`}function
|
|
8
|
-
`),o
|
|
7
|
+
</svg>`}function v(t){if(t instanceof e.Diagram)return ot(t);if(t instanceof e.Figure)return B(t);if(t instanceof e.Loop)return`<path d="${J(t)}" />`;if(t instanceof e.Strand)return`<path d="${st(t)}" />`;if(t instanceof e.Arc||t instanceof e.Line)return`<path d="${`M ${t.firstPoint.join(" ")}`} ${I(t)}" />`;throw new Error("Unknown shape type")}const R=t=>"shape"in t?t.shape:t,N=(t,n)=>{if(!("shape"in t))return n;const{color:r}=t;return r?`<g stroke="${r}">${n}</g>`:n};function at(t,n=1){if(Array.isArray(t)){const o=t.map(c=>R(c).mirror()),s=o.map((c,l)=>N(t[l],v(c))).join(`
|
|
8
|
+
`),i=o.slice(1).reduce((c,l)=>c.merge(l.boundingBox),o[0].boundingBox);return x(s,i)}const r=R(t).mirror();return x(N(t,v(r)),r.boundingBox,n)}const W=t=>{if(t.type==="LINE")return new e.Line(t.firstPoint,t.lastPoint);if(t.type==="ARC")return new e.Arc(t.firstPoint,t.lastPoint,t.center,t.clockwise);throw new Error("Unknown segment type")},E=t=>{const n=t.segments.map(W);return new e.Loop(n)},X=t=>{const n=E(t.contour),r=t.holes.map(E);return new e.Figure(n,r)},ct=t=>{const n=t.figures.map(X);return new e.Diagram(n)};function ut(t){if(t.type==="DIAGRAM")return ct(t);if(t.type==="FIGURE")return X(t);if(t.type==="LOOP")return E(t);if(t.type==="LINE"||t.type==="ARC")return W(t);throw new Error("Unknown shape type")}const $=Math.PI/180,Y=180/Math.PI;function lt(t,n){const r=Math.cos(n*$)*t,o=Math.sin(n*$)*t;return[r,o]}function pt([t,n]){const r=Math.sqrt(t*t+n*n),o=Math.atan2(n,t)*Y;return[r,o]}exports.draw=S.draw;exports.exportJSON=e.exportJSON;exports.DEG2RAD=$;exports.RAD2DEG=Y;exports.cartesianToPolar=pt;exports.confineStrand=Q;exports.cut=z;exports.eraseStrand=K;exports.exportSVG=at;exports.fuse=q;exports.fuseAll=M;exports.importJSON=ut;exports.intersect=H;exports.offset=it;exports.polarToCartesian=lt;exports.svgBody=v;
|
|
9
9
|
//# sourceMappingURL=pantograph.cjs.map
|
package/dist/pantograph.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pantograph.cjs","sources":["../src/algorithms/offsets/offsetSegment.ts","../src/algorithms/filletSegments.ts","../src/draw.ts","../src/utils/listOfFigures.ts","../src/booleanOperations.ts","../src/algorithms/distances/lineLineDistance.ts","../src/algorithms/distances/lineArcDistance.ts","../src/algorithms/distances/arcArcDistance.ts","../src/algorithms/distances/index.ts","../src/algorithms/offsets/offsetLoop.ts","../src/algorithms/offsets/offsetFigure.ts","../src/offsetOperations.ts","../src/export/svg/svgSegment.ts","../src/export/svg/svgLoop.ts","../src/export/svg/svgFigure.ts","../src/export/svg/svgDiagram.ts","../src/export/svg/svgStrand.ts","../src/export/svg/wrapSVG.ts","../src/export/svg/exportSVG.ts","../src/import/json/importJSON.ts","../src/main.ts"],"sourcesContent":["import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport {\n add,\n normalize,\n perpendicular,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\nimport { Vector } from \"../../definitions\";\n\nexport class DegenerateSegment {\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector\n ) {}\n}\n\nexport function offsetSegment(\n segment: Segment,\n offset: number\n): Segment | DegenerateSegment {\n if (segment instanceof Line) {\n return offsetLine(segment, offset);\n }\n\n if (segment instanceof Arc) {\n return offsetArc(segment, offset);\n }\n\n throw new Error(\"Not implemented\");\n}\n\nexport function offsetLine(line: Line, offset: number): Line {\n const { firstPoint, lastPoint } = line;\n\n const normal = line.normalVector;\n return new Line(\n add(firstPoint, scalarMultiply(normal, offset)),\n add(lastPoint, scalarMultiply(normal, offset))\n );\n}\n\nexport function offsetArc(arc: Arc, offset: number): Arc | DegenerateSegment {\n const offsetStartPoint = add(\n arc.firstPoint,\n scalarMultiply(perpendicular(arc.tangentAtFirstPoint), offset)\n );\n const offsetEndPoint = add(\n arc.lastPoint,\n scalarMultiply(perpendicular(arc.tangentAtLastPoint), offset)\n );\n\n const orientedOffset = offset * (arc.clockwise ? 1 : -1);\n const newRadius = arc.radius + orientedOffset;\n if (newRadius < arc.precision) {\n return new DegenerateSegment(offsetStartPoint, offsetEndPoint);\n }\n\n return new Arc(offsetStartPoint, offsetEndPoint, arc.center, arc.clockwise);\n}\n","import { Vector } from \"../definitions\";\nimport { Line } from \"../models/segments/Line\";\nimport { tangentArc } from \"../models/segments/Arc\";\nimport type { Segment } from \"../models/segments/Segment\";\nimport {\n add,\n crossProduct,\n perpendicular,\n perpendicularClockwise,\n scalarMultiply,\n} from \"../vectorOperations\";\nimport { findIntersections } from \"./intersections\";\nimport { DegenerateSegment, offsetSegment } from \"./offsets/offsetSegment\";\nimport { exportJSON } from \"../main\";\n\nfunction removeCorner(\n firstSegment: Segment,\n secondSegment: Segment,\n radius: number\n) {\n const sinAngle = crossProduct(\n firstSegment.tangentAtLastPoint,\n secondSegment.tangentAtFirstPoint\n );\n\n // This cover the case when the segments are colinear\n if (Math.abs(sinAngle) < 1e-10) return null;\n\n const orientationCorrection = sinAngle > 0 ? 1 : -1;\n const offset = Math.abs(radius) * orientationCorrection;\n\n const firstOffset = offsetSegment(firstSegment, offset);\n const secondOffset = offsetSegment(secondSegment, offset);\n\n if (\n firstOffset instanceof DegenerateSegment ||\n secondOffset instanceof DegenerateSegment\n ) {\n return null;\n }\n\n let potentialCenter: Vector | undefined;\n try {\n const intersections = findIntersections(firstOffset, secondOffset, 1e-9);\n\n // We need to work on the case where there are more than one intersections\n potentialCenter = intersections.at(-1);\n } catch (e) {\n return null;\n }\n\n if (!potentialCenter) {\n return null;\n }\n const center = potentialCenter;\n\n const splitForFillet = (segment: Segment, offsetSegment: Segment) => {\n const tgt = offsetSegment.tangentAt(center);\n const normal = perpendicularClockwise(tgt);\n const splitPoint = add(center, scalarMultiply(normal, offset));\n return segment.splitAt(splitPoint);\n };\n\n const [first] = splitForFillet(firstSegment, firstOffset);\n const [, second] = splitForFillet(secondSegment, secondOffset);\n\n return { first, second, center };\n}\n\nexport function filletSegments(\n firstSegment: Segment,\n secondSegment: Segment,\n radius: number\n) {\n const cornerRemoved = removeCorner(firstSegment, secondSegment, radius);\n if (!cornerRemoved) {\n console.warn(\n \"Cannot fillet between segments\",\n firstSegment.repr,\n secondSegment.repr\n );\n return [firstSegment, secondSegment];\n }\n\n const { first, second } = cornerRemoved;\n\n return [\n first,\n tangentArc(first.lastPoint, second.firstPoint, first.tangentAtLastPoint),\n second,\n ];\n}\n\nexport function chamferSegments(\n firstSegment: Segment,\n secondSegment: Segment,\n radius: number\n) {\n const cornerRemoved = removeCorner(firstSegment, secondSegment, radius);\n if (!cornerRemoved) {\n console.warn(\n \"Cannot chamfer between segments\",\n firstSegment.repr,\n secondSegment.repr\n );\n return [firstSegment, secondSegment];\n }\n\n const { first, second } = cornerRemoved;\n\n return [first, new Line(first.lastPoint, second.firstPoint), second];\n}\n","import { chamferSegments, filletSegments } from \"./algorithms/filletSegments\";\nimport { Vector } from \"./definitions\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { tangentArc, threePointsArc } from \"./models/segments/Arc\";\nimport { Line } from \"./models/segments/Line\";\nimport { Segment } from \"./models/segments/Segment\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n perpendicular,\n add,\n scalarMultiply,\n distance,\n} from \"./vectorOperations\";\n\nfunction loopySegmentsToDiagram(segments: Segment[]) {\n // Here we will need to do our best to fix cases where the drawing is\n // broken in some way (i.e. self-intersecting loops)\n\n return new Diagram([new Figure(new Loop(segments))]);\n}\n\nexport class DrawingPen {\n protected pointer: Vector;\n protected firstPoint: Vector;\n protected pendingSegments: Segment[];\n\n protected _nextCorner: { radius: number; mode: \"fillet\" | \"chamfer\" } | null;\n\n constructor(origin: Vector = [0, 0]) {\n this.pointer = origin;\n this.firstPoint = origin;\n\n this.pendingSegments = [];\n this._nextCorner = null;\n }\n\n movePointerTo(point: Vector): this {\n if (this.pendingSegments.length)\n throw new Error(\n \"You can only move the pointer if there is no segment defined\"\n );\n\n this.pointer = point;\n this.firstPoint = point;\n return this;\n }\n\n protected saveSegment(segment: Segment) {\n if (sameVector(segment.firstPoint, segment.lastPoint)) {\n throw new Error(`Segment has no length, ${segment.repr}`);\n }\n\n if (!this._nextCorner) {\n this.pendingSegments.push(segment);\n return this;\n }\n\n const previousSegment = this.pendingSegments.pop();\n if (!previousSegment) throw new Error(\"bug in the custom corner algorithm\");\n\n const makeCorner =\n this._nextCorner.mode === \"chamfer\" ? chamferSegments : filletSegments;\n\n this.pendingSegments.push(\n ...makeCorner(previousSegment, segment, this._nextCorner.radius)\n );\n this._nextCorner = null;\n return this;\n }\n\n lineTo(point: Vector): this {\n const segment = new Line(this.pointer, point);\n this.pointer = point;\n return this.saveSegment(segment);\n }\n\n line(xDist: number, yDist: number): this {\n return this.lineTo([this.pointer[0] + xDist, this.pointer[1] + yDist]);\n }\n\n vLine(distance: number): this {\n return this.line(0, distance);\n }\n\n hLine(distance: number): this {\n return this.line(distance, 0);\n }\n\n vLineTo(yPos: number): this {\n return this.lineTo([this.pointer[0], yPos]);\n }\n\n hLineTo(xPos: number): this {\n return this.lineTo([xPos, this.pointer[1]]);\n }\n\n polarLineTo([r, theta]: Vector): this {\n const angleInRads = theta * DEG2RAD;\n const point = polarToCartesian(r, angleInRads);\n return this.lineTo(point);\n }\n\n polarLine(distance: number, angle: number): this {\n const angleInRads = angle * DEG2RAD;\n const [x, y] = polarToCartesian(distance, angleInRads);\n return this.line(x, y);\n }\n\n tangentLine(distance: number): this {\n const previousCurve = this.pendingSegments.at(-1);\n\n if (!previousCurve)\n throw new Error(\"You need a previous segment to sketch a tangent line\");\n\n const [xDir, yDir] = previousCurve.tangentAtLastPoint;\n return this.line(xDir * distance, yDir * distance);\n }\n\n threePointsArcTo(end: Vector, midPoint: Vector): this {\n this.saveSegment(threePointsArc(this.pointer, midPoint, end));\n this.pointer = end;\n return this;\n }\n\n threePointsArc(\n xDist: number,\n yDist: number,\n viaXDist: number,\n viaYDist: number\n ): this {\n const [x0, y0] = this.pointer;\n return this.threePointsArcTo(\n [x0 + xDist, y0 + yDist],\n [x0 + viaXDist, y0 + viaYDist]\n );\n }\n\n sagittaArcTo(end: Vector, sagitta: number): this {\n if (!sagitta) return this.lineTo(end);\n const chord = new Line(this.pointer, end);\n const norm = perpendicular(chord.tangentAtFirstPoint);\n\n const sagPoint: Vector = add(chord.midPoint, scalarMultiply(norm, sagitta));\n\n return this.threePointsArcTo(end, sagPoint);\n }\n\n sagittaArc(xDist: number, yDist: number, sagitta: number): this {\n return this.sagittaArcTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n sagitta\n );\n }\n\n vSagittaArc(distance: number, sagitta: number): this {\n return this.sagittaArc(0, distance, sagitta);\n }\n\n hSagittaArc(distance: number, sagitta: number): this {\n return this.sagittaArc(distance, 0, sagitta);\n }\n\n bulgeArcTo(end: Vector, bulge: number): this {\n if (!bulge) return this.lineTo(end);\n const halfChord = distance(this.pointer, end) / 2;\n const bulgeAsSagitta = -bulge * halfChord;\n\n return this.sagittaArcTo(end, bulgeAsSagitta);\n }\n\n bulgeArc(xDist: number, yDist: number, bulge: number): this {\n return this.bulgeArcTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n bulge\n );\n }\n\n vBulgeArc(distance: number, bulge: number): this {\n return this.bulgeArc(0, distance, bulge);\n }\n\n hBulgeArc(distance: number, bulge: number): this {\n return this.bulgeArc(distance, 0, bulge);\n }\n\n tangentArcTo(end: Vector): this {\n const previousCurve = this.pendingSegments.at(-1);\n\n if (!previousCurve)\n throw new Error(\"You need a previous curve to sketch a tangent arc\");\n\n this.saveSegment(\n tangentArc(this.pointer, end, previousCurve.tangentAtLastPoint)\n );\n\n this.pointer = end;\n return this;\n }\n\n tangentArc(xDist: number, yDist: number): this {\n const [x0, y0] = this.pointer;\n return this.tangentArcTo([xDist + x0, yDist + y0]);\n }\n\n customCorner(radius: number, mode: \"fillet\" | \"chamfer\" = \"fillet\") {\n if (!this.pendingSegments.length)\n throw new Error(\"You need a segment defined to fillet the angle\");\n\n this._nextCorner = { mode, radius };\n return this;\n }\n\n protected _customCornerLastWithFirst(\n radius: number,\n mode: \"fillet\" | \"chamfer\" = \"fillet\"\n ) {\n if (!radius) return;\n\n const lastSegment = this.pendingSegments.pop();\n const firstSegment = this.pendingSegments.shift();\n\n if (!lastSegment || !firstSegment)\n throw new Error(\"Not enough curves to close and fillet\");\n\n const makeCorner = mode === \"chamfer\" ? chamferSegments : filletSegments;\n\n this.pendingSegments.push(...makeCorner(lastSegment, firstSegment, radius));\n }\n\n close(): Diagram {\n if (!this.pendingSegments.length) throw new Error(\"No segments to close\");\n const firstSegment = this.pendingSegments[0];\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = this.pendingSegments.at(-1)!;\n\n if (!sameVector(firstSegment.firstPoint, lastSegment.lastPoint)) {\n this.lineTo(firstSegment.firstPoint);\n }\n\n if (this._nextCorner !== null) {\n this._customCornerLastWithFirst(\n this._nextCorner.radius,\n this._nextCorner.mode\n );\n this._nextCorner = null;\n }\n\n return loopySegmentsToDiagram(this.pendingSegments);\n }\n\n closeWithMirror(): Diagram {\n if (!this.pendingSegments.length) throw new Error(\"No segments to close\");\n\n const firstSegment = this.pendingSegments[0];\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const lastSegment = this.pendingSegments.at(-1)!;\n\n const mirrorVector = subtract(\n lastSegment.lastPoint,\n firstSegment.firstPoint\n );\n const mirrorTranform = new TransformationMatrix().mirrorLine(\n mirrorVector,\n firstSegment.firstPoint\n );\n\n const mirroredSegments = this.pendingSegments.map((segment) =>\n segment.transform(mirrorTranform).reverse()\n );\n mirroredSegments.reverse();\n\n return loopySegmentsToDiagram([\n ...this.pendingSegments,\n ...mirroredSegments,\n ]);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n","import { Diagram } from \"../models/Diagram\";\nimport { Figure } from \"../models/Figure\";\nimport { Loop } from \"../models/Loop\";\n\nexport function listOfFigures(shape: Diagram | Figure | Loop): Figure[] {\n if (shape instanceof Figure) {\n return [shape];\n } else if (shape instanceof Loop) {\n return [new Figure(shape)];\n } else if (shape instanceof Diagram) {\n return shape.figures;\n }\n throw new Error(\"Unknown shape\");\n}\n","import {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"./algorithms/boolean/figureBooleans\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\n\nexport function fuse(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop\n): Diagram {\n return new Diagram(\n fuseFiguresLists(listOfFigures(first), listOfFigures(second))\n );\n}\n\nexport function fuseAll(shapes: (Diagram | Figure | Loop)[]): Diagram {\n return shapes.reduce(\n (acc: Diagram, shape: Diagram | Figure | Loop) => fuse(acc, shape),\n new Diagram()\n );\n}\n\nexport function cut(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop\n): Diagram {\n return new Diagram(\n cutFiguresLists(listOfFigures(first), listOfFigures(second))\n );\n}\n\nexport function intersect(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop\n): Diagram {\n return new Diagram(\n intersectFiguresLists(listOfFigures(first), listOfFigures(second))\n );\n}\n","import { lineLineParams } from \"../intersections/lineLineIntersection\";\nimport type { Line } from \"../../models/segments/Line\";\nimport { distance } from \"../../vectorOperations\";\n\nfunction segmentPosition(intersectionParam: number) {\n if (intersectionParam < 0) return \"before\";\n if (intersectionParam > 1) return \"after\";\n return \"between\";\n}\n\nconst handleBetween = (\n lineBetween: Line,\n otherLine: Line,\n otherPosition: \"before\" | \"after\"\n) => {\n if (otherPosition === \"before\")\n return lineBetween.distanceFrom(otherLine.firstPoint);\n else if (otherPosition === \"after\")\n return lineBetween.distanceFrom(otherLine.lastPoint);\n else throw new Error(\"Invalid position\");\n};\n\nexport function lineLineDistance(line1: Line, line2: Line): number {\n const intersectionParams = lineLineParams(line1, line2);\n\n if (intersectionParams === \"parallel\") {\n return Math.min(\n line1.distanceFrom(line2.firstPoint),\n line1.distanceFrom(line2.lastPoint)\n );\n }\n\n const { intersectionParam1, intersectionParam2 } = intersectionParams;\n\n const firstPosition = segmentPosition(intersectionParam1);\n const secondPosition = segmentPosition(intersectionParam2);\n\n if (firstPosition === \"between\" && secondPosition === \"between\") {\n return 0;\n } else if (firstPosition === \"between\" && secondPosition !== \"between\") {\n return handleBetween(line1, line2, secondPosition);\n } else if (secondPosition === \"between\" && firstPosition !== \"between\") {\n return handleBetween(line2, line1, firstPosition);\n } else if (firstPosition === \"before\" && secondPosition === \"before\") {\n return distance(line1.firstPoint, line2.firstPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"after\") {\n return distance(line1.lastPoint, line2.lastPoint);\n } else if (firstPosition === \"before\" && secondPosition === \"after\") {\n return distance(line1.firstPoint, line2.lastPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"before\") {\n return distance(line1.lastPoint, line2.firstPoint);\n } else {\n throw new Error(\"Invalid position\");\n }\n}\n","import type { Line } from \"../../models/segments/Line\";\nimport type { Arc } from \"../../models/segments/Arc\";\nimport {\n normalize,\n subtract,\n distance,\n add,\n scalarMultiply,\n} from \"../../vectorOperations\";\nimport { projectPointOnLine } from \"../../utils/projectPointOnLine\";\nimport { lineArcIntersection } from \"../intersections/lineArcIntersection\";\n\nexport function lineArcDistance(line: Line, arc: Arc): number {\n // We might be able to optimise this if necessary\n\n if (lineArcIntersection(line, arc).length > 0) {\n return 0;\n }\n\n const closestPointOnLine = projectPointOnLine(line, arc.center);\n\n if (line.isOnSegment(closestPointOnLine)) {\n const circleCenterLineDistance = distance(closestPointOnLine, arc.center);\n\n // The line is tangent to the circle\n if (Math.abs(circleCenterLineDistance - arc.radius) < line.precision) {\n if (arc.isOnSegment(closestPointOnLine)) {\n return 0;\n }\n }\n\n if (circleCenterLineDistance - arc.radius > line.precision) {\n const centerLineDirection = normalize(\n subtract(closestPointOnLine, arc.center)\n );\n\n const closestPointOnCircle = add(\n arc.center,\n scalarMultiply(centerLineDirection, arc.radius)\n );\n\n if (arc.isOnSegment(closestPointOnCircle)) {\n return distance(closestPointOnCircle, closestPointOnLine);\n }\n }\n }\n\n return Math.min(\n arc.distanceFrom(line.firstPoint),\n arc.distanceFrom(line.lastPoint),\n line.distanceFrom(arc.firstPoint),\n line.distanceFrom(arc.lastPoint)\n );\n}\n","import {\n distance,\n normalize,\n polarAngle,\n subtract,\n} from \"../../vectorOperations\";\nimport type { Arc } from \"../../models/segments/Arc\";\nimport { arcArcIntersection } from \"../intersections/arcArcIntersection\";\n\nconst overlappingAngles = (arc1: Arc, arc2: Arc): boolean => {\n const p1 = arc1.angleToParam(arc2.firstAngle);\n if (arc1.isValidParameter(p1)) return true;\n\n const p2 = arc1.angleToParam(arc2.lastAngle);\n if (arc1.isValidParameter(p2)) return true;\n return false;\n};\n\nexport function arcArcDistance(arc1: Arc, arc2: Arc): number {\n if (arcArcIntersection(arc1, arc2, true).length > 0) return 0;\n\n const centersDistance = distance(arc1.center, arc2.center);\n\n if (centersDistance < arc1.precision) {\n if (overlappingAngles(arc1, arc2)) {\n return Math.abs(arc1.radius - arc2.radius);\n }\n }\n\n const centerCenterDirection = normalize(subtract(arc2.center, arc1.center));\n\n const containedCircles =\n centersDistance - Math.abs(arc1.radius - arc2.radius) < arc1.precision;\n\n let arc1ClosestPointAngle = polarAngle(centerCenterDirection);\n if (containedCircles && arc2.radius > arc1.radius) {\n arc1ClosestPointAngle += Math.PI;\n }\n const arc2ClosestPointAngle = containedCircles\n ? arc1ClosestPointAngle\n : arc1ClosestPointAngle + Math.PI;\n\n const p1 = arc1.angleToParam(arc1ClosestPointAngle);\n const p2 = arc2.angleToParam(arc2ClosestPointAngle);\n\n if (arc1.isValidParameter(p1) && arc2.isValidParameter(p2)) {\n // There might be some optimization here (with the center distance and radius differences)\n return distance(arc1.paramPoint(p1), arc2.paramPoint(p2));\n }\n\n return Math.min(\n arc1.distanceFrom(arc2.firstPoint),\n arc1.distanceFrom(arc2.lastPoint),\n arc2.distanceFrom(arc1.firstPoint),\n arc2.distanceFrom(arc1.lastPoint)\n );\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { lineLineDistance } from \"./lineLineDistance\";\nimport { lineArcDistance } from \"./lineArcDistance\";\nimport { arcArcDistance } from \"./arcArcDistance\";\nimport type { Segment } from \"../../models/segments/Segment\";\n\nexport function distance(segment1: Segment, segment2: Segment): number {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n return lineLineDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Line && segment2 instanceof Arc) {\n return lineArcDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Line) {\n return lineArcDistance(segment2, segment1);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Arc) {\n return arcArcDistance(segment1, segment2);\n }\n\n throw new Error(\"Not implemented\");\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Loop } from \"../../models/Loop\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport {\n crossProduct,\n sameVector,\n squareDistance,\n subtract,\n} from \"../../vectorOperations\";\nimport { distance } from \"../distances\";\nimport { offsetSegment, DegenerateSegment } from \"./offsetSegment\";\nimport { Vector } from \"../../definitions\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport { Figure } from \"../../models/Figure\";\nimport { stitchSegments } from \"../stitchSegments\";\n\nconst PRECISION = 1e-8;\n\nexport function rawOffsets(\n segmentsToOffset: Segment[],\n offset: number\n): Segment[] {\n const offsetSegments: OffsetSegmentPair[] = segmentsToOffset.map((c) => ({\n offset: offsetSegment(c, offset),\n original: c,\n }));\n\n // Ideally we would use the length of the segment to make sure it is\n // not only a point, but the algo we have access to are a bit to\n // convoluted to be usable here\n\n const offsettedArray: Segment[] = [];\n\n let savedLastSegment: null | OffsetSegmentPair = null;\n\n let previousSegment = offsetSegments.at(-1);\n\n // We have no offseted segments\n if (!previousSegment) return [];\n if (offsettedArray.length === 1) return offsettedArray;\n\n const appendSegment = (segment: OffsetSegmentPair) => {\n if (!savedLastSegment) {\n savedLastSegment = segment;\n } else if (!(segment.offset instanceof DegenerateSegment)) {\n offsettedArray.push(segment.offset);\n } else if (\n !sameVector(segment.offset.firstPoint, segment.offset.lastPoint)\n ) {\n offsettedArray.push(\n new Line(segment.offset.firstPoint, segment.offset.lastPoint)\n );\n }\n };\n const iterateOffsetSegments = function* (): Generator<OffsetSegmentPair> {\n for (const segment of offsetSegments.slice(0, -1)) {\n yield segment;\n }\n // This should never happen\n if (!savedLastSegment) throw new Error(\"Bug in the offset algorithm\");\n yield savedLastSegment;\n };\n\n for (const segment of iterateOffsetSegments()) {\n const previousLastPoint = previousSegment.offset.lastPoint;\n const firstPoint = segment.offset.firstPoint;\n\n // When the offset segments do still touch we do nothing\n if (sameVector(previousLastPoint, firstPoint)) {\n appendSegment(previousSegment);\n previousSegment = segment;\n continue;\n }\n\n let intersections: Vector[] = [];\n\n if (\n !(previousSegment.offset instanceof DegenerateSegment) &&\n !(segment.offset instanceof DegenerateSegment)\n ) {\n // When the offset segments intersect we cut them and save them at\n const { intersections: pointIntersections, overlaps } =\n findIntersectionsAndOverlaps(\n previousSegment.offset,\n segment.offset,\n PRECISION / 100\n );\n intersections = [\n ...pointIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ];\n }\n\n if (intersections.length > 0) {\n let intersection = intersections[0];\n if (intersections.length > 1) {\n // We choose the intersection point the closest to the end of the\n // original segment endpoint (why? not sure, following\n // https://github.com/jbuckmccready/cavalier_contours/)\n\n const originalEndpoint = previousSegment?.original.lastPoint;\n const distances = intersections.map((i) =>\n squareDistance(i, originalEndpoint)\n );\n intersection = intersections[distances.indexOf(Math.min(...distances))];\n }\n\n // We need to be a lot more careful here with multiple intersections\n // as well as cases where segments overlap\n\n const splitPreviousSegment = (previousSegment.offset as Segment).splitAt([\n intersection,\n ])[0];\n const splitSegment = (segment.offset as Segment)\n .splitAt([intersection])\n .at(-1);\n\n if (!splitSegment) throw new Error(\"Bug in the splitting algo in offset\");\n\n appendSegment({\n offset: splitPreviousSegment,\n original: previousSegment.original,\n });\n previousSegment = { offset: splitSegment, original: segment.original };\n continue;\n }\n\n // When the offset segments do not intersect we link them with an arc of\n // radius offset\n const center = previousSegment.original.lastPoint;\n const clockwise =\n crossProduct(\n subtract(firstPoint, center),\n subtract(previousLastPoint, center)\n ) > 0;\n\n const joiner = new Arc(previousLastPoint, firstPoint, center, clockwise);\n\n appendSegment(previousSegment);\n offsettedArray.push(joiner);\n previousSegment = segment;\n }\n\n appendSegment(previousSegment);\n return offsettedArray;\n}\n\ninterface OffsetSegmentPair {\n offset: Segment | DegenerateSegment;\n original: Segment;\n}\n\nexport function offsetLoop(loop: Loop, offset: number): Diagram {\n const correctedOffset = loop.clockwise ? offset : -offset;\n const offsettedArray = rawOffsets(loop.segments, correctedOffset);\n\n if (offsettedArray.length < 2) return new Diagram();\n\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections: Map<number, Vector[]> = new Map();\n const updateIntersections = (index: number, newPoints: Vector[]) => {\n const intersections = allIntersections.get(index) || [];\n allIntersections.set(index, [...intersections, ...newPoints]);\n };\n\n offsettedArray.forEach((firstSegment, firstIndex) => {\n offsettedArray\n .slice(firstIndex + 1)\n .forEach((secondSegment, secondIndex) => {\n const { intersections: rawIntersections, overlaps } =\n findIntersectionsAndOverlaps(firstSegment, secondSegment, PRECISION);\n\n const intersections = [\n ...rawIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ].filter((intersection) => {\n const onFirstSegmentExtremity =\n sameVector(intersection, firstSegment.firstPoint) ||\n sameVector(intersection, firstSegment.lastPoint);\n\n const onSecondSegmentExtremity =\n sameVector(intersection, secondSegment.firstPoint) ||\n sameVector(intersection, secondSegment.lastPoint);\n\n return !(onFirstSegmentExtremity && onSecondSegmentExtremity);\n });\n\n if (!intersections.length) return;\n\n updateIntersections(firstIndex, intersections);\n updateIntersections(secondIndex + firstIndex + 1, intersections);\n });\n });\n\n if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n\n /* this was in the replicad algorithm - not sure why\n if (!loop.intersects(offsettedLoop)) return offsettedLoop;\n return new Diagram();\n */\n }\n\n const splitSegments = offsettedArray.flatMap((segment, index) => {\n if (!allIntersections.has(index)) return segment;\n\n const intersections = allIntersections.get(index) || [];\n const splitSegments = segment.splitAt(intersections);\n return splitSegments;\n });\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = splitSegments.filter((segment) => {\n const closeSegment = loop.segments.some((c) => {\n return distance(c, segment) < Math.abs(offset) - PRECISION;\n });\n return !closeSegment;\n });\n\n if (!prunedSegments.length) return new Diagram();\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n const newLoops = segmentsGrouped\n .filter((c) => c.length > 1)\n .filter((c) => sameVector(c[0].firstPoint, c.at(-1)!.lastPoint))\n .map((c) => new Loop(c));\n\n if (!newLoops.length) return new Diagram();\n return new Diagram(newLoops.map((l) => new Figure(l)));\n}\n","import { Figure } from \"../../models/Figure\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { cut, fuseAll } from \"../../booleanOperations\";\nimport { offsetLoop } from \"./offsetLoop\";\n\nexport default function offsetFigures(\n figures: Figure[],\n offsetDistance: number\n): Diagram {\n const offsetFigures = figures.map((figure) => {\n const innerShape = fuseAll(\n figure.holes.map((l) => offsetLoop(l, offsetDistance))\n );\n return cut(offsetLoop(figure.contour, offsetDistance), innerShape);\n });\n\n return fuseAll(offsetFigures);\n}\n","import offsetFigures from \"./algorithms/offsets/offsetFigure\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\n\nexport function offset(\n shape: Diagram | Figure | Loop,\n offsetDistance: number\n): Diagram {\n return offsetFigures(listOfFigures(shape), offsetDistance);\n}\n","import { Arc } from \"../../models/segments/Arc\";\nimport { Line } from \"../../models/segments/Line\";\nimport { Segment } from \"../../models/segments/Segment\";\n\nexport function svgSegmentToPath(segment: Segment) {\n if (segment instanceof Line) {\n return `L ${segment.lastPoint.join(\" \")}`;\n }\n if (segment instanceof Arc) {\n return `A ${segment.radius} ${segment.radius} 0 ${\n segment.angularLength > Math.PI ? \"1\" : \"0\"\n } ${segment.clockwise ? \"0\" : \"1\"} ${segment.lastPoint.join(\" \")}`;\n }\n\n throw new Error(\"Unknown segment type\");\n}\n","import type { Loop } from \"../../models/Loop\";\nimport { svgSegmentToPath } from \"./svgSegment\";\n\nexport function svgLoop(loop: Loop) {\n const start = `M ${loop.firstPoint.join(\" \")}`;\n const segments = loop.segments.map(svgSegmentToPath).join(\" \");\n return `${start} ${segments} Z`;\n}\n","import type { Figure } from \"../../models/Figure\";\nimport { svgLoop } from \"./svgLoop\";\n\nexport function svgFigure(figure: Figure) {\n const path = figure.allLoops.map(svgLoop).join(\" \");\n return `<path d=\"${path}\" />`;\n}\n","import { Diagram } from \"../../models/Diagram\";\nimport { svgFigure } from \"./svgFigure\";\n\nexport function svgDiagram(diagram: Diagram) {\n return `<g>\n ${diagram.figures.map(svgFigure).join(\"\\n\")}\n</g>`;\n}\n","import type { Strand } from \"../../models/Strand\";\nimport { svgSegmentToPath } from \"./svgSegment\";\n\nexport function svgStrand(strand: Strand) {\n const start = `M ${strand.firstPoint.join(\" \")}`;\n const segments = strand.segments.map(svgSegmentToPath).join(\" \");\n return `${start} ${segments}`;\n}\n","import { BoundingBox } from \"../../models/BoundingBox\";\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 { Strand } from \"../../models/Strand\";\nimport { 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 { svgStrand } from \"./svgStrand\";\nimport { wrapSVG } from \"./wrapSVG\";\n\ntype Shape = Loop | Figure | Diagram | Arc | Line | Strand;\n\nexport function svgBody(shape: Shape) {\n if (shape instanceof Diagram) {\n return svgDiagram(shape);\n } else if (shape instanceof Figure) {\n return svgFigure(shape);\n } else if (shape instanceof Loop) {\n return `<path d=\"${svgLoop(shape)}\" />`;\n } else if (shape instanceof Strand) {\n return `<path d=\"${svgStrand(shape)}\" />`;\n } else if (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\ntype ConfiguredShape = Shape | { shape: Shape; color?: string };\n\nconst extractShape = (shape: ConfiguredShape) =>\n \"shape\" in shape ? shape.shape : shape;\n\nconst addConfig = (shape: ConfiguredShape, body: string) => {\n if (!(\"shape\" in shape)) return body;\n const { color } = shape;\n if (!color) return body;\n return `<g stroke=\"${color}\">${body}</g>`;\n};\n\nexport function exportSVG(\n shape: ConfiguredShape | ConfiguredShape[],\n margin = 1\n) {\n if (Array.isArray(shape)) {\n const flipped = shape.map((s) => extractShape(s).mirror());\n const body = flipped\n .map((s, i) => addConfig(shape[i], svgBody(s)))\n .join(\"\\n\");\n const bbox = flipped\n .slice(1)\n .reduce((bbox, s) => bbox.merge(s.boundingBox), flipped[0].boundingBox);\n\n return wrapSVG(body, bbox);\n }\n const flipped = extractShape(shape).mirror();\n return wrapSVG(\n addConfig(shape, svgBody(flipped)),\n flipped.boundingBox,\n margin\n );\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Loop } from \"../../models/Loop\";\nimport { Figure } from \"../../models/Figure\";\nimport { Diagram } from \"../../models/Diagram\";\n\nconst importSegment = (json: any) => {\n if (json.type === \"LINE\") {\n return new Line(json.firstPoint, json.lastPoint);\n }\n if (json.type === \"ARC\") {\n return new Arc(\n json.firstPoint,\n json.lastPoint,\n json.center,\n json.clockwise\n );\n }\n throw new Error(\"Unknown segment type\");\n};\n\nconst importLoop = (json: any) => {\n const segments = json.segments.map(importSegment);\n return new Loop(segments);\n};\n\nconst importFigure = (json: any) => {\n const contour = importLoop(json.contour);\n const holes = json.holes.map(importLoop);\n return new Figure(contour, holes);\n};\n\nconst importDiagram = (json: any) => {\n const figures = json.figures.map(importFigure);\n return new Diagram(figures);\n};\n\nexport function importJSON(json: any) {\n if (json.type === \"DIAGRAM\") {\n return importDiagram(json);\n }\n if (json.type === \"FIGURE\") {\n return importFigure(json);\n }\n if (json.type === \"LOOP\") {\n return importLoop(json);\n }\n if (json.type === \"LINE\" || json.type === \"ARC\") {\n return importSegment(json);\n }\n throw new Error(\"Unknown shape type\");\n}\n","import type { Vector } from \"./definitions\";\nexport { Vector };\n\nexport const DEG2RAD = Math.PI / 180;\nexport const RAD2DEG = 180 / Math.PI;\n\nexport function polarToCartesian(r: number, theta: number): Vector {\n const x = Math.cos(theta * DEG2RAD) * r;\n const y = Math.sin(theta * DEG2RAD) * r;\n return [x, y];\n}\n\nexport function cartesianToPolar([x, y]: Vector): [number, number] {\n const r = Math.sqrt(x * x + y * y);\n const theta = Math.atan2(y, x) * RAD2DEG;\n return [r, theta];\n}\n\nexport type {\n Diagram,\n Figure,\n Loop,\n Strand,\n Stroke,\n TransformationMatrix,\n BoundingBox,\n Segment,\n Line,\n Arc,\n} from \"./models/exports\";\n\nexport { draw } from \"./draw\";\nexport { fuse, fuseAll, cut, intersect, offset } from \"./operations\";\n\nexport { exportSVG, svgBody } from \"./export/svg/exportSVG\";\n\nexport { exportJSON } from \"./export/json/exportJSON\";\nexport { importJSON } from \"./import/json/importJSON\";\n"],"names":["DegenerateSegment","firstPoint","lastPoint","offsetSegment","segment","offset","Line","offsetLine","Arc","offsetArc","line","normal","add","scalarMultiply","arc","offsetStartPoint","perpendicular","offsetEndPoint","orientedOffset","removeCorner","firstSegment","secondSegment","radius","sinAngle","crossProduct","orientationCorrection","firstOffset","secondOffset","potentialCenter","findIntersections","center","splitForFillet","tgt","perpendicularClockwise","splitPoint","first","second","filletSegments","cornerRemoved","tangentArc","chamferSegments","loopySegmentsToDiagram","segments","Diagram","Figure","Loop","DrawingPen","origin","point","sameVector","previousSegment","makeCorner","xDist","yDist","distance","yPos","xPos","r","theta","angleInRads","DEG2RAD","polarToCartesian","angle","x","y","previousCurve","xDir","yDir","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","sagPoint","bulge","halfChord","bulgeAsSagitta","mode","lastSegment","mirrorVector","subtract","mirrorTranform","TransformationMatrix","mirroredSegments","draw","listOfFigures","shape","fuse","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","segmentPosition","intersectionParam","handleBetween","lineBetween","otherLine","otherPosition","lineLineDistance","line1","line2","intersectionParams","lineLineParams","intersectionParam1","intersectionParam2","firstPosition","secondPosition","lineArcDistance","lineArcIntersection","closestPointOnLine","projectPointOnLine","circleCenterLineDistance","centerLineDirection","normalize","closestPointOnCircle","overlappingAngles","arc1","arc2","p1","p2","arcArcDistance","arcArcIntersection","centersDistance","centerCenterDirection","containedCircles","arc1ClosestPointAngle","polarAngle","arc2ClosestPointAngle","segment1","segment2","PRECISION","rawOffsets","segmentsToOffset","offsetSegments","c","offsettedArray","savedLastSegment","appendSegment","iterateOffsetSegments","previousLastPoint","intersections","pointIntersections","overlaps","findIntersectionsAndOverlaps","intersection","originalEndpoint","distances","i","squareDistance","splitPreviousSegment","splitSegment","clockwise","joiner","offsetLoop","loop","correctedOffset","allIntersections","updateIntersections","index","newPoints","firstIndex","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","offsettedLoop","prunedSegments","splitSegments","newLoops","stitchSegments","l","offsetFigures","figures","offsetDistance","figure","innerShape","svgSegmentToPath","svgLoop","start","svgFigure","svgDiagram","diagram","svgStrand","strand","SVGViewbox","bbox","margin","minX","minY","wrapSVG","body","boundingBox","svgBody","Strand","extractShape","addConfig","color","exportSVG","flipped","s","importSegment","json","importLoop","importFigure","contour","holes","importDiagram","importJSON","RAD2DEG","cartesianToPolar"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pantograph.cjs","sources":["../src/utils/listOfFigures.ts","../src/algorithms/boolean/strandBoolean.ts","../src/booleanOperations.ts","../src/algorithms/distances/lineLineDistance.ts","../src/algorithms/distances/lineArcDistance.ts","../src/algorithms/distances/arcArcDistance.ts","../src/algorithms/distances/index.ts","../src/algorithms/offsets/offsetLoop.ts","../src/algorithms/offsets/offsetFigure.ts","../src/offsetOperations.ts","../src/export/svg/svgSegment.ts","../src/export/svg/svgLoop.ts","../src/export/svg/svgFigure.ts","../src/export/svg/svgDiagram.ts","../src/export/svg/svgStrand.ts","../src/export/svg/wrapSVG.ts","../src/export/svg/exportSVG.ts","../src/import/json/importJSON.ts","../src/main.ts"],"sourcesContent":["import { Diagram } from \"../models/Diagram\";\nimport { Figure } from \"../models/Figure\";\nimport { Loop } from \"../models/Loop\";\n\nexport function listOfFigures(shape: Diagram | Figure | Loop): Figure[] {\n if (shape instanceof Figure) {\n return [shape];\n } else if (shape instanceof Loop) {\n return [new Figure(shape)];\n } else if (shape instanceof Diagram) {\n return shape.figures;\n }\n throw new Error(\"Unknown shape\");\n}\n","import { Vector } from \"../../definitions\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport { Loop } from \"../../models/Loop\";\nimport { Strand } from \"../../models/Strand\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport removeDuplicatePoints from \"../../utils/removeDuplicatePoints\";\nimport zip from \"../../utils/zip\";\nimport { strandsBetweenIntersections } from \"./strandsBetweenIntersections\";\nimport { Figure } from \"../../main\";\n\nfunction strandLoopSections(\n loop: Loop,\n strand: Strand,\n precision = 1e-9\n): Strand[] {\n let allIntersections: Vector[] = [];\n const allCommonSegments: Segment[] = [];\n\n const splitPoints: Vector[][] = new Array(strand.segments.length)\n .fill(0)\n .map(() => []);\n\n strand.segments.forEach((strandSegment, strandIndex) => {\n loop.segments.forEach((loopSegment) => {\n const { intersections, overlaps } = findIntersectionsAndOverlaps(\n strandSegment,\n loopSegment,\n precision\n );\n\n allIntersections.push(...intersections);\n splitPoints[strandIndex].push(...intersections);\n\n allCommonSegments.push(...overlaps);\n const commonSegmentsPoints = overlaps.flatMap((s) => [\n s.firstPoint,\n s.lastPoint,\n ]);\n allIntersections.push(...commonSegmentsPoints);\n splitPoints[strandIndex].push(...commonSegmentsPoints);\n });\n });\n\n allIntersections = removeDuplicatePoints(allIntersections, precision);\n\n const strandSegments = zip([strand.segments, splitPoints] as [\n Segment[],\n Vector[][]\n ]).flatMap(([segment, intersections]: [Segment, Vector[]]): Segment[] => {\n if (!intersections.length) return [segment];\n return segment.splitAt(intersections);\n });\n\n return Array.from(\n strandsBetweenIntersections(\n strandSegments,\n allIntersections,\n allCommonSegments\n )\n );\n}\n\nexport function eraseStrandWithinLoop(\n strand: Strand,\n loop: Loop,\n eraseOnBorder = false\n) {\n const strands = strandLoopSections(loop, strand);\n\n // We keep only the strands that are outside the loop\n return strands.filter((strand) => {\n const strandCenter = strand.segments[0].midPoint;\n if (loop.onStroke(strandCenter)) return !eraseOnBorder;\n\n return !loop.contains(strandCenter);\n });\n}\n\nexport function eraseStrandOutsideLoop(\n strand: Strand,\n loop: Loop,\n eraseOnBorder = false\n) {\n const strands = strandLoopSections(loop, strand);\n\n // We keep only the strands that are outside the loop\n return strands.filter((strand) => {\n const strandCenter = strand.segments[0].midPoint;\n if (loop.onStroke(strandCenter)) return !eraseOnBorder;\n\n return loop.contains(strandCenter);\n });\n}\n\nexport function eraseStrandWithinFigure(\n strand: Strand,\n figure: Figure,\n eraseOnBorder = false\n) {\n const outsideStrands = eraseStrandWithinLoop(\n strand,\n figure.contour,\n eraseOnBorder\n );\n\n const inLoopStrand = figure.holes.flatMap((hole: Loop) =>\n eraseStrandOutsideLoop(strand, hole, eraseOnBorder)\n );\n\n return [...outsideStrands, ...inLoopStrand];\n}\n\nexport function eraseStrandOutsideFigure(\n strand: Strand,\n figure: Figure,\n eraseOnBorder = false\n) {\n let insideStrands = eraseStrandOutsideLoop(\n strand,\n figure.contour,\n eraseOnBorder\n );\n\n figure.holes.forEach((hole: Loop) => {\n insideStrands = insideStrands.flatMap((strand) =>\n eraseStrandWithinLoop(strand, hole, eraseOnBorder)\n );\n });\n\n return insideStrands;\n}\n","import {\n cutFiguresLists,\n fuseFiguresLists,\n intersectFiguresLists,\n} from \"./algorithms/boolean/figureBooleans\";\nimport { Strand } from \"./models/Strand\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\nimport {\n eraseStrandOutsideFigure,\n eraseStrandOutsideLoop,\n eraseStrandWithinFigure,\n eraseStrandWithinLoop,\n} from \"./algorithms/boolean/strandBoolean\";\n\nexport function fuse(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop\n): Diagram {\n return new Diagram(\n fuseFiguresLists(listOfFigures(first), listOfFigures(second))\n );\n}\n\nexport function fuseAll(shapes: (Diagram | Figure | Loop)[]): Diagram {\n return shapes.reduce(\n (acc: Diagram, shape: Diagram | Figure | Loop) => fuse(acc, shape),\n new Diagram()\n );\n}\n\nexport function cut(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop\n): Diagram {\n return new Diagram(\n cutFiguresLists(listOfFigures(first), listOfFigures(second))\n );\n}\n\nexport function intersect(\n first: Diagram | Figure | Loop,\n second: Diagram | Figure | Loop\n): Diagram {\n return new Diagram(\n intersectFiguresLists(listOfFigures(first), listOfFigures(second))\n );\n}\n\nexport function eraseStrand(\n strand: Strand,\n diagram: Diagram | Figure | Loop,\n eraseOnBorder = true\n): Strand[] {\n if (diagram instanceof Loop) {\n return eraseStrandWithinLoop(strand, diagram, eraseOnBorder);\n }\n\n if (diagram instanceof Figure) {\n return eraseStrandWithinFigure(strand, diagram, eraseOnBorder);\n }\n\n let outStrands: Strand[] = [strand];\n diagram.figures.forEach((figure: Figure) => {\n outStrands = outStrands.flatMap((strand: Strand) => {\n return eraseStrandWithinFigure(strand, figure, eraseOnBorder);\n });\n });\n\n return outStrands;\n}\n\nexport function confineStrand(\n strand: Strand,\n diagram: Diagram | Figure | Loop,\n eraseOnBorder = false\n): Strand[] {\n if (diagram instanceof Loop) {\n return eraseStrandOutsideLoop(strand, diagram, eraseOnBorder);\n }\n\n if (diagram instanceof Figure) {\n return eraseStrandOutsideFigure(strand, diagram, eraseOnBorder);\n }\n\n let outStrands: Strand[] = [strand];\n diagram.figures.forEach((figure: Figure) => {\n outStrands = outStrands.flatMap((strand: Strand) => {\n return eraseStrandOutsideFigure(strand, figure, eraseOnBorder);\n });\n });\n\n return outStrands;\n}\n","import { lineLineParams } from \"../intersections/lineLineIntersection\";\nimport type { Line } from \"../../models/segments/Line\";\nimport { distance } from \"../../vectorOperations\";\n\nfunction segmentPosition(intersectionParam: number) {\n if (intersectionParam < 0) return \"before\";\n if (intersectionParam > 1) return \"after\";\n return \"between\";\n}\n\nconst handleBetween = (\n lineBetween: Line,\n otherLine: Line,\n otherPosition: \"before\" | \"after\"\n) => {\n if (otherPosition === \"before\")\n return lineBetween.distanceFrom(otherLine.firstPoint);\n else if (otherPosition === \"after\")\n return lineBetween.distanceFrom(otherLine.lastPoint);\n else throw new Error(\"Invalid position\");\n};\n\nexport function lineLineDistance(line1: Line, line2: Line): number {\n const intersectionParams = lineLineParams(line1, line2);\n\n if (intersectionParams === \"parallel\") {\n return Math.min(\n line1.distanceFrom(line2.firstPoint),\n line1.distanceFrom(line2.lastPoint)\n );\n }\n\n const { intersectionParam1, intersectionParam2 } = intersectionParams;\n\n const firstPosition = segmentPosition(intersectionParam1);\n const secondPosition = segmentPosition(intersectionParam2);\n\n if (firstPosition === \"between\" && secondPosition === \"between\") {\n return 0;\n } else if (firstPosition === \"between\" && secondPosition !== \"between\") {\n return handleBetween(line1, line2, secondPosition);\n } else if (secondPosition === \"between\" && firstPosition !== \"between\") {\n return handleBetween(line2, line1, firstPosition);\n } else if (firstPosition === \"before\" && secondPosition === \"before\") {\n return distance(line1.firstPoint, line2.firstPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"after\") {\n return distance(line1.lastPoint, line2.lastPoint);\n } else if (firstPosition === \"before\" && secondPosition === \"after\") {\n return distance(line1.firstPoint, line2.lastPoint);\n } else if (firstPosition === \"after\" && secondPosition === \"before\") {\n return distance(line1.lastPoint, line2.firstPoint);\n } else {\n throw new Error(\"Invalid position\");\n }\n}\n","import type { Line } from \"../../models/segments/Line\";\nimport type { Arc } from \"../../models/segments/Arc\";\nimport {\n normalize,\n subtract,\n distance,\n add,\n scalarMultiply,\n} from \"../../vectorOperations\";\nimport { projectPointOnLine } from \"../../utils/projectPointOnLine\";\nimport { lineArcIntersection } from \"../intersections/lineArcIntersection\";\n\nexport function lineArcDistance(line: Line, arc: Arc): number {\n // We might be able to optimise this if necessary\n\n if (lineArcIntersection(line, arc).length > 0) {\n return 0;\n }\n\n const closestPointOnLine = projectPointOnLine(line, arc.center);\n\n if (line.isOnSegment(closestPointOnLine)) {\n const circleCenterLineDistance = distance(closestPointOnLine, arc.center);\n\n // The line is tangent to the circle\n if (Math.abs(circleCenterLineDistance - arc.radius) < line.precision) {\n if (arc.isOnSegment(closestPointOnLine)) {\n return 0;\n }\n }\n\n if (circleCenterLineDistance - arc.radius > line.precision) {\n const centerLineDirection = normalize(\n subtract(closestPointOnLine, arc.center)\n );\n\n const closestPointOnCircle = add(\n arc.center,\n scalarMultiply(centerLineDirection, arc.radius)\n );\n\n if (arc.isOnSegment(closestPointOnCircle)) {\n return distance(closestPointOnCircle, closestPointOnLine);\n }\n }\n }\n\n return Math.min(\n arc.distanceFrom(line.firstPoint),\n arc.distanceFrom(line.lastPoint),\n line.distanceFrom(arc.firstPoint),\n line.distanceFrom(arc.lastPoint)\n );\n}\n","import {\n distance,\n normalize,\n polarAngle,\n subtract,\n} from \"../../vectorOperations\";\nimport type { Arc } from \"../../models/segments/Arc\";\nimport { arcArcIntersection } from \"../intersections/arcArcIntersection\";\n\nconst overlappingAngles = (arc1: Arc, arc2: Arc): boolean => {\n const p1 = arc1.angleToParam(arc2.firstAngle);\n if (arc1.isValidParameter(p1)) return true;\n\n const p2 = arc1.angleToParam(arc2.lastAngle);\n if (arc1.isValidParameter(p2)) return true;\n return false;\n};\n\nexport function arcArcDistance(arc1: Arc, arc2: Arc): number {\n if (arcArcIntersection(arc1, arc2, true).length > 0) return 0;\n\n const centersDistance = distance(arc1.center, arc2.center);\n\n if (centersDistance < arc1.precision) {\n if (overlappingAngles(arc1, arc2)) {\n return Math.abs(arc1.radius - arc2.radius);\n }\n }\n\n const centerCenterDirection = normalize(subtract(arc2.center, arc1.center));\n\n const containedCircles =\n centersDistance - Math.abs(arc1.radius - arc2.radius) < arc1.precision;\n\n let arc1ClosestPointAngle = polarAngle(centerCenterDirection);\n if (containedCircles && arc2.radius > arc1.radius) {\n arc1ClosestPointAngle += Math.PI;\n }\n const arc2ClosestPointAngle = containedCircles\n ? arc1ClosestPointAngle\n : arc1ClosestPointAngle + Math.PI;\n\n const p1 = arc1.angleToParam(arc1ClosestPointAngle);\n const p2 = arc2.angleToParam(arc2ClosestPointAngle);\n\n if (arc1.isValidParameter(p1) && arc2.isValidParameter(p2)) {\n // There might be some optimization here (with the center distance and radius differences)\n return distance(arc1.paramPoint(p1), arc2.paramPoint(p2));\n }\n\n return Math.min(\n arc1.distanceFrom(arc2.firstPoint),\n arc1.distanceFrom(arc2.lastPoint),\n arc2.distanceFrom(arc1.firstPoint),\n arc2.distanceFrom(arc1.lastPoint)\n );\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { lineLineDistance } from \"./lineLineDistance\";\nimport { lineArcDistance } from \"./lineArcDistance\";\nimport { arcArcDistance } from \"./arcArcDistance\";\nimport type { Segment } from \"../../models/segments/Segment\";\n\nexport function distance(segment1: Segment, segment2: Segment): number {\n if (segment1 instanceof Line && segment2 instanceof Line) {\n return lineLineDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Line && segment2 instanceof Arc) {\n return lineArcDistance(segment1, segment2);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Line) {\n return lineArcDistance(segment2, segment1);\n }\n\n if (segment1 instanceof Arc && segment2 instanceof Arc) {\n return arcArcDistance(segment1, segment2);\n }\n\n throw new Error(\"Not implemented\");\n}\n","import { Line } from \"../../models/segments/Line\";\nimport { Loop } from \"../../models/Loop\";\nimport { Segment } from \"../../models/segments/Segment\";\nimport {\n crossProduct,\n sameVector,\n squareDistance,\n subtract,\n} from \"../../vectorOperations\";\nimport { distance } from \"../distances\";\nimport { offsetSegment, DegenerateSegment } from \"./offsetSegment\";\nimport { Vector } from \"../../definitions\";\nimport { Arc } from \"../../models/segments/Arc\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { findIntersectionsAndOverlaps } from \"../intersections\";\nimport { Figure } from \"../../models/Figure\";\nimport { stitchSegments } from \"../stitchSegments\";\n\nconst PRECISION = 1e-8;\n\nexport function rawOffsets(\n segmentsToOffset: Segment[],\n offset: number\n): Segment[] {\n const offsetSegments: OffsetSegmentPair[] = segmentsToOffset.map((c) => ({\n offset: offsetSegment(c, offset),\n original: c,\n }));\n\n // Ideally we would use the length of the segment to make sure it is\n // not only a point, but the algo we have access to are a bit to\n // convoluted to be usable here\n\n const offsettedArray: Segment[] = [];\n\n let savedLastSegment: null | OffsetSegmentPair = null;\n\n let previousSegment = offsetSegments.at(-1);\n\n // We have no offseted segments\n if (!previousSegment) return [];\n if (offsettedArray.length === 1) return offsettedArray;\n\n const appendSegment = (segment: OffsetSegmentPair) => {\n if (!savedLastSegment) {\n savedLastSegment = segment;\n } else if (!(segment.offset instanceof DegenerateSegment)) {\n offsettedArray.push(segment.offset);\n } else if (\n !sameVector(segment.offset.firstPoint, segment.offset.lastPoint)\n ) {\n offsettedArray.push(\n new Line(segment.offset.firstPoint, segment.offset.lastPoint)\n );\n }\n };\n const iterateOffsetSegments = function* (): Generator<OffsetSegmentPair> {\n for (const segment of offsetSegments.slice(0, -1)) {\n yield segment;\n }\n // This should never happen\n if (!savedLastSegment) throw new Error(\"Bug in the offset algorithm\");\n yield savedLastSegment;\n };\n\n for (const segment of iterateOffsetSegments()) {\n const previousLastPoint = previousSegment.offset.lastPoint;\n const firstPoint = segment.offset.firstPoint;\n\n // When the offset segments do still touch we do nothing\n if (sameVector(previousLastPoint, firstPoint)) {\n appendSegment(previousSegment);\n previousSegment = segment;\n continue;\n }\n\n let intersections: Vector[] = [];\n\n if (\n !(previousSegment.offset instanceof DegenerateSegment) &&\n !(segment.offset instanceof DegenerateSegment)\n ) {\n // When the offset segments intersect we cut them and save them at\n const { intersections: pointIntersections, overlaps } =\n findIntersectionsAndOverlaps(\n previousSegment.offset,\n segment.offset,\n PRECISION / 100\n );\n intersections = [\n ...pointIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ];\n }\n\n if (intersections.length > 0) {\n let intersection = intersections[0];\n if (intersections.length > 1) {\n // We choose the intersection point the closest to the end of the\n // original segment endpoint (why? not sure, following\n // https://github.com/jbuckmccready/cavalier_contours/)\n\n const originalEndpoint = previousSegment?.original.lastPoint;\n const distances = intersections.map((i) =>\n squareDistance(i, originalEndpoint)\n );\n intersection = intersections[distances.indexOf(Math.min(...distances))];\n }\n\n // We need to be a lot more careful here with multiple intersections\n // as well as cases where segments overlap\n\n const splitPreviousSegment = (previousSegment.offset as Segment).splitAt([\n intersection,\n ])[0];\n const splitSegment = (segment.offset as Segment)\n .splitAt([intersection])\n .at(-1);\n\n if (!splitSegment) throw new Error(\"Bug in the splitting algo in offset\");\n\n appendSegment({\n offset: splitPreviousSegment,\n original: previousSegment.original,\n });\n previousSegment = { offset: splitSegment, original: segment.original };\n continue;\n }\n\n // When the offset segments do not intersect we link them with an arc of\n // radius offset\n const center = previousSegment.original.lastPoint;\n const clockwise =\n crossProduct(\n subtract(firstPoint, center),\n subtract(previousLastPoint, center)\n ) > 0;\n\n const joiner = new Arc(previousLastPoint, firstPoint, center, clockwise);\n\n appendSegment(previousSegment);\n offsettedArray.push(joiner);\n previousSegment = segment;\n }\n\n appendSegment(previousSegment);\n return offsettedArray;\n}\n\ninterface OffsetSegmentPair {\n offset: Segment | DegenerateSegment;\n original: Segment;\n}\n\nexport function offsetLoop(loop: Loop, offset: number): Diagram {\n const correctedOffset = loop.clockwise ? offset : -offset;\n const offsettedArray = rawOffsets(loop.segments, correctedOffset);\n\n if (offsettedArray.length < 2) return new Diagram();\n\n // We remove the self intersections with the use the the algorithm as described in\n // https://github.com/jbuckmccready/CavalierContours#offset-algorithm-and-stepwise-example\n\n const allIntersections: Map<number, Vector[]> = new Map();\n const updateIntersections = (index: number, newPoints: Vector[]) => {\n const intersections = allIntersections.get(index) || [];\n allIntersections.set(index, [...intersections, ...newPoints]);\n };\n\n offsettedArray.forEach((firstSegment, firstIndex) => {\n offsettedArray\n .slice(firstIndex + 1)\n .forEach((secondSegment, secondIndex) => {\n const { intersections: rawIntersections, overlaps } =\n findIntersectionsAndOverlaps(firstSegment, secondSegment, PRECISION);\n\n const intersections = [\n ...rawIntersections,\n ...overlaps.flatMap((c) => [c.firstPoint, c.lastPoint]),\n ].filter((intersection) => {\n const onFirstSegmentExtremity =\n sameVector(intersection, firstSegment.firstPoint) ||\n sameVector(intersection, firstSegment.lastPoint);\n\n const onSecondSegmentExtremity =\n sameVector(intersection, secondSegment.firstPoint) ||\n sameVector(intersection, secondSegment.lastPoint);\n\n return !(onFirstSegmentExtremity && onSecondSegmentExtremity);\n });\n\n if (!intersections.length) return;\n\n updateIntersections(firstIndex, intersections);\n updateIntersections(secondIndex + firstIndex + 1, intersections);\n });\n });\n\n if (!allIntersections.size) {\n const offsettedLoop = new Loop(offsettedArray);\n return new Diagram([new Figure(offsettedLoop)]);\n\n /* this was in the replicad algorithm - not sure why\n if (!loop.intersects(offsettedLoop)) return offsettedLoop;\n return new Diagram();\n */\n }\n\n const splitSegments = offsettedArray.flatMap((segment, index) => {\n if (!allIntersections.has(index)) return segment;\n\n const intersections = allIntersections.get(index) || [];\n const splitSegments = segment.splitAt(intersections);\n return splitSegments;\n });\n\n // We remove all the segments that are closer to the original segment than the offset\n const prunedSegments = splitSegments.filter((segment) => {\n const closeSegment = loop.segments.some((c) => {\n return distance(c, segment) < Math.abs(offset) - PRECISION;\n });\n return !closeSegment;\n });\n\n if (!prunedSegments.length) return new Diagram();\n\n const segmentsGrouped = stitchSegments(prunedSegments);\n\n const newLoops = segmentsGrouped\n .filter((c) => c.length > 1)\n .filter((c) => sameVector(c[0].firstPoint, c.at(-1)!.lastPoint))\n .map((c) => new Loop(c));\n\n if (!newLoops.length) return new Diagram();\n return new Diagram(newLoops.map((l) => new Figure(l)));\n}\n","import { Figure } from \"../../models/Figure\";\nimport { Diagram } from \"../../models/Diagram\";\nimport { cut, fuseAll } from \"../../booleanOperations\";\nimport { offsetLoop } from \"./offsetLoop\";\n\nexport default function offsetFigures(\n figures: Figure[],\n offsetDistance: number\n): Diagram {\n const offsetFigures = figures.map((figure) => {\n const innerShape = fuseAll(\n figure.holes.map((l) => offsetLoop(l, offsetDistance))\n );\n return cut(offsetLoop(figure.contour, offsetDistance), innerShape);\n });\n\n return fuseAll(offsetFigures);\n}\n","import offsetFigures from \"./algorithms/offsets/offsetFigure\";\nimport { Diagram } from \"./models/Diagram\";\nimport { Figure } from \"./models/Figure\";\nimport { Loop } from \"./models/Loop\";\nimport { listOfFigures } from \"./utils/listOfFigures\";\n\nexport function offset(\n shape: Diagram | Figure | Loop,\n offsetDistance: number\n): Diagram {\n return offsetFigures(listOfFigures(shape), offsetDistance);\n}\n","import { Arc } from \"../../models/segments/Arc\";\nimport { Line } from \"../../models/segments/Line\";\nimport { Segment } from \"../../models/segments/Segment\";\n\nexport function svgSegmentToPath(segment: Segment) {\n if (segment instanceof Line) {\n return `L ${segment.lastPoint.join(\" \")}`;\n }\n if (segment instanceof Arc) {\n return `A ${segment.radius} ${segment.radius} 0 ${\n segment.angularLength > Math.PI ? \"1\" : \"0\"\n } ${segment.clockwise ? \"0\" : \"1\"} ${segment.lastPoint.join(\" \")}`;\n }\n\n throw new Error(\"Unknown segment type\");\n}\n","import type { Loop } from \"../../models/Loop\";\nimport { svgSegmentToPath } from \"./svgSegment\";\n\nexport function svgLoop(loop: Loop) {\n const start = `M ${loop.firstPoint.join(\" \")}`;\n const segments = loop.segments.map(svgSegmentToPath).join(\" \");\n return `${start} ${segments} Z`;\n}\n","import type { Figure } from \"../../models/Figure\";\nimport { svgLoop } from \"./svgLoop\";\n\nexport function svgFigure(figure: Figure) {\n const path = figure.allLoops.map(svgLoop).join(\" \");\n return `<path d=\"${path}\" />`;\n}\n","import { Diagram } from \"../../models/Diagram\";\nimport { svgFigure } from \"./svgFigure\";\n\nexport function svgDiagram(diagram: Diagram) {\n return `<g>\n ${diagram.figures.map(svgFigure).join(\"\\n\")}\n</g>`;\n}\n","import type { Strand } from \"../../models/Strand\";\nimport { svgSegmentToPath } from \"./svgSegment\";\n\nexport function svgStrand(strand: Strand) {\n const start = `M ${strand.firstPoint.join(\" \")}`;\n const segments = strand.segments.map(svgSegmentToPath).join(\" \");\n return `${start} ${segments}`;\n}\n","import { BoundingBox } from \"../../models/BoundingBox\";\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 { Strand } from \"../../models/Strand\";\nimport { 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 { svgStrand } from \"./svgStrand\";\nimport { wrapSVG } from \"./wrapSVG\";\n\ntype Shape = Loop | Figure | Diagram | Arc | Line | Strand;\n\nexport function svgBody(shape: Shape) {\n if (shape instanceof Diagram) {\n return svgDiagram(shape);\n } else if (shape instanceof Figure) {\n return svgFigure(shape);\n } else if (shape instanceof Loop) {\n return `<path d=\"${svgLoop(shape)}\" />`;\n } else if (shape instanceof Strand) {\n return `<path d=\"${svgStrand(shape)}\" />`;\n } else if (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\ntype ConfiguredShape = Shape | { shape: Shape; color?: string };\n\nconst extractShape = (shape: ConfiguredShape) =>\n \"shape\" in shape ? shape.shape : shape;\n\nconst addConfig = (shape: ConfiguredShape, body: string) => {\n if (!(\"shape\" in shape)) return body;\n const { color } = shape;\n if (!color) return body;\n return `<g stroke=\"${color}\">${body}</g>`;\n};\n\nexport function exportSVG(\n shape: ConfiguredShape | ConfiguredShape[],\n margin = 1\n) {\n if (Array.isArray(shape)) {\n const flipped = shape.map((s) => extractShape(s).mirror());\n const body = flipped\n .map((s, i) => addConfig(shape[i], svgBody(s)))\n .join(\"\\n\");\n const bbox = flipped\n .slice(1)\n .reduce((bbox, s) => bbox.merge(s.boundingBox), flipped[0].boundingBox);\n\n return wrapSVG(body, bbox);\n }\n const flipped = extractShape(shape).mirror();\n return wrapSVG(\n addConfig(shape, svgBody(flipped)),\n flipped.boundingBox,\n margin\n );\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 {\n // Surface booleans\n fuseAll,\n fuse,\n cut,\n intersect,\n // Strand booleans\n eraseStrand,\n confineStrand,\n // Offset\n offset,\n} 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":["listOfFigures","shape","Figure","Loop","Diagram","strandLoopSections","loop","strand","precision","allIntersections","allCommonSegments","splitPoints","strandSegment","strandIndex","loopSegment","intersections","overlaps","findIntersectionsAndOverlaps","commonSegmentsPoints","s","removeDuplicatePoints","strandSegments","zip","segment","strandsBetweenIntersections","eraseStrandWithinLoop","eraseOnBorder","strandCenter","eraseStrandOutsideLoop","eraseStrandWithinFigure","figure","outsideStrands","inLoopStrand","hole","eraseStrandOutsideFigure","insideStrands","fuse","first","second","fuseFiguresLists","fuseAll","shapes","acc","cut","cutFiguresLists","intersect","intersectFiguresLists","eraseStrand","diagram","outStrands","confineStrand","segmentPosition","intersectionParam","handleBetween","lineBetween","otherLine","otherPosition","lineLineDistance","line1","line2","intersectionParams","lineLineParams","intersectionParam1","intersectionParam2","firstPosition","secondPosition","distance","lineArcDistance","line","arc","lineArcIntersection","closestPointOnLine","projectPointOnLine","circleCenterLineDistance","centerLineDirection","normalize","subtract","closestPointOnCircle","add","scalarMultiply","overlappingAngles","arc1","arc2","p1","p2","arcArcDistance","arcArcIntersection","centersDistance","centerCenterDirection","containedCircles","arc1ClosestPointAngle","polarAngle","arc2ClosestPointAngle","segment1","segment2","Line","Arc","PRECISION","rawOffsets","segmentsToOffset","offset","offsetSegments","c","offsetSegment","offsettedArray","savedLastSegment","previousSegment","appendSegment","DegenerateSegment","sameVector","iterateOffsetSegments","previousLastPoint","firstPoint","pointIntersections","intersection","originalEndpoint","distances","i","squareDistance","splitPreviousSegment","splitSegment","center","clockwise","crossProduct","joiner","offsetLoop","correctedOffset","updateIntersections","index","newPoints","firstSegment","firstIndex","secondSegment","secondIndex","rawIntersections","onFirstSegmentExtremity","onSecondSegmentExtremity","offsettedLoop","prunedSegments","splitSegments","newLoops","stitchSegments","l","offsetFigures","figures","offsetDistance","innerShape","svgSegmentToPath","svgLoop","start","segments","svgFigure","svgDiagram","svgStrand","SVGViewbox","bbox","margin","minX","minY","wrapSVG","body","boundingBox","svgBody","Strand","extractShape","addConfig","color","exportSVG","flipped","importSegment","json","importLoop","importFigure","contour","holes","importDiagram","importJSON","DEG2RAD","RAD2DEG","polarToCartesian","r","theta","x","y","cartesianToPolar"],"mappings":"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"}
|
package/dist/pantograph.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ declare abstract class AbstractSegment<T extends AbstractSegment<T>> extends Tra
|
|
|
5
5
|
readonly precision: number;
|
|
6
6
|
abstract segmentType: string;
|
|
7
7
|
get repr(): string;
|
|
8
|
+
get info(): string;
|
|
8
9
|
abstract get midPoint(): Vector;
|
|
9
10
|
abstract get boundingBox(): BoundingBox;
|
|
10
11
|
abstract clone(): T;
|
|
@@ -24,6 +25,7 @@ declare abstract class AbstractStroke<T extends AbstractStroke<T>> extends Trans
|
|
|
24
25
|
readonly segments: Segment[];
|
|
25
26
|
abstract strokeType: string;
|
|
26
27
|
get repr(): string;
|
|
28
|
+
get info(): string;
|
|
27
29
|
constructor(segments: Segment[], { ignoreChecks }?: {
|
|
28
30
|
ignoreChecks?: boolean | undefined;
|
|
29
31
|
});
|
|
@@ -32,6 +34,7 @@ declare abstract class AbstractStroke<T extends AbstractStroke<T>> extends Trans
|
|
|
32
34
|
get segmentsCount(): number;
|
|
33
35
|
onStroke(point: Vector): boolean;
|
|
34
36
|
intersects(other: Stroke): boolean;
|
|
37
|
+
overlappingSegments(other: Stroke): Segment[];
|
|
35
38
|
private _boundingBox;
|
|
36
39
|
get boundingBox(): BoundingBox;
|
|
37
40
|
abstract reverse(): T;
|
|
@@ -47,6 +50,7 @@ export declare class Arc extends AbstractSegment<Arc> {
|
|
|
47
50
|
constructor(firstPoint: Vector, lastPoint: Vector, center: Vector, clockwise?: boolean, { ignoreChecks }?: {
|
|
48
51
|
ignoreChecks?: boolean | undefined;
|
|
49
52
|
});
|
|
53
|
+
get info(): string;
|
|
50
54
|
isValidParameter(t: number): boolean;
|
|
51
55
|
angleToParam(angle: number): number;
|
|
52
56
|
private _angularLength;
|
|
@@ -97,6 +101,8 @@ declare type ConfiguredShape = Shape | {
|
|
|
97
101
|
color?: string;
|
|
98
102
|
};
|
|
99
103
|
|
|
104
|
+
export declare function confineStrand(strand: Strand, diagram: Diagram | Figure | Loop, eraseOnBorder?: boolean): Strand[];
|
|
105
|
+
|
|
100
106
|
export declare function cut(first: Diagram | Figure | Loop, second: Diagram | Figure | Loop): Diagram;
|
|
101
107
|
|
|
102
108
|
export declare const DEG2RAD: number;
|
|
@@ -113,6 +119,7 @@ export declare class Diagram extends Transformable<Diagram> {
|
|
|
113
119
|
transform(matrix: TransformationMatrix): Diagram;
|
|
114
120
|
contains(point: Vector): boolean;
|
|
115
121
|
intersects(other: Diagram): boolean;
|
|
122
|
+
overlappingStrands(other: Diagram | Figure | Stroke): Strand[];
|
|
116
123
|
fuse(other: Diagram): Diagram;
|
|
117
124
|
cut(other: Diagram): Diagram;
|
|
118
125
|
intersect(other: Diagram): Diagram;
|
|
@@ -150,14 +157,17 @@ declare class DrawingPen {
|
|
|
150
157
|
bulgeArc(xDist: number, yDist: number, bulge: number): this;
|
|
151
158
|
vBulgeArc(distance: number, bulge: number): this;
|
|
152
159
|
hBulgeArc(distance: number, bulge: number): this;
|
|
153
|
-
tangentArcTo(end: Vector): this;
|
|
154
|
-
tangentArc(xDist: number, yDist: number): this;
|
|
160
|
+
tangentArcTo(end: Vector, tangentAtStart?: Vector): this;
|
|
161
|
+
tangentArc(xDist: number, yDist: number, tangentAtStart?: Vector): this;
|
|
155
162
|
customCorner(radius: number, mode?: "fillet" | "chamfer"): this;
|
|
156
163
|
protected _customCornerLastWithFirst(radius: number, mode?: "fillet" | "chamfer"): void;
|
|
157
164
|
close(): Diagram;
|
|
158
165
|
closeWithMirror(): Diagram;
|
|
166
|
+
asStrand(): Strand;
|
|
159
167
|
}
|
|
160
168
|
|
|
169
|
+
export declare function eraseStrand(strand: Strand, diagram: Diagram | Figure | Loop, eraseOnBorder?: boolean): Strand[];
|
|
170
|
+
|
|
161
171
|
export declare function exportJSON(shape: Shape_2): {
|
|
162
172
|
type: string;
|
|
163
173
|
firstPoint: Vector;
|
|
@@ -273,6 +283,7 @@ export declare class Figure extends Transformable<Figure> {
|
|
|
273
283
|
transform(matrix: TransformationMatrix): Figure;
|
|
274
284
|
contains(point: Vector): boolean;
|
|
275
285
|
intersects(other: Figure): boolean;
|
|
286
|
+
overlappingStrands(other: Figure | Stroke): Strand[];
|
|
276
287
|
}
|
|
277
288
|
|
|
278
289
|
export declare function fuse(first: Diagram | Figure | Loop, second: Diagram | Figure | Loop): Diagram;
|