in packages/charts/src/chart_types/partition_chart/layout/utils/circline_geometry.ts [65:116]
function circlineValidSectors(refC: CirclinePredicate, c: CirclineArc): CirclineArc[] {
const { inside } = refC;
const { x, y, r, from, to } = c;
const fullContainment = fullyContained(refC, c);
const fullyOutside = noOverlap(refC, c) || fullyContained(c, refC);
// handle clear cases
// nothing kept:
if ((inside && fullContainment) || (!inside && fullyOutside)) {
return [];
}
// the entire sector is kept
if ((inside && fullyOutside) || (!inside && fullContainment)) {
return [c];
}
// now we know there's intersection and we're supposed to get back two distinct points
const circlineIntersections = circlineIntersect(refC, c);
// These conditions don't happen; kept for documentation purposes:
// if (circlineIntersections.length !== 2) throw new Error('Problem in intersection calculation.')
// if (from > to) throw new Error('From/to problem in intersection calculation.')
const [p1, p2] = circlineIntersections;
if (!p1 || !p2) return [];
const aPre1 = Math.atan2(p1.y - c.y, p1.x - c.x);
const aPre2 = Math.atan2(p2.y - c.y, p2.x - c.x);
const a1p = Math.max(from, Math.min(to, aPre1 < 0 ? aPre1 + TAU : aPre1));
const a2p = Math.max(from, Math.min(to, aPre2 < 0 ? aPre2 + TAU : aPre2));
const a1 = Math.min(a1p, a2p);
const a2 = a1p === a2p ? TAU : Math.max(a1p, a2p); // make a2 drop out in next step
// imperative, slightly optimized buildup of `breakpoints` as it's in the hot loop:
const breakpoints = [from];
if (from < a1 && a1 < to) breakpoints.push(a1);
if (from < a2 && a2 < to) breakpoints.push(a2);
breakpoints.push(to);
const predicate = inside ? noOverlap : fullyContained;
// imperative, slightly optimized buildup of `result` as it's in the hot loop:
const result = [];
for (let i = 0; i < breakpoints.length - 1; i++) {
const from = breakpoints[i] ?? 0;
const to = breakpoints[i + 1] ?? 0;
const midAngle = (from + to) / 2; // no winding clip ie. `meanAngle()` would be wrong here
const xx = x + r * Math.cos(midAngle);
const yy = y + r * Math.sin(midAngle);
if (predicate(refC, { x: xx, y: yy, r: 0 })) result.push({ x, y, r, from, to });
}
return result;
}