feat: Globe-Suche nutzt jetzt EXIF + Region + Overpass kombiniert
- EXIF-GPS: Marker direkt auf Globus + Kamera fliegt hin - EXIF-GPS als BBox (0.5 Grad Radius) fuer praezisere Overpass-Suche - Region aus VLM/Landscape Clues als Fallback-BBox - Statusanzeige zeigt alle genutzten Datenquellen - Overpass-Ergebnisse werden mit EXIF-Marker kombiniert
Dieser Commit ist enthalten in:
@@ -279,9 +279,10 @@ const VlmUI = {
|
||||
|
||||
_confirmAndSearch: function() {
|
||||
if (!this._currentAnalysis) return;
|
||||
var analysis = this._currentAnalysis;
|
||||
|
||||
// Ausgewaehlte Objekte sammeln
|
||||
var objects = this._currentAnalysis.objects || [];
|
||||
var objects = analysis.objects || [];
|
||||
var selected = [];
|
||||
objects.forEach(function(obj, idx) {
|
||||
var cb = document.getElementById('vlm-obj-' + idx);
|
||||
@@ -295,8 +296,49 @@ const VlmUI = {
|
||||
return;
|
||||
}
|
||||
|
||||
// BBox: Standard weltweit (null), optional auf Viewport einschraenken
|
||||
// === EXIF-GPS: Marker setzen + dorthin fliegen ===
|
||||
var exif = analysis.exif;
|
||||
var hasExifGps = exif && exif.has_gps && exif.latitude && exif.longitude;
|
||||
if (hasExifGps) {
|
||||
// EXIF-Position als Marker auf dem Globus
|
||||
OverpassLayer.start(Globe.viewer);
|
||||
OverpassLayer.setColor('#e040fb');
|
||||
var exifNode = {
|
||||
nodes: [{
|
||||
id: 'exif-gps',
|
||||
lat: exif.latitude,
|
||||
lon: exif.longitude,
|
||||
tags: {
|
||||
'source': 'EXIF GPS',
|
||||
'camera': (exif.camera_make || '') + ' ' + (exif.camera_model || ''),
|
||||
'timestamp': exif.timestamp || '',
|
||||
'altitude': exif.altitude ? exif.altitude + 'm' : '',
|
||||
},
|
||||
name: 'EXIF GPS-Position',
|
||||
}],
|
||||
ways: [],
|
||||
relations: [],
|
||||
total: 1,
|
||||
};
|
||||
OverpassLayer.render(exifNode);
|
||||
// Zur EXIF-Position fliegen
|
||||
Globe.viewer.camera.flyTo({
|
||||
destination: Cesium.Cartesian3.fromDegrees(exif.longitude, exif.latitude, 50000),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
|
||||
// === BBox bestimmen: EXIF-GPS > Viewport-Checkbox > Region ===
|
||||
var bbox = null;
|
||||
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,
|
||||
];
|
||||
} else {
|
||||
var bboxCb = document.getElementById('vlm-use-bbox');
|
||||
if (bboxCb && bboxCb.checked && Globe.viewer) {
|
||||
var rect = Globe.viewer.camera.computeViewRectangle();
|
||||
@@ -309,28 +351,35 @@ const VlmUI = {
|
||||
];
|
||||
}
|
||||
}
|
||||
// Kein explizites BBox? Region wird vom Backend aus estimated_location_type abgeleitet
|
||||
}
|
||||
|
||||
var btn = document.getElementById('vlm-search-btn');
|
||||
if (btn) { btn.disabled = true; btn.textContent = 'SUCHE LAEUFT...'; }
|
||||
var searchResult = document.getElementById('vlm-search-result');
|
||||
if (searchResult) { searchResult.style.display = 'block'; searchResult.textContent = 'Generiere Overpass-Queries...'; searchResult.style.color = 'var(--text-dim)'; }
|
||||
var statusParts = [];
|
||||
if (hasExifGps) statusParts.push('EXIF GPS-Marker gesetzt');
|
||||
if (searchResult) { searchResult.style.display = 'block'; searchResult.textContent = statusParts.join(' | ') + (statusParts.length ? ' | ' : '') + 'Generiere Overpass-Queries...'; searchResult.style.color = 'var(--text-dim)'; }
|
||||
|
||||
// 1. Queries generieren
|
||||
// === Overpass-Suche mit allen verfuegbaren Daten ===
|
||||
var startTime = Date.now();
|
||||
fetch('/api/vlm/generate-queries', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ objects: selected, bbox: bbox, estimated_location_type: VlmUI._currentAnalysis.estimated_location_type || null }),
|
||||
body: JSON.stringify({
|
||||
objects: selected,
|
||||
bbox: bbox,
|
||||
estimated_location_type: analysis.estimated_location_type || null,
|
||||
}),
|
||||
})
|
||||
.then(function(r) {
|
||||
if (!r.ok) return r.json().then(function(d) { throw new Error(d.detail || 'Fehler'); });
|
||||
return r.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
var regionInfo = data.region ? ' (Region: ' + data.region + ')' : ' (weltweit)';
|
||||
if (searchResult) searchResult.textContent = 'Query generiert (' + data.tag_count + ' Tags)' + regionInfo + '. Suche OSM-Daten...';
|
||||
var src = hasExifGps ? 'EXIF BBox' : (data.region ? 'Region: ' + data.region : 'weltweit');
|
||||
if (searchResult) searchResult.textContent = statusParts.join(' | ') + (statusParts.length ? ' | ' : '') + 'Query generiert (' + data.tag_count + ' Tags, ' + src + '). Suche OSM-Daten...';
|
||||
|
||||
// 2. Overpass-Query direkt ausfuehren
|
||||
OverpassLayer.setColor('#e040fb');
|
||||
return fetch('/api/overpass/query', {
|
||||
method: 'POST',
|
||||
@@ -343,27 +392,47 @@ const VlmUI = {
|
||||
return r.json().then(function(d) { throw new Error(d.detail || 'Rate-Limit'); });
|
||||
}
|
||||
if (!r.ok) {
|
||||
return r.json().then(function(d) { throw new Error(d.detail || 'Overpass-Fehler'); });
|
||||
return r.text().then(function(txt) {
|
||||
try { var d = JSON.parse(txt); throw new Error(d.detail || 'Overpass-Fehler'); }
|
||||
catch(e) { if (e.message && !e.message.startsWith('Unexpected')) throw e; throw new Error('Overpass-Fehler ' + r.status); }
|
||||
});
|
||||
}
|
||||
return r.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
var elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
||||
// Bei EXIF-GPS: Overpass-Ergebnisse zu bestehendem Marker hinzufuegen
|
||||
if (hasExifGps && data.total > 0) {
|
||||
// Bestehende EXIF-Daten beibehalten, Overpass hinzufuegen
|
||||
var combined = {
|
||||
nodes: [{ id: 'exif-gps', lat: exif.latitude, lon: exif.longitude, tags: { 'source': 'EXIF GPS' }, name: 'EXIF GPS-Position' }].concat(data.nodes || []),
|
||||
ways: data.ways || [],
|
||||
relations: data.relations || [],
|
||||
total: 1 + data.total,
|
||||
};
|
||||
OverpassLayer.render(combined);
|
||||
} else if (!hasExifGps) {
|
||||
OverpassLayer.render(data);
|
||||
}
|
||||
|
||||
if (searchResult) {
|
||||
var text = data.total + ' Orte gefunden (' + elapsed + 's)';
|
||||
var parts = [];
|
||||
if (hasExifGps) parts.push('EXIF GPS-Marker');
|
||||
parts.push(data.total + ' OSM-Orte');
|
||||
var text = parts.join(' + ') + ' (' + elapsed + 's)';
|
||||
if (data.cached) text += ' [Cache]';
|
||||
if (data.truncated) text += ' [Limit erreicht]';
|
||||
if (data.truncated) text += ' [Limit]';
|
||||
searchResult.textContent = text;
|
||||
searchResult.style.color = 'var(--accent)';
|
||||
}
|
||||
var countEl = document.getElementById('count-vlm');
|
||||
if (countEl) countEl.textContent = data.total;
|
||||
if (countEl) countEl.textContent = (hasExifGps ? 1 : 0) + data.total;
|
||||
})
|
||||
.catch(function(e) {
|
||||
if (searchResult) {
|
||||
searchResult.textContent = 'Fehler: ' + e.message;
|
||||
searchResult.style.color = '#ff5252';
|
||||
var prefix = hasExifGps ? 'EXIF GPS-Marker gesetzt | ' : '';
|
||||
searchResult.textContent = prefix + 'Overpass-Fehler: ' + e.message;
|
||||
searchResult.style.color = hasExifGps ? '#ff9800' : '#ff5252';
|
||||
}
|
||||
})
|
||||
.finally(function() {
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren