export function segments()

in packages/util-shapes/src/arc.ts [11:81]


export function segments(
	x: number,
	y: number,
	rx: number,
	ry: number,
	large: number,
	sweep: number,
	rotateX: number,
	ox: number,
	oy: number,
) {
	const key = join.call([x, y, rx, ry, large, sweep, rotateX, ox, oy])
	if (segmentCache[key]) {
		return segmentCache[key]
	}

	const th = rotateX * (Math.PI / 180)
	const sin_th = Math.sin(th)
	const cos_th = Math.cos(th)
	rx = Math.abs(rx)
	ry = Math.abs(ry)
	const px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5
	const py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5
	let pl = (px * px) / (rx * rx) + (py * py) / (ry * ry)
	if (pl > 1) {
		pl = Math.sqrt(pl)
		rx *= pl
		ry *= pl
	}

	const a00 = cos_th / rx
	const a01 = sin_th / rx
	const a10 = -sin_th / ry
	const a11 = cos_th / ry
	const x0 = a00 * ox + a01 * oy
	const y0 = a10 * ox + a11 * oy
	const x1 = a00 * x + a01 * y
	const y1 = a10 * x + a11 * y

	const d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)
	let sfactor_sq = 1 / d - 0.25
	if (sfactor_sq < 0) {
		sfactor_sq = 0
	}
	let sfactor = Math.sqrt(sfactor_sq)
	if (sweep === large) {
		sfactor = -sfactor
	}
	const xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0)
	const yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0)

	const th0 = Math.atan2(y0 - yc, x0 - xc)
	const th1 = Math.atan2(y1 - yc, x1 - xc)

	let th_arc = th1 - th0
	if (th_arc < 0 && sweep === 1) {
		th_arc += 2 * Math.PI
	} else if (th_arc > 0 && sweep === 0) {
		th_arc -= 2 * Math.PI
	}

	const segs = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)))
	const result: number[][] = []
	for (let i = 0; i < segs; ++i) {
		const th2 = th0 + (i * th_arc) / segs
		const th3 = th0 + ((i + 1) * th_arc) / segs
		result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th]
	}

	return (segmentCache[key] = result)
}