@tldraw/editor
Version:
tldraw infinite canvas SDK (editor).
8 lines (7 loc) • 5.9 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../../src/lib/primitives/geometry/Arc2d.ts"],
"sourcesContent": ["import { Vec, VecLike } from '../Vec'\nimport { intersectLineSegmentCircle } from '../intersect'\nimport { getArcMeasure, getPointInArcT, getPointOnCircle } from '../utils'\nimport { Geometry2d, Geometry2dOptions } from './Geometry2d'\nimport { getVerticesCountForArcLength } from './geometry-constants'\n\n/** @public */\nexport class Arc2d extends Geometry2d {\n\tprivate _center: Vec\n\tprivate _radius: number\n\tprivate _start: Vec\n\tprivate _end: Vec\n\tprivate _largeArcFlag: number\n\tprivate _sweepFlag: number\n\tprivate _measure: number\n\tprivate _angleStart: number\n\tprivate _angleEnd: number\n\n\tconstructor(\n\t\tconfig: Omit<Geometry2dOptions, 'isFilled' | 'isClosed'> & {\n\t\t\tcenter: Vec\n\t\t\tstart: Vec\n\t\t\tend: Vec\n\t\t\tsweepFlag: number\n\t\t\tlargeArcFlag: number\n\t\t}\n\t) {\n\t\tsuper({ ...config, isFilled: false, isClosed: false })\n\t\tconst { center, sweepFlag, largeArcFlag, start, end } = config\n\t\tif (start.equals(end)) throw Error(`Arc must have different start and end points.`)\n\n\t\t// ensure that the start and end are clockwise\n\t\tthis._angleStart = Vec.Angle(center, start)\n\t\tthis._angleEnd = Vec.Angle(center, end)\n\t\tthis._radius = Vec.Dist(center, start)\n\t\tthis._measure = getArcMeasure(this._angleStart, this._angleEnd, sweepFlag, largeArcFlag)\n\n\t\tthis._start = start\n\t\tthis._end = end\n\n\t\tthis._sweepFlag = sweepFlag\n\t\tthis._largeArcFlag = largeArcFlag\n\t\tthis._center = center\n\t}\n\n\tnearestPoint(point: VecLike): Vec {\n\t\tconst {\n\t\t\t_center,\n\t\t\t_measure: measure,\n\t\t\t_radius: radius,\n\t\t\t_angleEnd: angleEnd,\n\t\t\t_angleStart: angleStart,\n\t\t\t_start: A,\n\t\t\t_end: B,\n\t\t} = this\n\t\tconst t = getPointInArcT(measure, angleStart, angleEnd, _center.angle(point))\n\t\tif (t <= 0) return A\n\t\tif (t >= 1) return B\n\n\t\t// Get the point (P) on the arc, then pick the nearest of A, B, and P\n\t\tconst P = Vec.Sub(point, _center).uni().mul(radius).add(_center)\n\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number\n\t\tfor (const p of [A, B, P]) {\n\t\t\td = Vec.Dist2(point, p)\n\t\t\tif (d < dist) {\n\t\t\t\tnearest = p\n\t\t\t\tdist = d\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\thitTestLineSegment(A: VecLike, B: VecLike): boolean {\n\t\tconst {\n\t\t\t_center,\n\t\t\t_radius: radius,\n\t\t\t_measure: measure,\n\t\t\t_angleStart: angleStart,\n\t\t\t_angleEnd: angleEnd,\n\t\t} = this\n\t\tconst intersection = intersectLineSegmentCircle(A, B, _center, radius)\n\t\tif (intersection === null) return false\n\n\t\treturn intersection.some((p) => {\n\t\t\tconst result = getPointInArcT(measure, angleStart, angleEnd, _center.angle(p))\n\t\t\treturn result >= 0 && result <= 1\n\t\t})\n\t}\n\n\tgetVertices(): Vec[] {\n\t\tconst { _center, _measure: measure, length, _radius: radius, _angleStart: angleStart } = this\n\t\tconst vertices: Vec[] = []\n\t\tfor (let i = 0, n = getVerticesCountForArcLength(Math.abs(length)); i < n + 1; i++) {\n\t\t\tconst t = (i / n) * measure\n\t\t\tconst angle = angleStart + t\n\t\t\tvertices.push(getPointOnCircle(_center, radius, angle))\n\t\t}\n\t\treturn vertices\n\t}\n\n\tgetSvgPathData(first = true) {\n\t\tconst {\n\t\t\t_start: start,\n\t\t\t_end: end,\n\t\t\t_radius: radius,\n\t\t\t_largeArcFlag: largeArcFlag,\n\t\t\t_sweepFlag: sweepFlag,\n\t\t} = this\n\t\treturn `${first ? `M${start.toFixed()}` : ``} A${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${end.toFixed()}`\n\t}\n\n\toverride getLength() {\n\t\treturn Math.abs(this._measure * this._radius)\n\t}\n}\n"],
"mappings": "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",
"names": []
}