feature/Druck_tab #14
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user