Atlasobjekte sind jetzt weniger langgestrckt

This commit is contained in:
2026-03-20 22:56:10 +01:00
parent a54d4fbe3c
commit 4d0dcc0310

View File

@@ -94,6 +94,93 @@ class TabBLogic:
except Exception:
pass
@staticmethod
def _find_tile_grid_for_roll_atlas(
kartenbild_w_mm: float,
kartenbild_h_mm: float,
din_dims: tuple[int, int],
respect_max_sheet_size: bool = False,
) -> tuple[int, int, float, float]:
"""Bestimmt ein Atlas-Raster für Endlosrolle, das Kacheln statt Streifen erzeugt.
Ziel: Kachel-Seitenverhältnis möglichst nah am Einzelblatt-Kartenfenster
(inkl. Rändern) bei zugleich moderater Seitenanzahl.
"""
if kartenbild_w_mm <= 0 or kartenbild_h_mm <= 0:
return 1, 1, max(1.0, kartenbild_w_mm), max(1.0, kartenbild_h_mm)
# Einzelblatt-Kartenfenster für beide Orientierungen
dim_w, dim_h = float(din_dims[0]), float(din_dims[1])
orientation_candidates: list[tuple[float, float]] = [
(dim_w - 210.0, dim_h - 20.0),
(dim_h - 210.0, dim_w - 20.0),
]
best_score = math.inf
best_result: tuple[int, int, float, float] | None = None
for target_w, target_h in orientation_candidates:
if target_w <= 0 or target_h <= 0:
continue
target_aspect = target_w / target_h
px0 = max(1, int(round(kartenbild_w_mm / target_w)))
py0 = max(1, int(round(kartenbild_h_mm / target_h)))
for pages_x in range(max(1, px0 - 3), px0 + 4):
for pages_y in range(max(1, py0 - 3), py0 + 4):
tile_w = kartenbild_w_mm / pages_x
tile_h = kartenbild_h_mm / pages_y
if tile_w <= 0 or tile_h <= 0:
continue
# Im Blatt-Modus darf die resultierende Atlasseite die
# gewählte Zielgröße (inkl. Orientierung) nicht überschreiten.
if respect_max_sheet_size and (tile_w > target_w or tile_h > target_h):
continue
tile_aspect = tile_w / tile_h
# 0 bei perfekter Übereinstimmung; symmetrisch für >1/<1
aspect_error = abs(math.log(tile_aspect / target_aspect))
# Streifen bestrafen
strip_penalty = 0.0
if tile_aspect < 0.5:
strip_penalty = abs(math.log(tile_aspect / 0.5))
elif tile_aspect > 2.0:
strip_penalty = abs(math.log(tile_aspect / 2.0))
page_count = pages_x * pages_y
# Gewichtung: zuerst Formatnähe, dann Streifenvermeidung,
# danach Seitenzahl minimieren.
score = (aspect_error * 12.0) + (strip_penalty * 6.0) + (page_count * 0.20)
if score < best_score:
best_score = score
best_result = (pages_x, pages_y, tile_w, tile_h)
if best_result is None:
if respect_max_sheet_size:
fallback_candidates: list[tuple[int, int, float, float, int]] = []
for target_w, target_h in orientation_candidates:
if target_w <= 0 or target_h <= 0:
continue
pages_x = max(1, math.ceil(kartenbild_w_mm / target_w))
pages_y = max(1, math.ceil(kartenbild_h_mm / target_h))
tile_w = kartenbild_w_mm / pages_x
tile_h = kartenbild_h_mm / pages_y
fallback_candidates.append((pages_x, pages_y, tile_w, tile_h, pages_x * pages_y))
if fallback_candidates:
fallback_candidates.sort(key=lambda entry: (entry[4], abs(math.log((entry[2] / entry[3]) if entry[3] > 0 else 1.0))))
fx, fy, fw, fh, _ = fallback_candidates[0]
return fx, fy, fw, fh
return 1, 1, kartenbild_w_mm, kartenbild_h_mm
return best_result
def _create_atlasobjekte_layer(
self,
layer: Any,
@@ -396,6 +483,42 @@ class TabBLogic:
pages_x = math.ceil(kartenbild_w / seite_karte_w)
pages_y = math.ceil(kartenbild_h / seite_karte_h)
# Für Atlas in beiden Modi (Endlosrolle + Blatt): Seitenraster so wählen,
# dass Atlasobjekte näher am Einzelblattformat liegen und keine Streifen entstehen.
opt_pages_x, opt_pages_y, opt_tile_w_mm, opt_tile_h_mm = self._find_tile_grid_for_roll_atlas(
kartenbild_w_mm=kartenbild_w,
kartenbild_h_mm=kartenbild_h,
din_dims=din_dims,
respect_max_sheet_size=(not formfaktor),
)
# Endlosrolle: Nur die Breite darf wachsen, die Höhe muss innerhalb
# der gewählten Zielhöhe bleiben.
if formfaktor:
max_tile_h_mm = max(1.0, ziel_h - 20.0)
if opt_tile_h_mm > max_tile_h_mm:
required_pages_y = max(1, math.ceil(kartenbild_h / max_tile_h_mm))
opt_pages_y = max(opt_pages_y, required_pages_y)
opt_tile_h_mm = kartenbild_h / opt_pages_y
pages_x = max(1, opt_pages_x)
pages_y = max(1, opt_pages_y)
seite_karte_w = max(1.0, opt_tile_w_mm)
seite_karte_h = max(1.0, opt_tile_h_mm)
modus = "Endlosrolle" if formfaktor else "Blatt"
print(
f"[TabBLogic] {modus} Rasteroptimierung: pages_x={pages_x}, pages_y={pages_y}, "
f"tile_mm=({seite_karte_w:.1f}x{seite_karte_h:.1f}), "
f"tile_aspect={seite_karte_w / seite_karte_h:.3f}"
)
if formfaktor:
max_tile_h_mm = max(1.0, ziel_h - 20.0)
print(
f"[TabBLogic] Endlosrolle Höhenlimit: tile_h={seite_karte_h:.1f}mm, "
f"max_tile_h={max_tile_h_mm:.1f}mm, within_limit={seite_karte_h <= max_tile_h_mm}"
)
anzahl_seiten = pages_x * pages_y
ja = self.pruefmanager.frage_ja_nein(