pantograph2d 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{QuadraticBezier-B2g_Iyyl.js → QuadraticBezier-BeY2TXKH.js} +464 -433
- package/dist/QuadraticBezier-BeY2TXKH.js.map +1 -0
- package/dist/{QuadraticBezier-CuRsIP_D.cjs → QuadraticBezier-eSR75IzC.cjs} +9 -9
- package/dist/QuadraticBezier-eSR75IzC.cjs.map +1 -0
- package/dist/draw-BmJ8wIc9.cjs +2 -0
- package/dist/draw-BmJ8wIc9.cjs.map +1 -0
- package/dist/{draw-BJW5kfm9.js → draw-DzKVhurb.js} +94 -89
- package/dist/draw-DzKVhurb.js.map +1 -0
- package/dist/{models-DdZq-waE.js → models-BHeLX0dj.js} +544 -527
- package/dist/models-BHeLX0dj.js.map +1 -0
- package/dist/models-Fv9xfQBT.cjs +4 -0
- package/dist/models-Fv9xfQBT.cjs.map +1 -0
- package/dist/pantograph/drawShape.cjs +1 -1
- package/dist/pantograph/drawShape.js +2 -2
- package/dist/pantograph/models.cjs +1 -1
- package/dist/pantograph/models.js +2 -2
- package/dist/pantograph/svg.cjs +1 -1
- package/dist/pantograph/svg.js +1 -1
- package/dist/pantograph.cjs +2 -2
- package/dist/pantograph.cjs.map +1 -1
- package/dist/pantograph.js +83 -83
- package/dist/pantograph.js.map +1 -1
- package/dist/svg-BTO7h1ix.js +62 -0
- package/dist/svg-BTO7h1ix.js.map +1 -0
- package/dist/svg-b6SOnbda.cjs +8 -0
- package/dist/svg-b6SOnbda.cjs.map +1 -0
- package/dist/types/src/algorithms/offsets/offsetSegment.d.ts +1 -0
- package/dist/types/src/models/BoundingBox.d.ts +1 -0
- package/dist/types/src/models/Diagram.d.ts +1 -0
- package/dist/types/src/models/Figure.d.ts +1 -0
- package/dist/types/src/models/Loop.d.ts +1 -0
- package/dist/types/src/models/Strand.d.ts +5 -0
- package/dist/types/src/models/TransformationMatrix.d.ts +1 -0
- package/dist/types/src/models/segments/Arc.d.ts +1 -0
- package/dist/types/src/models/segments/CubicBezier.d.ts +1 -0
- package/dist/types/src/models/segments/EllipseArc.d.ts +1 -0
- package/dist/types/src/models/segments/Line.d.ts +2 -0
- package/dist/types/src/models/segments/QuadraticBezier.d.ts +1 -0
- package/dist/types/src/tesselationOperations.d.ts +4 -4
- package/package.json +2 -2
- package/dist/QuadraticBezier-B2g_Iyyl.js.map +0 -1
- package/dist/QuadraticBezier-CuRsIP_D.cjs.map +0 -1
- package/dist/draw-9Elv4xz6.cjs +0 -2
- package/dist/draw-9Elv4xz6.cjs.map +0 -1
- package/dist/draw-BJW5kfm9.js.map +0 -1
- package/dist/models-DdZq-waE.js.map +0 -1
- package/dist/models-LHGiMarC.cjs +0 -4
- package/dist/models-LHGiMarC.cjs.map +0 -1
- package/dist/svg-BzloQ9l1.cjs +0 -8
- package/dist/svg-BzloQ9l1.cjs.map +0 -1
- package/dist/svg-D8vwkQf7.js +0 -62
- package/dist/svg-D8vwkQf7.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var M=Object.defineProperty;var _=(e,t,n)=>t in e?M(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var f=(e,t,n)=>_(e,typeof t!="symbol"?t+"":t,n);const i=require("./QuadraticBezier-eSR75IzC.cjs"),d=require("./models-Fv9xfQBT.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))},C=Symbol.for("pantograph:DegenerateSegment");class m{constructor(t,n){this.firstPoint=t,this.lastPoint=n,Object.defineProperty(this,C,{value:!0})}static isInstance(t){return!!t&&t[C]===!0}}function T(e,t){if(i.Line.isInstance(e))return F(e,t);if(i.Arc.isInstance(e))return V(e,t);if(i.QuadraticBezier.isInstance(e)||i.CubicBezier.isInstance(e))return B(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 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(i.QuadraticBezier.isInstance(e)){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=T(e,o),c=T(t,o);if(m.isInstance(a)||m.isInstance(c))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 y=D.tangentAt(h),x=i.perpendicularClockwise(y),z=i.add(h,i.scalarMultiply(x,o));return P.splitAt(z)},[u]=p(e,a),[,g]=p(t,c);return{first:u,second:g,center:h}}function A(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 S(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 I=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 E(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"?S:A;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}=I(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"?S:A;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),E(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(),E([...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=A;exports.offsetSegment=T;
|
|
2
|
+
//# sourceMappingURL=draw-BmJ8wIc9.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draw-BmJ8wIc9.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\nconst DEGENERATE_SEGMENT_INSTANCE = Symbol.for(\n \"pantograph:DegenerateSegment\",\n);\n\nexport class DegenerateSegment {\n static isInstance(value: unknown): value is DegenerateSegment {\n return (\n !!value &&\n (value as { [DEGENERATE_SEGMENT_INSTANCE]?: boolean })[\n DEGENERATE_SEGMENT_INSTANCE\n ] === true\n );\n }\n\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector,\n ) {\n Object.defineProperty(this, DEGENERATE_SEGMENT_INSTANCE, { value: true });\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 (Line.isInstance(segment)) {\n return offsetLine(segment, offset);\n }\n\n if (Arc.isInstance(segment)) {\n return offsetArc(segment, offset);\n }\n\n if (QuadraticBezier.isInstance(segment) || CubicBezier.isInstance(segment)) {\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 (QuadraticBezier.isInstance(curve)) {\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 DegenerateSegment.isInstance(firstOffset) ||\n DegenerateSegment.isInstance(secondOffset)\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","DEGENERATE_SEGMENT_INSTANCE","DegenerateSegment","firstPoint","lastPoint","value","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,47 +1,52 @@
|
|
|
1
1
|
var W = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var m = (e, t, n) =>
|
|
4
|
-
import { a as l, s as u, c as
|
|
5
|
-
import { f as
|
|
2
|
+
var j = (e, t, n) => t in e ? W(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
3
|
+
var m = (e, t, n) => j(e, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
+
import { a as l, s as u, c as b, b as P, L as d, A as z, Q as w, C as D, p as x, d as q, e as T, t as k, f as Q, g as v, h as $, i as H, j as J, R as K, T as U, k as A, n as F, D as S } from "./QuadraticBezier-BeY2TXKH.js";
|
|
5
|
+
import { f as X, S as Z, D as tt, F as nt, L as et } from "./models-BHeLX0dj.js";
|
|
6
6
|
const B = (e, t, n) => {
|
|
7
|
-
const r =
|
|
7
|
+
const r = b(e.V, t.V), i = e.precision * t.precision;
|
|
8
8
|
if (r * r < i)
|
|
9
9
|
return "parallel";
|
|
10
|
-
const s = P(t.firstPoint, e.firstPoint), o =
|
|
10
|
+
const s = P(t.firstPoint, e.firstPoint), o = b(s, t.V) / r;
|
|
11
11
|
return l(e.firstPoint, u(e.V, o));
|
|
12
|
-
}
|
|
13
|
-
|
|
12
|
+
}, y = Symbol.for(
|
|
13
|
+
"pantograph:DegenerateSegment"
|
|
14
|
+
);
|
|
15
|
+
class C {
|
|
14
16
|
constructor(t, n) {
|
|
15
|
-
this.firstPoint = t, this.lastPoint = n;
|
|
17
|
+
this.firstPoint = t, this.lastPoint = n, Object.defineProperty(this, y, { value: !0 });
|
|
18
|
+
}
|
|
19
|
+
static isInstance(t) {
|
|
20
|
+
return !!t && t[y] === !0;
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
|
-
function
|
|
19
|
-
if (e
|
|
20
|
-
return et(e, t);
|
|
21
|
-
if (e instanceof R)
|
|
23
|
+
function _(e, t) {
|
|
24
|
+
if (d.isInstance(e))
|
|
22
25
|
return rt(e, t);
|
|
23
|
-
if (e
|
|
26
|
+
if (z.isInstance(e))
|
|
24
27
|
return it(e, t);
|
|
28
|
+
if (w.isInstance(e) || D.isInstance(e))
|
|
29
|
+
return st(e, t);
|
|
25
30
|
throw new Error("Not implemented");
|
|
26
31
|
}
|
|
27
|
-
function
|
|
32
|
+
function rt(e, t) {
|
|
28
33
|
const { firstPoint: n, lastPoint: r } = e, i = e.normalVector;
|
|
29
34
|
return new d(
|
|
30
35
|
l(n, u(i, t)),
|
|
31
36
|
l(r, u(i, t))
|
|
32
37
|
);
|
|
33
38
|
}
|
|
34
|
-
function
|
|
39
|
+
function it(e, t) {
|
|
35
40
|
const n = l(
|
|
36
41
|
e.firstPoint,
|
|
37
|
-
u(
|
|
42
|
+
u(x(e.tangentAtFirstPoint), t)
|
|
38
43
|
), r = l(
|
|
39
44
|
e.lastPoint,
|
|
40
|
-
u(
|
|
45
|
+
u(x(e.tangentAtLastPoint), t)
|
|
41
46
|
), i = t * (e.clockwise ? 1 : -1);
|
|
42
|
-
return e.radius + i < e.precision ? new
|
|
47
|
+
return e.radius + i < e.precision ? new C(n, r) : new z(n, r, e.center, e.clockwise);
|
|
43
48
|
}
|
|
44
|
-
function
|
|
49
|
+
function L(e, t, n, r, i) {
|
|
45
50
|
const s = B(
|
|
46
51
|
{
|
|
47
52
|
V: n,
|
|
@@ -60,26 +65,26 @@ function b(e, t, n, r, i) {
|
|
|
60
65
|
);
|
|
61
66
|
return s;
|
|
62
67
|
}
|
|
63
|
-
function
|
|
68
|
+
function st(e, t) {
|
|
64
69
|
const { firstPoint: n, lastPoint: r, normalAtFirstPoint: i, normalAtLastPoint: s } = e, o = B(
|
|
65
70
|
{ V: i, firstPoint: n, precision: e.precision },
|
|
66
71
|
{ V: s, firstPoint: r, precision: e.precision }
|
|
67
72
|
), a = l(
|
|
68
73
|
n,
|
|
69
74
|
u(i, t)
|
|
70
|
-
),
|
|
75
|
+
), c = l(
|
|
71
76
|
r,
|
|
72
77
|
u(s, t)
|
|
73
78
|
);
|
|
74
79
|
if (o === "parallel")
|
|
75
80
|
throw new Error("Parallel lines not expected in safe bezier offset");
|
|
76
|
-
if (
|
|
81
|
+
if (q(P(o, n), i) * t > 0 && Math.min(
|
|
77
82
|
T(n, o),
|
|
78
83
|
T(r, o)
|
|
79
84
|
) < t)
|
|
80
|
-
return new
|
|
81
|
-
if (e
|
|
82
|
-
const
|
|
85
|
+
return new C(a, c);
|
|
86
|
+
if (w.isInstance(e)) {
|
|
87
|
+
const f = L(
|
|
83
88
|
o,
|
|
84
89
|
e.controlPoint,
|
|
85
90
|
e.tangentAtFirstPoint,
|
|
@@ -88,54 +93,54 @@ function it(e, t) {
|
|
|
88
93
|
);
|
|
89
94
|
return new w(
|
|
90
95
|
a,
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
c,
|
|
97
|
+
f
|
|
93
98
|
);
|
|
94
99
|
}
|
|
95
|
-
const
|
|
100
|
+
const g = L(
|
|
96
101
|
o,
|
|
97
102
|
e.firstControlPoint,
|
|
98
103
|
e.tangentAtFirstPoint,
|
|
99
104
|
a,
|
|
100
105
|
e.precision
|
|
101
|
-
),
|
|
106
|
+
), p = L(
|
|
102
107
|
o,
|
|
103
108
|
e.lastControlPoint,
|
|
104
109
|
e.tangentAtLastPoint,
|
|
105
|
-
|
|
110
|
+
c,
|
|
106
111
|
e.precision
|
|
107
112
|
);
|
|
108
113
|
return new D(
|
|
109
114
|
a,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
c,
|
|
116
|
+
g,
|
|
117
|
+
p
|
|
113
118
|
);
|
|
114
119
|
}
|
|
115
120
|
function M(e, t, n) {
|
|
116
|
-
const r =
|
|
121
|
+
const r = b(
|
|
117
122
|
e.tangentAtLastPoint,
|
|
118
123
|
t.tangentAtFirstPoint
|
|
119
124
|
);
|
|
120
125
|
if (Math.abs(r) < 1e-10) return null;
|
|
121
|
-
const i = r > 0 ? 1 : -1, s = Math.abs(n) * i, o =
|
|
122
|
-
if (o
|
|
126
|
+
const i = r > 0 ? 1 : -1, s = Math.abs(n) * i, o = _(e, s), a = _(t, s);
|
|
127
|
+
if (C.isInstance(o) || C.isInstance(a))
|
|
123
128
|
return null;
|
|
124
|
-
let
|
|
129
|
+
let c;
|
|
125
130
|
try {
|
|
126
|
-
|
|
131
|
+
c = X(o, a, 1e-9).at(-1);
|
|
127
132
|
} catch {
|
|
128
133
|
return null;
|
|
129
134
|
}
|
|
130
|
-
if (!
|
|
135
|
+
if (!c)
|
|
131
136
|
return null;
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
return
|
|
135
|
-
}, [
|
|
136
|
-
return { first:
|
|
137
|
+
const h = c, g = (E, N) => {
|
|
138
|
+
const O = N.tangentAt(h), G = Q(O), Y = l(h, u(G, s));
|
|
139
|
+
return E.splitAt(Y);
|
|
140
|
+
}, [p] = g(e, o), [, f] = g(t, a);
|
|
141
|
+
return { first: p, second: f, center: h };
|
|
137
142
|
}
|
|
138
|
-
function
|
|
143
|
+
function I(e, t, n) {
|
|
139
144
|
const r = M(e, t, n);
|
|
140
145
|
if (!r)
|
|
141
146
|
return console.warn(
|
|
@@ -150,7 +155,7 @@ function V(e, t, n) {
|
|
|
150
155
|
s
|
|
151
156
|
];
|
|
152
157
|
}
|
|
153
|
-
function
|
|
158
|
+
function V(e, t, n) {
|
|
154
159
|
const r = M(e, t, n);
|
|
155
160
|
if (!r)
|
|
156
161
|
return console.warn(
|
|
@@ -161,7 +166,7 @@ function _(e, t, n) {
|
|
|
161
166
|
const { first: i, second: s } = r;
|
|
162
167
|
return [i, new d(i.lastPoint, s.firstPoint), s];
|
|
163
168
|
}
|
|
164
|
-
const
|
|
169
|
+
const ot = (e) => {
|
|
165
170
|
let t;
|
|
166
171
|
e ? typeof e == "number" || Array.isArray(e) && e.length === 2 ? t = { endTangent: e } : t = { endTangent: 0, ...e } : t = { endTangent: [1, 0] };
|
|
167
172
|
const {
|
|
@@ -171,14 +176,14 @@ const st = (e) => {
|
|
|
171
176
|
startTangent: s
|
|
172
177
|
} = t;
|
|
173
178
|
let o;
|
|
174
|
-
typeof n == "number" ? o = A(1, n *
|
|
179
|
+
typeof n == "number" ? o = A(1, n * S) : o = n;
|
|
175
180
|
let a;
|
|
176
|
-
return typeof s == "number" ? a = A(1, s *
|
|
181
|
+
return typeof s == "number" ? a = A(1, s * S) : a = s, { endTangent: o, startFactor: r, endFactor: i, startTangent: a };
|
|
177
182
|
};
|
|
178
|
-
function
|
|
179
|
-
return new
|
|
183
|
+
function R(e, { ignoreChecks: t = !1 } = {}) {
|
|
184
|
+
return new tt([new nt(new et([...e], { ignoreChecks: t }))]);
|
|
180
185
|
}
|
|
181
|
-
class
|
|
186
|
+
class at {
|
|
182
187
|
constructor(t = [0, 0]) {
|
|
183
188
|
m(this, "pointer");
|
|
184
189
|
m(this, "firstPoint");
|
|
@@ -194,13 +199,13 @@ class ot {
|
|
|
194
199
|
return this.pointer = t, this.firstPoint = t, this;
|
|
195
200
|
}
|
|
196
201
|
saveSegment(t) {
|
|
197
|
-
if (
|
|
202
|
+
if (v(t.firstPoint, t.lastPoint))
|
|
198
203
|
throw new Error(`Segment has no length, ${t.repr}`);
|
|
199
204
|
if (!this._nextCorner)
|
|
200
205
|
return this.pendingSegments.push(t), this;
|
|
201
206
|
const n = this.pendingSegments.pop();
|
|
202
207
|
if (!n) throw new Error("bug in the custom corner algorithm");
|
|
203
|
-
const r = this._nextCorner.mode === "chamfer" ?
|
|
208
|
+
const r = this._nextCorner.mode === "chamfer" ? V : I;
|
|
204
209
|
return this.pendingSegments.push(
|
|
205
210
|
...r(n, t, this._nextCorner.radius)
|
|
206
211
|
), this._nextCorner = null, this;
|
|
@@ -225,11 +230,11 @@ class ot {
|
|
|
225
230
|
return this.lineTo([t, this.pointer[1]]);
|
|
226
231
|
}
|
|
227
232
|
polarLineTo([t, n]) {
|
|
228
|
-
const r = n *
|
|
233
|
+
const r = n * S, i = A(t, r);
|
|
229
234
|
return this.lineTo(i);
|
|
230
235
|
}
|
|
231
236
|
polarLine(t, n) {
|
|
232
|
-
const r = n *
|
|
237
|
+
const r = n * S, [i, s] = A(t, r);
|
|
233
238
|
return this.line(i, s);
|
|
234
239
|
}
|
|
235
240
|
tangentLine(t) {
|
|
@@ -240,7 +245,7 @@ class ot {
|
|
|
240
245
|
return this.line(r * t, i * t);
|
|
241
246
|
}
|
|
242
247
|
threePointsArcTo(t, n) {
|
|
243
|
-
return this.saveSegment(
|
|
248
|
+
return this.saveSegment($(this.pointer, n, t)), this.pointer = t, this;
|
|
244
249
|
}
|
|
245
250
|
threePointsArc(t, n, r, i) {
|
|
246
251
|
const [s, o] = this.pointer;
|
|
@@ -251,7 +256,7 @@ class ot {
|
|
|
251
256
|
}
|
|
252
257
|
sagittaArcTo(t, n) {
|
|
253
258
|
if (!n) return this.lineTo(t);
|
|
254
|
-
const r = new d(this.pointer, t), i =
|
|
259
|
+
const r = new d(this.pointer, t), i = x(r.tangentAtFirstPoint), s = l(r.midPoint, u(i, n));
|
|
255
260
|
return this.threePointsArcTo(t, s);
|
|
256
261
|
}
|
|
257
262
|
sagittaArc(t, n, r) {
|
|
@@ -301,7 +306,7 @@ class ot {
|
|
|
301
306
|
}
|
|
302
307
|
ellipseTo(t, n, r, i, s, o) {
|
|
303
308
|
return this.saveSegment(
|
|
304
|
-
|
|
309
|
+
H(this.pointer, t, n, r, i, s, o)
|
|
305
310
|
), this.pointer = t, this;
|
|
306
311
|
}
|
|
307
312
|
ellipse(t, n, r, i, s, o, a) {
|
|
@@ -315,12 +320,12 @@ class ot {
|
|
|
315
320
|
);
|
|
316
321
|
}
|
|
317
322
|
halfEllipseTo(t, n) {
|
|
318
|
-
const [r, i] =
|
|
323
|
+
const [r, i] = J(P(t, this.pointer));
|
|
319
324
|
return this.ellipseTo(
|
|
320
325
|
t,
|
|
321
326
|
r / 2,
|
|
322
327
|
Math.abs(n),
|
|
323
|
-
i *
|
|
328
|
+
i * K,
|
|
324
329
|
!0,
|
|
325
330
|
n > 0
|
|
326
331
|
);
|
|
@@ -340,20 +345,20 @@ class ot {
|
|
|
340
345
|
return this.saveSegment(new w(this.pointer, t, n)), this.pointer = t, this;
|
|
341
346
|
}
|
|
342
347
|
smoothCurveTo(t, n) {
|
|
343
|
-
const { endTangent: r, startTangent: i, startFactor: s, endFactor: o } =
|
|
344
|
-
let
|
|
345
|
-
i ?
|
|
346
|
-
const p = [
|
|
347
|
-
this.pointer[0] + c[0] * s * h,
|
|
348
|
-
this.pointer[1] + c[1] * s * h
|
|
349
|
-
];
|
|
350
|
-
let f = r;
|
|
351
|
-
f = F(f);
|
|
348
|
+
const { endTangent: r, startTangent: i, startFactor: s, endFactor: o } = ot(n), a = this.pendingSegments.length ? this.pendingSegments[this.pendingSegments.length - 1] : null, c = T(this.pointer, t) / 3;
|
|
349
|
+
let h;
|
|
350
|
+
i ? h = i : a ? h = a.tangentAtLastPoint : h = [1, 0], h = F(h);
|
|
352
351
|
const g = [
|
|
353
|
-
|
|
354
|
-
|
|
352
|
+
this.pointer[0] + h[0] * s * c,
|
|
353
|
+
this.pointer[1] + h[1] * s * c
|
|
354
|
+
];
|
|
355
|
+
let p = r;
|
|
356
|
+
p = F(p);
|
|
357
|
+
const f = [
|
|
358
|
+
t[0] - p[0] * o * c,
|
|
359
|
+
t[1] - p[1] * o * c
|
|
355
360
|
];
|
|
356
|
-
return this.cubicBezierCurveTo(t,
|
|
361
|
+
return this.cubicBezierCurveTo(t, g, f);
|
|
357
362
|
}
|
|
358
363
|
smoothCurve(t, n, r) {
|
|
359
364
|
return this.smoothCurveTo(
|
|
@@ -371,49 +376,49 @@ class ot {
|
|
|
371
376
|
const r = this.pendingSegments.pop(), i = this.pendingSegments.shift();
|
|
372
377
|
if (!r || !i)
|
|
373
378
|
throw new Error("Not enough curves to close and fillet");
|
|
374
|
-
const s = n === "chamfer" ?
|
|
379
|
+
const s = n === "chamfer" ? V : I;
|
|
375
380
|
this.pendingSegments.push(...s(r, i, t));
|
|
376
381
|
}
|
|
377
382
|
close(t = !1) {
|
|
378
383
|
if (!this.pendingSegments.length) throw new Error("No segments to close");
|
|
379
384
|
const n = this.pendingSegments[0], r = this.pendingSegments.at(-1);
|
|
380
|
-
return
|
|
385
|
+
return v(n.firstPoint, r.lastPoint) || this.lineTo(n.firstPoint), this._nextCorner !== null && (this._customCornerLastWithFirst(
|
|
381
386
|
this._nextCorner.radius,
|
|
382
387
|
this._nextCorner.mode
|
|
383
|
-
), this._nextCorner = null),
|
|
388
|
+
), this._nextCorner = null), R(this.pendingSegments, { ignoreChecks: t });
|
|
384
389
|
}
|
|
385
390
|
closeWithMirror(t = !1) {
|
|
386
391
|
if (!this.pendingSegments.length) throw new Error("No segments to close");
|
|
387
392
|
const n = this.pendingSegments[0], r = this.pendingSegments.at(-1), i = P(
|
|
388
393
|
r.lastPoint,
|
|
389
394
|
n.firstPoint
|
|
390
|
-
), s = new
|
|
395
|
+
), s = new U().mirrorLine(
|
|
391
396
|
i,
|
|
392
397
|
n.firstPoint
|
|
393
398
|
), o = this.pendingSegments.map(
|
|
394
399
|
(a) => a.transform(s).reverse()
|
|
395
400
|
);
|
|
396
|
-
return o.reverse(),
|
|
401
|
+
return o.reverse(), R(
|
|
397
402
|
[...this.pendingSegments, ...o],
|
|
398
403
|
{ ignoreChecks: t }
|
|
399
404
|
);
|
|
400
405
|
}
|
|
401
406
|
asStrand() {
|
|
402
|
-
return new
|
|
407
|
+
return new Z([...this.pendingSegments]);
|
|
403
408
|
}
|
|
404
409
|
get isClosed() {
|
|
405
410
|
var t;
|
|
406
|
-
return
|
|
411
|
+
return v(this.pointer, (t = this.pendingSegments[0]) == null ? void 0 : t.firstPoint);
|
|
407
412
|
}
|
|
408
413
|
}
|
|
409
|
-
function
|
|
410
|
-
return new
|
|
414
|
+
function ut(e = [0, 0]) {
|
|
415
|
+
return new at(e);
|
|
411
416
|
}
|
|
412
417
|
export {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
+
C as D,
|
|
419
|
+
at as a,
|
|
420
|
+
ut as d,
|
|
421
|
+
I as f,
|
|
422
|
+
_ as o
|
|
418
423
|
};
|
|
419
|
-
//# sourceMappingURL=draw-
|
|
424
|
+
//# sourceMappingURL=draw-DzKVhurb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draw-DzKVhurb.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\nconst DEGENERATE_SEGMENT_INSTANCE = Symbol.for(\n \"pantograph:DegenerateSegment\",\n);\n\nexport class DegenerateSegment {\n static isInstance(value: unknown): value is DegenerateSegment {\n return (\n !!value &&\n (value as { [DEGENERATE_SEGMENT_INSTANCE]?: boolean })[\n DEGENERATE_SEGMENT_INSTANCE\n ] === true\n );\n }\n\n constructor(\n public readonly firstPoint: Vector,\n public readonly lastPoint: Vector,\n ) {\n Object.defineProperty(this, DEGENERATE_SEGMENT_INSTANCE, { value: true });\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 (Line.isInstance(segment)) {\n return offsetLine(segment, offset);\n }\n\n if (Arc.isInstance(segment)) {\n return offsetArc(segment, offset);\n }\n\n if (QuadraticBezier.isInstance(segment) || CubicBezier.isInstance(segment)) {\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 (QuadraticBezier.isInstance(curve)) {\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 DegenerateSegment.isInstance(firstOffset) ||\n DegenerateSegment.isInstance(secondOffset)\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","DEGENERATE_SEGMENT_INSTANCE","DegenerateSegment","firstPoint","lastPoint","value","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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"}
|