Basemap-Legende: Rand für weiße Flächen ohne Kontur (#92)
Die Basemap-Styles „Platz“ (Verkehrsfläche, weitere Nutzung) haben eine rein weiße Füllung ohne Umrandung und waren auf dem weißen Legendenhintergrund unsichtbar. baue_symbole gibt solchen Flächensymbolen jetzt in der Legende eine dünne graue Randlinie (0,15 mm). Erkannt wird das an Füllfarbe und fehlender Kontur (braucht_legendenrand), nicht an Style-Namen; der Basemap-Layer in der Karte bleibt unverändert. Wrapper: QgsSimpleLineSymbolLayer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ from sn_basis.functions.qgiscore_wrapper import (
|
||||
QgsLegendRenderer,
|
||||
QgsProperty,
|
||||
QgsRendererCategory,
|
||||
QgsSimpleLineSymbolLayer,
|
||||
QgsSymbolLayerUtils,
|
||||
QgsUnitTypes,
|
||||
QgsVectorLayer,
|
||||
@@ -62,6 +63,13 @@ LAYOUT_HILFSLAYER = "sn_basemap_hilfslayer"
|
||||
HILFSLAYER_KENNUNG = "sn_basemap_legende"
|
||||
|
||||
_GEOMETRIE_JE_SYMBOLTYP = {0: "Point", 1: "LineString", 2: "Polygon"}
|
||||
|
||||
# Legendenrand für weiße Flächen ohne Kontur (Basis #92)
|
||||
LEGENDENRAND_BREITE_MM = 0.15
|
||||
LEGENDENRAND_FARBE = "150,150,150,255"
|
||||
# Ab diesem Wert je Farbkanal gilt eine Farbe auf weißem Legendenhintergrund als unsichtbar.
|
||||
HELL_AB = 240
|
||||
DURCHSICHTIG_BIS = 25
|
||||
_ZOOM_VARIABLEN = {"vector_tile_zoom", "zoom_level"}
|
||||
_VARIABLE = re.compile(r"@([A-Za-z_][A-Za-z0-9_]*)")
|
||||
|
||||
@@ -181,10 +189,71 @@ def baue_symbole(layer: Any, eintraege: list, zoom_level: int, vector_tile_zoom:
|
||||
basis.appendSymbolLayer(symbol_layer.clone())
|
||||
if basis is not None:
|
||||
friere_zoom_ein(basis, zoom_level, vector_tile_zoom)
|
||||
ergaenze_legendenrand(basis)
|
||||
symbole[eintrag.schluessel] = basis
|
||||
return symbole
|
||||
|
||||
|
||||
def _ist_unsichtbar(farbe: tuple) -> bool:
|
||||
"""Ob eine RGBA-Farbe auf weißem Legendenhintergrund praktisch nicht zu sehen ist."""
|
||||
rot, gruen, blau, alpha = farbe
|
||||
return alpha <= DURCHSICHTIG_BIS or min(rot, gruen, blau) >= HELL_AB
|
||||
|
||||
|
||||
def braucht_legendenrand(ebenen: list[dict]) -> bool:
|
||||
"""Ob ein Flächensymbol in der Legende einen Rand braucht.
|
||||
|
||||
``ebenen`` beschreibt die Symbolebenen: ``art`` (``fuellung``, ``linie``, ``sonst``), ``farbe``
|
||||
(RGBA) und bei Füllungen ``rand`` (RGBA oder ``None`` ohne Kontur). Ein Rand ist nötig, wenn
|
||||
alle Ebenen auf weißem Hintergrund unsichtbar sind – z. B. die weiße Fläche „Platz“.
|
||||
"""
|
||||
if not ebenen:
|
||||
return False
|
||||
for ebene in ebenen:
|
||||
if ebene.get("art") not in ("fuellung", "linie") or not _ist_unsichtbar(ebene["farbe"]):
|
||||
return False
|
||||
if ebene.get("rand") is not None and not _ist_unsichtbar(ebene["rand"]):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _rgba(farbe: Any) -> tuple:
|
||||
return farbe.red(), farbe.green(), farbe.blue(), farbe.alpha()
|
||||
|
||||
|
||||
def _ebenen_beschreiben(symbol: Any) -> list[dict]:
|
||||
ebenen = []
|
||||
for ebene in symbol.symbolLayers():
|
||||
art = ebene.layerType()
|
||||
if art == "SimpleFill":
|
||||
ohne_kontur = _enum_int(ebene.strokeStyle()) == 0 # Qt.NoPen
|
||||
ebenen.append({"art": "fuellung", "farbe": _rgba(ebene.color()),
|
||||
"rand": None if ohne_kontur else _rgba(ebene.strokeColor())})
|
||||
elif art == "SimpleLine":
|
||||
ebenen.append({"art": "linie", "farbe": _rgba(ebene.color())})
|
||||
else:
|
||||
ebenen.append({"art": "sonst"})
|
||||
return ebenen
|
||||
|
||||
|
||||
def ergaenze_legendenrand(symbol: Any) -> bool:
|
||||
"""Gibt einem praktisch weißen Flächensymbol ohne Kontur einen dünnen grauen Rand (nur Legende).
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Ob ein Rand ergänzt wurde.
|
||||
"""
|
||||
if _enum_int(symbol.type()) != 2 or not braucht_legendenrand(_ebenen_beschreiben(symbol)):
|
||||
return False
|
||||
symbol.appendSymbolLayer(QgsSimpleLineSymbolLayer.create({
|
||||
"line_color": LEGENDENRAND_FARBE,
|
||||
"line_width": str(LEGENDENRAND_BREITE_MM),
|
||||
"line_width_unit": "MM",
|
||||
}))
|
||||
return True
|
||||
|
||||
|
||||
def vorschau_icon(symbol: Any) -> Any:
|
||||
if symbol is None:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user