Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

py/facett_demo/panes/map_pane.py

"""Sweden MAP pane — the REAL facett OSM 2D navigator, embedded as wasm.

This pane renders **no map of its own**. It fetches geometry from korp-server and
hands it to the `osm2d` component in the `facet-wrapped` registry, which is the very
same `facett_geomap::OsmView` the native `facett-demo` paints — compiled to wasm and
mounted as a live egui canvas. One implementation, two targets: the Python demo and
the Rust demo cannot drift, because there is only one renderer.

It previously re-implemented the map in pydeck. That lookalike drifted immediately:
pydeck's default `map_provider=CARTO` drew a third-party WORLD basemap under our
data, so a correctly-clipped Sweden appeared to include Africa. The data was never
wrong — the second renderer was.

Data source: korp-server ``KorpControl.MapQuery`` (the via-server GeoParquet render
path) over the region asset chosen via ``KorpControl.Assets``. The server prunes
row-groups to the viewport and returns only visible geometry; the raw OSM tags ride
along so the COMPONENT applies its own feature classification and styling.
"""

from __future__ import annotations

import streamlit as st
from ..facet_host import facett_component, is_data_driven

from ..client import KorpClient, KorpUnavailable

#: The facett component this pane embeds (registry name in `facet-wrapped`).
COMPONENT = "osm2d"


def _scene_payload(scene, asset: str) -> dict:
    """korp `MapQueryReply` → the `osm2d` payload.

    A pure re-shaping: flat coord runs and raw OSM tag JSON pass through untouched, so
    the component does the classifying/styling — this pane never decides a colour.
    """
    return {
        "title": f"{asset} — korp MapQuery",
        "points": [[p.lon, p.lat] for p in scene.points],
        "ways": [
            {"osm_id": w.osm_id, "coords": list(w.coords), "tags": w.tags}
            for w in scene.ways
        ],
    }


def render(client: KorpClient) -> None:
    st.subheader("🗺 Sweden map — the real facett OSM 2D navigator")
    st.caption(
        "Renderer: `facet-wrapped` → `osm2d` (facett_geomap::OsmView, wasm) · "
        "Data: korp-server `Assets` + `MapQuery`"
    )

    try:
        assets, asset_err = client.assets()
    except KorpUnavailable as e:
        st.error(f"Server unreachable — map assets unavailable.\n\n`{e}`")
        return

    if asset_err:
        st.warning(f"Asset listing partial (S3): `{asset_err}`")
    names = [a["name"] for a in assets] or ["sweden"]
    asset = st.selectbox("Region asset", names, index=0, key="map_asset")
    lod = st.slider("Level of detail", 1, 12, 6, key="map_lod")
    cap = st.slider("Max ways / points", 500, 8000, 4000, step=500, key="map_cap")

    try:
        scene = client.map_query(asset=asset, lod=lod, max_ways=cap, max_points=cap)
    except KorpUnavailable as e:
        st.error(
            "Map render failed — the server could not read the region GeoParquet.\n\n"
            f"`{e}`\n\n"
            "This is the honest empty state (commonly: MinIO/S3 offline and no local asset)."
        )
        return

    if not scene.ways and not scene.points:
        st.warning(f"Server returned no geometry for `{asset}` in this viewport (honest empty).")
        st.caption(scene.status)
        return

    c1, c2, c3, c4 = st.columns(4)
    c1.metric("Ways", len(scene.ways))
    c2.metric("Points", len(scene.points))
    c3.metric("Row-groups", f"{scene.row_groups_scanned}/{scene.row_groups_total}")
    c4.metric("Capped", "yes" if scene.truncated else "no")

    if not is_data_driven(COMPONENT):
        # The wasm bundle is missing or too old to accept data. Refuse loudly rather
        # than fall back to a demo fixture that would look like live Sweden data.
        st.error(
            f"`{COMPONENT}` is not available as a data-driven facett component — the "
            "`facet-wrapped` wasm bundle is missing or stale. Rebuild it with "
            "`cargo xtask wrap-wasm`. Refusing to show a demo fixture in place of "
            "your data."
        )
        return

    # The REAL component renders korp's geometry. No basemap, no second renderer.
    facett_component(COMPONENT, data=_scene_payload(scene, asset), height=620, key="osm2d_map")
    st.caption(scene.status)