swissBUILDINGS3D-Import: Absturz bei riesigen Kacheln behoben, Übersprungene sichtbar gemacht

Nutzer-Report „funktioniert nicht": Der Import stürzte mit einem harten
RangeError ab, sobald eine STAC-Kachel entpackt die maximale JS-String-Länge
überschritt (DXF komprimiert stark — eine Kachel unter dem 150-MB-Limit kann
trotzdem >700 MB unkomprimierten Text ergeben, real reproduziert für ein
dicht bebautes Stadtzentrum). downloadAssetText prüft jetzt zusätzlich die
JSZip-interne unkomprimierte Grössenschätzung VOR dem Entpacken und fängt
verbleibende Fehler (Netzwerk/ZIP/String-Länge) sicher ab, statt zu werfen.

Zu grosse/fehlgeschlagene Kacheln wurden bisher stumm übersprungen (0 Gebäude,
keine Erklärung — sah wie ein Bug aus). fetchBuildings3d liefert jetzt
skippedTiles mit; der Dialog zeigt „X Kachel(n) übersprungen, zu gross" statt
eines wortlosen Leer-Ergebnisses.
This commit is contained in:
2026-07-12 19:15:45 +02:00
parent 7dc8f0d5c6
commit 35a6834072
5 changed files with 85 additions and 24 deletions
+20 -5
View File
@@ -135,6 +135,10 @@ export function ContextImportDialog({
// Echte swissBUILDINGS3D-Meshes (v2/v3) landen direkt als ContextObject
// (kein Footprint+Box-Umweg über GeoFeature/featuresToContextObjects).
const extraObjs: ContextObject[] = [];
// Übersprungene Kacheln (zu gross entpackt, Netzwerkfehler o. Ä.) —
// damit „0 Gebäude" von „X Kacheln übersprungen" unterscheidbar bleibt
// statt eines stummen Leer-Ergebnisses (Nutzer-Report).
let buildingsSkipped = 0;
if (sources.swissBuildings === "flach") {
const r = await fetchBuildings(center, radius, origin);
@@ -149,6 +153,7 @@ export function ContextImportDialog({
);
origin = r.origin;
extraObjs.push(...r.meshes);
buildingsSkipped = r.skippedTiles;
}
const osmSel: OsmSelection = {
@@ -186,7 +191,11 @@ export function ContextImportDialog({
}
if (all.length === 0 && !terrain && extraObjs.length === 0) {
setError(t("ctxImport.empty"));
setError(
buildingsSkipped > 0
? t("ctxImport.buildingsSkipped", { count: buildingsSkipped })
: t("ctxImport.empty"),
);
setStatus(null);
return;
}
@@ -196,10 +205,16 @@ export function ContextImportDialog({
if (terrain) objs.push(terrain);
onImport(objs);
setStatus(
t("ctxImport.imported", {
count: all.length + extraObjs.length,
sets: objs.length,
}),
buildingsSkipped > 0
? t("ctxImport.importedWithSkipped", {
count: all.length + extraObjs.length,
sets: objs.length,
skipped: buildingsSkipped,
})
: t("ctxImport.imported", {
count: all.length + extraObjs.length,
sets: objs.length,
}),
);
onClose();
} catch {