Differentiate overlap and full-cover uncertainty states

This commit is contained in:
Morten V. Christiansen 2026-04-05 12:28:24 +02:00
parent fabc289471
commit b0b630ceb2
1 changed files with 44 additions and 10 deletions

View File

@ -122,6 +122,19 @@ function distanceToBoundsMeters(lat, lon, bounds) {
return metersBetween(lat, lon, clampedLat, clampedLon); return metersBetween(lat, lon, clampedLat, clampedLon);
} }
function maxDistanceToBoundsCornerMeters(lat, lon, bounds) {
const corners = [
[bounds.getSouth(), bounds.getWest()],
[bounds.getSouth(), bounds.getEast()],
[bounds.getNorth(), bounds.getWest()],
[bounds.getNorth(), bounds.getEast()]
];
return Math.max(...corners.map(([cornerLat, cornerLon]) =>
metersBetween(lat, lon, cornerLat, cornerLon)
));
}
function getPresenceState(lat, lon, uncertaintyM) { function getPresenceState(lat, lon, uncertaintyM) {
const bounds = map.getBounds(); const bounds = map.getBounds();
const centerInside = bounds.contains([lat, lon]); const centerInside = bounds.contains([lat, lon]);
@ -136,6 +149,14 @@ function getPresenceState(lat, lon, uncertaintyM) {
if (uncertaintyM > 0) { if (uncertaintyM > 0) {
const distToBounds = distanceToBoundsMeters(lat, lon, bounds); const distToBounds = distanceToBoundsMeters(lat, lon, bounds);
if (distToBounds <= uncertaintyM) { if (distToBounds <= uncertaintyM) {
const maxCornerDistance = maxDistanceToBoundsCornerMeters(lat, lon, bounds);
if (uncertaintyM >= maxCornerDistance) {
return {
code: "covers",
label: "dækker hele kortet"
};
}
return { return {
code: "possible", code: "possible",
label: "muligvis" label: "muligvis"
@ -191,6 +212,8 @@ function syncUncertaintyCircle(v) {
if (v.presenceState === "inside") { if (v.presenceState === "inside") {
v.uncertaintyCircle.setStyle({ opacity: 0.7, fillOpacity: 0.08 }); v.uncertaintyCircle.setStyle({ opacity: 0.7, fillOpacity: 0.08 });
} else if (v.presenceState === "covers") {
v.uncertaintyCircle.setStyle({ opacity: 0.28, fillOpacity: 0.05 });
} else if (v.presenceState === "possible") { } else if (v.presenceState === "possible") {
v.uncertaintyCircle.setStyle({ opacity: 0.35, fillOpacity: 0.03 }); v.uncertaintyCircle.setStyle({ opacity: 0.35, fillOpacity: 0.03 });
} else { } else {
@ -358,7 +381,7 @@ function updateVehicleDisplay(v) {
if (map.hasLayer(v.marker)) { if (map.hasLayer(v.marker)) {
map.removeLayer(v.marker); map.removeLayer(v.marker);
} }
v.trail.setStyle({ opacity: 0.25 }); v.trail.setStyle({ opacity: presence.code === "covers" ? 0.4 : 0.25 });
} }
v.marker.setPopupContent(popupHtml(v.name, v)); v.marker.setPopupContent(popupHtml(v.name, v));
@ -367,21 +390,32 @@ function updateVehicleDisplay(v) {
} }
function updateAlerts() { function updateAlerts() {
const possibleVehicles = vehicleNames const alertVehicles = vehicleNames
.map(name => vehicles[name]) .map(name => vehicles[name])
.filter(v => v.presenceState === "possible"); .filter(v => v.presenceState === "possible" || v.presenceState === "covers");
if (possibleVehicles.length === 0) { if (alertVehicles.length === 0) {
alertsEl.innerHTML = ""; alertsEl.innerHTML = "";
return; return;
} }
alertsEl.innerHTML = possibleVehicles.map(v => ` alertsEl.innerHTML = alertVehicles.map(v => {
if (v.presenceState === "covers") {
return `
<div class="alert-item">
<strong>${v.name}: usikkerhed dækker hele kortet</strong>
Estimatet er udenfor kortet, men usikkerheden spænder over hele viewporten.
</div>
`;
}
return `
<div class="alert-item"> <div class="alert-item">
<strong>${v.name}: mulig tilstedeværelse</strong> <strong>${v.name}: mulig tilstedeværelse</strong>
Estimatet er udenfor kortet, men usikkerheden overlapper det viste område. Estimatet er udenfor kortet, men usikkerheden overlapper det viste område delvist.
</div> </div>
`).join(""); `;
}).join("");
} }
function updateStatus() { function updateStatus() {