osm generate code fix
This commit is contained in:
116
src/App.tsx
116
src/App.tsx
@@ -207,7 +207,14 @@ function AppShell({
|
||||
range_assets: number;
|
||||
osm_roads: number;
|
||||
scope_features: number;
|
||||
}>({ fixed_assets: 0, range_assets: 0, osm_roads: 0, scope_features: 0 });
|
||||
video_metadata: number;
|
||||
}>({
|
||||
fixed_assets: 0,
|
||||
range_assets: 0,
|
||||
osm_roads: 0,
|
||||
scope_features: 0,
|
||||
video_metadata: 0,
|
||||
});
|
||||
const [recentActions, setRecentActions] = useState<ActionRow[]>([]);
|
||||
const [status, setStatus] = useState<string>("");
|
||||
const [busy, setBusy] = useState<boolean>(false);
|
||||
@@ -1580,6 +1587,7 @@ function AppShell({
|
||||
range_assets: number;
|
||||
osm_roads: number;
|
||||
scope_features: number;
|
||||
video_metadata: number;
|
||||
}>("data_source_counts");
|
||||
setDataCounts(c);
|
||||
} catch {
|
||||
@@ -1830,46 +1838,82 @@ function AppShell({
|
||||
folder.endsWith("/") || folder.endsWith("\\") ? "" : "/";
|
||||
const ts = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
||||
const hasAssets = dataCounts.fixed_assets + dataCounts.range_assets > 0;
|
||||
const hasMetadata = (dataCounts.video_metadata ?? 0) > 0
|
||||
|| Object.keys(metadataByVideo).length > 0;
|
||||
if (!hasAssets && !hasMetadata) {
|
||||
setStatus(
|
||||
"Import per-video metadata or assets first — the generator filters Overpass results against them.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
// We need a bbox to query Overpass against. Prefer the current visible
|
||||
// viewport (gives the user direct control over scope); fall back to the
|
||||
// bbox of all loaded assets if the viewport isn't valid yet (e.g. user
|
||||
// never panned the map). Either way the bbox is what Overpass filters
|
||||
// on, and the post-filter then narrows by metadata + asset proximity.
|
||||
let b = boundsRef.current;
|
||||
if (!b) {
|
||||
try {
|
||||
const ab = await invoke<{
|
||||
min_lat: number;
|
||||
min_lng: number;
|
||||
max_lat: number;
|
||||
max_lng: number;
|
||||
} | null>("assets_bbox");
|
||||
if (ab) {
|
||||
b = {
|
||||
south: ab.min_lat,
|
||||
north: ab.max_lat,
|
||||
west: ab.min_lng,
|
||||
east: ab.max_lng,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
/* fall through to error below */
|
||||
}
|
||||
}
|
||||
if (!b) {
|
||||
setStatus(
|
||||
"No visible map bbox and no asset bbox available — pan/zoom the map or import assets first.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
setBusy(true);
|
||||
setOsmFetchActive(true);
|
||||
try {
|
||||
if (hasAssets) {
|
||||
// Tight per-asset filter: fetch a small candidate set with
|
||||
// around:60m, then keep only roads where ≥2 assets sit within 30 m
|
||||
// of the centerline. That way the output is the road(s) the
|
||||
// assets are actually on, not every street that happens to be
|
||||
// within bbox or radius.
|
||||
setStatus("Fetching OSM near assets from Overpass…");
|
||||
const path = `${folder}${sep}osm_on_asset_roads_${ts}.geojson`;
|
||||
const n = await invoke<number>("generate_osm_near_assets", {
|
||||
radiusM: 60,
|
||||
maxSamples: 800,
|
||||
path,
|
||||
});
|
||||
setStatus(
|
||||
`Generated ${n} road(s) carrying assets → ${path}. Use Import → OSM roads to load.`,
|
||||
);
|
||||
} else if (boundsRef.current) {
|
||||
const b = boundsRef.current;
|
||||
const path = `${folder}${sep}osm_${b.south.toFixed(4)}_${b.west.toFixed(4)}_${b.north.toFixed(4)}_${b.east.toFixed(4)}_${ts}.geojson`;
|
||||
setStatus("Fetching OSM for visible viewport from Overpass…");
|
||||
const n = await invoke<number>("generate_osm_for_bbox", {
|
||||
minLat: b.south,
|
||||
minLng: b.west,
|
||||
maxLat: b.north,
|
||||
maxLng: b.east,
|
||||
path,
|
||||
});
|
||||
setStatus(
|
||||
`Generated ${n} OSM way(s) from viewport → ${path}. Use Import → OSM roads to load.`,
|
||||
);
|
||||
} else {
|
||||
setStatus(
|
||||
"No assets imported and no map viewport set. Import assets or pan/zoom the map first.",
|
||||
);
|
||||
}
|
||||
const sourceHint = hasMetadata && hasAssets
|
||||
? "metadata + assets"
|
||||
: hasMetadata
|
||||
? "metadata"
|
||||
: "assets";
|
||||
setStatus(
|
||||
`Fetching OSM for visible bbox from Overpass, then filtering by ${sourceHint}…`,
|
||||
);
|
||||
const path = `${folder}${sep}osm_on_asset_roads_${ts}.geojson`;
|
||||
const r = await invoke<{
|
||||
ways_kept: number;
|
||||
source: string;
|
||||
points_used: number;
|
||||
videos_used: number;
|
||||
}>("generate_osm_near_assets", {
|
||||
minLat: b.south,
|
||||
minLng: b.west,
|
||||
maxLat: b.north,
|
||||
maxLng: b.east,
|
||||
keepThresholdM: 50,
|
||||
path,
|
||||
});
|
||||
const refDesc =
|
||||
r.videos_used > 0
|
||||
? `${r.points_used} ref points (${r.videos_used} video track(s) + assets)`
|
||||
: `${r.points_used} asset ref points`;
|
||||
setStatus(
|
||||
`Generated ${r.ways_kept} road(s) [bbox + ${r.source}, ${refDesc}] → ${path}. Use Import → OSM roads to load.`,
|
||||
);
|
||||
return;
|
||||
} catch (e) {
|
||||
setStatus(`Generate OSM failed: ${e}`);
|
||||
return;
|
||||
} finally {
|
||||
setOsmFetchActive(false);
|
||||
setBusy(false);
|
||||
|
||||
Reference in New Issue
Block a user