function arcToSegments()

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
}