feat: initial map matching
Some checks failed
TrafficCue CI / check (push) Failing after 1m38s

This commit is contained in:
2025-10-21 20:08:08 +02:00
parent 5ec74129e2
commit aa0bcdd091
3 changed files with 87 additions and 4 deletions

View File

@ -1,7 +1,8 @@
import { LNV_SERVER } from "$lib/services/hosts";
import { routing } from "$lib/services/navigation/routing.svelte";
import type { WrappedValue } from "$lib/services/stores.svelte";
import { getMeta } from "$lib/services/TileMeta";
import { getFeature, getMeta } from "$lib/services/TileMeta";
import { lineString, nearestPointOnLine, point } from "@turf/turf";
import { map } from "./map.svelte";
export const location = $state({
@ -44,11 +45,59 @@ export function isDriving() {
const roadMetadata: WrappedValue<GeoJSON.GeoJsonProperties> = $state({
current: null,
});
const roadFeature: WrappedValue<GeoJSON.Feature | null> = $state({
current: null,
});
const snappedLocation: WrappedValue<WorldLocation | null> = $state({
current: null,
});
export function getRoadMetadata() {
return roadMetadata;
}
export function getRoadFeature() {
return roadFeature;
}
export function getSnappedLocation() {
return snappedLocation;
}
function snapLocation() {
const feature = roadFeature.current;
console.log("Snapping location to road feature:", feature);
if (!feature) return;
if (feature.geometry.type === "LineString") {
const loc = nearestPointOnLine(lineString(feature.geometry.coordinates), point([location.lng, location.lat]));
snappedLocation.current = {
lat: loc.geometry.coordinates[1],
lon: loc.geometry.coordinates[0],
};
} else if (feature.geometry.type === "MultiLineString") {
// Find nearest point across all parts
let nearestLoc: GeoJSON.Feature<GeoJSON.Point> | null = null;
let minDist = Infinity;
for (const coords of feature.geometry.coordinates) {
const loc = nearestPointOnLine(lineString(coords), point([location.lng, location.lat]));
const dist = Math.hypot(
loc.geometry.coordinates[0] - location.lng,
loc.geometry.coordinates[1] - location.lat,
);
if (dist < minDist) {
minDist = dist;
nearestLoc = loc;
}
}
if (nearestLoc) {
snappedLocation.current = {
lat: nearestLoc.geometry.coordinates[1],
lon: nearestLoc.geometry.coordinates[0],
};
}
}
}
export function watchLocation() {
if (navigator.geolocation) {
navigator.geolocation.watchPosition(
@ -63,12 +112,32 @@ export function watchLocation() {
location.heading = pos.coords.heading;
location.lastUpdate = new Date();
const blacklist = ["footway", "platform"];
getMeta(
{ lat: location.lat, lon: location.lng },
"transportation",
(f) => {
if(f.properties) {
return !blacklist.includes(f.properties["subclass"]);
}
return true;
}
).then((meta) => {
roadMetadata.current = meta;
});
getFeature(
{ lat: location.lat, lon: location.lng },
"transportation",
(f) => {
if(f.properties) {
return !blacklist.includes(f.properties["subclass"]);
}
return true;
}
).then((feature) => {
roadFeature.current = feature;
snapLocation();
});
if (location.locked) {
map.value?.flyTo(