The geo/map subsystem — for idiots
Class:
idiot. Every step, nothing assumed. Goal: get the map/geomap/osm tests running green and see the actual map render in the demo app, from a cold shell. If you already know Rust, readmap-guide.mdinstead — this one spells out every keystroke.
What you need first
- A terminal (the black window where you type commands).
- The facett repo on disk. In the terminal, type this and press Enter:
cd /run/media/rickard/T9/git/facett
f0 — zero to a green test, the whole thing
Step 1 — build the three crates
Type and press Enter:
cargo build -p facett-osm -p facett-map -p facett-geomap
Wait for it to finish. Red text = an error; it will name a file and line — that's the only thing to fix before moving on. Quiet + no red = it built.
Step 2 — run the tests (no window, no GPU needed)
Type and press Enter:
cargo test -p facett-osm -p facett-map -p facett-geomap
You should see a wall of test ... ok lines and, at the bottom, several blocks that say:
test result: ok. NN passed; 0 failed
That is "green". These tests build fake (or bundled real) map data, feed it to the components, and check the output — no window ever opens.
Step 3 — see it for real in the demo app
Type and press Enter:
cargo run -p facett-demo
A window opens. Look for a tab or button in the sidebar/toolbar for the map (labelled something like OSM 2D, OSM 3D, or a 📍 Geo/🎬 Demo tab depending on the build). Click it. You should see dots (points) and, once you scroll/zoom, lines and coloured shapes (roads, water, parks) — that is the vector basemap.
- Scroll the mouse wheel over the map: it zooms in/out, centred on your cursor.
- Click and drag: it pans.
- Click a shape: it highlights (selects) it.
If instead you see "no geo data" text, the demo didn't find any sample geometry — that is still a successful build, just nothing to look at. Continuing to the next step gives it something.
f1 — MapView, from nothing to a picture
Step 1 — a point-only map
Open (or create) a small Rust file, e.g. a scratch binary, with this body:
fn main() {
let map = facett_map::MapView::new("test", vec![(11.0, 57.0), (18.0, 59.0)]);
println!("{}", map.state()... ); // see step 2 for a real assertion instead
}
(You don't need to actually run this by hand — the next step does it as a test, which is the normal way facett components are checked.)
Step 2 — write a one-line test and run it
At the bottom of facett-map/src/lib.rs, inside the existing #[cfg(test)] mod tests { ... } block, you can add:
#[test]
fn my_first_map_test() {
let v = MapView::new("test", vec![(11.0, 57.0), (18.0, 59.0)]);
assert_eq!(v.state_json()["points"], 2);
}
Save the file. Type and press Enter:
cargo test -p facett-map my_first_map_test
test result: ok = it passed. You just proved a map holds the points you gave it, with no window.
f2 — GeoMap, from nothing to a picture
Same recipe, in facett-geomap/src/lib.rs's test module:
#[test]
fn my_first_geomap_test() {
let m = GeoMap::new("test", vec![(18.0686, 59.3293)], vec![Hotspot::new(18.0686, 59.3293, 5, "test")]);
assert!(m.zoom() > 0.0);
}
Run it:
cargo test -p facett-geomap my_first_geomap_test
f3 — read a real OSM file
You need a nodes.parquet / ways.parquet pair (the osm2geoparquet / katana-osm output format). If you don't have one, the crate's own tests build tiny synthetic ones on the fly — you don't need a real file to see the reading code work; run:
cargo test -p facett-osm read_ways_from_synthetic_ways_geoparquet
test result: ok means the WKB-decoding + tag-classification pipeline works end to end on a fake 3-row file it built and deleted itself. If you do have a real nodes.parquet, this snippet reads it:
let points = facett_osm::read_points("/path/to/nodes.parquet", 0)?;
println!("read {} points", points.len());
f4 — turning on the GPU basemap (optional, needs a real GPU)
This step is optional — everything above already works with no GPU at all (the CPU painter). Only do this if you specifically want to see the GPU-accelerated basemap path.
Step 1 — build with the feature on
cargo build -p facett-demo --features map-wgpu
Step 2 — run it
cargo run -p facett-demo --features map-wgpu
If your machine has a working GPU, the basemap's roads/coastlines now render through the GPU compute-cull pipeline instead of the CPU painter — visually identical, just a different path drew it. If there is no GPU, nothing breaks: the CPU painter quietly draws instead.
f5 — the region picker (see it clip real data)
This step needs a cached OSM planet file on disk (a large download the picker deliberately never fetches itself — see map-guide.md f5). If you don't have one, skip this step; everything else above still works.
Step 1 — run the demo
cargo run -p facett-demo
Step 2 — click the region button
Find and click the 🌍 Region button in the toolbar. A small dialog appears listing Sverige, Skandinavien, Europa.
Step 3 — pick one and wait
Click Sverige. The dialog shows a status changing from "clipping" to "loading" to "ready" — this can take a while the first time (it's cutting Sweden out of the whole planet file). Once it says ready, the OSM 2D tab now shows real Swedish OpenStreetMap data.
Step 4 — pick it again (instant this time)
Close and reopen the region picker, click Sverige again. This time it should load almost instantly — the result was cached on disk the first time, so it skips the clip entirely.
f7 — "the map went all white" — what that is and how to check it
If the map ever goes completely white (or completely the paper colour), and it comes and goes as you pan around, that is one specific bug and it has a name here: "vita marken tar över allt".
What it means in plain words: the map draws a big land shape first, underneath everything else, so you can tell land from sea. That land shape has a number saying "I am at the bottom". Roads and lakes have numbers too, and a road in a tunnel gets a very, very low number — lower than the land's. When any tunnel was loaded, the land's number stopped being the lowest, and the land got drawn last, i.e. on top of everything. White map.
Type this and press Enter to check it is still fixed:
cargo test -p facett-map --lib paint_order
Quiet + ok = fine. If you have a real graphics card, this one actually looks at the picture:
env -u WAYLAND_DISPLAY -u DISPLAY FACETT_TEST_GPU=discrete cargo test -p facett-map --features wgpu --test gpu_lane_paint_order -- --nocapture
It saves the pictures it drew into /home/rickard/scratch/cargo/ — files starting with gpu_lane_landmass_. Open them. One is "with an ordinary road", one is "with a tunnel". They must look the same. If the tunnel one is a blank white rectangle, the bug is back.
The rule if you ever add a new bottom layer (a satellite photo, a hill shading): do not give it a small negative number and assume that puts it at the bottom. Use paint_order::WAY_RANK_FLOOR as your starting point. The guide (map-guide.md, f7) explains why.
"I pointed it at my roads file and the map is empty"
Open the file's schema. If it has a geometry column and no tags column, that used to be the bug: the reader treated every row as an OSM way with nothing to say, and an OSM way with nothing to say is not a road, so it drew zero of them and said nothing about it.
It works now, and it draws magenta.
Magenta on purpose. That is what an overprint is on a paper map — the colour a surveyor adds on top of a printed base sheet, picked because nothing on the base sheet is that colour. So the lines you can see are the ones out of your file, and everything else is the basemap.
Two things that follow from that, and both are meant:
- It is not grey. The old grey (
road_generic) is the ink that was painting fake roads across the sea; against the cream paper it measures 1.24 : 1, which is another way of saying you could not see it. Nobody gets that ink for a whole file. - It is not orange either. Orange means motorway. Your file might be motorways, and it might be bus stops — the reader has no idea, and pretending it knows is exactly the mistake that put roads on the water.
"But my OSM extract went magenta." Then this reader could not read your tags column — wrong type, most likely. That is deliberately loud: a whole magenta map is a question you will ask, and a blank one is not.
"An untagged way in my normal OSM cut still doesn't draw." Correct, and leave it that way. Those are the invisible halves of boundary and multipolygon relations — 496 of them in one Stockholm screenful — and drawing them is how the kommungräns ended up looking like a road through Riddarfjärden.
"What about piers?" A man_made=pier draws, in the paper colour, so it reads as a cream finger sticking out into the water. Over land you will not see it, which is right — a pier over land is not telling you anything. A man_made=pipeline still draws nothing: it is under the sea, and it was one of the fake roads.