44 lines
1.6 KiB
JavaScript
44 lines
1.6 KiB
JavaScript
// Pure circle-circle geometry for the DEEP SCAN pulse (js/scan/ScanPulse.js).
|
|
// No Phaser — kept separately so it is unit-testable in Node
|
|
// (dev/scan.test.mjs).
|
|
//
|
|
// The wavefront is a ship-centered circle of radius r. Only the part inside
|
|
// the tether region (the UNION of tether circles) is drawn — outside the
|
|
// union the wave is absorbed, so the pulse stops at the union boundary.
|
|
// For one tether circle (center A, radius R) vs the origin circle (center
|
|
// O, radius r), both "windows" are the classic circle-circle intersection:
|
|
|
|
/**
|
|
* The arc of a circle of radius `a` (around its center) that lies inside a
|
|
* circle of radius `b`, the two centers `d` apart.
|
|
*
|
|
* Returns the half-angle (radians) of the window, centered on the
|
|
* `a`-center → `b`-center direction:
|
|
* Math.PI — the whole circle `a` is inside `b`
|
|
* -1 — no overlap
|
|
*/
|
|
export function arcInCircle(a, b, d) {
|
|
if (a <= 0) return -1;
|
|
if (d === 0) return a <= b ? Math.PI : -1;
|
|
const c = (a * a + d * d - b * b) / (2 * a * d);
|
|
if (c <= -1) return Math.PI;
|
|
if (c >= 1) return -1;
|
|
return Math.acos(c);
|
|
}
|
|
|
|
/**
|
|
* The wavefront radius at which an origin-centered front first touches a
|
|
* tether of radius `R` whose anchor is `d` away (0 = concentric circles —
|
|
* the front grows through the whole rim at once, at r = R).
|
|
*/
|
|
export function contactRadius(R, d) {
|
|
if (d === 0) return R;
|
|
return Math.abs(R - d);
|
|
}
|
|
|
|
/** The farthest point of a tether rim from the origin — the point the wave
|
|
* is absorbed last. The sweep runs to the max of this over all tethers. */
|
|
export function farRadius(R, d) {
|
|
return R + d;
|
|
}
|