Files
gods-eye-view/src/data/modelEligibility.js
T
1fc795577a feat(sdr): local receivers — browser RTL-SDR, Local ADS-B layer and decoder feeds (#732)
Adds a Local ADS-B layer fed by your own receivers: a browser WebUSB
RTL-SDR (with FM listening) and local 1090/978 MHz decoder feeds
(LOCAL_RECEIVER_FEEDS, local and private addresses only). Local aircraft
draw in magenta with class, silhouettes, 3D models, trails and a position
sanity filter; the click card names the band and input that heard them.

Builds on Sameh Khamis's SDR prototype and the initial GEV port by
Mazeyar Moeini Feizabadi (#134); the decoder-feed design follows the
notes on #57. Closes #57.

Co-authored-by: Sameh Khamis <[email protected]>
Co-authored-by: Mazeyar Moeini Feizabadi <[email protected]>
2026-09-23 16:00:53 -05:00

46 lines
1.8 KiB
JavaScript

/**
* Shared 3D-model eligibility for the aircraft layers.
*
* Eligibility is by DISTANCE (the mode's add/keep band) with ON-SCREEN
* PRIORITY under the cap, in four visible-first passes so the slots are spent
* on what the operator can see:
* 1. KEEP on-screen contacts that already have a model (hysteresis for
* visible planes);
* 2. ADD on-screen new contacts inside the add radius, nearest first;
* 3. KEEP off-screen contacts that already have a model;
* 4. ADD off-screen new contacts inside the add radius with leftover slots.
* KEEP is split by frustum so an off-screen retained model can never starve
* an on-screen contact that wants one.
*
* Portable: no Cesium, DOM or layer state.
*/
/**
* @param {Array<[string, number, boolean]>} candidates `[id, distanceSq,
* onScreen]` for every contact inside the KEEP radius, sorted nearest first.
* @param {object} options
* @param {number} options.cap Maximum number of eligible contacts.
* @param {number} options.addDistSq Squared ADD radius (m²).
* @param {(id: string) => boolean} options.isModeled Whether the contact
* already has a model (live, not merely pending).
* @returns {Set<string>} Contacts that may hold a model this tick.
*/
export function selectModelEligible(candidates, { cap, addDistSq, isModeled }) {
const eligible = new Set();
const passes = [
(onScreen, modeled) => onScreen && modeled,
(onScreen, modeled, inAdd) => onScreen && inAdd,
(onScreen, modeled) => !onScreen && modeled,
(onScreen, modeled, inAdd) => !onScreen && inAdd,
];
for (const admit of passes) {
for (const [id, distanceSq, onScreen] of candidates) {
if (eligible.size >= cap) return eligible;
if (eligible.has(id)) continue;
if (admit(onScreen, isModeled(id), distanceSq <= addDistSq))
eligible.add(id);
}
}
return eligible;
}