feat: Praezisere Geolocation durch Koordinatenschaetzung + Feature-Erkennung

VLM-Schema:
- estimated_coordinates: Claude schaetzt Lat/Lon + Radius direkt
- identified_features: Konkreter Gewaessername, engste Region, Landmarken
- landscape_clues um water_characteristics erweitert

VLM-Prompt: Komplett ueberarbeitet
- Primaerziel ist jetzt Reverse Geolocation statt nur Objekterkennung
- Spezifische Anleitungen: Fluss-ID (Rhein vs Donau), Kiesfarbe, Uferform
- Explizite Aufforderung fuer Koordinatenschaetzung

BBox-Kaskade (Prioritaet):
1. EXIF-GPS (exakt)
2. estimated_coordinates + Radius (VLM-Schaetzung)
3. identified_features (Gewaesser/Region aus Matching)
4. estimated_location_type (grobe Region)
5. Weltweit (Fallback)

Regions-Mapping: 30+ neue Eintraege
- Deutsche Bundeslaender (NRW, Bayern, Hessen, etc.)
- Flussgebiete (Niederrhein, Oberrhein, Mosel, Elbe, etc.)
- Staedte (Duesseldorf, Koeln, Bonn, Neuss)

Frontend:
- Gruen hervorgehobene Koordinaten-Box mit Radius
- Identifizierte Features (Gewaesser, Region, Landmarken)
- Fly-To zur geschaetzten Position
Dieser Commit ist enthalten in:
Claude Dev
2026-03-26 10:38:22 +01:00
Ursprung 9709536036
Commit 51e85b2572
2 geänderte Dateien mit 150 neuen und 20 gelöschten Zeilen

Datei anzeigen

@@ -238,14 +238,41 @@ const VlmUI = {
}
}
// Geschaetzte Koordinaten
var coordsHtml = '';
if (data.estimated_coordinates && data.estimated_coordinates.latitude) {
var ec = data.estimated_coordinates;
var rKm = ec.confidence_radius_km || '?';
coordsHtml = '<div class="vlm-exif-card" style="border-color:rgba(0,255,136,0.3);background:rgba(0,255,136,0.06);margin-top:8px">' +
'<div style="font-size:9px;letter-spacing:1.5px;color:var(--accent);margin-bottom:4px">GESCHAETZTE POSITION</div>' +
'<div style="font-size:13px;color:var(--accent);font-weight:700">' + ec.latitude.toFixed(4) + ', ' + ec.longitude.toFixed(4) +
' <span style="font-size:11px;font-weight:400;color:var(--text-dim)">(&#177;' + rKm + ' km)</span></div>' +
(ec.reasoning ? '<div style="font-size:10px;color:var(--text-dim);margin-top:4px">' + ec.reasoning + '</div>' : '') +
'</div>';
}
// Identifizierte Features
var featHtml = '';
if (data.identified_features) {
var if_ = data.identified_features;
var fp = [];
if (if_.water_body) fp.push('<b>Gewaesser:</b> ' + if_.water_body);
if (if_.specific_region) fp.push('<b>Region:</b> ' + if_.specific_region);
if (if_.nearby_landmarks) fp.push('<b>Landmarken:</b> ' + if_.nearby_landmarks);
if (fp.length > 0) {
featHtml = '<div style="font-size:9px;letter-spacing:1.5px;color:#00bcd4;margin:8px 0 4px">IDENTIFIZIERTE MERKMALE</div>' +
'<div style="font-size:11px;color:var(--text);line-height:1.8">' + fp.join('<br>') + '</div>';
}
}
// Szene
var sceneEl = document.getElementById('vlm-scene');
if (sceneEl) {
sceneEl.innerHTML = exifHtml +
sceneEl.innerHTML = exifHtml + coordsHtml +
'<div style="margin-top:8px">' + (data.scene_description || 'Keine Beschreibung') +
(data.terrain ? ' | Gelaende: ' + data.terrain : '') +
(data.estimated_location_type ? ' | Region: ' + data.estimated_location_type : '') +
'</div>' + cluesHtml;
'</div>' + featHtml + cluesHtml;
}
// Objekte
@@ -350,16 +377,29 @@ const VlmUI = {
});
}
// === BBox bestimmen: EXIF-GPS > Viewport-Checkbox > Region ===
// === BBox bestimmen: EXIF-GPS > estimated_coordinates > Viewport > Region (Backend) ===
var bbox = null;
var ec = analysis.estimated_coordinates;
var hasEstCoords = ec && ec.latitude && ec.longitude;
if (hasExifGps) {
// 0.5 Grad um EXIF-Position
bbox = [
exif.latitude - 0.5,
exif.longitude - 0.5,
exif.latitude + 0.5,
exif.longitude + 0.5,
exif.latitude - 0.5, exif.longitude - 0.5,
exif.latitude + 0.5, exif.longitude + 0.5,
];
} else if (hasEstCoords) {
// VLM-geschaetzte Koordinaten: Radius in Grad
var rKm = ec.confidence_radius_km || 50;
var rDeg = Math.max(0.1, Math.min(rKm / 111, 10));
bbox = [
ec.latitude - rDeg, ec.longitude - rDeg,
ec.latitude + rDeg, ec.longitude + rDeg,
];
// Zur geschaetzten Position fliegen
Globe.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(ec.longitude, ec.latitude, Math.max(50000, rKm * 2000)),
duration: 2,
});
} else {
var bboxCb = document.getElementById('vlm-use-bbox');
if (bboxCb && bboxCb.checked && Globe.viewer) {
@@ -373,7 +413,6 @@ const VlmUI = {
];
}
}
// Kein explizites BBox? Region wird vom Backend aus estimated_location_type abgeleitet
}
var btn = document.getElementById('vlm-search-btn');
@@ -393,6 +432,8 @@ const VlmUI = {
objects: selected,
bbox: bbox,
estimated_location_type: analysis.estimated_location_type || null,
estimated_coordinates: analysis.estimated_coordinates || null,
identified_features: analysis.identified_features || null,
}),
})
.then(function(r) {