Source code for districtheatingsim.utilities.crs_utils

"""
CRS (Coordinate Reference System) utilities for DistrictHeatingSim.

Provides automatic CRS suggestion based on geographic location and a curated
list of common projected coordinate systems.

:author: Dipl.-Ing. (FH) Jonas Pfeiffer
"""

# Curated list of common projected CRS options (epsg_code, display_label)
COMMON_CRS_OPTIONS: list[tuple[str, str]] = [
    ("EPSG:25832", "EPSG:25832 – ETRS89 / UTM Zone 32N (Westdeutschland, 6°–12°E)"),
    ("EPSG:25833", "EPSG:25833 – ETRS89 / UTM Zone 33N (Ostdeutschland, 12°–18°E)"),
    ("EPSG:25834", "EPSG:25834 – ETRS89 / UTM Zone 34N (Osteuropa, 18°–24°E)"),
    ("EPSG:25835", "EPSG:25835 – ETRS89 / UTM Zone 35N (24°–30°E)"),
    ("EPSG:32632", "EPSG:32632 – WGS84 / UTM Zone 32N"),
    ("EPSG:32633", "EPSG:32633 – WGS84 / UTM Zone 33N"),
    ("EPSG:32634", "EPSG:32634 – WGS84 / UTM Zone 34N"),
    ("EPSG:31467", "EPSG:31467 – DHDN / Gauß-Krüger Zone 3 (Deutschland)"),
    ("EPSG:31468", "EPSG:31468 – DHDN / Gauß-Krüger Zone 4 (Deutschland)"),
    ("EPSG:2056", "EPSG:2056  – CH1903+ / LV95 (Schweiz)"),
    ("EPSG:31287", "EPSG:31287 – MGI / Austria Lambert (Österreich)"),
    ("EPSG:3035", "EPSG:3035  – ETRS89 / LAEA Europe (ganz Europa)"),
    ("EPSG:3857", "EPSG:3857  – Web Mercator (globale Webkarten)"),
    ("EPSG:32601", "EPSG:32601 – WGS84 / UTM Zone 1N"),
    ("EPSG:32755", "EPSG:32755 – WGS84 / UTM Zone 55S (Australien)"),
]

# Default fallback CRS
DEFAULT_CRS = "EPSG:25833"


[docs] def suggest_crs_from_location(lon: float, lat: float) -> str: """ Suggest an appropriate projected CRS based on WGS84 coordinates. For European locations (lon −6° to 36°, lat 35° to 72°) the function returns an ETRS89 UTM zone (EPSG:25832–25834). Outside Europe it returns the matching WGS84 UTM zone (EPSG:326xx / 327xx). :param lon: Longitude in decimal degrees (WGS84) :type lon: float :param lat: Latitude in decimal degrees (WGS84) :type lat: float :return: EPSG code string, e.g. ``"EPSG:25833"`` :rtype: str """ # UTM zone number (1–60) zone = int((lon + 180) / 6) + 1 if lat >= 0: # Northern hemisphere if -6 <= lon <= 36 and 35 <= lat <= 72: # ETRS89 UTM for continental Europe (zones 28-37 → EPSG:25828-25837) return f"EPSG:{25800 + zone}" else: # WGS84 UTM North return f"EPSG:{32600 + zone}" else: # Southern hemisphere return f"EPSG:{32700 + zone}"
[docs] def epsg_from_urn(urn: str) -> str: """ Convert an OGC URN CRS identifier to a plain EPSG code string. Example: ``"urn:ogc:def:crs:EPSG::25833"`` → ``"EPSG:25833"`` If the input is already in ``"EPSG:XXXXX"`` form it is returned unchanged. :param urn: OGC URN or EPSG string :type urn: str :return: EPSG code string :rtype: str """ if urn.upper().startswith("EPSG:"): return urn # urn:ogc:def:crs:EPSG::25833 or urn:ogc:def:crs:EPSG:6.6:25833 parts = urn.split(":") for part in reversed(parts): if part.isdigit(): return f"EPSG:{part}" return urn
[docs] def crs_to_urn(crs: str) -> str: """ Convert a plain EPSG code to the OGC URN format used in GeoJSON CRS objects. Example: ``"EPSG:25833"`` → ``"urn:ogc:def:crs:EPSG::25833"`` :param crs: EPSG code string (e.g. ``"EPSG:25833"``) :type crs: str :return: OGC URN string :rtype: str """ code = crs.upper().replace("EPSG:", "") return f"urn:ogc:def:crs:EPSG::{code}"