in packages/core/src/utils/path.ts [395:459]
function arcToSegments(
toX: number,
toY: number,
rx: number,
ry: number,
large: number,
sweep: number,
rotateX: number,) {
const PI = Math.PI
const th = rotateX * PI / 180
const sinTh = Math.sin(th)
const cosTh = Math.cos(th)
let fromX = 0
let fromY = 0
rx = Math.abs(rx)
ry = Math.abs(ry)
const px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,
py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,
rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,
pl = rx2 * ry2 - rx2 * py2 - ry2 * px2
let root = 0
if (pl < 0) {
const s = Math.sqrt(1 - pl / (rx2 * ry2))
rx *= s
ry *= s
} else {
root = (large === sweep ? -1.0 : 1.0) *
Math.sqrt(pl / (rx2 * py2 + ry2 * px2))
}
const cx = root * rx * py / ry,
cy = -root * ry * px / rx,
cx1 = cosTh * cx - sinTh * cy + toX * 0.5,
cy1 = sinTh * cx + cosTh * cy + toY * 0.5
let mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry)
let dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry)
if (sweep === 0 && dtheta > 0) {
dtheta -= 2 * PI
}
else if (sweep === 1 && dtheta < 0) {
dtheta += 2 * PI
}
// Convert into cubic bezier segments <= 90deg
const segments = Math.ceil(Math.abs(dtheta / PI * 2))
const result = []
const mDelta = dtheta / segments
const mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2)
let th3 = mTheta + mDelta
for (let i = 0; i < segments; i++) {
result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY)
fromX = result[i][5]
fromY = result[i][6]
mTheta = th3
th3 += mDelta
}
return result
}