tldraw
Version:
A tiny little drawing editor.
8 lines (7 loc) • 32 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../../src/lib/shapes/shared/PathBuilder.tsx"],
"sourcesContent": ["import {\n\tassert,\n\tclamp,\n\texhaustiveSwitchError,\n\tGeometry2dOptions,\n\tgetPerfectDashProps,\n\tGroup2d,\n\tinvLerp,\n\tlerp,\n\tPolygon2d,\n\tPolyline2d,\n\trng,\n\ttoDomPrecision,\n\tVec,\n\tVecLike,\n\tVecModel,\n} from '@tldraw/editor'\nimport { SVGProps } from 'react'\n\nfunction getVerticesCountForLength(length: number, spacing = 20) {\n\treturn Math.max(8, Math.ceil(length / spacing))\n}\n\nexport interface BasePathBuilderOpts {\n\tstrokeWidth: number\n\tforceSolid?: boolean\n\tprops?: SVGProps<SVGPathElement & SVGGElement>\n}\n\nexport interface SolidPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'solid'\n}\n\nexport interface DashedPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'dashed' | 'dotted'\n\tsnap?: number\n\tend?: 'skip' | 'outset' | 'none'\n\tstart?: 'skip' | 'outset' | 'none'\n\tlengthRatio?: number\n}\n\nexport interface DrawPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'draw'\n\trandomSeed: string\n\toffset?: number\n\troundness?: number\n\tpasses?: number\n}\n\nexport type PathBuilderOpts = SolidPathBuilderOpts | DashedPathBuilderOpts | DrawPathBuilderOpts\n\ninterface SegmentOpts {\n\toffset?: number\n\troundness?: number\n}\n\ninterface LineOpts extends SegmentOpts {\n\tgeometry?: Omit<Geometry2dOptions, 'isClosed'> | false\n}\n\ninterface MoveToPathBuilderSegment {\n\ttype: 'moveTo'\n\tx: number\n\ty: number\n\topts?: LineOpts\n}\n\ninterface LineToPathBuilderSegment {\n\ttype: 'lineTo'\n\tx: number\n\ty: number\n\topts?: SegmentOpts\n}\n\ninterface ArcToPathBuilderSegment {\n\ttype: 'arcTo'\n\tradius: number\n\tlargeArcFlag: boolean\n\tsweepFlag: boolean\n\tx: number\n\ty: number\n\topts?: SegmentOpts\n}\n\ntype PathBuilderSegment = LineToPathBuilderSegment | ArcToPathBuilderSegment\n\ninterface PathBuilderLine {\n\tinitial: MoveToPathBuilderSegment\n\tsegments: PathBuilderSegment[]\n\tclosed: boolean\n}\n\nexport class PathBuilder {\n\tstatic throughPoints(points: VecLike[], opts?: LineOpts) {\n\t\tconst path = new PathBuilder()\n\t\tpath.moveTo(points[0].x, points[0].y, opts)\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tpath.lineTo(points[i].x, points[i].y)\n\t\t}\n\t\treturn path\n\t}\n\n\tconstructor() {}\n\n\tprivate lines: PathBuilderLine[] = []\n\n\tprivate currentLine() {\n\t\tconst lastLine = this.lines[this.lines.length - 1]\n\t\tassert(lastLine, 'Start an SVGPathBuilder with `.moveTo()`')\n\t\tassert(!lastLine.closed, 'Cannot work on a closed line')\n\t\treturn lastLine\n\t}\n\n\tmoveTo(x: number, y: number, opts?: LineOpts) {\n\t\tthis.lines.push({\n\t\t\tinitial: { type: 'moveTo', x, y, opts },\n\t\t\tsegments: [],\n\t\t\tclosed: false,\n\t\t})\n\t\treturn this\n\t}\n\n\tlineTo(x: number, y: number, opts?: SegmentOpts) {\n\t\tthis.currentLine().segments.push({ type: 'lineTo', x, y, opts })\n\t\treturn this\n\t}\n\n\tarcTo(\n\t\tradius: number,\n\t\tlargeArcFlag: boolean,\n\t\tsweepFlag: boolean,\n\t\tx: number,\n\t\ty: number,\n\t\topts?: SegmentOpts\n\t) {\n\t\tthis.currentLine().segments.push({\n\t\t\ttype: 'arcTo',\n\t\t\tradius,\n\t\t\tlargeArcFlag,\n\t\t\tsweepFlag,\n\t\t\tx,\n\t\t\ty,\n\t\t\topts,\n\t\t})\n\t\treturn this\n\t}\n\tclose() {\n\t\tthis.currentLine().closed = true\n\t\treturn this\n\t}\n\n\ttoD(opts: { closedOnly?: boolean } = {}) {\n\t\tconst closedOnly = opts.closedOnly ?? false\n\t\tconst parts = []\n\t\tfor (const { initial, segments, closed } of this.lines) {\n\t\t\tif (closedOnly && !closed) continue\n\t\t\tparts.push('M', toDomPrecision(initial.x), toDomPrecision(initial.y))\n\t\t\tfor (const segment of segments) {\n\t\t\t\tswitch (segment.type) {\n\t\t\t\t\tcase 'lineTo':\n\t\t\t\t\t\tparts.push('L', toDomPrecision(segment.x), toDomPrecision(segment.y))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'arcTo':\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t'A',\n\t\t\t\t\t\t\tsegment.radius,\n\t\t\t\t\t\t\tsegment.radius,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tsegment.largeArcFlag ? '1' : '0',\n\t\t\t\t\t\t\tsegment.sweepFlag ? '1' : '0',\n\t\t\t\t\t\t\ttoDomPrecision(segment.x),\n\t\t\t\t\t\t\ttoDomPrecision(segment.y)\n\t\t\t\t\t\t)\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (closed) {\n\t\t\t\tparts.push('Z')\n\t\t\t}\n\t\t}\n\t\treturn parts.join(' ')\n\t}\n\n\ttoSvg(opts: PathBuilderOpts) {\n\t\tif (opts.forceSolid) {\n\t\t\treturn this.toSolidSvg(opts)\n\t\t}\n\t\tswitch (opts.style) {\n\t\t\tcase 'solid':\n\t\t\t\treturn this.toSolidSvg(opts)\n\t\t\tcase 'dashed':\n\t\t\tcase 'dotted':\n\t\t\t\treturn this.toDashedSvg(opts)\n\t\t\tcase 'draw':\n\t\t\t\treturn this.toDrawSvg(opts)\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(opts, 'style')\n\t\t}\n\t}\n\n\ttoGeometry() {\n\t\tconst geometries = []\n\t\tfor (const { initial, segments, closed } of this.lines) {\n\t\t\tif (initial.opts?.geometry === false) continue\n\t\t\tconst vertices = [new Vec(initial.x, initial.y)]\n\t\t\tfor (const segment of segments) {\n\t\t\t\tswitch (segment.type) {\n\t\t\t\t\tcase 'lineTo': {\n\t\t\t\t\t\tvertices.push(new Vec(segment.x, segment.y))\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'arcTo': {\n\t\t\t\t\t\tconst info = getArcSegmentInfo(vertices[vertices.length - 1], segment)\n\t\t\t\t\t\tif (info === null) break\n\t\t\t\t\t\tif (info === 'straight-line') {\n\t\t\t\t\t\t\tvertices.push(new Vec(segment.x, segment.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst verticesCount = getVerticesCountForLength(info.length)\n\t\t\t\t\t\tfor (let i = 0; i < verticesCount + 1; i++) {\n\t\t\t\t\t\t\tconst t = (i / verticesCount) * info.sweepAngle\n\t\t\t\t\t\t\tconst point = Vec.Rot(info.startVector, t).mul(info.radius).add(info.center)\n\t\t\t\t\t\t\tvertices.push(point)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\texhaustiveSwitchError(segment, 'type')\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst geometry = closed\n\t\t\t\t? new Polygon2d({ points: vertices, isFilled: false, ...initial.opts?.geometry })\n\t\t\t\t: new Polyline2d({ points: vertices, ...initial.opts?.geometry })\n\n\t\t\tgeometries.push(geometry)\n\t\t}\n\n\t\tif (geometries.length === 0) return null\n\t\tif (geometries.length === 1) return geometries[0]\n\t\treturn new Group2d({ children: geometries })\n\t}\n\n\tprivate toSolidSvg(opts: PathBuilderOpts) {\n\t\tconst { strokeWidth, props } = opts\n\n\t\treturn <path strokeWidth={strokeWidth} d={this.toD()} {...props} />\n\t}\n\n\tprivate toDashedSvg(opts: DashedPathBuilderOpts) {\n\t\tconst {\n\t\t\tstyle,\n\t\t\tstrokeWidth,\n\t\t\tsnap,\n\t\t\tend,\n\t\t\tstart,\n\t\t\tlengthRatio,\n\t\t\tprops: { markerStart, markerEnd, ...props } = {},\n\t\t} = opts\n\n\t\tconst parts = []\n\t\tfor (const { initial, segments, closed } of this.lines) {\n\t\t\tlet lastPoint: VecLike = initial\n\n\t\t\tfor (let i = 0; i < segments.length; i++) {\n\t\t\t\tconst segment = segments[i]\n\t\t\t\tconst isFirst = i === 0\n\t\t\t\tconst isLast = i === segments.length - 1 && !closed\n\n\t\t\t\tconst segmentLength = this.segmentLength(lastPoint, segment)\n\t\t\t\tconst { strokeDasharray, strokeDashoffset } = getPerfectDashProps(\n\t\t\t\t\tsegmentLength,\n\t\t\t\t\tstrokeWidth,\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle,\n\t\t\t\t\t\tsnap,\n\t\t\t\t\t\tlengthRatio,\n\t\t\t\t\t\tstart: isFirst ? (closed ? 'none' : start) : 'outset',\n\t\t\t\t\t\tend: isLast ? (closed ? 'none' : end) : 'outset',\n\t\t\t\t\t}\n\t\t\t\t)\n\n\t\t\t\tswitch (segment.type) {\n\t\t\t\t\tcase 'lineTo':\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\tx1={toDomPrecision(lastPoint.x)}\n\t\t\t\t\t\t\t\ty1={toDomPrecision(lastPoint.y)}\n\t\t\t\t\t\t\t\tx2={toDomPrecision(segment.x)}\n\t\t\t\t\t\t\t\ty2={toDomPrecision(segment.y)}\n\t\t\t\t\t\t\t\tstrokeDasharray={strokeDasharray}\n\t\t\t\t\t\t\t\tstrokeDashoffset={strokeDashoffset}\n\t\t\t\t\t\t\t\tmarkerStart={isFirst ? markerStart : undefined}\n\t\t\t\t\t\t\t\tmarkerEnd={isLast ? markerEnd : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'arcTo':\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\td={[\n\t\t\t\t\t\t\t\t\t'M',\n\t\t\t\t\t\t\t\t\ttoDomPrecision(lastPoint.x),\n\t\t\t\t\t\t\t\t\ttoDomPrecision(lastPoint.y),\n\t\t\t\t\t\t\t\t\t'A',\n\t\t\t\t\t\t\t\t\tsegment.radius,\n\t\t\t\t\t\t\t\t\tsegment.radius,\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tsegment.largeArcFlag ? '1' : '0',\n\t\t\t\t\t\t\t\t\tsegment.sweepFlag ? '1' : '0',\n\t\t\t\t\t\t\t\t\ttoDomPrecision(segment.x),\n\t\t\t\t\t\t\t\t\ttoDomPrecision(segment.y),\n\t\t\t\t\t\t\t\t].join(' ')}\n\t\t\t\t\t\t\t\tstrokeDasharray={strokeDasharray}\n\t\t\t\t\t\t\t\tstrokeDashoffset={strokeDashoffset}\n\t\t\t\t\t\t\t\tmarkerStart={isFirst ? markerStart : undefined}\n\t\t\t\t\t\t\t\tmarkerEnd={isLast ? markerEnd : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\texhaustiveSwitchError(segment, 'type')\n\t\t\t\t}\n\n\t\t\t\tlastPoint = segment\n\t\t\t}\n\n\t\t\tif (closed && lastPoint !== initial) {\n\t\t\t\tconst dist = Vec.Dist(lastPoint, initial)\n\t\t\t\tconst { strokeDasharray, strokeDashoffset } = getPerfectDashProps(dist, strokeWidth, {\n\t\t\t\t\tstyle,\n\t\t\t\t\tsnap,\n\t\t\t\t\tlengthRatio,\n\t\t\t\t\tstart: 'outset',\n\t\t\t\t\tend: 'none',\n\t\t\t\t})\n\n\t\t\t\tparts.push(\n\t\t\t\t\t<line\n\t\t\t\t\t\tkey=\"last\"\n\t\t\t\t\t\tx1={toDomPrecision(lastPoint.x)}\n\t\t\t\t\t\ty1={toDomPrecision(lastPoint.y)}\n\t\t\t\t\t\tx2={toDomPrecision(initial.x)}\n\t\t\t\t\t\ty2={toDomPrecision(initial.y)}\n\t\t\t\t\t\tstrokeDasharray={strokeDasharray}\n\t\t\t\t\t\tstrokeDashoffset={strokeDashoffset}\n\t\t\t\t\t\tmarkerEnd={markerEnd}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\treturn (\n\t\t\t<g strokeWidth={strokeWidth} {...props}>\n\t\t\t\t{parts}\n\t\t\t</g>\n\t\t)\n\t}\n\n\tprivate toDrawSvg(opts: DrawPathBuilderOpts) {\n\t\tconst {\n\t\t\tstrokeWidth,\n\t\t\trandomSeed,\n\t\t\toffset: defaultOffset = strokeWidth / 3,\n\t\t\troundness: defaultRoundness = strokeWidth * 2,\n\t\t\tpasses = 2,\n\t\t\tprops,\n\t\t} = opts\n\n\t\tconst parts = []\n\n\t\tconst tangents = this.lines.map(({ initial, segments, closed }) => {\n\t\t\tconst tangents = []\n\t\t\tconst segmentCount = closed ? segments.length + 1 : segments.length\n\n\t\t\tfor (let i = 0; i < segmentCount; i++) {\n\t\t\t\tlet previous: PathBuilderSegment | MoveToPathBuilderSegment = segments[i - 1]\n\t\t\t\tlet current: PathBuilderSegment | MoveToPathBuilderSegment = segments[i]\n\t\t\t\tlet next: PathBuilderSegment | MoveToPathBuilderSegment = segments[i + 1]\n\n\t\t\t\tif (!previous) previous = initial\n\t\t\t\tif (!current) {\n\t\t\t\t\tcurrent = initial\n\t\t\t\t\tnext = segments[0]\n\t\t\t\t}\n\t\t\t\tif (!next) {\n\t\t\t\t\tnext = initial\n\t\t\t\t}\n\n\t\t\t\tlet tangentBefore, tangentAfter\n\t\t\t\tswitch (current.type) {\n\t\t\t\t\tcase 'lineTo':\n\t\t\t\t\tcase 'moveTo': {\n\t\t\t\t\t\ttangentBefore = Vec.Sub(previous, current).norm()\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'arcTo': {\n\t\t\t\t\t\tconst info = getArcSegmentInfo(previous, current)\n\t\t\t\t\t\tif (info === null || info === 'straight-line') {\n\t\t\t\t\t\t\ttangentBefore = Vec.Sub(current, previous).norm().per()\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttangentBefore = Vec.Per(info.endVector).mul(Math.sign(info.sweepAngle))\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\texhaustiveSwitchError(current, 'type')\n\t\t\t\t}\n\n\t\t\t\tswitch (next.type) {\n\t\t\t\t\tcase 'lineTo':\n\t\t\t\t\tcase 'moveTo': {\n\t\t\t\t\t\ttangentAfter = Vec.Sub(next, current).norm()\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'arcTo': {\n\t\t\t\t\t\tconst info = getArcSegmentInfo(current, next)\n\t\t\t\t\t\tif (info === null || info === 'straight-line') {\n\t\t\t\t\t\t\ttangentAfter = Vec.Sub(next, current).norm().per()\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttangentAfter = Vec.Per(info.startVector).mul(Math.sign(info.sweepAngle))\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\texhaustiveSwitchError(next, 'type')\n\t\t\t\t}\n\n\t\t\t\ttangents.push({ tangentBefore, tangentAfter })\n\t\t\t}\n\n\t\t\treturn tangents\n\t\t})\n\n\t\tfor (let pass = 0; pass < passes; pass++) {\n\t\t\tfor (let lineIdx = 0; lineIdx < this.lines.length; lineIdx++) {\n\t\t\t\tconst { initial, segments, closed } = this.lines[lineIdx]\n\t\t\t\tconst random = rng(randomSeed + pass + lineIdx)\n\t\t\t\tconst initialOffset = initial.opts?.offset ?? defaultOffset\n\t\t\t\tconst initialPOffset = {\n\t\t\t\t\tx: initial.x + random() * initialOffset,\n\t\t\t\t\ty: initial.y + random() * initialOffset,\n\t\t\t\t}\n\n\t\t\t\tconst offsetPoints: VecModel[] = []\n\t\t\t\tlet lastDistance = Vec.Dist(initialPOffset, segments[0])\n\n\t\t\t\tfor (let i = 0; i < segments.length; i++) {\n\t\t\t\t\tconst segment = segments[i]\n\t\t\t\t\tconst nextSegment =\n\t\t\t\t\t\ti === segments.length - 1 ? (closed ? segments[0] : null) : segments[i + 1]\n\t\t\t\t\tconst nextDistance = nextSegment ? Vec.Dist(segment, nextSegment) : Infinity\n\n\t\t\t\t\tconst shortestDistance =\n\t\t\t\t\t\tMath.min(lastDistance, nextDistance) - (segment.opts?.roundness ?? defaultRoundness)\n\n\t\t\t\t\tconst offset = clamp(segment.opts?.offset ?? defaultOffset, 0, shortestDistance / 10)\n\t\t\t\t\tconst offsetPoint = {\n\t\t\t\t\t\tx: segment.x + random() * offset,\n\t\t\t\t\t\ty: segment.y + random() * offset,\n\t\t\t\t\t}\n\n\t\t\t\t\toffsetPoints.push(offsetPoint)\n\t\t\t\t\tlastDistance = nextDistance\n\t\t\t\t}\n\n\t\t\t\tif (closed) {\n\t\t\t\t\tconst roundness = initial.opts?.roundness ?? defaultRoundness\n\t\t\t\t\toffsetPoints.push(initialPOffset)\n\n\t\t\t\t\tconst next = offsetPoints[0]\n\t\t\t\t\tconst nudgeAmount = Math.min(Vec.Dist(initialPOffset, next) / 2, roundness)\n\t\t\t\t\tconst nudged = Vec.Nudge(initialPOffset, next, nudgeAmount)\n\t\t\t\t\tparts.push('M', toDomPrecision(nudged.x), toDomPrecision(nudged.y))\n\t\t\t\t} else {\n\t\t\t\t\tparts.push('M', toDomPrecision(initialPOffset.x), toDomPrecision(initialPOffset.y))\n\t\t\t\t}\n\n\t\t\t\tconst segmentCount = closed ? segments.length + 1 : segments.length\n\t\t\t\tfor (let i = 0; i < segmentCount; i++) {\n\t\t\t\t\tconst segment = i === segments.length ? initial : segments[i]\n\t\t\t\t\tconst roundness = segment.opts?.roundness ?? defaultRoundness\n\t\t\t\t\tconst offsetP = offsetPoints[i]\n\t\t\t\t\tconst { tangentBefore, tangentAfter } = tangents[lineIdx][i]\n\n\t\t\t\t\tconst previousOffsetP = i === 0 ? initialPOffset : offsetPoints[i - 1]\n\t\t\t\t\tconst nextOffsetP =\n\t\t\t\t\t\ti === segments.length - 1 && !closed\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: offsetPoints[(i + 1) % offsetPoints.length]\n\n\t\t\t\t\tswitch (segment.type) {\n\t\t\t\t\t\tcase 'lineTo':\n\t\t\t\t\t\tcase 'moveTo': {\n\t\t\t\t\t\t\tif (!nextOffsetP || roundness === 0) {\n\t\t\t\t\t\t\t\tparts.push('L', toDomPrecision(offsetP.x), toDomPrecision(offsetP.y))\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst clampedRoundness = lerp(\n\t\t\t\t\t\t\t\troundness,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tclamp(\n\t\t\t\t\t\t\t\t\tinvLerp(\n\t\t\t\t\t\t\t\t\t\tMath.PI / 2,\n\t\t\t\t\t\t\t\t\t\tMath.PI,\n\t\t\t\t\t\t\t\t\t\tMath.abs(Vec.AngleBetween(tangentBefore, tangentAfter))\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t1\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tconst nudgeBeforeAmount = Math.min(\n\t\t\t\t\t\t\t\tVec.Dist(previousOffsetP, offsetP) / 2,\n\t\t\t\t\t\t\t\tclampedRoundness\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tconst nudgeBefore = Vec.Mul(tangentBefore, nudgeBeforeAmount).add(offsetP)\n\n\t\t\t\t\t\t\tconst nudgeAfterAmount = Math.min(\n\t\t\t\t\t\t\t\tVec.Dist(nextOffsetP, offsetP) / 2,\n\t\t\t\t\t\t\t\tclampedRoundness\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tconst nudgeAfter = Vec.Mul(tangentAfter, nudgeAfterAmount).add(offsetP)\n\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'L',\n\t\t\t\t\t\t\t\ttoDomPrecision(nudgeBefore.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(nudgeBefore.y),\n\t\t\t\t\t\t\t\t'Q',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetP.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetP.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(nudgeAfter.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(nudgeAfter.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'arcTo':\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'A',\n\t\t\t\t\t\t\t\tsegment.radius,\n\t\t\t\t\t\t\t\tsegment.radius,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tsegment.largeArcFlag ? '1' : '0',\n\t\t\t\t\t\t\t\tsegment.sweepFlag ? '1' : '0',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetP.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetP.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\texhaustiveSwitchError(segment, 'type')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (closed) {\n\t\t\t\t\tparts.push('Z')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn <path strokeWidth={strokeWidth} d={parts.join(' ')} {...props} />\n\t}\n\n\tprivate segmentLength(lastPoint: VecLike, segment: PathBuilderSegment) {\n\t\tswitch (segment.type) {\n\t\t\tcase 'lineTo':\n\t\t\t\treturn Vec.Dist(lastPoint, segment)\n\t\t\tcase 'arcTo': {\n\t\t\t\tconst info = getArcSegmentInfo(lastPoint, segment)\n\t\t\t\tif (info === null) return 0\n\t\t\t\tif (info === 'straight-line') return Vec.Dist(lastPoint, segment)\n\t\t\t\treturn info.length\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(segment, 'type')\n\t\t}\n\t}\n}\n\n/*!\n * Adapted from https://github.com/rveciana/svg-path-properties\n * MIT License: https://github.com/rveciana/svg-path-properties/blob/master/LICENSE\n * https://github.com/rveciana/svg-path-properties/blob/74d850d14998274f6eae279424bdc2194f156490/src/arc.ts#L121\n */\nfunction getArcSegmentInfo(\n\tlastPoint: VecLike,\n\t{ radius, largeArcFlag, sweepFlag, x, y }: ArcToPathBuilderSegment\n) {\n\t// In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters\n\tradius = Math.abs(radius)\n\n\t// If the endpoints are identical, then this is equivalent to omitting the elliptical arc segment entirely.\n\tif (lastPoint.x === x && lastPoint.y === y) {\n\t\treturn null\n\t}\n\n\t// If radius is 0 then this arc is treated as a straight line segment joining the endpoints.\n\tif (radius === 0) {\n\t\treturn 'straight-line'\n\t}\n\n\t// Following \"Conversion from endpoint to center parameterization\"\n\t// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter\n\n\t// Step #1: Compute transformedPoint\n\tconst dx = (lastPoint.x - x) / 2\n\tconst dy = (lastPoint.y - y) / 2\n\n\t// Ensure radii are large enough\n\tconst radiiCheck = Math.pow(dx, 2) / Math.pow(radius, 2) + Math.pow(dy, 2) / Math.pow(radius, 2)\n\n\tif (radiiCheck > 1) {\n\t\tradius = Math.sqrt(radiiCheck) * radius\n\t}\n\n\t// Step #2: Compute transformedCenter\n\tconst cSquareNumerator =\n\t\tMath.pow(radius, 2) * Math.pow(radius, 2) -\n\t\tMath.pow(radius, 2) * Math.pow(dy, 2) -\n\t\tMath.pow(radius, 2) * Math.pow(dx, 2)\n\tconst cSquareRootDenom =\n\t\tMath.pow(radius, 2) * Math.pow(dy, 2) + Math.pow(radius, 2) * Math.pow(dx, 2)\n\tlet cRadicand = cSquareNumerator / cSquareRootDenom\n\t// Make sure this never drops below zero because of precision\n\tcRadicand = cRadicand < 0 ? 0 : cRadicand\n\tconst cCoef = (largeArcFlag !== sweepFlag ? 1 : -1) * Math.sqrt(cRadicand)\n\tconst transformedCenter = {\n\t\tx: cCoef * ((radius * dy) / radius),\n\t\ty: cCoef * (-(radius * dx) / radius),\n\t}\n\n\t// Step #3: Compute center\n\tconst center = {\n\t\tx: transformedCenter.x + (lastPoint.x + x) / 2,\n\t\ty: transformedCenter.y + (lastPoint.y + y) / 2,\n\t}\n\n\t// Step #4: Compute start/sweep angles\n\t// Start angle of the elliptical arc prior to the stretch and rotate operations.\n\t// Difference between the start and end angles\n\tconst startVector = {\n\t\tx: (dx - transformedCenter.x) / radius,\n\t\ty: (dy - transformedCenter.y) / radius,\n\t}\n\t// const startAngle = Vec.AngleBetween({ x: 1, y: 0 }, startVector)\n\n\tconst endVector = {\n\t\tx: (-dx - transformedCenter.x) / radius,\n\t\ty: (-dy - transformedCenter.y) / radius,\n\t}\n\tlet sweepAngle = Vec.AngleBetween(startVector, endVector)\n\n\tif (!sweepFlag && sweepAngle > 0) {\n\t\tsweepAngle -= 2 * Math.PI\n\t} else if (sweepFlag && sweepAngle < 0) {\n\t\tsweepAngle += 2 * Math.PI\n\t}\n\t// We use % instead of `mod(..)` because we want it to be -360deg to 360deg(but actually in radians)\n\tsweepAngle %= 2 * Math.PI\n\n\treturn {\n\t\tlength: Math.abs(sweepAngle * radius),\n\t\tradius,\n\t\tsweepAngle,\n\t\tstartVector,\n\t\tendVector,\n\t\tcenter,\n\t}\n}\n"],
"mappings": "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",
"names": ["tangents"]
}