{
  "version": 3,
  "sources": ["../../../../../src/lib/shapes/shared/freehand/svgInk.ts"],
  "sourcesContent": ["import {\n\tVec2d,\n\tVecLike,\n\tassert,\n\taverage,\n\tprecise,\n\tshortAngleDist,\n\ttoDomPrecision,\n} from '@bigbluebutton/editor'\nimport { getStrokeOutlineTracks } from './getStrokeOutlinePoints'\nimport { getStrokePoints } from './getStrokePoints'\nimport { setStrokePointRadii } from './setStrokePointRadii'\nimport { StrokeOptions, StrokePoint } from './types'\n\nexport function svgInk(rawInputPoints: VecLike[], options: StrokeOptions = {}) {\n\tconst { start = {}, end = {} } = options\n\tconst { cap: capStart = true } = start\n\tconst { cap: capEnd = true } = end\n\tassert(!start.taper && !end.taper, 'cap taper not supported here')\n\tassert(!start.easing && !end.easing, 'cap easing not supported here')\n\tassert(capStart && capEnd, 'cap must be true')\n\n\tconst points = getStrokePoints(rawInputPoints, options)\n\tsetStrokePointRadii(points, options)\n\tconst partitions = partitionAtElbows(points)\n\tlet svg = ''\n\tfor (const partition of partitions) {\n\t\tsvg += renderPartition(partition, options)\n\t}\n\n\treturn svg\n}\n\nfunction partitionAtElbows(points: StrokePoint[]): StrokePoint[][] {\n\tif (points.length <= 2) return [points]\n\n\tconst result: StrokePoint[][] = []\n\tlet currentPartition: StrokePoint[] = [points[0]]\n\tfor (let i = 1; i < points.length - 1; i++) {\n\t\tconst prevPoint = points[i - 1]\n\t\tconst thisPoint = points[i]\n\t\tconst nextPoint = points[i + 1]\n\t\tconst prevAngle = Vec2d.Angle(prevPoint.point, thisPoint.point)\n\t\tconst nextAngle = Vec2d.Angle(thisPoint.point, nextPoint.point)\n\t\t// acuteness is a normalized representation of how acute the angle is.\n\t\t// 1 is an infinitely thin wedge\n\t\t// 0 is a straight line\n\t\tconst acuteness = Math.abs(shortAngleDist(prevAngle, nextAngle)) / Math.PI\n\t\tif (acuteness > 0.8) {\n\t\t\t// always treat such acute angles as elbows\n\t\t\t// and use the extended .input point as the elbow point for swooshiness in fast zaggy lines\n\t\t\tconst elbowPoint = {\n\t\t\t\t...thisPoint,\n\t\t\t\tpoint: thisPoint.input,\n\t\t\t}\n\t\t\tcurrentPartition.push(elbowPoint)\n\t\t\tresult.push(cleanUpPartition(currentPartition))\n\t\t\tcurrentPartition = [elbowPoint]\n\t\t\tcontinue\n\t\t}\n\t\tcurrentPartition.push(thisPoint)\n\t\tif (acuteness < 0.25) {\n\t\t\t// this is not an elbow, bail out\n\t\t\tcontinue\n\t\t}\n\t\t// so now we have a reasonably acute angle but it might not be an elbow if it's far\n\t\t// away from it's neighbors\n\t\tconst avgRadius = (prevPoint.radius + thisPoint.radius + nextPoint.radius) / 3\n\t\tconst incomingNormalizedDist = Vec2d.Dist(prevPoint.point, thisPoint.point) / avgRadius\n\t\tconst outgoingNormalizedDist = Vec2d.Dist(thisPoint.point, nextPoint.point) / avgRadius\n\t\t// angular dist is a normalized representation of how far away the point is from it's neighbors\n\t\t// (normalized by the radius)\n\t\tconst angularDist = incomingNormalizedDist + outgoingNormalizedDist\n\t\tif (angularDist < 1.5) {\n\t\t\t// if this point is kinda close to its neighbors and it has a reasonably\n\t\t\t// acute angle, it's probably a hard elbow\n\t\t\tcurrentPartition.push(thisPoint)\n\t\t\tresult.push(cleanUpPartition(currentPartition))\n\t\t\tcurrentPartition = [thisPoint]\n\t\t\tcontinue\n\t\t}\n\t}\n\tcurrentPartition.push(points[points.length - 1])\n\tresult.push(cleanUpPartition(currentPartition))\n\n\treturn result\n}\n\nfunction cleanUpPartition(partition: StrokePoint[]) {\n\t// clean up start of partition (remove points that are too close to the start)\n\tconst startPoint = partition[0]\n\twhile (partition.length > 2) {\n\t\tconst nextPoint = partition[1]\n\t\tconst dist = Vec2d.Dist(startPoint.point, nextPoint.point)\n\t\tconst avgRadius = (startPoint.radius + nextPoint.radius) / 2\n\t\tif (dist < avgRadius * 0.5) {\n\t\t\tpartition.splice(1, 1)\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\t// clean up end of partition in the same fashion\n\tconst endPoint = partition[partition.length - 1]\n\twhile (partition.length > 2) {\n\t\tconst prevPoint = partition[partition.length - 2]\n\t\tconst dist = Vec2d.Dist(endPoint.point, prevPoint.point)\n\t\tconst avgRadius = (endPoint.radius + prevPoint.radius) / 2\n\t\tif (dist < avgRadius * 0.5) {\n\t\t\tpartition.splice(partition.length - 2, 1)\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\t// now readjust the cap point vectors to point to their nearest neighbors\n\tif (partition.length > 1) {\n\t\tpartition[0] = {\n\t\t\t...partition[0],\n\t\t\tvector: Vec2d.FromAngle(Vec2d.Angle(partition[1].point, partition[0].point)),\n\t\t}\n\t\tpartition[partition.length - 1] = {\n\t\t\t...partition[partition.length - 1],\n\t\t\tvector: Vec2d.FromAngle(\n\t\t\t\tVec2d.Angle(partition[partition.length - 1].point, partition[partition.length - 2].point)\n\t\t\t),\n\t\t}\n\t}\n\treturn partition\n}\n\nfunction circlePath(cx: number, cy: number, r: number) {\n\treturn (\n\t\t'M ' +\n\t\tcx +\n\t\t' ' +\n\t\tcy +\n\t\t' m -' +\n\t\tr +\n\t\t', 0 a ' +\n\t\tr +\n\t\t',' +\n\t\tr +\n\t\t' 0 1,1 ' +\n\t\tr * 2 +\n\t\t',0 a ' +\n\t\tr +\n\t\t',' +\n\t\tr +\n\t\t' 0 1,1 -' +\n\t\tr * 2 +\n\t\t',0'\n\t)\n}\n\nexport function renderPartition(strokePoints: StrokePoint[], options: StrokeOptions = {}): string {\n\tif (strokePoints.length === 0) return ''\n\tif (strokePoints.length === 1) {\n\t\treturn circlePath(strokePoints[0].point.x, strokePoints[0].point.y, strokePoints[0].radius)\n\t}\n\n\tconst { left, right } = getStrokeOutlineTracks(strokePoints, options)\n\tright.reverse()\n\tlet svg = `M${precise(left[0])}T`\n\n\t// draw left track\n\tfor (let i = 1; i < left.length; i++) {\n\t\tsvg += average(left[i - 1], left[i])\n\t}\n\t// draw end cap arc\n\t{\n\t\tconst point = strokePoints[strokePoints.length - 1]\n\t\tconst radius = point.radius\n\t\tconst direction = point.vector.clone().per().neg()\n\t\tconst arcStart = Vec2d.Add(point.point, Vec2d.Mul(direction, radius))\n\t\tconst arcEnd = Vec2d.Add(point.point, Vec2d.Mul(direction, -radius))\n\t\tsvg += `${precise(arcStart)}A${toDomPrecision(radius)},${toDomPrecision(\n\t\t\tradius\n\t\t)} 0 0 1 ${precise(arcEnd)}T`\n\t}\n\t// draw right track\n\tfor (let i = 1; i < right.length; i++) {\n\t\tsvg += average(right[i - 1], right[i])\n\t}\n\t// draw start cap arc\n\t{\n\t\tconst point = strokePoints[0]\n\t\tconst radius = point.radius\n\t\tconst direction = point.vector.clone().per()\n\t\tconst arcStart = Vec2d.Add(point.point, Vec2d.Mul(direction, radius))\n\t\tconst arcEnd = Vec2d.Add(point.point, Vec2d.Mul(direction, -radius))\n\t\tsvg += `${precise(arcStart)}A${toDomPrecision(radius)},${toDomPrecision(\n\t\t\tradius\n\t\t)} 0 0 1 ${precise(arcEnd)}Z`\n\t}\n\treturn svg\n}\n"],
  "mappings": "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",
  "names": []
}
