pantograph2d 0.9.0 → 0.10.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.
Files changed (42) hide show
  1. package/dist/{QuadraticBezier-BKElJOgn.cjs → QuadraticBezier--UZr_xcV.cjs} +2 -2
  2. package/dist/QuadraticBezier--UZr_xcV.cjs.map +1 -0
  3. package/dist/{QuadraticBezier-PcRS9HZK.js → QuadraticBezier-DxieHk9z.js} +4 -2
  4. package/dist/QuadraticBezier-DxieHk9z.js.map +1 -0
  5. package/dist/{draw-L71G180-.cjs → draw-BUUNobTS.cjs} +2 -2
  6. package/dist/{draw-L71G180-.cjs.map → draw-BUUNobTS.cjs.map} +1 -1
  7. package/dist/{draw-N2ntigsw.js → draw-lOWnIN1o.js} +5 -3
  8. package/dist/{draw-N2ntigsw.js.map → draw-lOWnIN1o.js.map} +1 -1
  9. package/dist/models-CCo90hZc.cjs +4 -0
  10. package/dist/models-CCo90hZc.cjs.map +1 -0
  11. package/dist/{models-BjaFYsN2.js → models-DCkOI0hV.js} +643 -581
  12. package/dist/models-DCkOI0hV.js.map +1 -0
  13. package/dist/pantograph/drawShape.cjs +1 -1
  14. package/dist/pantograph/drawShape.js +1 -1
  15. package/dist/pantograph/models.cjs +1 -1
  16. package/dist/pantograph/models.js +2 -2
  17. package/dist/pantograph/svg.cjs +1 -1
  18. package/dist/pantograph/svg.js +1 -1
  19. package/dist/pantograph.cjs +2 -2
  20. package/dist/pantograph.cjs.map +1 -1
  21. package/dist/pantograph.js +621 -425
  22. package/dist/pantograph.js.map +1 -1
  23. package/dist/{svg-hNHYuj_r.js → svg-BIphc_zE.js} +3 -3
  24. package/dist/{svg-hNHYuj_r.js.map → svg-BIphc_zE.js.map} +1 -1
  25. package/dist/{svg-ZTvNxsWu.cjs → svg-BY5h3CDD.cjs} +3 -3
  26. package/dist/{svg-ZTvNxsWu.cjs.map → svg-BY5h3CDD.cjs.map} +1 -1
  27. package/dist/types/src/algorithms/boolean/loopBooleans.d.ts +10 -5
  28. package/dist/types/src/drawShape/drawPolysides.d.ts +1 -0
  29. package/dist/types/src/drawShape/index.d.ts +1 -0
  30. package/dist/types/src/featureOperations.d.ts +88 -0
  31. package/dist/types/src/main.d.ts +2 -2
  32. package/dist/types/src/models/Diagram.d.ts +3 -1
  33. package/dist/types/src/models/Figure.d.ts +3 -1
  34. package/dist/types/src/models/Loop.d.ts +3 -1
  35. package/dist/types/src/operations.d.ts +1 -0
  36. package/dist/types/src/vectorOperations.d.ts +1 -1
  37. package/package.json +3 -2
  38. package/dist/QuadraticBezier-BKElJOgn.cjs.map +0 -1
  39. package/dist/QuadraticBezier-PcRS9HZK.js.map +0 -1
  40. package/dist/models-BXU-Gx3U.cjs +0 -4
  41. package/dist/models-BXU-Gx3U.cjs.map +0 -1
  42. package/dist/models-BjaFYsN2.js.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";var x=Object.defineProperty;var z=(e,t,n)=>t in e?x(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var f=(e,t,n)=>z(e,typeof t!="symbol"?t+"":t,n);const i=require("./QuadraticBezier-BKElJOgn.cjs"),d=require("./models-BXU-Gx3U.cjs"),b=(e,t,n)=>{const r=i.crossProduct(e.V,t.V),s=e.precision*t.precision;if(r*r<s)return"parallel";const o=i.subtract(t.firstPoint,e.firstPoint),a=i.crossProduct(o,t.V)/r;return i.add(e.firstPoint,i.scalarMultiply(e.V,a))};class m{constructor(t,n){this.firstPoint=t,this.lastPoint=n}}function A(e,t){if(e instanceof i.Line)return F(e,t);if(e instanceof i.Arc)return M(e,t);if(e instanceof i.QuadraticBezier||e instanceof i.CubicBezier)return V(e,t);throw new Error("Not implemented")}function F(e,t){const{firstPoint:n,lastPoint:r}=e,s=e.normalVector;return new i.Line(i.add(n,i.scalarMultiply(s,t)),i.add(r,i.scalarMultiply(s,t)))}function M(e,t){const n=i.add(e.firstPoint,i.scalarMultiply(i.perpendicular(e.tangentAtFirstPoint),t)),r=i.add(e.lastPoint,i.scalarMultiply(i.perpendicular(e.tangentAtLastPoint),t)),s=t*(e.clockwise?1:-1);return e.radius+s<e.precision?new m(n,r):new i.Arc(n,r,e.center,e.clockwise)}function w(e,t,n,r,s){const o=b({V:n,firstPoint:r,precision:s},{V:i.subtract(t,e),firstPoint:e,precision:s});if(o==="parallel")throw new Error("Parallel lines not expected in safe bezier offset control point calculation");return o}function V(e,t){const{firstPoint:n,lastPoint:r,normalAtFirstPoint:s,normalAtLastPoint:o}=e,a=b({V:s,firstPoint:n,precision:e.precision},{V:o,firstPoint:r,precision:e.precision}),c=i.add(n,i.scalarMultiply(s,t)),l=i.add(r,i.scalarMultiply(o,t));if(a==="parallel")throw new Error("Parallel lines not expected in safe bezier offset");if(i.dotProduct(i.subtract(a,n),s)*t>0&&Math.min(i.distance(n,a),i.distance(r,a))<t)return new m(c,l);if(e instanceof i.QuadraticBezier){const g=w(a,e.controlPoint,e.tangentAtFirstPoint,c,e.precision);return new i.QuadraticBezier(c,l,g)}const p=w(a,e.firstControlPoint,e.tangentAtFirstPoint,c,e.precision),u=w(a,e.lastControlPoint,e.tangentAtLastPoint,l,e.precision);return new i.CubicBezier(c,l,p,u)}function L(e,t,n){const r=i.crossProduct(e.tangentAtLastPoint,t.tangentAtFirstPoint);if(Math.abs(r)<1e-10)return null;const s=r>0?1:-1,o=Math.abs(n)*s,a=A(e,o),c=A(t,o);if(a instanceof m||c instanceof m)return null;let l;try{l=d.findIntersections(a,c,1e-9).at(-1)}catch{return null}if(!l)return null;const h=l,p=(P,v)=>{const E=v.tangentAt(h),D=i.perpendicularClockwise(E),y=i.add(h,i.scalarMultiply(D,o));return P.splitAt(y)},[u]=p(e,a),[,g]=p(t,c);return{first:u,second:g,center:h}}function T(e,t,n){const r=L(e,t,n);if(!r)return console.warn("Cannot fillet between segments",e.repr,t.repr),[e,t];const{first:s,second:o}=r;return[s,i.tangentArc(s.lastPoint,o.firstPoint,s.tangentAtLastPoint),o]}function C(e,t,n){const r=L(e,t,n);if(!r)return console.warn("Cannot chamfer between segments",e.repr,t.repr),[e,t];const{first:s,second:o}=r;return[s,new i.Line(s.lastPoint,o.firstPoint),o]}const B=e=>{let t;e?typeof e=="number"||Array.isArray(e)&&e.length===2?t={endTangent:e}:t={endTangent:0,...e}:t={endTangent:[1,0]};const{endTangent:n,startFactor:r=1,endFactor:s=1,startTangent:o}=t;let a;typeof n=="number"?a=i.polarToCartesian(1,n*i.DEG2RAD):a=n;let c;return typeof o=="number"?c=i.polarToCartesian(1,o*i.DEG2RAD):c=o,{endTangent:a,startFactor:r,endFactor:s,startTangent:c}};function S(e,{ignoreChecks:t=!1}={}){return new d.Diagram([new d.Figure(new d.Loop([...e],{ignoreChecks:t}))])}class _{constructor(t=[0,0]){f(this,"pointer");f(this,"firstPoint");f(this,"pendingSegments");f(this,"_nextCorner");this.pointer=t,this.firstPoint=t,this.pendingSegments=[],this._nextCorner=null}movePointerTo(t){if(this.pendingSegments.length)throw new Error("You can only move the pointer if there is no segment defined");return this.pointer=t,this.firstPoint=t,this}saveSegment(t){if(i.sameVector(t.firstPoint,t.lastPoint))throw new Error(`Segment has no length, ${t.repr}`);if(!this._nextCorner)return this.pendingSegments.push(t),this;const n=this.pendingSegments.pop();if(!n)throw new Error("bug in the custom corner algorithm");const r=this._nextCorner.mode==="chamfer"?C:T;return this.pendingSegments.push(...r(n,t,this._nextCorner.radius)),this._nextCorner=null,this}lineTo(t){const n=new i.Line(this.pointer,t);return this.pointer=t,this.saveSegment(n)}line(t,n){return this.lineTo([this.pointer[0]+t,this.pointer[1]+n])}vLine(t){return this.line(0,t)}hLine(t){return this.line(t,0)}vLineTo(t){return this.lineTo([this.pointer[0],t])}hLineTo(t){return this.lineTo([t,this.pointer[1]])}polarLineTo([t,n]){const r=n*i.DEG2RAD,s=i.polarToCartesian(t,r);return this.lineTo(s)}polarLine(t,n){const r=n*i.DEG2RAD,[s,o]=i.polarToCartesian(t,r);return this.line(s,o)}tangentLine(t){const n=this.pendingSegments.at(-1);if(!n)throw new Error("You need a previous segment to sketch a tangent line");const[r,s]=n.tangentAtLastPoint;return this.line(r*t,s*t)}threePointsArcTo(t,n){return this.saveSegment(i.threePointsArc(this.pointer,n,t)),this.pointer=t,this}threePointsArc(t,n,r,s){const[o,a]=this.pointer;return this.threePointsArcTo([o+t,a+n],[o+r,a+s])}sagittaArcTo(t,n){if(!n)return this.lineTo(t);const r=new i.Line(this.pointer,t),s=i.perpendicular(r.tangentAtFirstPoint),o=i.add(r.midPoint,i.scalarMultiply(s,n));return this.threePointsArcTo(t,o)}sagittaArc(t,n,r){return this.sagittaArcTo([t+this.pointer[0],n+this.pointer[1]],r)}vSagittaArc(t,n){return this.sagittaArc(0,t,n)}hSagittaArc(t,n){return this.sagittaArc(t,0,n)}bulgeArcTo(t,n){if(!n)return this.lineTo(t);const r=i.distance(this.pointer,t)/2,s=-n*r;return this.sagittaArcTo(t,s)}bulgeArc(t,n,r){return this.bulgeArcTo([t+this.pointer[0],n+this.pointer[1]],r)}vBulgeArc(t,n){return this.bulgeArc(0,t,n)}hBulgeArc(t,n){return this.bulgeArc(t,0,n)}tangentArcTo(t,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(i.tangentArc(this.pointer,t,n??r.tangentAtLastPoint)),this.pointer=t,this}tangentArc(t,n,r){const[s,o]=this.pointer;return this.tangentArcTo([t+s,n+o],r)}ellipseTo(t,n,r,s,o,a){return this.saveSegment(i.svgEllipse(this.pointer,t,n,r,s,o,a)),this.pointer=t,this}ellipse(t,n,r,s,o,a,c){return this.ellipseTo([t+this.pointer[0],n+this.pointer[1]],r,s,o,a,c)}halfEllipseTo(t,n){const[r,s]=i.cartesianToPolar(i.subtract(t,this.pointer));return this.ellipseTo(t,r/2,Math.abs(n),s*i.RAD2DEG,!0,n>0)}halfEllipse(t,n,r){return this.halfEllipseTo([t+this.pointer[0],n+this.pointer[1]],r)}cubicBezierCurveTo(t,n,r){return this.saveSegment(new i.CubicBezier(this.pointer,t,n,r)),this.pointer=t,this}quadraticBezierCurveTo(t,n){return this.saveSegment(new i.QuadraticBezier(this.pointer,t,n)),this.pointer=t,this}smoothCurveTo(t,n){const{endTangent:r,startTangent:s,startFactor:o,endFactor:a}=B(n),c=this.pendingSegments.length?this.pendingSegments[this.pendingSegments.length-1]:null,l=i.distance(this.pointer,t)/3;let h;s?h=s:c?h=c.tangentAtLastPoint:h=[1,0],h=i.normalize(h);const p=[this.pointer[0]+h[0]*o*l,this.pointer[1]+h[1]*o*l];let u=r;u=i.normalize(u);const g=[t[0]-u[0]*a*l,t[1]-u[1]*a*l];return this.cubicBezierCurveTo(t,p,g)}smoothCurve(t,n,r){return this.smoothCurveTo([t+this.pointer[0],n+this.pointer[1]],r)}customCorner(t,n="fillet"){if(!this.pendingSegments.length)throw new Error("You need a segment defined to fillet the angle");return t?(this._nextCorner={mode:n,radius:t},this):this}_customCornerLastWithFirst(t,n="fillet"){if(!t)return;const r=this.pendingSegments.pop(),s=this.pendingSegments.shift();if(!r||!s)throw new Error("Not enough curves to close and fillet");const o=n==="chamfer"?C:T;this.pendingSegments.push(...o(r,s,t))}close(t=!1){if(!this.pendingSegments.length)throw new Error("No segments to close");const n=this.pendingSegments[0],r=this.pendingSegments.at(-1);return i.sameVector(n.firstPoint,r.lastPoint)||this.lineTo(n.firstPoint),this._nextCorner!==null&&(this._customCornerLastWithFirst(this._nextCorner.radius,this._nextCorner.mode),this._nextCorner=null),S(this.pendingSegments,{ignoreChecks:t})}closeWithMirror(t=!1){if(!this.pendingSegments.length)throw new Error("No segments to close");const n=this.pendingSegments[0],r=this.pendingSegments.at(-1),s=i.subtract(r.lastPoint,n.firstPoint),o=new i.TransformationMatrix().mirrorLine(s,n.firstPoint),a=this.pendingSegments.map(c=>c.transform(o).reverse());return a.reverse(),S([...this.pendingSegments,...a],{ignoreChecks:t})}asStrand(){return new d.Strand([...this.pendingSegments])}get isClosed(){var t;return i.sameVector(this.pointer,(t=this.pendingSegments[0])==null?void 0:t.firstPoint)}}function R(e=[0,0]){return new _(e)}exports.DegenerateSegment=m;exports.draw=R;exports.offsetSegment=A;
2
- //# sourceMappingURL=draw-L71G180-.cjs.map
1
+ "use strict";var z=Object.defineProperty;var F=(e,t,n)=>t in e?z(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var f=(e,t,n)=>F(e,typeof t!="symbol"?t+"":t,n);const i=require("./QuadraticBezier--UZr_xcV.cjs"),d=require("./models-CCo90hZc.cjs"),b=(e,t,n)=>{const r=i.crossProduct(e.V,t.V),s=e.precision*t.precision;if(r*r<s)return"parallel";const o=i.subtract(t.firstPoint,e.firstPoint),a=i.crossProduct(o,t.V)/r;return i.add(e.firstPoint,i.scalarMultiply(e.V,a))};class m{constructor(t,n){this.firstPoint=t,this.lastPoint=n}}function A(e,t){if(e instanceof i.Line)return M(e,t);if(e instanceof i.Arc)return V(e,t);if(e instanceof i.QuadraticBezier||e instanceof i.CubicBezier)return B(e,t);throw new Error("Not implemented")}function M(e,t){const{firstPoint:n,lastPoint:r}=e,s=e.normalVector;return new i.Line(i.add(n,i.scalarMultiply(s,t)),i.add(r,i.scalarMultiply(s,t)))}function V(e,t){const n=i.add(e.firstPoint,i.scalarMultiply(i.perpendicular(e.tangentAtFirstPoint),t)),r=i.add(e.lastPoint,i.scalarMultiply(i.perpendicular(e.tangentAtLastPoint),t)),s=t*(e.clockwise?1:-1);return e.radius+s<e.precision?new m(n,r):new i.Arc(n,r,e.center,e.clockwise)}function w(e,t,n,r,s){const o=b({V:n,firstPoint:r,precision:s},{V:i.subtract(t,e),firstPoint:e,precision:s});if(o==="parallel")throw new Error("Parallel lines not expected in safe bezier offset control point calculation");return o}function B(e,t){const{firstPoint:n,lastPoint:r,normalAtFirstPoint:s,normalAtLastPoint:o}=e,a=b({V:s,firstPoint:n,precision:e.precision},{V:o,firstPoint:r,precision:e.precision}),c=i.add(n,i.scalarMultiply(s,t)),l=i.add(r,i.scalarMultiply(o,t));if(a==="parallel")throw new Error("Parallel lines not expected in safe bezier offset");if(i.dotProduct(i.subtract(a,n),s)*t>0&&Math.min(i.distance(n,a),i.distance(r,a))<t)return new m(c,l);if(e instanceof i.QuadraticBezier){const g=w(a,e.controlPoint,e.tangentAtFirstPoint,c,e.precision);return new i.QuadraticBezier(c,l,g)}const p=w(a,e.firstControlPoint,e.tangentAtFirstPoint,c,e.precision),u=w(a,e.lastControlPoint,e.tangentAtLastPoint,l,e.precision);return new i.CubicBezier(c,l,p,u)}function L(e,t,n){const r=i.crossProduct(e.tangentAtLastPoint,t.tangentAtFirstPoint);if(Math.abs(r)<1e-10)return null;const s=r>0?1:-1,o=Math.abs(n)*s,a=A(e,o),c=A(t,o);if(a instanceof m||c instanceof m)return null;let l;try{l=d.findIntersections(a,c,1e-9).at(-1)}catch{return null}if(!l)return null;const h=l,p=(P,D)=>{const E=D.tangentAt(h),y=i.perpendicularClockwise(E),x=i.add(h,i.scalarMultiply(y,o));return P.splitAt(x)},[u]=p(e,a),[,g]=p(t,c);return{first:u,second:g,center:h}}function T(e,t,n){const r=L(e,t,n);if(!r)return console.warn("Cannot fillet between segments",e.repr,t.repr),[e,t];const{first:s,second:o}=r;return[s,i.tangentArc(s.lastPoint,o.firstPoint,s.tangentAtLastPoint),o]}function C(e,t,n){const r=L(e,t,n);if(!r)return console.warn("Cannot chamfer between segments",e.repr,t.repr),[e,t];const{first:s,second:o}=r;return[s,new i.Line(s.lastPoint,o.firstPoint),o]}const _=e=>{let t;e?typeof e=="number"||Array.isArray(e)&&e.length===2?t={endTangent:e}:t={endTangent:0,...e}:t={endTangent:[1,0]};const{endTangent:n,startFactor:r=1,endFactor:s=1,startTangent:o}=t;let a;typeof n=="number"?a=i.polarToCartesian(1,n*i.DEG2RAD):a=n;let c;return typeof o=="number"?c=i.polarToCartesian(1,o*i.DEG2RAD):c=o,{endTangent:a,startFactor:r,endFactor:s,startTangent:c}};function S(e,{ignoreChecks:t=!1}={}){return new d.Diagram([new d.Figure(new d.Loop([...e],{ignoreChecks:t}))])}class v{constructor(t=[0,0]){f(this,"pointer");f(this,"firstPoint");f(this,"pendingSegments");f(this,"_nextCorner");this.pointer=t,this.firstPoint=t,this.pendingSegments=[],this._nextCorner=null}movePointerTo(t){if(this.pendingSegments.length)throw new Error("You can only move the pointer if there is no segment defined");return this.pointer=t,this.firstPoint=t,this}saveSegment(t){if(i.sameVector(t.firstPoint,t.lastPoint))throw new Error(`Segment has no length, ${t.repr}`);if(!this._nextCorner)return this.pendingSegments.push(t),this;const n=this.pendingSegments.pop();if(!n)throw new Error("bug in the custom corner algorithm");const r=this._nextCorner.mode==="chamfer"?C:T;return this.pendingSegments.push(...r(n,t,this._nextCorner.radius)),this._nextCorner=null,this}lineTo(t){const n=new i.Line(this.pointer,t);return this.pointer=t,this.saveSegment(n)}line(t,n){return this.lineTo([this.pointer[0]+t,this.pointer[1]+n])}vLine(t){return this.line(0,t)}hLine(t){return this.line(t,0)}vLineTo(t){return this.lineTo([this.pointer[0],t])}hLineTo(t){return this.lineTo([t,this.pointer[1]])}polarLineTo([t,n]){const r=n*i.DEG2RAD,s=i.polarToCartesian(t,r);return this.lineTo(s)}polarLine(t,n){const r=n*i.DEG2RAD,[s,o]=i.polarToCartesian(t,r);return this.line(s,o)}tangentLine(t){const n=this.pendingSegments.at(-1);if(!n)throw new Error("You need a previous segment to sketch a tangent line");const[r,s]=n.tangentAtLastPoint;return this.line(r*t,s*t)}threePointsArcTo(t,n){return this.saveSegment(i.threePointsArc(this.pointer,n,t)),this.pointer=t,this}threePointsArc(t,n,r,s){const[o,a]=this.pointer;return this.threePointsArcTo([o+t,a+n],[o+r,a+s])}sagittaArcTo(t,n){if(!n)return this.lineTo(t);const r=new i.Line(this.pointer,t),s=i.perpendicular(r.tangentAtFirstPoint),o=i.add(r.midPoint,i.scalarMultiply(s,n));return this.threePointsArcTo(t,o)}sagittaArc(t,n,r){return this.sagittaArcTo([t+this.pointer[0],n+this.pointer[1]],r)}vSagittaArc(t,n){return this.sagittaArc(0,t,n)}hSagittaArc(t,n){return this.sagittaArc(t,0,n)}bulgeArcTo(t,n){if(!n)return this.lineTo(t);const r=i.distance(this.pointer,t)/2,s=-n*r;return this.sagittaArcTo(t,s)}bulgeArc(t,n,r){return this.bulgeArcTo([t+this.pointer[0],n+this.pointer[1]],r)}vBulgeArc(t,n){return this.bulgeArc(0,t,n)}hBulgeArc(t,n){return this.bulgeArc(t,0,n)}tangentArcTo(t,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(i.tangentArc(this.pointer,t,n??r.tangentAtLastPoint)),this.pointer=t,this}tangentArc(t,n,r){const[s,o]=this.pointer;return this.tangentArcTo([t+s,n+o],r)}ellipseTo(t,n,r,s,o,a){return this.saveSegment(i.svgEllipse(this.pointer,t,n,r,s,o,a)),this.pointer=t,this}ellipse(t,n,r,s,o,a,c){return this.ellipseTo([t+this.pointer[0],n+this.pointer[1]],r,s,o,a,c)}halfEllipseTo(t,n){const[r,s]=i.cartesianToPolar(i.subtract(t,this.pointer));return this.ellipseTo(t,r/2,Math.abs(n),s*i.RAD2DEG,!0,n>0)}halfEllipse(t,n,r){return this.halfEllipseTo([t+this.pointer[0],n+this.pointer[1]],r)}cubicBezierCurveTo(t,n,r){return this.saveSegment(new i.CubicBezier(this.pointer,t,n,r)),this.pointer=t,this}quadraticBezierCurveTo(t,n){return this.saveSegment(new i.QuadraticBezier(this.pointer,t,n)),this.pointer=t,this}smoothCurveTo(t,n){const{endTangent:r,startTangent:s,startFactor:o,endFactor:a}=_(n),c=this.pendingSegments.length?this.pendingSegments[this.pendingSegments.length-1]:null,l=i.distance(this.pointer,t)/3;let h;s?h=s:c?h=c.tangentAtLastPoint:h=[1,0],h=i.normalize(h);const p=[this.pointer[0]+h[0]*o*l,this.pointer[1]+h[1]*o*l];let u=r;u=i.normalize(u);const g=[t[0]-u[0]*a*l,t[1]-u[1]*a*l];return this.cubicBezierCurveTo(t,p,g)}smoothCurve(t,n,r){return this.smoothCurveTo([t+this.pointer[0],n+this.pointer[1]],r)}customCorner(t,n="fillet"){if(!this.pendingSegments.length)throw new Error("You need a segment defined to fillet the angle");return t?(this._nextCorner={mode:n,radius:t},this):this}_customCornerLastWithFirst(t,n="fillet"){if(!t)return;const r=this.pendingSegments.pop(),s=this.pendingSegments.shift();if(!r||!s)throw new Error("Not enough curves to close and fillet");const o=n==="chamfer"?C:T;this.pendingSegments.push(...o(r,s,t))}close(t=!1){if(!this.pendingSegments.length)throw new Error("No segments to close");const n=this.pendingSegments[0],r=this.pendingSegments.at(-1);return i.sameVector(n.firstPoint,r.lastPoint)||this.lineTo(n.firstPoint),this._nextCorner!==null&&(this._customCornerLastWithFirst(this._nextCorner.radius,this._nextCorner.mode),this._nextCorner=null),S(this.pendingSegments,{ignoreChecks:t})}closeWithMirror(t=!1){if(!this.pendingSegments.length)throw new Error("No segments to close");const n=this.pendingSegments[0],r=this.pendingSegments.at(-1),s=i.subtract(r.lastPoint,n.firstPoint),o=new i.TransformationMatrix().mirrorLine(s,n.firstPoint),a=this.pendingSegments.map(c=>c.transform(o).reverse());return a.reverse(),S([...this.pendingSegments,...a],{ignoreChecks:t})}asStrand(){return new d.Strand([...this.pendingSegments])}get isClosed(){var t;return i.sameVector(this.pointer,(t=this.pendingSegments[0])==null?void 0:t.firstPoint)}}function R(e=[0,0]){return new v(e)}exports.DegenerateSegment=m;exports.DrawingPen=v;exports.draw=R;exports.filletSegments=T;exports.offsetSegment=A;
2
+ //# sourceMappingURL=draw-BUUNobTS.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"draw-L71G180-.cjs","sources":["../src/algorithms/intersections/fullLinesIntersection.ts","../src/algorithms/offsets/offsetSegment.ts","../src/algorithms/filletSegments.ts","../src/draw.ts"],"sourcesContent":["import { Vector } from \"../../definitions\";\nimport {\n add,\n crossProduct,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\n\n/**\n * Returns the intersection point between two full lines\n *\n * Note that collinear lines are not considered to intersect at all.\n *\n * Lines are represented by a vector V with **unit length** and a point on the line.\n *\n */\nexport const fullLineIntersection = (\n line1: { V: Vector; firstPoint: Vector; precision: number },\n line2: { V: Vector; firstPoint: Vector; precision: number },\n precision?: number,\n): \"parallel\" | Vector => {\n const V1xV2 = crossProduct(line1.V, line2.V);\n\n /*\n const xLength = squareLength(line1.V);\n const yLength = squareLength(line2.V);\n */\n\n const squarePrecision = precision\n ? precision * precision\n : line1.precision * line2.precision;\n\n if (V1xV2 * V1xV2 < squarePrecision) {\n return \"parallel\";\n }\n\n const diffPoint = subtract(line2.firstPoint, line1.firstPoint);\n const intersectionParam = crossProduct(diffPoint, line2.V) / V1xV2;\n\n return add(line1.firstPoint, scalarMultiply(line1.V, intersectionParam));\n};\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport {\n add,\n distance,\n dotProduct,\n perpendicular,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\nimport { Vector } from \"../../definitions.js\";\nimport { CubicBezier, QuadraticBezier } from \"../../models/exports.js\";\nimport { fullLineIntersection } from \"../intersections/fullLinesIntersection.js\";\nimport {\n SafeCubicBezier,\n SafeQuadraticBezier,\n} from \"../conversions/bezierToSafeBezier.js\";\n\nexport class DegenerateSegment {\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector,\n ) {}\n}\n\nexport type OffsettableSegment =\n | Line\n | Arc\n | SafeCubicBezier\n | SafeQuadraticBezier;\n\nexport function offsetSegment(\n segment: OffsettableSegment,\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 if (segment instanceof QuadraticBezier || segment instanceof CubicBezier) {\n return offsetSafeBezier(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\nfunction computeControlPointOffset(\n origin: Vector,\n controlPoint: Vector,\n tangent: Vector,\n newPoint: Vector,\n precision: number,\n): Vector {\n const newControlPoint = fullLineIntersection(\n {\n V: tangent,\n firstPoint: newPoint,\n precision: precision,\n },\n {\n V: subtract(controlPoint, origin),\n firstPoint: origin,\n precision: precision,\n },\n );\n\n if (newControlPoint === \"parallel\") {\n throw new Error(\n \"Parallel lines not expected in safe bezier offset control point calculation\",\n );\n }\n\n return newControlPoint;\n}\n\nexport function offsetSafeBezier(\n curve: SafeQuadraticBezier | SafeCubicBezier,\n offset: number,\n): typeof curve | DegenerateSegment {\n const { firstPoint, lastPoint, normalAtFirstPoint, normalAtLastPoint } =\n curve;\n\n const origin = fullLineIntersection(\n { V: normalAtFirstPoint, firstPoint, precision: curve.precision },\n { V: normalAtLastPoint, firstPoint: lastPoint, precision: curve.precision },\n );\n\n const offsetStartPoint = add(\n firstPoint,\n scalarMultiply(normalAtFirstPoint, offset),\n );\n const offsetEndPoint = add(\n lastPoint,\n scalarMultiply(normalAtLastPoint, offset),\n );\n\n if (origin === \"parallel\") {\n throw new Error(\"Parallel lines not expected in safe bezier offset\");\n }\n\n const offsetTowardsOrigin =\n dotProduct(subtract(origin, firstPoint), normalAtFirstPoint) * offset > 0;\n if (offsetTowardsOrigin) {\n const minDistance = Math.min(\n distance(firstPoint, origin),\n distance(lastPoint, origin),\n );\n\n if (minDistance < offset) {\n return new DegenerateSegment(offsetStartPoint, offsetEndPoint);\n }\n }\n\n if (curve instanceof QuadraticBezier) {\n const newControlPoint = computeControlPointOffset(\n origin,\n curve.controlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n\n return new QuadraticBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint,\n );\n }\n\n const newControlPoint1 = computeControlPointOffset(\n origin,\n curve.firstControlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n const newControlPoint2 = computeControlPointOffset(\n origin,\n curve.lastControlPoint,\n curve.tangentAtLastPoint,\n offsetEndPoint,\n curve.precision,\n );\n\n return new CubicBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint1,\n newControlPoint2,\n );\n}\n","import { Vector } from \"../definitions.js\";\nimport { Line } from \"../models/segments/Line.js\";\nimport { tangentArc } from \"../models/segments/Arc.js\";\nimport type { Segment } from \"../models/segments/Segment.js\";\nimport {\n add,\n crossProduct,\n perpendicular,\n perpendicularClockwise,\n scalarMultiply,\n} from \"../vectorOperations\";\nimport { findIntersections } from \"./intersections\";\nimport { DegenerateSegment, offsetSegment } from \"./offsets/offsetSegment.js\";\nimport { exportJSON } from \"../main.js\";\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 {\n chamferSegments,\n filletSegments,\n} from \"./algorithms/filletSegments.js\";\nimport { Vector } from \"./definitions.js\";\nimport { Strand } from \"./models/Strand.js\";\nimport { Diagram } from \"./models/Diagram.js\";\nimport { Figure } from \"./models/Figure.js\";\nimport { Loop } from \"./models/Loop.js\";\nimport { tangentArc, threePointsArc } from \"./models/segments/Arc.js\";\nimport { Line } from \"./models/segments/Line.js\";\nimport { Segment } from \"./models/segments/Segment.js\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix.js\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n perpendicular,\n add,\n scalarMultiply,\n distance,\n cartesianToPolar,\n RAD2DEG,\n normalize,\n} from \"./vectorOperations.js\";\nimport { svgEllipse } from \"./models/segments/EllipseArc.js\";\nimport { QuadraticBezier } from \"./models/segments/QuadraticBezier.js\";\nimport { CubicBezier } from \"./models/segments/CubicBezier.js\";\n\nconst parseSmoothCurveConfig = (\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n) => {\n let conf: {\n endTangent: number | Vector;\n startFactor?: number;\n endFactor?: number;\n startTangent?: number | Vector;\n };\n\n if (!config) conf = { endTangent: [1, 0] };\n else if (\n typeof config === \"number\" ||\n (Array.isArray(config) && config.length === 2)\n ) {\n conf = { endTangent: config };\n } else {\n conf = { endTangent: 0, ...config };\n }\n const {\n endTangent: endTgt,\n startFactor = 1,\n endFactor = 1,\n startTangent: startTgt,\n } = conf;\n\n let endTangent: Vector;\n if (typeof endTgt === \"number\") {\n endTangent = polarToCartesian(1, endTgt * DEG2RAD);\n } else {\n endTangent = endTgt;\n }\n\n let startTangent: Vector | undefined;\n if (typeof startTgt === \"number\") {\n startTangent = polarToCartesian(1, startTgt * DEG2RAD);\n } else {\n startTangent = startTgt;\n }\n\n return { endTangent, startFactor, endFactor, startTangent };\n};\n\nfunction loopySegmentsToDiagram(\n segments: Segment[],\n { ignoreChecks = false } = {},\n) {\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], { ignoreChecks }))]);\n}\n\nexport class DrawingPen {\n 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, tangentAtStart?: 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(\n this.pointer,\n end,\n tangentAtStart ?? previousCurve.tangentAtLastPoint,\n ),\n );\n\n this.pointer = end;\n return this;\n }\n\n tangentArc(xDist: number, yDist: number, tangentAtStart?: Vector): this {\n const [x0, y0] = this.pointer;\n return this.tangentArcTo([xDist + x0, yDist + y0], tangentAtStart);\n }\n\n ellipseTo(\n end: Vector,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n this.saveSegment(\n svgEllipse(this.pointer, end, r0, r1, xAxisRotation, longArc, sweepFlag),\n );\n this.pointer = end;\n return this;\n }\n\n ellipse(\n xDist: number,\n yDist: number,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n return this.ellipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n r0,\n r1,\n xAxisRotation,\n longArc,\n sweepFlag,\n );\n }\n\n halfEllipseTo(end: Vector, sagitta: number): this {\n const [distance, angle] = cartesianToPolar(subtract(end, this.pointer));\n\n return this.ellipseTo(\n end,\n distance / 2,\n Math.abs(sagitta),\n angle * RAD2DEG,\n true,\n sagitta > 0,\n );\n }\n\n halfEllipse(xDist: number, yDist: number, sagitta: number): this {\n return this.halfEllipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n sagitta,\n );\n }\n\n cubicBezierCurveTo(\n end: Vector,\n startControlPoint: Vector,\n endControlPoint: Vector,\n ): this {\n this.saveSegment(\n new CubicBezier(this.pointer, end, startControlPoint, endControlPoint),\n );\n this.pointer = end;\n return this;\n }\n\n quadraticBezierCurveTo(end: Vector, controlPoint: Vector): this {\n this.saveSegment(new QuadraticBezier(this.pointer, end, controlPoint));\n this.pointer = end;\n return this;\n }\n\n smoothCurveTo(\n end: Vector,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ): this {\n const { endTangent, startTangent, startFactor, endFactor } =\n parseSmoothCurveConfig(config);\n\n const previousCurve = this.pendingSegments.length\n ? this.pendingSegments[this.pendingSegments.length - 1]\n : null;\n\n const defaultDistance = distance(this.pointer, end) / 3;\n\n let startPoleDirection: Vector;\n if (startTangent) {\n startPoleDirection = startTangent;\n } else if (!previousCurve) {\n startPoleDirection = [1, 0];\n } else {\n startPoleDirection = previousCurve.tangentAtLastPoint;\n }\n\n startPoleDirection = normalize(startPoleDirection);\n const startControl: Vector = [\n this.pointer[0] + startPoleDirection[0] * startFactor * defaultDistance,\n this.pointer[1] + startPoleDirection[1] * startFactor * defaultDistance,\n ];\n\n let endPoleDirection = endTangent;\n\n endPoleDirection = normalize(endPoleDirection);\n const endControl: Vector = [\n end[0] - endPoleDirection[0] * endFactor * defaultDistance,\n end[1] - endPoleDirection[1] * endFactor * defaultDistance,\n ];\n\n return this.cubicBezierCurveTo(end, startControl, endControl);\n }\n\n smoothCurve(\n xDist: number,\n yDist: number,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ) {\n return this.smoothCurveTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n config,\n );\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 if (!radius) return this;\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(ignoreChecks = false): 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, { ignoreChecks });\n }\n\n closeWithMirror(ignoreChecks = false): 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, ...mirroredSegments],\n { ignoreChecks },\n );\n }\n\n asStrand(): Strand {\n return new Strand([...this.pendingSegments]);\n }\n\n get isClosed(): boolean {\n return sameVector(this.pointer, this.pendingSegments[0]?.firstPoint);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n"],"names":["fullLineIntersection","line1","line2","precision","V1xV2","crossProduct","squarePrecision","diffPoint","subtract","intersectionParam","add","scalarMultiply","DegenerateSegment","firstPoint","lastPoint","offsetSegment","segment","offset","Line","offsetLine","Arc","offsetArc","QuadraticBezier","CubicBezier","offsetSafeBezier","line","normal","arc","offsetStartPoint","perpendicular","offsetEndPoint","orientedOffset","computeControlPointOffset","origin","controlPoint","tangent","newPoint","newControlPoint","curve","normalAtFirstPoint","normalAtLastPoint","dotProduct","distance","newControlPoint1","newControlPoint2","removeCorner","firstSegment","secondSegment","radius","sinAngle","orientationCorrection","firstOffset","secondOffset","potentialCenter","findIntersections","center","splitForFillet","tgt","perpendicularClockwise","splitPoint","first","second","filletSegments","cornerRemoved","tangentArc","chamferSegments","parseSmoothCurveConfig","config","conf","endTgt","startFactor","endFactor","startTgt","endTangent","polarToCartesian","DEG2RAD","startTangent","loopySegmentsToDiagram","segments","ignoreChecks","Diagram","Figure","Loop","DrawingPen","__publicField","point","sameVector","previousSegment","makeCorner","xDist","yDist","yPos","xPos","r","theta","angleInRads","angle","x","y","previousCurve","xDir","yDir","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","sagPoint","bulge","halfChord","bulgeAsSagitta","tangentAtStart","r0","r1","xAxisRotation","longArc","sweepFlag","svgEllipse","cartesianToPolar","RAD2DEG","startControlPoint","endControlPoint","defaultDistance","startPoleDirection","normalize","startControl","endPoleDirection","endControl","mode","lastSegment","mirrorVector","mirrorTranform","TransformationMatrix","mirroredSegments","Strand","_a","draw"],"mappings":"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"}
1
+ {"version":3,"file":"draw-BUUNobTS.cjs","sources":["../src/algorithms/intersections/fullLinesIntersection.ts","../src/algorithms/offsets/offsetSegment.ts","../src/algorithms/filletSegments.ts","../src/draw.ts"],"sourcesContent":["import { Vector } from \"../../definitions\";\nimport {\n add,\n crossProduct,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\n\n/**\n * Returns the intersection point between two full lines\n *\n * Note that collinear lines are not considered to intersect at all.\n *\n * Lines are represented by a vector V with **unit length** and a point on the line.\n *\n */\nexport const fullLineIntersection = (\n line1: { V: Vector; firstPoint: Vector; precision: number },\n line2: { V: Vector; firstPoint: Vector; precision: number },\n precision?: number,\n): \"parallel\" | Vector => {\n const V1xV2 = crossProduct(line1.V, line2.V);\n\n /*\n const xLength = squareLength(line1.V);\n const yLength = squareLength(line2.V);\n */\n\n const squarePrecision = precision\n ? precision * precision\n : line1.precision * line2.precision;\n\n if (V1xV2 * V1xV2 < squarePrecision) {\n return \"parallel\";\n }\n\n const diffPoint = subtract(line2.firstPoint, line1.firstPoint);\n const intersectionParam = crossProduct(diffPoint, line2.V) / V1xV2;\n\n return add(line1.firstPoint, scalarMultiply(line1.V, intersectionParam));\n};\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport {\n add,\n distance,\n dotProduct,\n perpendicular,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\nimport { Vector } from \"../../definitions.js\";\nimport { CubicBezier, QuadraticBezier } from \"../../models/exports.js\";\nimport { fullLineIntersection } from \"../intersections/fullLinesIntersection.js\";\nimport {\n SafeCubicBezier,\n SafeQuadraticBezier,\n} from \"../conversions/bezierToSafeBezier.js\";\n\nexport class DegenerateSegment {\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector,\n ) {}\n}\n\nexport type OffsettableSegment =\n | Line\n | Arc\n | SafeCubicBezier\n | SafeQuadraticBezier;\n\nexport function offsetSegment(\n segment: OffsettableSegment,\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 if (segment instanceof QuadraticBezier || segment instanceof CubicBezier) {\n return offsetSafeBezier(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\nfunction computeControlPointOffset(\n origin: Vector,\n controlPoint: Vector,\n tangent: Vector,\n newPoint: Vector,\n precision: number,\n): Vector {\n const newControlPoint = fullLineIntersection(\n {\n V: tangent,\n firstPoint: newPoint,\n precision: precision,\n },\n {\n V: subtract(controlPoint, origin),\n firstPoint: origin,\n precision: precision,\n },\n );\n\n if (newControlPoint === \"parallel\") {\n throw new Error(\n \"Parallel lines not expected in safe bezier offset control point calculation\",\n );\n }\n\n return newControlPoint;\n}\n\nexport function offsetSafeBezier(\n curve: SafeQuadraticBezier | SafeCubicBezier,\n offset: number,\n): typeof curve | DegenerateSegment {\n const { firstPoint, lastPoint, normalAtFirstPoint, normalAtLastPoint } =\n curve;\n\n const origin = fullLineIntersection(\n { V: normalAtFirstPoint, firstPoint, precision: curve.precision },\n { V: normalAtLastPoint, firstPoint: lastPoint, precision: curve.precision },\n );\n\n const offsetStartPoint = add(\n firstPoint,\n scalarMultiply(normalAtFirstPoint, offset),\n );\n const offsetEndPoint = add(\n lastPoint,\n scalarMultiply(normalAtLastPoint, offset),\n );\n\n if (origin === \"parallel\") {\n throw new Error(\"Parallel lines not expected in safe bezier offset\");\n }\n\n const offsetTowardsOrigin =\n dotProduct(subtract(origin, firstPoint), normalAtFirstPoint) * offset > 0;\n if (offsetTowardsOrigin) {\n const minDistance = Math.min(\n distance(firstPoint, origin),\n distance(lastPoint, origin),\n );\n\n if (minDistance < offset) {\n return new DegenerateSegment(offsetStartPoint, offsetEndPoint);\n }\n }\n\n if (curve instanceof QuadraticBezier) {\n const newControlPoint = computeControlPointOffset(\n origin,\n curve.controlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n\n return new QuadraticBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint,\n );\n }\n\n const newControlPoint1 = computeControlPointOffset(\n origin,\n curve.firstControlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n const newControlPoint2 = computeControlPointOffset(\n origin,\n curve.lastControlPoint,\n curve.tangentAtLastPoint,\n offsetEndPoint,\n curve.precision,\n );\n\n return new CubicBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint1,\n newControlPoint2,\n );\n}\n","import { Vector } from \"../definitions.js\";\nimport { Line } from \"../models/segments/Line.js\";\nimport { tangentArc } from \"../models/segments/Arc.js\";\nimport type { Segment } from \"../models/segments/Segment.js\";\nimport {\n add,\n crossProduct,\n perpendicular,\n perpendicularClockwise,\n scalarMultiply,\n} from \"../vectorOperations\";\nimport { findIntersections } from \"./intersections\";\nimport { DegenerateSegment, offsetSegment } from \"./offsets/offsetSegment.js\";\nimport { exportJSON } from \"../main.js\";\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 {\n chamferSegments,\n filletSegments,\n} from \"./algorithms/filletSegments.js\";\nimport { Vector } from \"./definitions.js\";\nimport { Strand } from \"./models/Strand.js\";\nimport { Diagram } from \"./models/Diagram.js\";\nimport { Figure } from \"./models/Figure.js\";\nimport { Loop } from \"./models/Loop.js\";\nimport { tangentArc, threePointsArc } from \"./models/segments/Arc.js\";\nimport { Line } from \"./models/segments/Line.js\";\nimport { Segment } from \"./models/segments/Segment.js\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix.js\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n perpendicular,\n add,\n scalarMultiply,\n distance,\n cartesianToPolar,\n RAD2DEG,\n normalize,\n} from \"./vectorOperations.js\";\nimport { svgEllipse } from \"./models/segments/EllipseArc.js\";\nimport { QuadraticBezier } from \"./models/segments/QuadraticBezier.js\";\nimport { CubicBezier } from \"./models/segments/CubicBezier.js\";\n\nconst parseSmoothCurveConfig = (\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n) => {\n let conf: {\n endTangent: number | Vector;\n startFactor?: number;\n endFactor?: number;\n startTangent?: number | Vector;\n };\n\n if (!config) conf = { endTangent: [1, 0] };\n else if (\n typeof config === \"number\" ||\n (Array.isArray(config) && config.length === 2)\n ) {\n conf = { endTangent: config };\n } else {\n conf = { endTangent: 0, ...config };\n }\n const {\n endTangent: endTgt,\n startFactor = 1,\n endFactor = 1,\n startTangent: startTgt,\n } = conf;\n\n let endTangent: Vector;\n if (typeof endTgt === \"number\") {\n endTangent = polarToCartesian(1, endTgt * DEG2RAD);\n } else {\n endTangent = endTgt;\n }\n\n let startTangent: Vector | undefined;\n if (typeof startTgt === \"number\") {\n startTangent = polarToCartesian(1, startTgt * DEG2RAD);\n } else {\n startTangent = startTgt;\n }\n\n return { endTangent, startFactor, endFactor, startTangent };\n};\n\nfunction loopySegmentsToDiagram(\n segments: Segment[],\n { ignoreChecks = false } = {},\n) {\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], { ignoreChecks }))]);\n}\n\nexport class DrawingPen {\n 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, tangentAtStart?: 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(\n this.pointer,\n end,\n tangentAtStart ?? previousCurve.tangentAtLastPoint,\n ),\n );\n\n this.pointer = end;\n return this;\n }\n\n tangentArc(xDist: number, yDist: number, tangentAtStart?: Vector): this {\n const [x0, y0] = this.pointer;\n return this.tangentArcTo([xDist + x0, yDist + y0], tangentAtStart);\n }\n\n ellipseTo(\n end: Vector,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n this.saveSegment(\n svgEllipse(this.pointer, end, r0, r1, xAxisRotation, longArc, sweepFlag),\n );\n this.pointer = end;\n return this;\n }\n\n ellipse(\n xDist: number,\n yDist: number,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n return this.ellipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n r0,\n r1,\n xAxisRotation,\n longArc,\n sweepFlag,\n );\n }\n\n halfEllipseTo(end: Vector, sagitta: number): this {\n const [distance, angle] = cartesianToPolar(subtract(end, this.pointer));\n\n return this.ellipseTo(\n end,\n distance / 2,\n Math.abs(sagitta),\n angle * RAD2DEG,\n true,\n sagitta > 0,\n );\n }\n\n halfEllipse(xDist: number, yDist: number, sagitta: number): this {\n return this.halfEllipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n sagitta,\n );\n }\n\n cubicBezierCurveTo(\n end: Vector,\n startControlPoint: Vector,\n endControlPoint: Vector,\n ): this {\n this.saveSegment(\n new CubicBezier(this.pointer, end, startControlPoint, endControlPoint),\n );\n this.pointer = end;\n return this;\n }\n\n quadraticBezierCurveTo(end: Vector, controlPoint: Vector): this {\n this.saveSegment(new QuadraticBezier(this.pointer, end, controlPoint));\n this.pointer = end;\n return this;\n }\n\n smoothCurveTo(\n end: Vector,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ): this {\n const { endTangent, startTangent, startFactor, endFactor } =\n parseSmoothCurveConfig(config);\n\n const previousCurve = this.pendingSegments.length\n ? this.pendingSegments[this.pendingSegments.length - 1]\n : null;\n\n const defaultDistance = distance(this.pointer, end) / 3;\n\n let startPoleDirection: Vector;\n if (startTangent) {\n startPoleDirection = startTangent;\n } else if (!previousCurve) {\n startPoleDirection = [1, 0];\n } else {\n startPoleDirection = previousCurve.tangentAtLastPoint;\n }\n\n startPoleDirection = normalize(startPoleDirection);\n const startControl: Vector = [\n this.pointer[0] + startPoleDirection[0] * startFactor * defaultDistance,\n this.pointer[1] + startPoleDirection[1] * startFactor * defaultDistance,\n ];\n\n let endPoleDirection = endTangent;\n\n endPoleDirection = normalize(endPoleDirection);\n const endControl: Vector = [\n end[0] - endPoleDirection[0] * endFactor * defaultDistance,\n end[1] - endPoleDirection[1] * endFactor * defaultDistance,\n ];\n\n return this.cubicBezierCurveTo(end, startControl, endControl);\n }\n\n smoothCurve(\n xDist: number,\n yDist: number,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ) {\n return this.smoothCurveTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n config,\n );\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 if (!radius) return this;\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(ignoreChecks = false): 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, { ignoreChecks });\n }\n\n closeWithMirror(ignoreChecks = false): 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, ...mirroredSegments],\n { ignoreChecks },\n );\n }\n\n asStrand(): Strand {\n return new Strand([...this.pendingSegments]);\n }\n\n get isClosed(): boolean {\n return sameVector(this.pointer, this.pendingSegments[0]?.firstPoint);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n"],"names":["fullLineIntersection","line1","line2","precision","V1xV2","crossProduct","squarePrecision","diffPoint","subtract","intersectionParam","add","scalarMultiply","DegenerateSegment","firstPoint","lastPoint","offsetSegment","segment","offset","Line","offsetLine","Arc","offsetArc","QuadraticBezier","CubicBezier","offsetSafeBezier","line","normal","arc","offsetStartPoint","perpendicular","offsetEndPoint","orientedOffset","computeControlPointOffset","origin","controlPoint","tangent","newPoint","newControlPoint","curve","normalAtFirstPoint","normalAtLastPoint","dotProduct","distance","newControlPoint1","newControlPoint2","removeCorner","firstSegment","secondSegment","radius","sinAngle","orientationCorrection","firstOffset","secondOffset","potentialCenter","findIntersections","center","splitForFillet","tgt","perpendicularClockwise","splitPoint","first","second","filletSegments","cornerRemoved","tangentArc","chamferSegments","parseSmoothCurveConfig","config","conf","endTgt","startFactor","endFactor","startTgt","endTangent","polarToCartesian","DEG2RAD","startTangent","loopySegmentsToDiagram","segments","ignoreChecks","Diagram","Figure","Loop","DrawingPen","__publicField","point","sameVector","previousSegment","makeCorner","xDist","yDist","yPos","xPos","r","theta","angleInRads","angle","x","y","previousCurve","xDir","yDir","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","sagPoint","bulge","halfChord","bulgeAsSagitta","tangentAtStart","r0","r1","xAxisRotation","longArc","sweepFlag","svgEllipse","cartesianToPolar","RAD2DEG","startControlPoint","endControlPoint","defaultDistance","startPoleDirection","normalize","startControl","endPoleDirection","endControl","mode","lastSegment","mirrorVector","mirrorTranform","TransformationMatrix","mirroredSegments","Strand","_a","draw"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  var W = Object.defineProperty;
2
2
  var q = (e, t, n) => t in e ? W(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
3
  var m = (e, t, n) => q(e, typeof t != "symbol" ? t + "" : t, n);
4
- import { a as l, s as u, c as x, b as P, L as d, A as R, Q as w, C as D, p as E, d as G, e as T, t as k, f as Q, g as L, h as j, i as $, j as H, R as J, T as K, k as A, n as F, D as C } from "./QuadraticBezier-PcRS9HZK.js";
5
- import { f as U, S as X, D as Z, F as tt, L as nt } from "./models-BjaFYsN2.js";
4
+ import { a as l, s as u, c as x, b as P, L as d, A as R, Q as w, C as D, p as E, d as G, e as T, t as k, f as Q, g as L, h as j, i as $, j as H, R as J, T as K, k as A, n as F, D as C } from "./QuadraticBezier-DxieHk9z.js";
5
+ import { f as U, S as X, D as Z, F as tt, L as nt } from "./models-DCkOI0hV.js";
6
6
  const B = (e, t, n) => {
7
7
  const r = x(e.V, t.V), i = e.precision * t.precision;
8
8
  if (r * r < i)
@@ -411,7 +411,9 @@ function lt(e = [0, 0]) {
411
411
  }
412
412
  export {
413
413
  S as D,
414
+ ot as a,
414
415
  lt as d,
416
+ V as f,
415
417
  y as o
416
418
  };
417
- //# sourceMappingURL=draw-N2ntigsw.js.map
419
+ //# sourceMappingURL=draw-lOWnIN1o.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"draw-N2ntigsw.js","sources":["../src/algorithms/intersections/fullLinesIntersection.ts","../src/algorithms/offsets/offsetSegment.ts","../src/algorithms/filletSegments.ts","../src/draw.ts"],"sourcesContent":["import { Vector } from \"../../definitions\";\nimport {\n add,\n crossProduct,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\n\n/**\n * Returns the intersection point between two full lines\n *\n * Note that collinear lines are not considered to intersect at all.\n *\n * Lines are represented by a vector V with **unit length** and a point on the line.\n *\n */\nexport const fullLineIntersection = (\n line1: { V: Vector; firstPoint: Vector; precision: number },\n line2: { V: Vector; firstPoint: Vector; precision: number },\n precision?: number,\n): \"parallel\" | Vector => {\n const V1xV2 = crossProduct(line1.V, line2.V);\n\n /*\n const xLength = squareLength(line1.V);\n const yLength = squareLength(line2.V);\n */\n\n const squarePrecision = precision\n ? precision * precision\n : line1.precision * line2.precision;\n\n if (V1xV2 * V1xV2 < squarePrecision) {\n return \"parallel\";\n }\n\n const diffPoint = subtract(line2.firstPoint, line1.firstPoint);\n const intersectionParam = crossProduct(diffPoint, line2.V) / V1xV2;\n\n return add(line1.firstPoint, scalarMultiply(line1.V, intersectionParam));\n};\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport {\n add,\n distance,\n dotProduct,\n perpendicular,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\nimport { Vector } from \"../../definitions.js\";\nimport { CubicBezier, QuadraticBezier } from \"../../models/exports.js\";\nimport { fullLineIntersection } from \"../intersections/fullLinesIntersection.js\";\nimport {\n SafeCubicBezier,\n SafeQuadraticBezier,\n} from \"../conversions/bezierToSafeBezier.js\";\n\nexport class DegenerateSegment {\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector,\n ) {}\n}\n\nexport type OffsettableSegment =\n | Line\n | Arc\n | SafeCubicBezier\n | SafeQuadraticBezier;\n\nexport function offsetSegment(\n segment: OffsettableSegment,\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 if (segment instanceof QuadraticBezier || segment instanceof CubicBezier) {\n return offsetSafeBezier(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\nfunction computeControlPointOffset(\n origin: Vector,\n controlPoint: Vector,\n tangent: Vector,\n newPoint: Vector,\n precision: number,\n): Vector {\n const newControlPoint = fullLineIntersection(\n {\n V: tangent,\n firstPoint: newPoint,\n precision: precision,\n },\n {\n V: subtract(controlPoint, origin),\n firstPoint: origin,\n precision: precision,\n },\n );\n\n if (newControlPoint === \"parallel\") {\n throw new Error(\n \"Parallel lines not expected in safe bezier offset control point calculation\",\n );\n }\n\n return newControlPoint;\n}\n\nexport function offsetSafeBezier(\n curve: SafeQuadraticBezier | SafeCubicBezier,\n offset: number,\n): typeof curve | DegenerateSegment {\n const { firstPoint, lastPoint, normalAtFirstPoint, normalAtLastPoint } =\n curve;\n\n const origin = fullLineIntersection(\n { V: normalAtFirstPoint, firstPoint, precision: curve.precision },\n { V: normalAtLastPoint, firstPoint: lastPoint, precision: curve.precision },\n );\n\n const offsetStartPoint = add(\n firstPoint,\n scalarMultiply(normalAtFirstPoint, offset),\n );\n const offsetEndPoint = add(\n lastPoint,\n scalarMultiply(normalAtLastPoint, offset),\n );\n\n if (origin === \"parallel\") {\n throw new Error(\"Parallel lines not expected in safe bezier offset\");\n }\n\n const offsetTowardsOrigin =\n dotProduct(subtract(origin, firstPoint), normalAtFirstPoint) * offset > 0;\n if (offsetTowardsOrigin) {\n const minDistance = Math.min(\n distance(firstPoint, origin),\n distance(lastPoint, origin),\n );\n\n if (minDistance < offset) {\n return new DegenerateSegment(offsetStartPoint, offsetEndPoint);\n }\n }\n\n if (curve instanceof QuadraticBezier) {\n const newControlPoint = computeControlPointOffset(\n origin,\n curve.controlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n\n return new QuadraticBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint,\n );\n }\n\n const newControlPoint1 = computeControlPointOffset(\n origin,\n curve.firstControlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n const newControlPoint2 = computeControlPointOffset(\n origin,\n curve.lastControlPoint,\n curve.tangentAtLastPoint,\n offsetEndPoint,\n curve.precision,\n );\n\n return new CubicBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint1,\n newControlPoint2,\n );\n}\n","import { Vector } from \"../definitions.js\";\nimport { Line } from \"../models/segments/Line.js\";\nimport { tangentArc } from \"../models/segments/Arc.js\";\nimport type { Segment } from \"../models/segments/Segment.js\";\nimport {\n add,\n crossProduct,\n perpendicular,\n perpendicularClockwise,\n scalarMultiply,\n} from \"../vectorOperations\";\nimport { findIntersections } from \"./intersections\";\nimport { DegenerateSegment, offsetSegment } from \"./offsets/offsetSegment.js\";\nimport { exportJSON } from \"../main.js\";\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 {\n chamferSegments,\n filletSegments,\n} from \"./algorithms/filletSegments.js\";\nimport { Vector } from \"./definitions.js\";\nimport { Strand } from \"./models/Strand.js\";\nimport { Diagram } from \"./models/Diagram.js\";\nimport { Figure } from \"./models/Figure.js\";\nimport { Loop } from \"./models/Loop.js\";\nimport { tangentArc, threePointsArc } from \"./models/segments/Arc.js\";\nimport { Line } from \"./models/segments/Line.js\";\nimport { Segment } from \"./models/segments/Segment.js\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix.js\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n perpendicular,\n add,\n scalarMultiply,\n distance,\n cartesianToPolar,\n RAD2DEG,\n normalize,\n} from \"./vectorOperations.js\";\nimport { svgEllipse } from \"./models/segments/EllipseArc.js\";\nimport { QuadraticBezier } from \"./models/segments/QuadraticBezier.js\";\nimport { CubicBezier } from \"./models/segments/CubicBezier.js\";\n\nconst parseSmoothCurveConfig = (\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n) => {\n let conf: {\n endTangent: number | Vector;\n startFactor?: number;\n endFactor?: number;\n startTangent?: number | Vector;\n };\n\n if (!config) conf = { endTangent: [1, 0] };\n else if (\n typeof config === \"number\" ||\n (Array.isArray(config) && config.length === 2)\n ) {\n conf = { endTangent: config };\n } else {\n conf = { endTangent: 0, ...config };\n }\n const {\n endTangent: endTgt,\n startFactor = 1,\n endFactor = 1,\n startTangent: startTgt,\n } = conf;\n\n let endTangent: Vector;\n if (typeof endTgt === \"number\") {\n endTangent = polarToCartesian(1, endTgt * DEG2RAD);\n } else {\n endTangent = endTgt;\n }\n\n let startTangent: Vector | undefined;\n if (typeof startTgt === \"number\") {\n startTangent = polarToCartesian(1, startTgt * DEG2RAD);\n } else {\n startTangent = startTgt;\n }\n\n return { endTangent, startFactor, endFactor, startTangent };\n};\n\nfunction loopySegmentsToDiagram(\n segments: Segment[],\n { ignoreChecks = false } = {},\n) {\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], { ignoreChecks }))]);\n}\n\nexport class DrawingPen {\n 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, tangentAtStart?: 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(\n this.pointer,\n end,\n tangentAtStart ?? previousCurve.tangentAtLastPoint,\n ),\n );\n\n this.pointer = end;\n return this;\n }\n\n tangentArc(xDist: number, yDist: number, tangentAtStart?: Vector): this {\n const [x0, y0] = this.pointer;\n return this.tangentArcTo([xDist + x0, yDist + y0], tangentAtStart);\n }\n\n ellipseTo(\n end: Vector,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n this.saveSegment(\n svgEllipse(this.pointer, end, r0, r1, xAxisRotation, longArc, sweepFlag),\n );\n this.pointer = end;\n return this;\n }\n\n ellipse(\n xDist: number,\n yDist: number,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n return this.ellipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n r0,\n r1,\n xAxisRotation,\n longArc,\n sweepFlag,\n );\n }\n\n halfEllipseTo(end: Vector, sagitta: number): this {\n const [distance, angle] = cartesianToPolar(subtract(end, this.pointer));\n\n return this.ellipseTo(\n end,\n distance / 2,\n Math.abs(sagitta),\n angle * RAD2DEG,\n true,\n sagitta > 0,\n );\n }\n\n halfEllipse(xDist: number, yDist: number, sagitta: number): this {\n return this.halfEllipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n sagitta,\n );\n }\n\n cubicBezierCurveTo(\n end: Vector,\n startControlPoint: Vector,\n endControlPoint: Vector,\n ): this {\n this.saveSegment(\n new CubicBezier(this.pointer, end, startControlPoint, endControlPoint),\n );\n this.pointer = end;\n return this;\n }\n\n quadraticBezierCurveTo(end: Vector, controlPoint: Vector): this {\n this.saveSegment(new QuadraticBezier(this.pointer, end, controlPoint));\n this.pointer = end;\n return this;\n }\n\n smoothCurveTo(\n end: Vector,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ): this {\n const { endTangent, startTangent, startFactor, endFactor } =\n parseSmoothCurveConfig(config);\n\n const previousCurve = this.pendingSegments.length\n ? this.pendingSegments[this.pendingSegments.length - 1]\n : null;\n\n const defaultDistance = distance(this.pointer, end) / 3;\n\n let startPoleDirection: Vector;\n if (startTangent) {\n startPoleDirection = startTangent;\n } else if (!previousCurve) {\n startPoleDirection = [1, 0];\n } else {\n startPoleDirection = previousCurve.tangentAtLastPoint;\n }\n\n startPoleDirection = normalize(startPoleDirection);\n const startControl: Vector = [\n this.pointer[0] + startPoleDirection[0] * startFactor * defaultDistance,\n this.pointer[1] + startPoleDirection[1] * startFactor * defaultDistance,\n ];\n\n let endPoleDirection = endTangent;\n\n endPoleDirection = normalize(endPoleDirection);\n const endControl: Vector = [\n end[0] - endPoleDirection[0] * endFactor * defaultDistance,\n end[1] - endPoleDirection[1] * endFactor * defaultDistance,\n ];\n\n return this.cubicBezierCurveTo(end, startControl, endControl);\n }\n\n smoothCurve(\n xDist: number,\n yDist: number,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ) {\n return this.smoothCurveTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n config,\n );\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 if (!radius) return this;\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(ignoreChecks = false): 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, { ignoreChecks });\n }\n\n closeWithMirror(ignoreChecks = false): 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, ...mirroredSegments],\n { ignoreChecks },\n );\n }\n\n asStrand(): Strand {\n return new Strand([...this.pendingSegments]);\n }\n\n get isClosed(): boolean {\n return sameVector(this.pointer, this.pendingSegments[0]?.firstPoint);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n"],"names":["fullLineIntersection","line1","line2","precision","V1xV2","crossProduct","squarePrecision","diffPoint","subtract","intersectionParam","add","scalarMultiply","DegenerateSegment","firstPoint","lastPoint","offsetSegment","segment","offset","Line","offsetLine","Arc","offsetArc","QuadraticBezier","CubicBezier","offsetSafeBezier","line","normal","arc","offsetStartPoint","perpendicular","offsetEndPoint","orientedOffset","computeControlPointOffset","origin","controlPoint","tangent","newPoint","newControlPoint","curve","normalAtFirstPoint","normalAtLastPoint","dotProduct","distance","newControlPoint1","newControlPoint2","removeCorner","firstSegment","secondSegment","radius","sinAngle","orientationCorrection","firstOffset","secondOffset","potentialCenter","findIntersections","center","splitForFillet","tgt","perpendicularClockwise","splitPoint","first","second","filletSegments","cornerRemoved","tangentArc","chamferSegments","parseSmoothCurveConfig","config","conf","endTgt","startFactor","endFactor","startTgt","endTangent","polarToCartesian","DEG2RAD","startTangent","loopySegmentsToDiagram","segments","ignoreChecks","Diagram","Figure","Loop","DrawingPen","__publicField","point","sameVector","previousSegment","makeCorner","xDist","yDist","yPos","xPos","r","theta","angleInRads","angle","x","y","previousCurve","xDir","yDir","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","sagPoint","bulge","halfChord","bulgeAsSagitta","tangentAtStart","r0","r1","xAxisRotation","longArc","sweepFlag","svgEllipse","cartesianToPolar","RAD2DEG","startControlPoint","endControlPoint","defaultDistance","startPoleDirection","normalize","startControl","endPoleDirection","endControl","mode","lastSegment","mirrorVector","mirrorTranform","TransformationMatrix","mirroredSegments","Strand","_a","draw"],"mappings":";;;;;AAgBO,MAAMA,IAAuB,CAClCC,GACAC,GACAC,MACwB;AACxB,QAAMC,IAAQC,EAAaJ,EAAM,GAAGC,EAAM,CAAC,GAOrCI,IAEFL,EAAM,YAAYC,EAAM;AAExB,MAAAE,IAAQA,IAAQE;AACX,WAAA;AAGT,QAAMC,IAAYC,EAASN,EAAM,YAAYD,EAAM,UAAU,GACvDQ,IAAoBJ,EAAaE,GAAWL,EAAM,CAAC,IAAIE;AAE7D,SAAOM,EAAIT,EAAM,YAAYU,EAAeV,EAAM,GAAGQ,CAAiB,CAAC;AACzE;ACrBO,MAAMG,EAAkB;AAAA,EAC7B,YACkBC,GACAC,GAChB;AAFgB,SAAA,aAAAD,GACA,KAAA,YAAAC;AAAA,EAAA;AAEpB;AAQgB,SAAAC,EACdC,GACAC,GAC6B;AAC7B,MAAID,aAAmBE;AACd,WAAAC,GAAWH,GAASC,CAAM;AAGnC,MAAID,aAAmBI;AACd,WAAAC,GAAUL,GAASC,CAAM;AAG9B,MAAAD,aAAmBM,KAAmBN,aAAmBO;AACpD,WAAAC,GAAiBR,GAASC,CAAM;AAGnC,QAAA,IAAI,MAAM,iBAAiB;AACnC;AAEgB,SAAAE,GAAWM,GAAYR,GAAsB;AACrD,QAAA,EAAE,YAAAJ,GAAY,WAAAC,EAAA,IAAcW,GAE5BC,IAASD,EAAK;AACpB,SAAO,IAAIP;AAAA,IACTR,EAAIG,GAAYF,EAAee,GAAQT,CAAM,CAAC;AAAA,IAC9CP,EAAII,GAAWH,EAAee,GAAQT,CAAM,CAAC;AAAA,EAC/C;AACF;AAEgB,SAAAI,GAAUM,GAAUV,GAAyC;AAC3E,QAAMW,IAAmBlB;AAAA,IACvBiB,EAAI;AAAA,IACJhB,EAAekB,EAAcF,EAAI,mBAAmB,GAAGV,CAAM;AAAA,EAC/D,GACMa,IAAiBpB;AAAA,IACrBiB,EAAI;AAAA,IACJhB,EAAekB,EAAcF,EAAI,kBAAkB,GAAGV,CAAM;AAAA,EAC9D,GAEMc,IAAiBd,KAAUU,EAAI,YAAY,IAAI;AAEjD,SADcA,EAAI,SAASI,IACfJ,EAAI,YACX,IAAIf,EAAkBgB,GAAkBE,CAAc,IAGxD,IAAIV,EAAIQ,GAAkBE,GAAgBH,EAAI,QAAQA,EAAI,SAAS;AAC5E;AAEA,SAASK,EACPC,GACAC,GACAC,GACAC,GACAjC,GACQ;AACR,QAAMkC,IAAkBrC;AAAA,IACtB;AAAA,MACE,GAAGmC;AAAA,MACH,YAAYC;AAAA,MACZ,WAAAjC;AAAA,IACF;AAAA,IACA;AAAA,MACE,GAAGK,EAAS0B,GAAcD,CAAM;AAAA,MAChC,YAAYA;AAAA,MACZ,WAAA9B;AAAA,IAAA;AAAA,EAEJ;AAEA,MAAIkC,MAAoB;AACtB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGK,SAAAA;AACT;AAEgB,SAAAb,GACdc,GACArB,GACkC;AAClC,QAAM,EAAE,YAAAJ,GAAY,WAAAC,GAAW,oBAAAyB,GAAoB,mBAAAC,EACjD,IAAAF,GAEIL,IAASjC;AAAA,IACb,EAAE,GAAGuC,GAAoB,YAAA1B,GAAY,WAAWyB,EAAM,UAAU;AAAA,IAChE,EAAE,GAAGE,GAAmB,YAAY1B,GAAW,WAAWwB,EAAM,UAAU;AAAA,EAC5E,GAEMV,IAAmBlB;AAAA,IACvBG;AAAA,IACAF,EAAe4B,GAAoBtB,CAAM;AAAA,EAC3C,GACMa,IAAiBpB;AAAA,IACrBI;AAAA,IACAH,EAAe6B,GAAmBvB,CAAM;AAAA,EAC1C;AAEA,MAAIgB,MAAW;AACP,UAAA,IAAI,MAAM,mDAAmD;AAKrE,MADEQ,EAAWjC,EAASyB,GAAQpB,CAAU,GAAG0B,CAAkB,IAAItB,IAAS,KAEpD,KAAK;AAAA,IACvByB,EAAS7B,GAAYoB,CAAM;AAAA,IAC3BS,EAAS5B,GAAWmB,CAAM;AAAA,EAC5B,IAEkBhB;AACT,WAAA,IAAIL,EAAkBgB,GAAkBE,CAAc;AAIjE,MAAIQ,aAAiBhB,GAAiB;AACpC,UAAMe,IAAkBL;AAAA,MACtBC;AAAA,MACAK,EAAM;AAAA,MACNA,EAAM;AAAA,MACNV;AAAA,MACAU,EAAM;AAAA,IACR;AAEA,WAAO,IAAIhB;AAAA,MACTM;AAAA,MACAE;AAAA,MACAO;AAAA,IACF;AAAA,EAAA;AAGF,QAAMM,IAAmBX;AAAA,IACvBC;AAAA,IACAK,EAAM;AAAA,IACNA,EAAM;AAAA,IACNV;AAAA,IACAU,EAAM;AAAA,EACR,GACMM,IAAmBZ;AAAA,IACvBC;AAAA,IACAK,EAAM;AAAA,IACNA,EAAM;AAAA,IACNR;AAAA,IACAQ,EAAM;AAAA,EACR;AAEA,SAAO,IAAIf;AAAA,IACTK;AAAA,IACAE;AAAA,IACAa;AAAA,IACAC;AAAA,EACF;AACF;ACzKA,SAASC,EACPC,GACAC,GACAC,GACA;AACA,QAAMC,IAAW5C;AAAA,IACfyC,EAAa;AAAA,IACbC,EAAc;AAAA,EAChB;AAGA,MAAI,KAAK,IAAIE,CAAQ,IAAI,MAAc,QAAA;AAEjC,QAAAC,IAAwBD,IAAW,IAAI,IAAI,IAC3ChC,IAAS,KAAK,IAAI+B,CAAM,IAAIE,GAE5BC,IAAcpC,EAAc+B,GAAc7B,CAAM,GAChDmC,IAAerC,EAAcgC,GAAe9B,CAAM;AAGtD,MAAAkC,aAAuBvC,KACvBwC,aAAwBxC;AAEjB,WAAA;AAGL,MAAAyC;AACA,MAAA;AAIgB,IAAAA,IAHIC,EAAkBH,GAAaC,GAAc,IAAI,EAGvC,GAAG,EAAE;AAAA,UAC3B;AACH,WAAA;AAAA,EAAA;AAGT,MAAI,CAACC;AACI,WAAA;AAET,QAAME,IAASF,GAETG,IAAiB,CAACxC,GAAkBD,MAA2B;AAC7D,UAAA0C,IAAM1C,EAAc,UAAUwC,CAAM,GACpC7B,IAASgC,EAAuBD,CAAG,GACnCE,IAAajD,EAAI6C,GAAQ5C,EAAee,GAAQT,CAAM,CAAC;AACtD,WAAAD,EAAQ,QAAQ2C,CAAU;AAAA,EACnC,GAEM,CAACC,CAAK,IAAIJ,EAAeV,GAAcK,CAAW,GAClD,CAAG,EAAAU,CAAM,IAAIL,EAAeT,GAAeK,CAAY;AAEtD,SAAA,EAAE,OAAAQ,GAAO,QAAAC,GAAQ,QAAAN,EAAO;AACjC;AAEgB,SAAAO,EACdhB,GACAC,GACAC,GACA;AACA,QAAMe,IAAgBlB,EAAaC,GAAcC,GAAeC,CAAM;AACtE,MAAI,CAACe;AACK,mBAAA;AAAA,MACN;AAAA,MACAjB,EAAa;AAAA,MACbC,EAAc;AAAA,IAChB,GACO,CAACD,GAAcC,CAAa;AAG/B,QAAA,EAAE,OAAAa,GAAO,QAAAC,EAAA,IAAWE;AAEnB,SAAA;AAAA,IACLH;AAAA,IACAI,EAAWJ,EAAM,WAAWC,EAAO,YAAYD,EAAM,kBAAkB;AAAA,IACvEC;AAAA,EACF;AACF;AAEgB,SAAAI,EACdnB,GACAC,GACAC,GACA;AACA,QAAMe,IAAgBlB,EAAaC,GAAcC,GAAeC,CAAM;AACtE,MAAI,CAACe;AACK,mBAAA;AAAA,MACN;AAAA,MACAjB,EAAa;AAAA,MACbC,EAAc;AAAA,IAChB,GACO,CAACD,GAAcC,CAAa;AAG/B,QAAA,EAAE,OAAAa,GAAO,QAAAC,EAAA,IAAWE;AAEnB,SAAA,CAACH,GAAO,IAAI1C,EAAK0C,EAAM,WAAWC,EAAO,UAAU,GAAGA,CAAM;AACrE;ACjFA,MAAMK,KAAyB,CAC7BC,MASG;AACC,MAAAC;AAOA,EAACD,IAEH,OAAOA,KAAW,YACjB,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,IAErCC,IAAA,EAAE,YAAYD,EAAO,IAE5BC,IAAO,EAAE,YAAY,GAAG,GAAGD,EAAO,IAPhBC,IAAA,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE;AASnC,QAAA;AAAA,IACJ,YAAYC;AAAA,IACZ,aAAAC,IAAc;AAAA,IACd,WAAAC,IAAY;AAAA,IACZ,cAAcC;AAAA,EAAA,IACZJ;AAEA,MAAAK;AACA,EAAA,OAAOJ,KAAW,WACPI,IAAAC,EAAiB,GAAGL,IAASM,CAAO,IAEpCF,IAAAJ;AAGX,MAAAO;AACA,SAAA,OAAOJ,KAAa,WACPI,IAAAF,EAAiB,GAAGF,IAAWG,CAAO,IAEtCC,IAAAJ,GAGV,EAAE,YAAAC,GAAY,aAAAH,GAAa,WAAAC,GAAW,cAAAK,EAAa;AAC5D;AAEA,SAASC,EACPC,GACA,EAAE,cAAAC,IAAe,GAAM,IAAI,CAAA,GAC3B;AAIA,SAAO,IAAIC,EAAQ,CAAC,IAAIC,GAAO,IAAIC,GAAK,CAAC,GAAGJ,CAAQ,GAAG,EAAE,cAAAC,EAAc,CAAA,CAAC,CAAC,CAAC;AAC5E;AAEO,MAAMI,GAAW;AAAA,EAOtB,YAAYlD,IAAiB,CAAC,GAAG,CAAC,GAAG;AANrC,IAAAmD,EAAA;AACU,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAGR,SAAK,UAAUnD,GACf,KAAK,aAAaA,GAElB,KAAK,kBAAkB,CAAC,GACxB,KAAK,cAAc;AAAA,EAAA;AAAA,EAGrB,cAAcoD,GAAqB;AACjC,QAAI,KAAK,gBAAgB;AACvB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,gBAAK,UAAUA,GACf,KAAK,aAAaA,GACX;AAAA,EAAA;AAAA,EAGC,YAAYrE,GAAkB;AACtC,QAAIsE,EAAWtE,EAAQ,YAAYA,EAAQ,SAAS;AAClD,YAAM,IAAI,MAAM,0BAA0BA,EAAQ,IAAI,EAAE;AAGtD,QAAA,CAAC,KAAK;AACH,kBAAA,gBAAgB,KAAKA,CAAO,GAC1B;AAGH,UAAAuE,IAAkB,KAAK,gBAAgB,IAAI;AACjD,QAAI,CAACA,EAAuB,OAAA,IAAI,MAAM,oCAAoC;AAE1E,UAAMC,IACJ,KAAK,YAAY,SAAS,YAAYvB,IAAkBH;AAE1D,gBAAK,gBAAgB;AAAA,MACnB,GAAG0B,EAAWD,GAAiBvE,GAAS,KAAK,YAAY,MAAM;AAAA,IACjE,GACA,KAAK,cAAc,MACZ;AAAA,EAAA;AAAA,EAGT,OAAOqE,GAAqB;AAC1B,UAAMrE,IAAU,IAAIE,EAAK,KAAK,SAASmE,CAAK;AAC5C,gBAAK,UAAUA,GACR,KAAK,YAAYrE,CAAO;AAAA,EAAA;AAAA,EAGjC,KAAKyE,GAAeC,GAAqB;AACvC,WAAO,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC,IAAID,GAAO,KAAK,QAAQ,CAAC,IAAIC,CAAK,CAAC;AAAA,EAAA;AAAA,EAGvE,MAAMhD,GAAwB;AACrB,WAAA,KAAK,KAAK,GAAGA,CAAQ;AAAA,EAAA;AAAA,EAG9B,MAAMA,GAAwB;AACrB,WAAA,KAAK,KAAKA,GAAU,CAAC;AAAA,EAAA;AAAA,EAG9B,QAAQiD,GAAoB;AACnB,WAAA,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC,GAAGA,CAAI,CAAC;AAAA,EAAA;AAAA,EAG5C,QAAQC,GAAoB;AACnB,WAAA,KAAK,OAAO,CAACA,GAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,EAAA;AAAA,EAG5C,YAAY,CAACC,GAAGC,CAAK,GAAiB;AACpC,UAAMC,IAAcD,IAAQnB,GACtBU,IAAQX,EAAiBmB,GAAGE,CAAW;AACtC,WAAA,KAAK,OAAOV,CAAK;AAAA,EAAA;AAAA,EAG1B,UAAU3C,GAAkBsD,GAAqB;AAC/C,UAAMD,IAAcC,IAAQrB,GACtB,CAACsB,GAAGC,CAAC,IAAIxB,EAAiBhC,GAAUqD,CAAW;AAC9C,WAAA,KAAK,KAAKE,GAAGC,CAAC;AAAA,EAAA;AAAA,EAGvB,YAAYxD,GAAwB;AAClC,UAAMyD,IAAgB,KAAK,gBAAgB,GAAG,EAAE;AAEhD,QAAI,CAACA;AACG,YAAA,IAAI,MAAM,sDAAsD;AAExE,UAAM,CAACC,GAAMC,CAAI,IAAIF,EAAc;AACnC,WAAO,KAAK,KAAKC,IAAO1D,GAAU2D,IAAO3D,CAAQ;AAAA,EAAA;AAAA,EAGnD,iBAAiB4D,GAAaC,GAAwB;AACpD,gBAAK,YAAYC,EAAe,KAAK,SAASD,GAAUD,CAAG,CAAC,GAC5D,KAAK,UAAUA,GACR;AAAA,EAAA;AAAA,EAGT,eACEb,GACAC,GACAe,GACAC,GACM;AACN,UAAM,CAACC,GAAIC,CAAE,IAAI,KAAK;AACtB,WAAO,KAAK;AAAA,MACV,CAACD,IAAKlB,GAAOmB,IAAKlB,CAAK;AAAA,MACvB,CAACiB,IAAKF,GAAUG,IAAKF,CAAQ;AAAA,IAC/B;AAAA,EAAA;AAAA,EAGF,aAAaJ,GAAaO,GAAuB;AAC/C,QAAI,CAACA,EAAgB,QAAA,KAAK,OAAOP,CAAG;AACpC,UAAMQ,IAAQ,IAAI5F,EAAK,KAAK,SAASoF,CAAG,GAClCS,IAAOlF,EAAciF,EAAM,mBAAmB,GAE9CE,IAAmBtG,EAAIoG,EAAM,UAAUnG,EAAeoG,GAAMF,CAAO,CAAC;AAEnE,WAAA,KAAK,iBAAiBP,GAAKU,CAAQ;AAAA,EAAA;AAAA,EAG5C,WAAWvB,GAAeC,GAAemB,GAAuB;AAC9D,WAAO,KAAK;AAAA,MACV,CAACpB,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjDmB;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,YAAYnE,GAAkBmE,GAAuB;AACnD,WAAO,KAAK,WAAW,GAAGnE,GAAUmE,CAAO;AAAA,EAAA;AAAA,EAG7C,YAAYnE,GAAkBmE,GAAuB;AACnD,WAAO,KAAK,WAAWnE,GAAU,GAAGmE,CAAO;AAAA,EAAA;AAAA,EAG7C,WAAWP,GAAaW,GAAqB;AAC3C,QAAI,CAACA,EAAc,QAAA,KAAK,OAAOX,CAAG;AAClC,UAAMY,IAAYxE,EAAS,KAAK,SAAS4D,CAAG,IAAI,GAC1Ca,IAAiB,CAACF,IAAQC;AAEzB,WAAA,KAAK,aAAaZ,GAAKa,CAAc;AAAA,EAAA;AAAA,EAG9C,SAAS1B,GAAeC,GAAeuB,GAAqB;AAC1D,WAAO,KAAK;AAAA,MACV,CAACxB,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjDuB;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,UAAUvE,GAAkBuE,GAAqB;AAC/C,WAAO,KAAK,SAAS,GAAGvE,GAAUuE,CAAK;AAAA,EAAA;AAAA,EAGzC,UAAUvE,GAAkBuE,GAAqB;AAC/C,WAAO,KAAK,SAASvE,GAAU,GAAGuE,CAAK;AAAA,EAAA;AAAA,EAGzC,aAAaX,GAAac,GAA+B;AACvD,UAAMjB,IAAgB,KAAK,gBAAgB,GAAG,EAAE;AAEhD,QAAI,CAACA;AACG,YAAA,IAAI,MAAM,mDAAmD;AAEhE,gBAAA;AAAA,MACHnC;AAAA,QACE,KAAK;AAAA,QACLsC;AAAA,QACAc,KAAkBjB,EAAc;AAAA,MAAA;AAAA,IAEpC,GAEA,KAAK,UAAUG,GACR;AAAA,EAAA;AAAA,EAGT,WAAWb,GAAeC,GAAe0B,GAA+B;AACtE,UAAM,CAACT,GAAIC,CAAE,IAAI,KAAK;AACf,WAAA,KAAK,aAAa,CAACnB,IAAQkB,GAAIjB,IAAQkB,CAAE,GAAGQ,CAAc;AAAA,EAAA;AAAA,EAGnE,UACEd,GACAe,GACAC,GACAC,GACAC,GACAC,GACM;AACD,gBAAA;AAAA,MACHC,EAAW,KAAK,SAASpB,GAAKe,GAAIC,GAAIC,GAAeC,GAASC,CAAS;AAAA,IACzE,GACA,KAAK,UAAUnB,GACR;AAAA,EAAA;AAAA,EAGT,QACEb,GACAC,GACA2B,GACAC,GACAC,GACAC,GACAC,GACM;AACN,WAAO,KAAK;AAAA,MACV,CAAChC,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjD2B;AAAA,MACAC;AAAA,MACAC;AAAA,MACAC;AAAA,MACAC;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,cAAcnB,GAAaO,GAAuB;AAC1C,UAAA,CAACnE,GAAUsD,CAAK,IAAI2B,EAAiBnH,EAAS8F,GAAK,KAAK,OAAO,CAAC;AAEtE,WAAO,KAAK;AAAA,MACVA;AAAA,MACA5D,IAAW;AAAA,MACX,KAAK,IAAImE,CAAO;AAAA,MAChBb,IAAQ4B;AAAA,MACR;AAAA,MACAf,IAAU;AAAA,IACZ;AAAA,EAAA;AAAA,EAGF,YAAYpB,GAAeC,GAAemB,GAAuB;AAC/D,WAAO,KAAK;AAAA,MACV,CAACpB,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjDmB;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,mBACEP,GACAuB,GACAC,GACM;AACD,gBAAA;AAAA,MACH,IAAIvG,EAAY,KAAK,SAAS+E,GAAKuB,GAAmBC,CAAe;AAAA,IACvE,GACA,KAAK,UAAUxB,GACR;AAAA,EAAA;AAAA,EAGT,uBAAuBA,GAAapE,GAA4B;AAC9D,gBAAK,YAAY,IAAIZ,EAAgB,KAAK,SAASgF,GAAKpE,CAAY,CAAC,GACrE,KAAK,UAAUoE,GACR;AAAA,EAAA;AAAA,EAGT,cACEA,GACAnC,GASM;AACN,UAAM,EAAE,YAAAM,GAAY,cAAAG,GAAc,aAAAN,GAAa,WAAAC,EAAU,IACvDL,GAAuBC,CAAM,GAEzBgC,IAAgB,KAAK,gBAAgB,SACvC,KAAK,gBAAgB,KAAK,gBAAgB,SAAS,CAAC,IACpD,MAEE4B,IAAkBrF,EAAS,KAAK,SAAS4D,CAAG,IAAI;AAElD,QAAA0B;AACJ,IAAIpD,IACmBoD,IAAApD,IACXuB,IAGV6B,IAAqB7B,EAAc,qBAFd6B,IAAA,CAAC,GAAG,CAAC,GAK5BA,IAAqBC,EAAUD,CAAkB;AACjD,UAAME,IAAuB;AAAA,MAC3B,KAAK,QAAQ,CAAC,IAAIF,EAAmB,CAAC,IAAI1D,IAAcyD;AAAA,MACxD,KAAK,QAAQ,CAAC,IAAIC,EAAmB,CAAC,IAAI1D,IAAcyD;AAAA,IAC1D;AAEA,QAAII,IAAmB1D;AAEvB,IAAA0D,IAAmBF,EAAUE,CAAgB;AAC7C,UAAMC,IAAqB;AAAA,MACzB9B,EAAI,CAAC,IAAI6B,EAAiB,CAAC,IAAI5D,IAAYwD;AAAA,MAC3CzB,EAAI,CAAC,IAAI6B,EAAiB,CAAC,IAAI5D,IAAYwD;AAAA,IAC7C;AAEA,WAAO,KAAK,mBAAmBzB,GAAK4B,GAAcE,CAAU;AAAA,EAAA;AAAA,EAG9D,YACE3C,GACAC,GACAvB,GASA;AACA,WAAO,KAAK;AAAA,MACV,CAACsB,IAAQ,KAAK,QAAQ,CAAC,GAAGC,IAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACjDvB;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,aAAanB,GAAgBqF,IAA6B,UAAU;AAC9D,QAAA,CAAC,KAAK,gBAAgB;AAClB,YAAA,IAAI,MAAM,gDAAgD;AAE9D,WAACrF,KAEA,KAAA,cAAc,EAAE,MAAAqF,GAAM,QAAArF,EAAO,GAC3B,QAHa;AAAA,EAGb;AAAA,EAGC,2BACRA,GACAqF,IAA6B,UAC7B;AACA,QAAI,CAACrF,EAAQ;AAEP,UAAAsF,IAAc,KAAK,gBAAgB,IAAI,GACvCxF,IAAe,KAAK,gBAAgB,MAAM;AAE5C,QAAA,CAACwF,KAAe,CAACxF;AACb,YAAA,IAAI,MAAM,uCAAuC;AAEnD,UAAA0C,IAAa6C,MAAS,YAAYpE,IAAkBH;AAE1D,SAAK,gBAAgB,KAAK,GAAG0B,EAAW8C,GAAaxF,GAAcE,CAAM,CAAC;AAAA,EAAA;AAAA,EAG5E,MAAM+B,IAAe,IAAgB;AACnC,QAAI,CAAC,KAAK,gBAAgB,OAAc,OAAA,IAAI,MAAM,sBAAsB;AAClE,UAAAjC,IAAe,KAAK,gBAAgB,CAAC,GAErCwF,IAAc,KAAK,gBAAgB,GAAG,EAAE;AAE9C,WAAKhD,EAAWxC,EAAa,YAAYwF,EAAY,SAAS,KACvD,KAAA,OAAOxF,EAAa,UAAU,GAGjC,KAAK,gBAAgB,SAClB,KAAA;AAAA,MACH,KAAK,YAAY;AAAA,MACjB,KAAK,YAAY;AAAA,IACnB,GACA,KAAK,cAAc,OAGd+B,EAAuB,KAAK,iBAAiB,EAAE,cAAAE,GAAc;AAAA,EAAA;AAAA,EAGtE,gBAAgBA,IAAe,IAAgB;AAC7C,QAAI,CAAC,KAAK,gBAAgB,OAAc,OAAA,IAAI,MAAM,sBAAsB;AAElE,UAAAjC,IAAe,KAAK,gBAAgB,CAAC,GAErCwF,IAAc,KAAK,gBAAgB,GAAG,EAAE,GAExCC,IAAe/H;AAAA,MACnB8H,EAAY;AAAA,MACZxF,EAAa;AAAA,IACf,GACM0F,IAAiB,IAAIC,EAAA,EAAuB;AAAA,MAChDF;AAAA,MACAzF,EAAa;AAAA,IACf,GAEM4F,IAAmB,KAAK,gBAAgB;AAAA,MAAI,CAAC1H,MACjDA,EAAQ,UAAUwH,CAAc,EAAE,QAAQ;AAAA,IAC5C;AACA,WAAAE,EAAiB,QAAQ,GAElB7D;AAAA,MACL,CAAC,GAAG,KAAK,iBAAiB,GAAG6D,CAAgB;AAAA,MAC7C,EAAE,cAAA3D,EAAa;AAAA,IACjB;AAAA,EAAA;AAAA,EAGF,WAAmB;AACjB,WAAO,IAAI4D,EAAO,CAAC,GAAG,KAAK,eAAe,CAAC;AAAA,EAAA;AAAA,EAG7C,IAAI,WAAoB;;AACtB,WAAOrD,EAAW,KAAK,UAASsD,IAAA,KAAK,gBAAgB,CAAC,MAAtB,gBAAAA,EAAyB,UAAU;AAAA,EAAA;AAEvE;AAEO,SAASC,GAAK5G,IAAiB,CAAC,GAAG,CAAC,GAAe;AACjD,SAAA,IAAIkD,GAAWlD,CAAM;AAC9B;"}
1
+ {"version":3,"file":"draw-lOWnIN1o.js","sources":["../src/algorithms/intersections/fullLinesIntersection.ts","../src/algorithms/offsets/offsetSegment.ts","../src/algorithms/filletSegments.ts","../src/draw.ts"],"sourcesContent":["import { Vector } from \"../../definitions\";\nimport {\n add,\n crossProduct,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\n\n/**\n * Returns the intersection point between two full lines\n *\n * Note that collinear lines are not considered to intersect at all.\n *\n * Lines are represented by a vector V with **unit length** and a point on the line.\n *\n */\nexport const fullLineIntersection = (\n line1: { V: Vector; firstPoint: Vector; precision: number },\n line2: { V: Vector; firstPoint: Vector; precision: number },\n precision?: number,\n): \"parallel\" | Vector => {\n const V1xV2 = crossProduct(line1.V, line2.V);\n\n /*\n const xLength = squareLength(line1.V);\n const yLength = squareLength(line2.V);\n */\n\n const squarePrecision = precision\n ? precision * precision\n : line1.precision * line2.precision;\n\n if (V1xV2 * V1xV2 < squarePrecision) {\n return \"parallel\";\n }\n\n const diffPoint = subtract(line2.firstPoint, line1.firstPoint);\n const intersectionParam = crossProduct(diffPoint, line2.V) / V1xV2;\n\n return add(line1.firstPoint, scalarMultiply(line1.V, intersectionParam));\n};\n","import { Line } from \"../../models/segments/Line.js\";\nimport { Arc } from \"../../models/segments/Arc.js\";\nimport { Segment } from \"../../models/segments/Segment.js\";\nimport {\n add,\n distance,\n dotProduct,\n perpendicular,\n scalarMultiply,\n subtract,\n} from \"../../vectorOperations\";\nimport { Vector } from \"../../definitions.js\";\nimport { CubicBezier, QuadraticBezier } from \"../../models/exports.js\";\nimport { fullLineIntersection } from \"../intersections/fullLinesIntersection.js\";\nimport {\n SafeCubicBezier,\n SafeQuadraticBezier,\n} from \"../conversions/bezierToSafeBezier.js\";\n\nexport class DegenerateSegment {\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector,\n ) {}\n}\n\nexport type OffsettableSegment =\n | Line\n | Arc\n | SafeCubicBezier\n | SafeQuadraticBezier;\n\nexport function offsetSegment(\n segment: OffsettableSegment,\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 if (segment instanceof QuadraticBezier || segment instanceof CubicBezier) {\n return offsetSafeBezier(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\nfunction computeControlPointOffset(\n origin: Vector,\n controlPoint: Vector,\n tangent: Vector,\n newPoint: Vector,\n precision: number,\n): Vector {\n const newControlPoint = fullLineIntersection(\n {\n V: tangent,\n firstPoint: newPoint,\n precision: precision,\n },\n {\n V: subtract(controlPoint, origin),\n firstPoint: origin,\n precision: precision,\n },\n );\n\n if (newControlPoint === \"parallel\") {\n throw new Error(\n \"Parallel lines not expected in safe bezier offset control point calculation\",\n );\n }\n\n return newControlPoint;\n}\n\nexport function offsetSafeBezier(\n curve: SafeQuadraticBezier | SafeCubicBezier,\n offset: number,\n): typeof curve | DegenerateSegment {\n const { firstPoint, lastPoint, normalAtFirstPoint, normalAtLastPoint } =\n curve;\n\n const origin = fullLineIntersection(\n { V: normalAtFirstPoint, firstPoint, precision: curve.precision },\n { V: normalAtLastPoint, firstPoint: lastPoint, precision: curve.precision },\n );\n\n const offsetStartPoint = add(\n firstPoint,\n scalarMultiply(normalAtFirstPoint, offset),\n );\n const offsetEndPoint = add(\n lastPoint,\n scalarMultiply(normalAtLastPoint, offset),\n );\n\n if (origin === \"parallel\") {\n throw new Error(\"Parallel lines not expected in safe bezier offset\");\n }\n\n const offsetTowardsOrigin =\n dotProduct(subtract(origin, firstPoint), normalAtFirstPoint) * offset > 0;\n if (offsetTowardsOrigin) {\n const minDistance = Math.min(\n distance(firstPoint, origin),\n distance(lastPoint, origin),\n );\n\n if (minDistance < offset) {\n return new DegenerateSegment(offsetStartPoint, offsetEndPoint);\n }\n }\n\n if (curve instanceof QuadraticBezier) {\n const newControlPoint = computeControlPointOffset(\n origin,\n curve.controlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n\n return new QuadraticBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint,\n );\n }\n\n const newControlPoint1 = computeControlPointOffset(\n origin,\n curve.firstControlPoint,\n curve.tangentAtFirstPoint,\n offsetStartPoint,\n curve.precision,\n );\n const newControlPoint2 = computeControlPointOffset(\n origin,\n curve.lastControlPoint,\n curve.tangentAtLastPoint,\n offsetEndPoint,\n curve.precision,\n );\n\n return new CubicBezier(\n offsetStartPoint,\n offsetEndPoint,\n newControlPoint1,\n newControlPoint2,\n );\n}\n","import { Vector } from \"../definitions.js\";\nimport { Line } from \"../models/segments/Line.js\";\nimport { tangentArc } from \"../models/segments/Arc.js\";\nimport type { Segment } from \"../models/segments/Segment.js\";\nimport {\n add,\n crossProduct,\n perpendicular,\n perpendicularClockwise,\n scalarMultiply,\n} from \"../vectorOperations\";\nimport { findIntersections } from \"./intersections\";\nimport { DegenerateSegment, offsetSegment } from \"./offsets/offsetSegment.js\";\nimport { exportJSON } from \"../main.js\";\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 {\n chamferSegments,\n filletSegments,\n} from \"./algorithms/filletSegments.js\";\nimport { Vector } from \"./definitions.js\";\nimport { Strand } from \"./models/Strand.js\";\nimport { Diagram } from \"./models/Diagram.js\";\nimport { Figure } from \"./models/Figure.js\";\nimport { Loop } from \"./models/Loop.js\";\nimport { tangentArc, threePointsArc } from \"./models/segments/Arc.js\";\nimport { Line } from \"./models/segments/Line.js\";\nimport { Segment } from \"./models/segments/Segment.js\";\nimport { TransformationMatrix } from \"./models/TransformationMatrix.js\";\nimport {\n polarToCartesian,\n DEG2RAD,\n subtract,\n sameVector,\n perpendicular,\n add,\n scalarMultiply,\n distance,\n cartesianToPolar,\n RAD2DEG,\n normalize,\n} from \"./vectorOperations.js\";\nimport { svgEllipse } from \"./models/segments/EllipseArc.js\";\nimport { QuadraticBezier } from \"./models/segments/QuadraticBezier.js\";\nimport { CubicBezier } from \"./models/segments/CubicBezier.js\";\n\nconst parseSmoothCurveConfig = (\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n) => {\n let conf: {\n endTangent: number | Vector;\n startFactor?: number;\n endFactor?: number;\n startTangent?: number | Vector;\n };\n\n if (!config) conf = { endTangent: [1, 0] };\n else if (\n typeof config === \"number\" ||\n (Array.isArray(config) && config.length === 2)\n ) {\n conf = { endTangent: config };\n } else {\n conf = { endTangent: 0, ...config };\n }\n const {\n endTangent: endTgt,\n startFactor = 1,\n endFactor = 1,\n startTangent: startTgt,\n } = conf;\n\n let endTangent: Vector;\n if (typeof endTgt === \"number\") {\n endTangent = polarToCartesian(1, endTgt * DEG2RAD);\n } else {\n endTangent = endTgt;\n }\n\n let startTangent: Vector | undefined;\n if (typeof startTgt === \"number\") {\n startTangent = polarToCartesian(1, startTgt * DEG2RAD);\n } else {\n startTangent = startTgt;\n }\n\n return { endTangent, startFactor, endFactor, startTangent };\n};\n\nfunction loopySegmentsToDiagram(\n segments: Segment[],\n { ignoreChecks = false } = {},\n) {\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], { ignoreChecks }))]);\n}\n\nexport class DrawingPen {\n 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, tangentAtStart?: 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(\n this.pointer,\n end,\n tangentAtStart ?? previousCurve.tangentAtLastPoint,\n ),\n );\n\n this.pointer = end;\n return this;\n }\n\n tangentArc(xDist: number, yDist: number, tangentAtStart?: Vector): this {\n const [x0, y0] = this.pointer;\n return this.tangentArcTo([xDist + x0, yDist + y0], tangentAtStart);\n }\n\n ellipseTo(\n end: Vector,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n this.saveSegment(\n svgEllipse(this.pointer, end, r0, r1, xAxisRotation, longArc, sweepFlag),\n );\n this.pointer = end;\n return this;\n }\n\n ellipse(\n xDist: number,\n yDist: number,\n r0: number,\n r1: number,\n xAxisRotation: number,\n longArc: boolean,\n sweepFlag: boolean,\n ): this {\n return this.ellipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n r0,\n r1,\n xAxisRotation,\n longArc,\n sweepFlag,\n );\n }\n\n halfEllipseTo(end: Vector, sagitta: number): this {\n const [distance, angle] = cartesianToPolar(subtract(end, this.pointer));\n\n return this.ellipseTo(\n end,\n distance / 2,\n Math.abs(sagitta),\n angle * RAD2DEG,\n true,\n sagitta > 0,\n );\n }\n\n halfEllipse(xDist: number, yDist: number, sagitta: number): this {\n return this.halfEllipseTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n sagitta,\n );\n }\n\n cubicBezierCurveTo(\n end: Vector,\n startControlPoint: Vector,\n endControlPoint: Vector,\n ): this {\n this.saveSegment(\n new CubicBezier(this.pointer, end, startControlPoint, endControlPoint),\n );\n this.pointer = end;\n return this;\n }\n\n quadraticBezierCurveTo(end: Vector, controlPoint: Vector): this {\n this.saveSegment(new QuadraticBezier(this.pointer, end, controlPoint));\n this.pointer = end;\n return this;\n }\n\n smoothCurveTo(\n end: Vector,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ): this {\n const { endTangent, startTangent, startFactor, endFactor } =\n parseSmoothCurveConfig(config);\n\n const previousCurve = this.pendingSegments.length\n ? this.pendingSegments[this.pendingSegments.length - 1]\n : null;\n\n const defaultDistance = distance(this.pointer, end) / 3;\n\n let startPoleDirection: Vector;\n if (startTangent) {\n startPoleDirection = startTangent;\n } else if (!previousCurve) {\n startPoleDirection = [1, 0];\n } else {\n startPoleDirection = previousCurve.tangentAtLastPoint;\n }\n\n startPoleDirection = normalize(startPoleDirection);\n const startControl: Vector = [\n this.pointer[0] + startPoleDirection[0] * startFactor * defaultDistance,\n this.pointer[1] + startPoleDirection[1] * startFactor * defaultDistance,\n ];\n\n let endPoleDirection = endTangent;\n\n endPoleDirection = normalize(endPoleDirection);\n const endControl: Vector = [\n end[0] - endPoleDirection[0] * endFactor * defaultDistance,\n end[1] - endPoleDirection[1] * endFactor * defaultDistance,\n ];\n\n return this.cubicBezierCurveTo(end, startControl, endControl);\n }\n\n smoothCurve(\n xDist: number,\n yDist: number,\n config?:\n | number\n | Vector\n | {\n endTangent?: number | Vector;\n startTangent?: number | Vector;\n startFactor?: number;\n endFactor?: number;\n },\n ) {\n return this.smoothCurveTo(\n [xDist + this.pointer[0], yDist + this.pointer[1]],\n config,\n );\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 if (!radius) return this;\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(ignoreChecks = false): 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, { ignoreChecks });\n }\n\n closeWithMirror(ignoreChecks = false): 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, ...mirroredSegments],\n { ignoreChecks },\n );\n }\n\n asStrand(): Strand {\n return new Strand([...this.pendingSegments]);\n }\n\n get isClosed(): boolean {\n return sameVector(this.pointer, this.pendingSegments[0]?.firstPoint);\n }\n}\n\nexport function draw(origin: Vector = [0, 0]): DrawingPen {\n return new DrawingPen(origin);\n}\n"],"names":["fullLineIntersection","line1","line2","precision","V1xV2","crossProduct","squarePrecision","diffPoint","subtract","intersectionParam","add","scalarMultiply","DegenerateSegment","firstPoint","lastPoint","offsetSegment","segment","offset","Line","offsetLine","Arc","offsetArc","QuadraticBezier","CubicBezier","offsetSafeBezier","line","normal","arc","offsetStartPoint","perpendicular","offsetEndPoint","orientedOffset","computeControlPointOffset","origin","controlPoint","tangent","newPoint","newControlPoint","curve","normalAtFirstPoint","normalAtLastPoint","dotProduct","distance","newControlPoint1","newControlPoint2","removeCorner","firstSegment","secondSegment","radius","sinAngle","orientationCorrection","firstOffset","secondOffset","potentialCenter","findIntersections","center","splitForFillet","tgt","perpendicularClockwise","splitPoint","first","second","filletSegments","cornerRemoved","tangentArc","chamferSegments","parseSmoothCurveConfig","config","conf","endTgt","startFactor","endFactor","startTgt","endTangent","polarToCartesian","DEG2RAD","startTangent","loopySegmentsToDiagram","segments","ignoreChecks","Diagram","Figure","Loop","DrawingPen","__publicField","point","sameVector","previousSegment","makeCorner","xDist","yDist","yPos","xPos","r","theta","angleInRads","angle","x","y","previousCurve","xDir","yDir","end","midPoint","threePointsArc","viaXDist","viaYDist","x0","y0","sagitta","chord","norm","sagPoint","bulge","halfChord","bulgeAsSagitta","tangentAtStart","r0","r1","xAxisRotation","longArc","sweepFlag","svgEllipse","cartesianToPolar","RAD2DEG","startControlPoint","endControlPoint","defaultDistance","startPoleDirection","normalize","startControl","endPoleDirection","endControl","mode","lastSegment","mirrorVector","mirrorTranform","TransformationMatrix","mirroredSegments","Strand","_a","draw"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ "use strict";var Rt=Object.defineProperty;var Nt=(t,n,e)=>n in t?Rt(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var b=(t,n,e)=>Nt(t,typeof n!="symbol"?n+"":n,e);const l=require("./QuadraticBezier--UZr_xcV.cjs");function yt(t,n){const e=l.subtract(n,t.firstPoint),i=l.dotProduct(e,t.V)/t.squareLength;return t.paramPoint(i)}function D(t,n,e){const i=e||t.precision,s=yt(t,n.center),r=l.distance(s,n.center);if(r>n.radius+i)return[];if(Math.abs(r-n.radius)<i){const a=s;return t.isOnSegment(a)&&n.isOnSegment(a)?[a]:[]}const c=[],o=Math.sqrt(n.radius*n.radius-r*r),u=t.tangentAtFirstPoint,f=l.add(s,l.scalarMultiply(u,o));t.isOnSegment(f)&&n.isOnSegment(f)&&c.push(f);const h=l.add(s,l.scalarMultiply(u,-o));return t.isOnSegment(h)&&n.isOnSegment(h)&&c.push(h),c}const Qt=t=>{const{firstPoint:n,lastPoint:e,center:i,clockwise:s}=t;return new l.Arc(e,n,i,s,{ignoreChecks:!0})},Ut=(t,n)=>{if(t.isSame(n))return[t];const e=l.removeDuplicatePoints([n.isOnSegment(t.firstPoint)?t.firstPoint:null,n.isOnSegment(t.lastPoint)?t.lastPoint:null,t.isOnSegment(n.firstPoint)?n.firstPoint:null,t.isOnSegment(n.lastPoint)?n.lastPoint:null].filter(i=>i!==null)).sort((i,s)=>t.pointToParam(i)-t.pointToParam(s));if(e.length===0)return[];if(e.length===1)return[];if(e.length===2)return t.isSame(Qt(n))?[]:[new l.Arc(e[0],e[1],t.center,t.clockwise)];if(e.length===3){const i=l.sameVector(e[0],n.lastPoint)||l.sameVector(e[0],n.firstPoint)?1:0;return[new l.Arc(e[0+i],e[1+i],t.center,t.clockwise)]}else if(e.length===4)return[new l.Arc(e[0],e[1],t.center,t.clockwise),new l.Arc(e[2],e[3],t.center,t.clockwise)];throw new Error("Bug in the arc arc overlap algorithm")};function Z(t,n,e=!1,i){const s=i||t.precision,r=l.distance(t.center,n.center),c=t.radius+n.radius;if(r>c+s)return[];const o=Math.abs(t.radius-n.radius);if(r<o-s)return[];if(r<s)return o>s?[]:e?Ut(t,n):[];const u=l.normalize(l.subtract(n.center,t.center)),f=r>c-s;if(f||Math.abs(r-o)<s){const P=f||t.radius>n.radius?1:-1,w=l.add(t.center,l.scalarMultiply(u,P*t.radius));return t.isOnSegment(w)&&n.isOnSegment(w)?[w]:[]}const h=t.radius*t.radius/(2*r)-n.radius*n.radius/(2*r)+r/2,a=l.add(t.center,l.scalarMultiply(u,h)),p=Math.sqrt(t.radius*t.radius-h*h),d=l.perpendicular(u),m=l.add(a,l.scalarMultiply(d,p)),g=l.add(a,l.scalarMultiply(d,-p)),x=[];return t.isOnSegment(m)&&n.isOnSegment(m)&&x.push(m),t.isOnSegment(g)&&n.isOnSegment(g)&&x.push(g),x}function Y(t,n,e=1e-9){const i=t.transform(n.ellipseReferenceFrameTransform),s=i.slope,r=i.yIntercept,c=n.majorRadius*n.majorRadius,o=n.minorRadius*n.minorRadius,u=n.majorRadius*n.minorRadius,f=i.slope*i.slope,h=i.yIntercept*i.yIntercept,a=P=>P.map(w=>n.reverseEllipseReferenceFrameTransform.transform(w)).filter(w=>t.isOnSegment(w)&&n.isOnSegment(w));if(!Number.isFinite(s)){const P=i.firstPoint[0];if(Math.abs(P)-n.majorRadius>e)return[];if(Math.abs(Math.abs(P)-n.majorRadius)<e)return a([[P,0]]);const w=n.minorRadius*Math.sqrt(1-P*P/c),y=[P,w],A=[P,-w];return a([y,A])}const p=c*f+o-h;if(p<-e)return[];const d=c*f+o;if(Math.abs(p)<e){const P=-(c*s*r)/d,w=o*r/d;return a([[P,w]])}const m=Math.sqrt(p),g=[-(c*s*r+u*m)/d,(o*r-u*s*m)/d],x=[-(c*s*r-u*m)/d,(o*r+u*s*m)/d];return a([g,x])}function Ct(t,n){const e=Math.max(t.precision,n.precision),i=t.coefficients,s=i.x2,r=i.xy,c=i.y2,o=i.x,u=i.y,f=i.c,h=n.coefficients,a=h.x2,p=h.xy,d=h.y2,m=h.x,g=h.y,x=h.c,P={z0:f*s*m*m+s*s*x*x-o*s*m*x+a*a*f*f-2*s*x*a*f-o*m*a*f+a*o*o*x,z1:g*o*o*a-x*m*s*r-2*s*x*a*u-f*a*p*o+2*m*p*s*f+2*g*x*s*s+m*m*s*u-g*m*s*o-2*s*g*a*f-f*a*m*r+2*f*u*a*a-x*p*s*o-u*a*m*o+2*x*r*a*o,z2:g*g*s*s+2*d*x*s*s-u*a*m*r+x*a*r*r-u*a*p*o-x*p*s*r-2*s*g*a*u+2*m*p*s*u-d*m*s*o-2*s*d*a*f+p*p*s*f+2*g*r*a*o+u*u*a*a-c*a*m*o-g*p*s*o+2*f*c*a*a-f*a*p*r+d*o*o*a+m*m*s*c-g*m*s*r-2*s*x*a*c,z3:-2*s*a*c*g+g*a*r*r+2*d*r*a*o-c*a*p*o+p*p*s*u-g*p*s*r-2*s*d*a*u-u*a*p*r-d*p*s*o+2*g*d*s*s+2*u*c*a*a-c*a*m*r+2*m*p*s*c-d*m*s*r,z4:s*s*d*d-2*s*d*a*c+a*a*c*c-r*s*p*d-r*p*a*c+r*r*a*d+c*s*p*p},y=l.solveGenericPolynomial([P.z0,P.z1,P.z2,P.z3,P.z4],e).flatMap(A=>{const z=s*p*A+s*m-a*r*A-a*o;if(z)return[[-(s*x+s*d*A*A-a*c*A*A+s*g*A-a*u*A-a*f)/z,A]];const E=r*A+o,v=-E/(2*s),V=c*A*A+u*A+f,F=E*E/(4*s*s)-V/s;if(Math.abs(F)<e)return[[v,A]];if(F>0){const _=Math.sqrt(F);return[[v+_,A],[v-_,A]]}return[]});return l.removeDuplicatePoints(y,e)}function ct(t,n){return Ct(t,n).filter(i=>t.isOnSegment(i)&&n.isOnSegment(i))}const jt=t=>{const{firstPoint:n,lastPoint:e,center:i,majorRadius:s,minorRadius:r,tiltAngle:c,clockwise:o}=t;return new l.EllipseArc(e,n,i,s,r,c,o,{ignoreChecks:!0,angleUnits:"rad"})},$t=(t,n)=>{if(t.isSame(n))return[t];const e=(s,r)=>new l.EllipseArc(s,r,t.center,t.majorRadius,t.minorRadius,t.tiltAngle,t.clockwise,{ignoreChecks:!0,angleUnits:"rad"}),i=l.removeDuplicatePoints([n.isOnSegment(t.firstPoint)?t.firstPoint:null,n.isOnSegment(t.lastPoint)?t.lastPoint:null,t.isOnSegment(n.firstPoint)?n.firstPoint:null,t.isOnSegment(n.lastPoint)?n.lastPoint:null].filter(s=>s!==null)).sort((s,r)=>t.pointToParam(s)-t.pointToParam(r));if(i.length===0)return[];if(i.length===1)return[];if(i.length===2)return t.isSame(jt(n))?[]:[e(i[0],i[1])];if(i.length===3){const s=l.sameVector(i[0],n.lastPoint)||l.sameVector(i[0],n.firstPoint)?1:0;return[e(i[0+s],i[1+s])]}else if(i.length===4)return[e(i[0],i[1]),e(i[2],i[3])];throw new Error("Bug in the ellipse arc ellipse arc overlap algorithm")};function Ht(t,n,e=!1){const i=Math.max(t.precision,n.precision);return l.sameVector(t.center,n.center)&&Math.abs(t.majorRadius-n.majorRadius)<i&&Math.abs(t.minorRadius-n.minorRadius)<i&&(Math.abs(t.tiltAngle-n.tiltAngle)<i||Math.abs(Math.abs(t.tiltAngle-n.tiltAngle)-Math.PI)<i)?e?$t(t,n):[]:Ct(t,n).filter(c=>t.isOnSegment(c)&&n.isOnSegment(c))}function lt(t,n){const[e,i]=t.firstPoint,[s,r]=t.lastPoint,c=new l.TransformationMatrix().translate(-e,-i).rotate(-Math.atan2(r-i,s-e)),o=c.clone().inverse(),u=n.transform(c);return u.paramsAtY(0).map(f=>u.paramPoint(f)).map(f=>o.transform(f)).filter(f=>t.isOnSegment(f))}const Yt=(t,n=1e-9)=>{let e=t;return Math.abs(t)<n&&(e=0),e.toFixed(-Math.log10(n))};function Mt(t,n=1e-9){return Array.from(new Map(t.map(e=>[Yt(e,n),e])).values())}const Xt=(t,n)=>{const[[e,i,s,r],[c,o,u,f]]=n.polynomialCoefficients,h=t.coefficients,a=h.x2,p=h.xy,d=h.y2,m=h.x,g=h.y,x=h.c,P=e*e,w=i*i,y=s*s,A=r*r,z=c*c,E=o*o,v=u*u,V=f*f,F=x+m*e+a*P+g*c+p*e*c+d*z,_=m*i+2*a*e*i+p*i*c+g*o+p*e*o+2*d*c*o,Vt=a*w+m*s+2*a*e*s+p*s*c+p*i*o+d*E+g*u+p*e*u+2*d*c*u,_t=2*a*i*s+m*r+2*a*e*r+p*r*c+p*s*o+p*i*u+2*d*o*u+g*f+p*e*f+2*d*c*f,Tt=a*y+2*a*i*r+p*r*o+p*s*u+d*v+p*i*f+2*d*o*f,qt=2*a*s*r+p*r*u+p*s*f+2*d*u*f,Dt=a*A+p*r*f+d*V;return[F,_,Vt,_t,Tt,qt,Dt]};function ut(t,n){const e=Math.max(t.precision,n.precision),i=Xt(t,n),s=l.solveGenericPolynomial(i,e).filter(r=>r>=-n.precision&&r<=1+n.precision);return Mt(s,e).map(r=>n.paramPoint(r)).filter(r=>t.isOnSegment(r))}const Gt=(t,n)=>{const[[e,i,s],[r,c,o]]=n.polynomialCoefficients,u=t.coefficients,f=u.x2,h=u.xy,a=u.y2,p=u.x,d=u.y,m=u.c,g=e*e,x=i*i,P=s*s,w=r*r,y=c*c,A=o*o,z=f*g+h*e*r+a*w+p*e+d*r+m,E=2*f*e*i+h*e*c+h*i*r+2*a*r*c+p*i+d*c,v=2*f*e*s+f*x+h*e*o+h*i*c+h*s*r+2*a*r*o+a*y+p*s+d*o,V=2*f*i*s+h*i*o+h*s*c+2*a*c*o,F=f*P+h*s*o+a*A;return[z,E,v,V,F]};function at(t,n){const e=Math.max(t.precision,n.precision),i=Gt(t,n),s=l.solveQuartic(...i).filter(r=>r>=-n.precision&&r<=1+n.precision);return Mt(s,e).map(r=>n.paramPoint(r)).filter(r=>t.isOnSegment(r))}function S(t,{firstPoint:n,lastPoint:e},i=1e-9){const s=l.subtract(e,n);return Math.abs(s[0])<i?s[1]>0?n[0]-t[0]:t[0]-n[0]:Math.abs(s[1])<i?s[0]>0?t[1]-n[1]:n[1]-t[1]:l.crossProduct(s,l.subtract(t,n))/l.length(s)}class tt{constructor(n,e,i,s){this.firstPoint=n,this.lastPoint=e,this.negativeThickness=i,this.positiveThickness=s}get width(){return this.positiveThickness-this.negativeThickness}}const Wt=3/4,Jt=4/9;function Kt(t){const n=S(t.firstControlPoint,t),e=S(t.lastControlPoint,t),i=n*e>0?Wt:Jt;return new tt(t.firstPoint,t.lastPoint,i*Math.min(0,n,e),i*Math.max(0,n,e))}function Zt(t){const n=S(t.controlPoint,t);return new tt(t.firstPoint,t.lastPoint,Math.min(0,n/2),Math.max(0,n/2))}function tn(t){if(t instanceof l.CubicBezier)return Kt(t);if(t instanceof l.QuadraticBezier)return Zt(t);throw new Error("Not implemented")}function nn(t){const n=t.paramPoint(.5),e=l.perpendicular(l.subtract(n,t.firstPoint)),i=l.add(n,e),s={firstPoint:n,lastPoint:i},r=[S(t.firstPoint,s),S(t.lastPoint,s)];return t instanceof l.CubicBezier?r.push(S(t.firstControlPoint,s),S(t.lastControlPoint,s)):t instanceof l.QuadraticBezier&&r.push(S(t.controlPoint,s)),new tt(n,i,Math.min(...r),Math.max(...r))}function ft(t,n){const e=[];for(let i=1;i<t.length;i++){const s=t[i];if(s[1]===n){e.push(s[0]);continue}const r=t[i-1],c=n-r[1],o=n-s[1];if(c*o<0){e.push(r[0]+(n-r[1])*(s[0]-r[0])/(s[1]-r[1]));continue}}return e}class T{constructor(n,e){this.from=n,this.to=e}get size(){return this.from==="start"?this.to==="end"?1:this.to:this.to==="end"?1-this.from:Math.abs(this.from-this.to)}clipCurve(n){return this.from==="start"?this.to==="end"?n:n.splitAtParameters([this.to])[0]:this.to==="end"?n.splitAtParameters([this.from])[1]:n.splitAtParameters([this.from,this.to])[1]}}function en(t,n){if(t instanceof l.CubicBezier)return new rn([S(t.firstPoint,n),S(t.firstControlPoint,n),S(t.lastControlPoint,n),S(t.lastPoint,n)]);if(t instanceof l.QuadraticBezier)return new sn([S(t.firstPoint,n),S(t.controlPoint,n),S(t.lastPoint,n)]);throw new Error("Not implemented")}class sn{constructor(n){b(this,"topHull",[]);b(this,"bottomHull",[]);this.distances=n;const[e,i,s]=n,r=[0,e],c=[1/2,i],o=[1,s],u=s-e,f=e;i-(u*(1/2)+f)>0?(this.topHull=[r,c,o],this.bottomHull=[r,o]):(this.topHull=[r,o],this.bottomHull=[r,c,o])}get startDistance(){return this.distances[0]}get endDistance(){return this.distances[2]}}class rn{constructor(n){b(this,"topHull",[]);b(this,"bottomHull",[]);this.distances=n;const[e,i,s,r]=n,c=[0,e],o=[1/3,i],u=[2/3,s],f=[1,r],h=r-e,a=e,p=i-(h*(1/3)+a),d=s-(h*(2/3)+a);let m=null,g=null;if(p*d<0)m=[c,o,f],g=[c,u,f];else{const P=p/d;P>=2?(m=[c,o,f],g=[c,f]):P<=.5?(m=[c,u,f],g=[c,f]):(m=[c,o,u,f],g=[c,f])}p<0&&([m,g]=[g,m]),this.topHull=m,this.bottomHull=g}get startDistance(){return this.distances[0]}get endDistance(){return this.distances[3]}}function ht(t,n){const e=en(n,t),i=ft(e.topHull,t.negativeThickness),s=ft(e.bottomHull,t.positiveThickness),r=e.endDistance>=t.negativeThickness&&e.endDistance<=t.positiveThickness;if(!i.length&&!s.length)return r?new T("start","end"):null;if(i.length===1&&s.length===1)return new T(i[0],s[0]);if(i.length===2&&s.length===2)throw new Error("Bug in the clipping algorithm, unexpected number of crossing points");const c=i.length?i:s;return c.length===2?new T(c[0],c[1]):r?new T(c[0],"end"):new T("start",c[0])}function pt(t,n){const e=tn(t),i=ht(e,n);if(!i)return null;const s=nn(t),r=ht(s,n);return r?i.size>r.size?r.clipCurve(n):i.clipCurve(n):null}const N=t=>t instanceof l.QuadraticBezier?l.squareLength(l.subtract(t.controlPoint,t.firstPoint))+l.squareLength(l.subtract(t.controlPoint,t.lastPoint)):l.squareLength(l.subtract(t.firstControlPoint,t.firstPoint))+l.squareLength(l.subtract(t.lastControlPoint,t.firstControlPoint))+l.squareLength(l.subtract(t.lastControlPoint,t.lastPoint));function L(t,n,e=1e-9,{maxIterations:i=100}={}){const s=Math.max(e*e,Number.EPSILON*10);let r=t,c=n,o=N(r),u=N(c);for(let f=0;f<i;f++){const h=o>s?pt(c,r):r;if(!h)return[];const a=N(h),p=u>s?pt(h,c):c;if(!p)return[];const d=N(p);if(a<=s&&d<=s)return[h.boundingBox.intersection(p.boundingBox).center];if(l.sameVector(h.firstPoint,h.lastPoint)&&p.isOnSegment(h.firstPoint))return[h.firstPoint];if(l.sameVector(p.firstPoint,p.lastPoint)&&h.isOnSegment(p.firstPoint))return[p.firstPoint];if(a>.8*o&&d>.8*u)if(a/o>d/u){const[m,g]=h.splitAtParameters([.5]);return l.removeDuplicatePoints([...L(m,p,e,{maxIterations:i-f}),...L(g,p,e,{maxIterations:i-f})],e)}else{const[m,g]=p.splitAtParameters([.5]);return l.removeDuplicatePoints([...L(h,m,e,{maxIterations:i-f}),...L(h,g,e,{maxIterations:i-f})],e)}r=h,c=p,o=a,u=d}throw new Error("Bézier clip: Maximum number of iterations reached")}function on(t,n){const e=[];if([[t.firstPoint,n],[t.lastPoint,n],[n.firstPoint,t],[n.lastPoint,t]].forEach(([s,r])=>{r.isOnSegment(s)&&e.push(s)}),e.length<2)return null;if(e.length===2)return[t.splitAt(e)[1]];if(e.length===3)return l.sameVector(e[0],t.firstPoint)&&l.sameVector(e[1],t.lastPoint)?[t]:[n];if(e.length===4)return[t]}function cn(t,n,e=!1){const i=Math.max(t.precision,n.precision);if(e){const s=on(t,n);if(s)return s}return L(t,n,i)}function ln(t,n){const e=[];if([[t.firstPoint,n],[t.lastPoint,n],[n.firstPoint,t],[n.lastPoint,t]].forEach(([s,r])=>{r.isOnSegment(s)&&e.push(s)}),e.length<2)return null;if(e.length===2)return[t.splitAt(e)[1]];if(e.length===3)return l.sameVector(e[0],t.firstPoint)&&l.sameVector(e[1],t.lastPoint)?[t]:[n];if(e.length===4)return[t]}function un(t,n,e=!1){const i=Math.max(t.precision,n.precision);if(e){const s=ln(t,n);if(s)return s}return L(t,n,i)}function an(t,n,e){if(t instanceof l.Line&&n instanceof l.Line){const i=l.lineLineIntersection(t,n,!1,e);return i===null?[]:[i]}if(t instanceof l.Line&&n instanceof l.Arc)return D(t,n,e);if(t instanceof l.Arc&&n instanceof l.Line)return D(n,t,e);if(t instanceof l.Arc&&n instanceof l.Arc)return Z(t,n,!1,e);throw new Error("Not implemented")}function R(t,n,e){if(t instanceof l.Line&&n instanceof l.Line){const i=l.lineLineIntersection(t,n,!0,e);return i===null?{intersections:[],overlaps:[],count:0}:i instanceof l.Line?{intersections:[],overlaps:[i],count:1}:{intersections:[i],overlaps:[],count:1}}if(!t.boundingBox.overlaps(n.boundingBox))return{intersections:[],overlaps:[],count:0};if(t instanceof l.Line&&n instanceof l.Arc){const i=D(t,n,e);return{intersections:i,overlaps:[],count:i.length}}if(t instanceof l.Arc&&n instanceof l.Line){const i=D(n,t,e);return{intersections:i,overlaps:[],count:i.length}}if(t instanceof l.Arc&&n instanceof l.Arc){const i=Z(t,n,!0,e);return i.length?i[0]instanceof l.Arc?{intersections:[],overlaps:i,count:i.length}:{intersections:i,overlaps:[],count:i.length}:{intersections:[],overlaps:[],count:0}}if(t instanceof l.Line&&n instanceof l.EllipseArc){const i=Y(t,n,e);return{intersections:i,overlaps:[],count:i.length}}if(n instanceof l.Line&&t instanceof l.EllipseArc){const i=Y(n,t,e);return{intersections:i,overlaps:[],count:i.length}}if(t instanceof l.Arc&&n instanceof l.EllipseArc){const i=ct(t,n);return{intersections:i,overlaps:[],count:i.length}}if(n instanceof l.Arc&&t instanceof l.EllipseArc){const i=ct(n,t);return{intersections:i,overlaps:[],count:i.length}}if(t instanceof l.EllipseArc&&n instanceof l.EllipseArc){const i=Ht(t,n,!0);return i.length?i[0]instanceof l.EllipseArc?{intersections:[],overlaps:i,count:i.length}:{intersections:i,overlaps:[],count:i.length}:{intersections:[],overlaps:[],count:0}}if(t instanceof l.Line&&(n instanceof l.CubicBezier||n instanceof l.QuadraticBezier)){const i=lt(t,n);return{intersections:i,overlaps:[],count:i.length}}if(n instanceof l.Line&&(t instanceof l.CubicBezier||t instanceof l.QuadraticBezier)){const i=lt(n,t);return{intersections:i,overlaps:[],count:i.length}}if((t instanceof l.Arc||t instanceof l.EllipseArc)&&n instanceof l.QuadraticBezier){const i=at(t,n);return{intersections:i,overlaps:[],count:i.length}}if((n instanceof l.Arc||n instanceof l.EllipseArc)&&t instanceof l.QuadraticBezier){const i=at(n,t);return{intersections:i,overlaps:[],count:i.length}}if((t instanceof l.Arc||t instanceof l.EllipseArc)&&n instanceof l.CubicBezier){const i=ut(t,n);return{intersections:i,overlaps:[],count:i.length}}if((n instanceof l.Arc||n instanceof l.EllipseArc)&&t instanceof l.CubicBezier){const i=ut(n,t);return{intersections:i,overlaps:[],count:i.length}}if(t instanceof l.QuadraticBezier&&n instanceof l.QuadraticBezier){const i=un(t,n);return i.length?i[0]instanceof l.QuadraticBezier?{intersections:[],overlaps:i,count:i.length}:{intersections:i,overlaps:[],count:i.length}:{intersections:[],overlaps:[],count:0}}if(t instanceof l.QuadraticBezier&&n instanceof l.CubicBezier||n instanceof l.QuadraticBezier&&t instanceof l.CubicBezier){const i=L(t,n);return{intersections:i,overlaps:[],count:i.length}}if(t instanceof l.CubicBezier&&n instanceof l.CubicBezier){const i=cn(t,n);return i.length?i[0]instanceof l.CubicBezier?{intersections:[],overlaps:i,count:i.length}:{intersections:i,overlaps:[],count:i.length}:{intersections:[],overlaps:[],count:0}}throw new Error("Not implemented")}function It(t){const n=[];for(let e=0;e<t;e++)for(let i=0;i<=e;i++)n.push([e,i]);return n}function*X(t){for(const[n,e]of It(t.length))n!==e&&(yield[t[n],t[e]])}class Bt extends l.Transformable{constructor(e,{ignoreChecks:i=!1}={}){super();b(this,"segments");b(this,"_boundingBox",null);i||Et(e),this.segments=e}get repr(){return this.segments.map(e=>e.repr).join(`
2
+ `)+`
3
+ `}get info(){return this.repr}get firstPoint(){return this.segments[0].firstPoint}get lastPoint(){return this.segments[this.segments.length-1].lastPoint}get segmentsCount(){return this.segments.length}onStroke(e){return this.segments.some(i=>i.isOnSegment(e))}intersects(e){return this.boundingBox.overlaps(e.boundingBox)?this.segments.some(i=>e.segments.some(s=>R(i,s).count>0)):!1}overlappingSegments(e){return this.segments.flatMap(i=>e.segments.flatMap(s=>i.boundingBox.overlaps(s.boundingBox)?R(i,s).overlaps:[]))}get boundingBox(){if(this._boundingBox===null){let e=this.segments[0].boundingBox;this.segments.slice(1).forEach(i=>{e=e.merge(i.boundingBox)}),this._boundingBox=e}return this._boundingBox}[Symbol.for("nodejs.util.inspect.custom")](){return this.repr}}function fn(t,n="Stroke"){It(t.length).forEach(([e,i])=>{if(e===i)return;const s=t[e],r=t[i],c=R(s,r),o=Math.max(s.precision,r.precision);if(c.count!==0){if(c.count===1&&!c.overlaps.length){const u=e-i,f=c.intersections[0];if(u===1&&l.sameVector(s.firstPoint,f,o)||u===-1&&l.sameVector(s.lastPoint,f,o)||u===t.length-1&&l.sameVector(s.lastPoint,f,o)&&l.sameVector(r.firstPoint,f,o)||-u===t.length-1&&l.sameVector(s.firstPoint,f,o)&&l.sameVector(r.lastPoint,f,o))return}if(!(c.count===2&&t.length===2&&(l.sameVector(s.firstPoint,c.intersections[0],o)&&l.sameVector(s.lastPoint,c.intersections[1],o)||l.sameVector(s.firstPoint,c.intersections[1],o)&&l.sameVector(s.lastPoint,c.intersections[0],o))))throw new Error(`${n} segments must not intersect, but segments ${s.info} and ${r.info} do at ${JSON.stringify(c.intersections)}`)}})}function Et(t,n="Stroke"){if(t.length===0)throw new Error(`${n} must have at least one segment`);l.zip([t.slice(0,-1),t.slice(1)]).forEach(([e,i])=>{if(!l.sameVector(e.lastPoint,i.firstPoint))throw new Error(`${n} segments must be connected, but ${e.info} and ${i.info} are not`)}),fn(t,n)}function dt(t,n){return!!(t instanceof l.Line&&n instanceof l.Line&&l.parallel(t.V,n.V)||t instanceof l.Arc&&n instanceof l.Arc&&l.sameVector(t.center,n.center)&&t.radius-n.radius<t.precision)}function mt(t,n){if(t instanceof l.Line&&n instanceof l.Line)return new l.Line(t.firstPoint,n.lastPoint);if(t instanceof l.Arc&&n instanceof l.Arc)return new l.Arc(t.firstPoint,n.lastPoint,t.center,t.clockwise);throw new Error("Not implemented")}function vt(t){let n=!1;const e=[];for(const i of t.segments){if(e.length===0){e.push(i);continue}const s=e[e.length-1];dt(s,i)?(n=!0,e.pop(),e.push(mt(s,i))):e.push(i)}if(l.sameVector(t.firstPoint,t.lastPoint)&&dt(e[0],e[e.length-1])){n=!0;const i=e.pop();e[0]=mt(i,e[0])}return n?e:null}class M extends Bt{constructor(){super(...arguments);b(this,"strokeType","STRAND")}reverse(){const e=this.segments.map(i=>i.reverse());return e.reverse(),new M(e,{ignoreChecks:!0})}clone(){return new M(this.segments.map(e=>e.clone()),{ignoreChecks:!0})}extend(e){if(!l.sameVector(this.lastPoint,e.firstPoint))throw console.error(this.repr,e.repr),new Error("Cannot extend strand: connection point is not the same");return new M([...this.segments,...e.segments])}simplify(){const e=vt(this);return e?new M(e,{ignoreChecks:!0}):this}transform(e){return new M(this.segments.map(i=>i.transform(e)),{ignoreChecks:!0})}}const hn=(t,n)=>{const e=l.lineLineParams(n,{V:[1,0],firstPoint:t,precision:n.precision});if(e==="parallel")return 0;const{intersectionParam1:i,intersectionParam2:s}=e;if(!n.isValidParameter(i)||s<=-n.precision)return 0;if(Math.abs(i)<n.precision||Math.abs(i-1)<n.precision){const[,r]=n.midPoint;return t[1]-r<0?1:0}return 1};class nt{constructor(n){b(this,"_count",0);b(this,"segment");this.segment=n}update(n,e=!1){!e&&!this.segment.isOnSegment(n)||(l.sameVector(n,this.segment.firstPoint)?this._count+=this.segment.tangentAtFirstPoint[1]>0?1:0:l.sameVector(n,this.segment.lastPoint)?this._count+=this.segment.tangentAtLastPoint[1]>0?0:1:this._count+=1)}get count(){return this._count}}const pn=(t,n)=>{const e=n.precision,i=Math.abs(t[1]-n.center[1]);if(i>n.radius+e)return 0;const s=l.squareDistance(t,n.center),r=n.radius*n.radius,c=e*e;if(Math.abs(s-r)<c&&n.isOnSegment(t))return 0;const o=s-r>c;if(o&&n.center[0]<t[0])return 0;const u=Math.sqrt(n.radius*n.radius-i*i),f=new nt(n);return f.update([n.center[0]+u,t[1]]),o&&f.update([n.center[0]-u,t[1]]),f.count},dn=(t,n)=>{const e=n.boundingBox.xMax+n.boundingBox.width/2,i=new l.Line(t,[e,t[1]]),s=new nt(n);return Y(i,n).forEach(r=>{s.update(r,!0)}),s.count},mn=(t,n)=>{const e=new nt(n);return n.paramsAtY(t[1]).map(i=>{try{return n.paramPoint(i)}catch{return null}}).filter(i=>i!==null).filter(i=>{const[s]=i;return s>=t[0]}).forEach(i=>{e.update(i,!0)}),e.count};function gn(t,n){if(n instanceof l.Line)return hn(t,n);if(n instanceof l.Arc)return pn(t,n);if(n instanceof l.EllipseArc)return dn(t,n);if(n instanceof l.CubicBezier||n instanceof l.QuadraticBezier)return mn(t,n);throw new Error("Not implemented")}class B extends Bt{constructor(e,{ignoreChecks:i=!1}={}){super(e,{ignoreChecks:!0});b(this,"strokeType","LOOP");b(this,"_clockwise",null);i||Pn(e)}get clockwise(){if(this._clockwise===null){const e=this.segments.flatMap(s=>s instanceof l.Line?[s.firstPoint]:[s.firstPoint,s.paramPoint(.5)]),i=e.map((s,r)=>{const c=e[(r+1)%e.length];return(c[0]-s[0])*(c[1]+s[1])}).reduce((s,r)=>s+r,0);this._clockwise=i>0}return this._clockwise}clone(){return new B(this.segments.map(e=>e.clone()),{ignoreChecks:!0})}reverse(){const e=this.segments.map(i=>i.reverse());return e.reverse(),new B(e,{ignoreChecks:!0})}transform(e){return new B(this.segments.map(i=>i.transform(e)),{ignoreChecks:!0})}contains(e,{strokeIsInside:i=!1}={}){return this.onStroke(e)?i:this.boundingBox.contains(e)?this.segments.reduce((r,c)=>r+gn(e,c),0)%2===1:!1}simplify(){const e=vt(this);return e?new B(e,{ignoreChecks:!0}):this}}function Pn(t){if(Et(t,"Loop"),!l.sameVector(t[0].firstPoint,t[t.length-1].lastPoint))throw new Error("Loop segment must be closed")}const wn=[l.Line,l.Arc,l.EllipseArc,l.QuadraticBezier,l.CubicBezier];function Ft(t){return wn.some(n=>t instanceof n)}function Lt(t){if(t instanceof l.Line)return{type:t.segmentType,firstPoint:t.firstPoint,lastPoint:t.lastPoint};if(t instanceof l.Arc)return{type:t.segmentType,firstPoint:t.firstPoint,lastPoint:t.lastPoint,center:t.center,clockwise:t.clockwise};if(t instanceof l.EllipseArc)return{type:t.segmentType,firstPoint:t.firstPoint,lastPoint:t.lastPoint,center:t.center,clockwise:t.clockwise,majorRadius:t.majorRadius,minorRadius:t.minorRadius,tiltAngle:t.tiltAngle};if(t instanceof l.QuadraticBezier)return{type:t.segmentType,firstPoint:t.firstPoint,lastPoint:t.lastPoint,controlPoint:t.controlPoint};if(t instanceof l.CubicBezier)return{type:t.segmentType,firstPoint:t.firstPoint,lastPoint:t.lastPoint,firstControlPoint:t.firstControlPoint,lastControlPoint:t.lastControlPoint};throw new Error("Unknown segment type")}function G(t){return{type:"LOOP",segments:t.segments.map(Lt)}}function zt(t){return{type:"FIGURE",contour:G(t.contour),holes:t.holes.map(G)}}function xn(t){return{type:"DIAGRAM",figures:t.figures.map(zt)}}function W(t){if(t instanceof I)return xn(t);if(t instanceof C)return zt(t);if(t instanceof B)return G(t);if(Ft(t))return Lt(t);throw new Error("Unknown shape type")}class An{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(n,e){let i=this.length++;for(;i>0;){const s=i-1>>1,r=this.values[s];if(e>=r)break;this.ids[i]=this.ids[s],this.values[i]=r,i=s}this.ids[i]=n,this.values[i]=e}pop(){if(this.length===0)return;const n=this.ids[0];if(this.length--,this.length>0){const e=this.ids[0]=this.ids[this.length],i=this.values[0]=this.values[this.length],s=this.length>>1;let r=0;for(;r<s;){let c=(r<<1)+1;const o=c+1;let u=this.ids[c],f=this.values[c];const h=this.values[o];if(o<this.length&&h<f&&(c=o,u=this.ids[o],f=h),f>=i)break;this.ids[r]=u,this.values[r]=f,r=c}this.ids[r]=e,this.values[r]=i}return n}peek(){if(this.length!==0)return this.ids[0]}peekValue(){if(this.length!==0)return this.values[0]}shrink(){this.ids.length=this.values.length=this.length}}const gt=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],H=3;class et{static from(n,e=0){if(e%8!==0)throw new Error("byteOffset must be 8-byte aligned.");if(!n||n.byteLength===void 0||n.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[i,s]=new Uint8Array(n,e+0,2);if(i!==251)throw new Error("Data does not appear to be in a Flatbush format.");const r=s>>4;if(r!==H)throw new Error(`Got v${r} data when expected v${H}.`);const c=gt[s&15];if(!c)throw new Error("Unrecognized array type.");const[o]=new Uint16Array(n,e+2,1),[u]=new Uint32Array(n,e+4,1);return new et(u,o,c,void 0,n,e)}constructor(n,e=16,i=Float64Array,s=ArrayBuffer,r,c=0){if(n===void 0)throw new Error("Missing required argument: numItems.");if(isNaN(n)||n<=0)throw new Error(`Unexpected numItems value: ${n}.`);this.numItems=+n,this.nodeSize=Math.min(Math.max(+e,2),65535),this.byteOffset=c;let o=n,u=o;this._levelBounds=[o*4];do o=Math.ceil(o/this.nodeSize),u+=o,this._levelBounds.push(u*4);while(o!==1);this.ArrayType=i,this.IndexArrayType=u<16384?Uint16Array:Uint32Array;const f=gt.indexOf(this.ArrayType),h=u*4*this.ArrayType.BYTES_PER_ELEMENT;if(f<0)throw new Error(`Unexpected typed array class: ${i}.`);r&&r.byteLength!==void 0&&!r.buffer?(this.data=r,this._boxes=new this.ArrayType(this.data,c+8,u*4),this._indices=new this.IndexArrayType(this.data,c+8+h,u),this._pos=u*4,this.minX=this._boxes[this._pos-4],this.minY=this._boxes[this._pos-3],this.maxX=this._boxes[this._pos-2],this.maxY=this._boxes[this._pos-1]):(this.data=new s(8+h+u*this.IndexArrayType.BYTES_PER_ELEMENT),this._boxes=new this.ArrayType(this.data,8,u*4),this._indices=new this.IndexArrayType(this.data,8+h,u),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(this.data,0,2).set([251,(H<<4)+f]),new Uint16Array(this.data,2,1)[0]=e,new Uint32Array(this.data,4,1)[0]=n),this._queue=new An}add(n,e,i=n,s=e){const r=this._pos>>2,c=this._boxes;return this._indices[r]=r,c[this._pos++]=n,c[this._pos++]=e,c[this._pos++]=i,c[this._pos++]=s,n<this.minX&&(this.minX=n),e<this.minY&&(this.minY=e),i>this.maxX&&(this.maxX=i),s>this.maxY&&(this.maxY=s),r}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const n=this._boxes;if(this.numItems<=this.nodeSize){n[this._pos++]=this.minX,n[this._pos++]=this.minY,n[this._pos++]=this.maxX,n[this._pos++]=this.maxY;return}const e=this.maxX-this.minX||1,i=this.maxY-this.minY||1,s=new Uint32Array(this.numItems),r=65535;for(let c=0,o=0;c<this.numItems;c++){const u=n[o++],f=n[o++],h=n[o++],a=n[o++],p=Math.floor(r*((u+h)/2-this.minX)/e),d=Math.floor(r*((f+a)/2-this.minY)/i);s[c]=Sn(p,d)}J(s,n,this._indices,0,this.numItems-1,this.nodeSize);for(let c=0,o=0;c<this._levelBounds.length-1;c++){const u=this._levelBounds[c];for(;o<u;){const f=o;let h=n[o++],a=n[o++],p=n[o++],d=n[o++];for(let m=1;m<this.nodeSize&&o<u;m++)h=Math.min(h,n[o++]),a=Math.min(a,n[o++]),p=Math.max(p,n[o++]),d=Math.max(d,n[o++]);this._indices[this._pos>>2]=f,n[this._pos++]=h,n[this._pos++]=a,n[this._pos++]=p,n[this._pos++]=d}}}search(n,e,i,s,r){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let c=this._boxes.length-4;const o=[],u=[];for(;c!==void 0;){const f=Math.min(c+this.nodeSize*4,wt(c,this._levelBounds));for(let h=c;h<f;h+=4){if(i<this._boxes[h]||s<this._boxes[h+1]||n>this._boxes[h+2]||e>this._boxes[h+3])continue;const a=this._indices[h>>2]|0;c>=this.numItems*4?o.push(a):(r===void 0||r(a))&&u.push(a)}c=o.pop()}return u}neighbors(n,e,i=1/0,s=1/0,r){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let c=this._boxes.length-4;const o=this._queue,u=[],f=s*s;t:for(;c!==void 0;){const h=Math.min(c+this.nodeSize*4,wt(c,this._levelBounds));for(let a=c;a<h;a+=4){const p=this._indices[a>>2]|0,d=Pt(n,this._boxes[a],this._boxes[a+2]),m=Pt(e,this._boxes[a+1],this._boxes[a+3]),g=d*d+m*m;g>f||(c>=this.numItems*4?o.push(p<<1,g):(r===void 0||r(p))&&o.push((p<<1)+1,g))}for(;o.length&&o.peek()&1;)if(o.peekValue()>f||(u.push(o.pop()>>1),u.length===i))break t;c=o.length?o.pop()>>1:void 0}return o.clear(),u}}function Pt(t,n,e){return t<n?n-t:t<=e?0:t-e}function wt(t,n){let e=0,i=n.length-1;for(;e<i;){const s=e+i>>1;n[s]>t?i=s:e=s+1}return n[e]}function J(t,n,e,i,s,r){if(Math.floor(i/r)>=Math.floor(s/r))return;const c=t[i+s>>1];let o=i-1,u=s+1;for(;;){do o++;while(t[o]<c);do u--;while(t[u]>c);if(o>=u)break;bn(t,n,e,o,u)}J(t,n,e,i,u,r),J(t,n,e,u+1,s,r)}function bn(t,n,e,i,s){const r=t[i];t[i]=t[s],t[s]=r;const c=4*i,o=4*s,u=n[c],f=n[c+1],h=n[c+2],a=n[c+3];n[c]=n[o],n[c+1]=n[o+1],n[c+2]=n[o+2],n[c+3]=n[o+3],n[o]=u,n[o+1]=f,n[o+2]=h,n[o+3]=a;const p=e[i];e[i]=e[s],e[s]=p}function Sn(t,n){let e=t^n,i=65535^e,s=65535^(t|n),r=t&(n^65535),c=e|i>>1,o=e>>1^e,u=s>>1^i&r>>1^s,f=e&s>>1^r>>1^r;e=c,i=o,s=u,r=f,c=e&e>>2^i&i>>2,o=e&i>>2^i&(e^i)>>2,u^=e&s>>2^i&r>>2,f^=i&s>>2^(e^i)&r>>2,e=c,i=o,s=u,r=f,c=e&e>>4^i&i>>4,o=e&i>>4^i&(e^i)>>4,u^=e&s>>4^i&r>>4,f^=i&s>>4^(e^i)&r>>4,e=c,i=o,s=u,r=f,u^=e&s>>8^i&r>>8,f^=i&s>>8^(e^i)&r>>8,e=u^u>>1,i=f^f>>1;let h=t^n,a=i|65535^(h|e);return h=(h|h<<8)&16711935,h=(h|h<<4)&252645135,h=(h|h<<2)&858993459,h=(h|h<<1)&1431655765,a=(a|a<<8)&16711935,a=(a|a<<4)&252645135,a=(a|a<<2)&858993459,a=(a|a<<1)&1431655765,(a<<1|h)>>>0}function it(t,n=1e-7){if(t.length===0)return[];if(t.length===1)return[t];const e=new et(t.length);t.forEach(r=>{const[c,o]=r.firstPoint;e.add(c-n,o-n,c+n,o+n)}),e.finish();const i=[],s=new Set;return t.forEach((r,c)=>{if(s.has(c))return;const o=[r];let u=c;s.add(c);let f=t.length;for(;;){if(f--<0)throw new Error("Infinite loop detected");const h=o[o.length-1].lastPoint,[a,p]=h,d=e.search(a-n,p-n,a+n,p+n),m=w=>Math.abs((u-w)%t.length),g=d.filter(w=>!s.has(w)).map(w=>[t[w],w,m(w)]).sort(([,,w],[,,y])=>m(w)-m(y));if(g.length===0){i.push(o);break}const[x,P]=g[0];o.push(x),s.add(P),u=P}}),i}class C extends l.Transformable{constructor(e,i=[],{ignoreChecks:s=!1}={}){super();b(this,"contour");b(this,"holes");s||yn(e,i),this.contour=e,this.holes=i}get boundingBox(){return this.contour.boundingBox}get isFull(){return this.holes.length===0}get allLoops(){return[this.contour,...this.holes]}clone(){return new C(this.contour.clone(),this.holes.map(e=>e.clone()))}transform(e){return new C(this.contour.transform(e),this.holes.map(i=>i.transform(e)))}contains(e,{strokeIsInside:i=!1}={}){return this.contour.contains(e,{strokeIsInside:i})&&!this.holes.some(s=>s.contains(e,{strokeIsInside:i}))}intersects(e){return this.allLoops.some(i=>e.allLoops.some(s=>i.intersects(s)))}overlappingStrands(e){const i=e instanceof C?e.allLoops:[e],s=this.allLoops.flatMap(r=>i.flatMap(c=>r.overlappingSegments(c)));return it(s).map(r=>new M(r))}}function yn(t,n=[]){if(!t)throw new Error("Figure must have a contour");for(const[e,i]of X([t,...n]))if(e.intersects(i))throw new Error("Loops in a figure must not intersect");if(n.some(e=>!t.contains(e.firstPoint)&&!t.onStroke(e.firstPoint)))throw new Error("Holes must be inside the contour");for(const[e,i]of X(n))if(e.contains(i.firstPoint))throw console.error(W(e),W(i)),new Error("Holes must not be inside other holes")}const Q=(t,n,e=1e-7)=>Math.abs(t-n)<=e,Cn=(t,n)=>{const e=t.boundingBox,i=n.boundingBox;return Q(e.xMin,i.xMin)&&Q(e.yMin,i.yMin)&&Q(e.xMax,i.xMax)&&Q(e.yMax,i.yMax)},Mn=(t,n)=>{if(t.segmentsCount!==n.segmentsCount||!Cn(t,n))return!1;const e=t.segments,i=n.segments,s=e.length,r=(c,o)=>{for(let u=0;u<s;u+=1){const f=(c+o*u+s)%s;if(!e[u].isSame(i[f]))return!1}return!0};for(let c=0;c<s;c+=1)if(e[0].isSame(i[c])&&(r(c,1)||r(c,-1)))return!0;return!1},In=t=>{const n=[];return t.forEach(e=>{n.some(i=>Mn(e,i))||n.push(e)}),n},Bn=t=>{const n=t.map((s,r)=>t.slice(r+1).map((c,o)=>[o+r+1,c]).filter(([,c])=>s.boundingBox.overlaps(c.boundingBox)).map(([c])=>c)),e=[],i=Array(n.length);return n.forEach((s,r)=>{let c=i[r];c||(c=[],e.push(c)),c.push(t[r]),s.length&&s.forEach(o=>{i[o]=c})}),e},kt=t=>t.map((n,e)=>{const s=n.segments[0].midPoint,r=t.filter((c,o)=>e===o?!1:c.contains(s));return{loop:n,isIn:r}}),En=(t,n)=>t.flatMap(({loop:e})=>st(n.filter(({loop:i,isIn:s})=>i===e||s.indexOf(e)!==-1))),vn=(t,n)=>{const e=n.filter(({isIn:s})=>s.length<=1),i=st(kt(t.map(({loop:s})=>s)));return[e,...i]},st=t=>{if(!t.length)return[];const n=t.filter(({isIn:i})=>!i.length),e=t.filter(({isIn:i})=>i.length>1);return n.length===1&&e.length===0?[t]:n.length>1?En(n,t):vn(e,t)};function q(t){const n=In(t);return Bn(n).map(kt).flatMap(st).map(i=>{if(i.length===1)return new C(i[0].loop);i.sort((c,o)=>c.isIn.length-o.isIn.length);const[s,...r]=i.map(({loop:c})=>c);return new C(s,r)})}function Fn(t,n){const e=[];for(const i of t)for(const s of n)e.push([i,s]);return e}function*K(t,n,e){const i=o=>n.some(u=>l.sameVector(u,o.lastPoint)),s=(o,u)=>o.segmentType!==u.segmentType||!u.isOnSegment(o.firstPoint)||!u.isOnSegment(o.lastPoint)?!1:o.segmentType!=="LINE"?u.isOnSegment(o.midPoint):!0,r=o=>e.some(u=>o.isSame(u)||s(o,u));let c=[];for(const o of t)i(o)?(c.push(o),yield new M(c,{ignoreChecks:!0}),c=[]):r(o)?(c.length&&(yield new M(c,{ignoreChecks:!0}),c=[]),yield new M([o],{ignoreChecks:!0})):c.push(o);c.length&&(yield new M(c,{ignoreChecks:!0}))}const xt=(t,n)=>{const e=t.findIndex(r=>l.sameVector(n,r.firstPoint)),i=t.slice(0,e);return t.slice(e).concat(i)},At=(t,n)=>{let e=t;const i=o=>l.sameVector(o.firstPoint,n.firstPoint)&&l.sameVector(o.lastPoint,n.lastPoint);let s=t.findIndex(i);if(s===-1){const o=t.map(u=>u.reverse());if(o.reverse(),s=o.findIndex(i),s===-1)throw console.error(o.map(u=>u.repr),n.repr),new Error("Failed to rotate to segment start");e=o}const r=e.slice(0,s);return e.slice(s).concat(r)};function Ln(t,n,e){return t.filter(i=>{const s=n.filter(o=>l.sameVector(o.firstPoint,i)||l.sameVector(o.lastPoint,i));if(s.length%2)throw new Error("Bug in the intersection algo on non crossing point");const r=s.map(o=>e.contains(o.midPoint));return!(r.every(o=>o)||!r.some(o=>o))})}function zn(t,n,e,i=!1){let s=[];const r=[],c=new Array(t.segments.length).fill(0).map(()=>[]),o=new Array(n.segments.length).fill(0).map(()=>[]);if(t.segments.forEach((d,m)=>{n.segments.forEach((g,x)=>{const{intersections:P,overlaps:w}=R(d,g,e);s.push(...P),c[m].push(...P),o[x].push(...P),r.push(...w);const y=w.flatMap(A=>[A.firstPoint,A.lastPoint]);s.push(...y),c[m].push(...y),o[x].push(...y)})}),s=l.removeDuplicatePoints(s,e),!s.length||s.length===1)return null;const u=([d,m])=>m.length?d.splitAt(m):[d];let f=l.zip([t.segments,c]).flatMap(u),h=l.zip([n.segments,o]).flatMap(u);if(s=Ln(s,f,n),!s.length&&!r.length)return null;if(r.length){const d=r[0];f=At(f,d),h=At(h,d)}else{const d=s[0];f=xt(f,d),h=xt(h,d)}let a=Array.from(K(f,s,r)),p=Array.from(K(h,s,r));return(!l.sameVector(p[0].lastPoint,a[0].lastPoint)||r.length>0&&p[0].segmentsCount!==1)&&(p=p.map(d=>d.reverse()).reverse(),l.sameVector(p[0].lastPoint,a[0].lastPoint)||(a=a.map(d=>d.reverse()).reverse())),l.zip([a,p]).map(([d,m])=>{if(i){if((x=>x.segments.every(P=>r.some(w=>P.isSame(w)||P.segmentType===w.segmentType&&w.isOnSegment(P.firstPoint)&&w.isOnSegment(P.lastPoint)&&(P.segmentType==="LINE"||w.isOnSegment(P.midPoint)))))(d))return[d,"same"]}else if(d.segmentsCount===1&&r.some(g=>d.segments[0].isSame(g)))return[d,"same"];return[d,m]})}function bt(t){let n=t[0];for(const e of t.slice(1))n=n.extend(e);if(!l.sameVector(n.firstPoint,n.lastPoint))throw console.error(l.reprVector(n.firstPoint),l.reprVector(n.lastPoint)),new Error("Bug in the intersection algo on non closing strand");return new B(n.segments)}function kn(t,n){const e=l.zip([n.slice(0,-1),n.slice(1)]).map(([s,r])=>bt(t.slice(s,r)));let i=t.slice(n[n.length-1]);return n[0]!==0&&(i=i.concat(t.slice(0,n[0]))),e.push(bt(i)),e}function On(t){if(!t.length)return[];const n=t.map(s=>s.firstPoint);let e=t.map(s=>s.lastPoint);e=e.slice(-1).concat(e.slice(0,-1));const i=l.zip([n,e]).flatMap(([s,r],c)=>l.sameVector(s,r)?[]:c);try{return kn(t,i)}catch{return it(t.flatMap(r=>r.segments)).filter(r=>r.length>1).filter(r=>l.sameVector(r[0].firstPoint,r.at(-1).lastPoint)).map(r=>new B(r))}}const St=(t,n)=>{if(t.length===0)return[n];const e=t.at(-1);return l.sameVector(e.lastPoint,n.firstPoint)?t.slice(0,-1).concat([e.extend(n)]):l.sameVector(e.lastPoint,n.lastPoint)?t.slice(0,-1).concat([e.extend(n.reverse())]):t.concat([n])},Vn=(t,n)=>t.length===0?[n]:l.sameVector(t[0].firstPoint,n.lastPoint)?[n.extend(t[0])].concat(t.slice(1)):[n].concat(t);function rt(t,n,{firstInside:e,secondInside:i,firstBoundaryInside:s=!1,secondBoundaryInside:r=!1}){const c=zn(t,n,void 0,s||r);if(!c){const h=t.segments[0].midPoint,a=n.contains(h,{strokeIsInside:r}),p=n.segments[0].midPoint,d=t.contains(p,{strokeIsInside:s});return{identical:!1,firstCurveInSecond:a,secondCurveInFirst:d}}if(c.every(([,h])=>h==="same"))return{identical:!0};let o=null,u=null;const f=c.flatMap(([h,a])=>{let p=[],d=0;if(a==="same")return u===1?(u=1,h):u===2||u===0?(u=null,[]):u===null?(o?o=o.extend(h):o=h,[]):(console.error("weird situation"),[]);const m=h.segments[0].midPoint,g=n.contains(m,{strokeIsInside:r});(e==="keep"&&g||e==="remove"&&!g)&&(d+=1,p=St(p,h));const x=a.segments[0].midPoint,P=t.contains(x,{strokeIsInside:s});if(i==="keep"&&P||i==="remove"&&!P){const w=a;d+=1,d===2&&p.length?(p=St(p,w),o=null):p=[w]}return u===null&&d===1&&o&&(p=Vn(p,o)),d===1&&(u=d,o=null),p.length?p:(o=null,[])});return On(f)}const _n=(t,n,e)=>{const i=rt(t,n,{firstInside:"remove",secondInside:"remove",...e});return Array.isArray(i)?i:i.identical?[t]:i.firstCurveInSecond?[n]:i.secondCurveInFirst?[t]:[t,n]},U=(t,n,e)=>{const i=rt(t,n,{firstInside:"remove",secondInside:"keep",...e});return Array.isArray(i)?i:i.identical?[]:i.firstCurveInSecond?[]:i.secondCurveInFirst?[t,n]:[t]},ot=(t,n,e)=>{const i=(e==null?void 0:e.firstBoundaryInside)??!1,s=(e==null?void 0:e.secondBoundaryInside)??!1,r=i||s,c=(u,f,h)=>u.segments.every(a=>f.contains(a.midPoint,{strokeIsInside:h}));if(r){if(c(t,n,s))return[t];if(c(n,t,i))return[n]}const o=rt(t,n,{firstInside:"keep",secondInside:"keep",...e});return Array.isArray(o)?o:o.identical?[t]:o.firstCurveInSecond?[t]:o.secondCurveInFirst?[n]:[]};function Tn(t){const n=new Map,e=[];return t.forEach((i,s)=>{let r;n.has(s)?r=n.get(s):(r={current:[i],fusedWith:new Set([s])},e.push(r)),t.slice(s+1).forEach((c,o)=>{const u=r.current,f=s+o+1;if(r.fusedWith.has(f))return;let h=[c],a=!1;if(n.has(f)&&(h=n.get(f).current,a=!0),!u.some(m=>h.some(g=>m.intersects(g))))return;let d;u.length>1||h.length>1?d=k(u,h):d=Ot(u[0],h[0]),r.fusedWith.add(f),r.current=d,a||n.set(f,r)})}),e.flatMap(({current:i})=>i)}function Ot(t,n){const e=_n(t.contour,n.contour),i=n.holes.flatMap(c=>U(c,t.contour)),s=t.holes.flatMap(c=>U(c,n.contour)),r=Fn(t.holes,n.holes).flatMap(([c,o])=>ot(c,o));return q([...e,...i,...s,...r])}function j(t,n){if(t.isFull&&n.isFull)return q(U(t.contour,n.contour));if(t.isFull){const i=U(t.contour,n.contour),s=n.holes.flatMap(r=>ot(r,t.contour,{firstBoundaryInside:!0}));return q([...i,...s])}else if(n.isFull&&!t.contour.intersects(n.contour))if(t.contour.contains(n.contour.firstPoint)){const i=k(t.holes.map(s=>new C(s)),[n]);return q([t.contour,...i.flatMap(s=>s.allLoops)])}else return[t];let e=j(new C(t.contour),n);return t.holes.forEach(i=>{e=e.flatMap(s=>j(s,new C(i)))}),e}function qn(t,n){const e=ot(t.contour,n.contour);if(!e.length)return[];let i=q(e);return i=O(i,t.holes.map(s=>new C(s))),O(i,n.holes.map(s=>new C(s)))}function k(t,n){if(!t.length)return n;if(!n.length)return t;if(t.length===1&&n.length>1||n.length===1&&t.length>1)return Tn([...t,...n]);if(t.length>1&&n.length>1){let e=k([t[0]],n);return t.slice(1).forEach(i=>{e=k([i],e)}),e}return t.length===1&&n.length===1?Ot(t[0],n[0]):[]}function O(t,n){if(!t.length)return[];if(!n.length)return t;if(t.length===1&&n.length===1)return j(t[0],n[0]);if(t.length>1)return t.flatMap(i=>O([i],n));let e=j(t[0],n[0]);return n.slice(1).forEach(i=>{e=O(e,[i])}),e}function $(t,n){return!t.length||!n.length?[]:t.length===1&&n.length===1?qn(t[0],n[0]):t.length>1?t.flatMap(e=>$([e],n)):n.flatMap(e=>$(t,[e]))}class I extends l.Transformable{constructor(e=[],{ignoreChecks:i=!1}={}){super();b(this,"figures");b(this,"_boundingBox",null);i||Dn(e),this.figures=e}get isEmpty(){return this.figures.length===0}get boundingBox(){if(this.isEmpty)return new l.BoundingBox;if(this._boundingBox===null){let e=this.figures[0].boundingBox;for(const i of this.figures.slice(1))e=e.merge(i.boundingBox);this._boundingBox=e}return this._boundingBox}clone(){return new I(this.figures.map(e=>e.clone()))}transform(e){return new I(this.figures.map(i=>i.transform(e)))}contains(e,{strokeIsInside:i=!1}={}){return this.figures.some(s=>s.contains(e,{strokeIsInside:i}))}intersects(e){return this.figures.some(i=>e.figures.some(s=>i.intersects(s)))}overlappingStrands(e){return this.figures.flatMap(i=>e instanceof I?e.figures.flatMap(s=>i.overlappingStrands(s)):i.overlappingStrands(e))}fuse(e){return new I(k(this.figures,e.figures))}cut(e){return new I(O(this.figures,e.figures))}intersect(e){return new I($(this.figures,e.figures))}}function Dn(t){for(const[n,e]of X(t))if(n.intersects(e))throw new Error("Diagram figures must not intersect")}exports.Diagram=I;exports.Figure=C;exports.Loop=B;exports.Strand=M;exports.arcArcIntersection=Z;exports.cutFiguresLists=O;exports.exportJSON=W;exports.findIntersections=an;exports.findIntersectionsAndOverlaps=R;exports.fuseFiguresLists=k;exports.intersectFiguresLists=$;exports.isSegment=Ft;exports.lineArcIntersection=D;exports.projectPointOnLine=yt;exports.stitchSegments=it;exports.strandsBetweenIntersections=K;
4
+ //# sourceMappingURL=models-CCo90hZc.cjs.map