Files
App/www/map-behavior-zones.js
HiepLM 365a15c32a
Some checks are pending
Test / test (push) Waiting to run
update full objects type
2026-06-20 11:43:48 +02:00

90 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(() => {
/**
* Runtime hooks for Speed / Sound map zones (MiR §4.2.6.89).
* Vector overlay only — consumed by motion controller / mission runner.
*/
const TYPES = {
speed: "speed",
sound: "sound",
};
const BEHAVIOR_TYPES = new Set([TYPES.speed, TYPES.sound]);
const SPEED_MIN = 0.1;
const SPEED_MAX = 1.5;
const DEFAULT_SPEED_MPS = 0.8;
function pointInPolygon(px, py, points) {
return window.MapPlannerZones?.pointInPolygon(px, py, points) || false;
}
function clampSpeed(value) {
const n = Number(value);
if (!Number.isFinite(n)) return DEFAULT_SPEED_MPS;
return Math.min(SPEED_MAX, Math.max(SPEED_MIN, n));
}
function isBehaviorZoneType(type) {
return BEHAVIOR_TYPES.has(type);
}
function filterBehaviorZones(zones) {
return (Array.isArray(zones) ? zones : []).filter((z) => isBehaviorZoneType(z?.type));
}
/** Topmost behavior zones containing image pixel (newest wins for overlaps). */
function zonesAtPoint(zones, px, py) {
const list = Array.isArray(zones) ? zones : [];
const hits = [];
for (let i = list.length - 1; i >= 0; i--) {
const z = list[i];
if (!isBehaviorZoneType(z?.type) || !z.points?.length) continue;
if (pointInPolygon(px, py, z.points)) hits.push(z);
}
return hits;
}
function getSpeedLimit(zones, px, py) {
const hit = zonesAtPoint(zones, px, py).find((z) => z.type === TYPES.speed);
if (!hit) return null;
return clampSpeed(hit.speed_mps);
}
function getSoundAtPoint(zones, px, py) {
const hit = zonesAtPoint(zones, px, py).find((z) => z.type === TYPES.sound);
if (!hit?.sound_id) return null;
return {
sound_id: hit.sound_id,
zone_id: hit.id,
};
}
function classifyPoint(zones, px, py) {
const hits = zonesAtPoint(zones, px, py);
const speedZone = hits.find((z) => z.type === TYPES.speed);
const soundZone = hits.find((z) => z.type === TYPES.sound);
return {
speed_mps: speedZone ? clampSpeed(speedZone.speed_mps) : null,
sound_id: soundZone?.sound_id || null,
speed_zone: speedZone || null,
sound_zone: soundZone || null,
zones: hits,
};
}
window.MapBehaviorZones = {
TYPES,
BEHAVIOR_TYPES,
SPEED_MIN,
SPEED_MAX,
DEFAULT_SPEED_MPS,
clampSpeed,
isBehaviorZoneType,
filterBehaviorZones,
zonesAtPoint,
getSpeedLimit,
getSoundAtPoint,
classifyPoint,
};
})();