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

nordisk/facett

facett-demo/src/bin/osm2d_demo.rs

//! **osm2d_demo** — the standalone "test application" for facett's state-of-the-art
//! 2D OSM viewer ([`facett::geomap::OsmView`]). A self-contained eframe app: it
//! opens the viewer full-window over a real OSM dataset and lets you drive it with
//! the mouse wheel (zoom **to the cursor**), click-drag pan, the keyboard (arrows /
//! WASD pan, `+`/`−` / PageUp/PageDown zoom, `F`/Cmd-0 fit) and the trackpad
//! (macOS pinch + two-finger pan).
//!
//! **Data source (graceful):**
//!   - `$FACETT_OSM_PARQUET` — a GeoParquet `nodes.parquet` (points), and
//!   - `$FACETT_OSM_WAYS`   — a GeoParquet `ways.parquet` (the vector basemap),
//!
//! loaded through [`facett::osm`]. With neither set, it falls back to a synthetic
//! Liechtenstein-ish dataset ([`facett::geomap::osm2d::sample_dataset`]) so the app
//! always runs with no fixture on disk.
//!
//! Run:
//!   cargo run -p facett-demo --bin osm2d_demo
//!   FACETT_OSM_PARQUET=/tmp/li_geo/nodes.parquet \
//!   FACETT_OSM_WAYS=/tmp/li_geo/ways.parquet \
//!     cargo run -p facett-demo --bin osm2d_demo
//!
//! This is intentionally separate from facett-demo's shared `main` + tab registry.

// This standalone viewer drives `eframe::run_native`, which only exists on native
// targets. It is intentionally NOT part of the wasm web demo (the web demo is the
// shared `main.rs` deck). Compile it to an empty `main` on wasm so the whole
// `facett-demo` package builds for `wasm32-unknown-unknown`.
#[cfg(target_arch = "wasm32")]
fn main() {}

#[cfg(not(target_arch = "wasm32"))]
use eframe::egui;
#[cfg(not(target_arch = "wasm32"))]
use facett::Facet;
#[cfg(not(target_arch = "wasm32"))]
use facett::LookTheme;
#[cfg(not(target_arch = "wasm32"))]
use facett::geomap::OsmView;

#[cfg(not(target_arch = "wasm32"))]
fn main() -> eframe::Result<()> {
    let native_options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default()
            .with_inner_size([1100.0, 760.0])
            .with_min_inner_size([640.0, 480.0])
            .with_title("facett — OSM 2D viewer"),
        ..Default::default()
    };
    eframe::run_native(
        "facett-osm2d-demo",
        native_options,
        Box::new(|cc| {
            // Match the running OS look preset (drives the per-OS keymap + feel the
            // viewer reads for pan/zoom). Linux → Windows-dark (documented default).
            LookTheme::from_os(cc.egui_ctx.os()).apply(&cc.egui_ctx);
            Ok(Box::new(OsmApp::new()))
        }),
    )
}

#[cfg(not(target_arch = "wasm32"))]
struct OsmApp {
    view: OsmView,
    source: String,
}

#[cfg(not(target_arch = "wasm32"))]
impl OsmApp {
    fn new() -> Self {
        let (view, source) = load_view();
        Self { view, source }
    }
}

/// Load the viewer from `$FACETT_OSM_PARQUET` / `$FACETT_OSM_WAYS` if present,
/// else the synthetic sample. Returns the view + a human label of the source.
#[cfg(not(target_arch = "wasm32"))]
fn load_view() -> (OsmView, String) {
    let pts_path = std::env::var("FACETT_OSM_PARQUET").ok();
    let ways_path = std::env::var("FACETT_OSM_WAYS").ok();

    if pts_path.is_some() || ways_path.is_some() {
        let theme = facett::Theme::default();
        let points = pts_path
            .as_deref()
            .and_then(|p| match facett::osm::read_points(p, 2_000_000) {
                Ok(v) => Some(v),
                Err(e) => {
                    eprintln!("osm2d_demo: read_points({p}) failed: {e}");
                    None
                }
            })
            .unwrap_or_default();
        let ways = ways_path
            .as_deref()
            .and_then(|p| match facett::osm::read_ways(p, 0, &theme) {
                Ok(v) => Some(v),
                Err(e) => {
                    eprintln!("osm2d_demo: read_ways({p}) failed: {e}");
                    None
                }
            })
            .unwrap_or_default();
        if !points.is_empty() || !ways.is_empty() {
            let label = format!(
                "GeoParquet — {} points, {} ways",
                points.len(),
                ways.len()
            );
            return (OsmView::new("OSM 2D", points, ways), label);
        }
        eprintln!("osm2d_demo: no features read from the GeoParquet paths; using the synthetic sample.");
    }

    let (points, ways) = facett::geomap::osm2d::sample_dataset(20_000);
    let label = format!("synthetic sample — {} points, {} ways", points.len(), ways.len());
    (OsmView::new("OSM 2D (sample)", points, ways), label)
}

#[cfg(not(target_arch = "wasm32"))]
impl eframe::App for OsmApp {
    // This eframe build hands the app a `Ui` directly (same surface the shared
    // facett-demo `main` uses — CLI/GUI parity).
    fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
        ui.horizontal_wrapped(|ui| {
            ui.label("Source:");
            ui.monospace(&self.source);
            ui.separator();
            ui.label("wheel = zoom-to-cursor · drag = pan · arrows/WASD = pan · +/− & PageUp/Down = zoom · F / Ctrl-0 = fit");
        });
        ui.separator();
        self.view.ui(ui);
    }
}