Water Biscuits
I couldn't quite get it ready for my EdinburghJS presentation but I now have water being properly handled in Linzer. It's a subtlety, but I found when exploring in my Garibaldi iteration that you got better regions if you treated water as part of the boundary.
Just to recap, the way I previously defined regions ('biscuits') was:
- Find city boundary
- Choose random start/end points in that boundary
- Find routes between those points, either biased to be pedestrian or car (
auto
) routes - Draw the city boundary as black and the routes as white borders (see below); this effectively unions the routes
- Find connected white pixels and turn back into regions

(note: image is reflected in x-axis)
The changes I made were to steps 2 and 4:
- 2: Mask-out the water areas from the city bounds so that they can't be used as start/end points (sorry swimmers!):
- 4: Draw the water areas as border pixels:
This is hugely impactful for somewhere like Amsterdam which is 15% water! (maybe more on that later in a related side-project)
One of the funny things about long-term side-projects is that you get the "opportunity" to come back to short-cuts you'd taken earlier. I was wondering why in places like Paris it wasn't finding regions on the islands in the center of the city. Before adding water I didn't really have to deal with drawing any polygons with holes, which these parts of Paris happen to have. So, it wasn't finding them because ... I hadn't bothered implementing rendering of interiors.
Turns out it was actually fairly easy to implement on top of tiny-skia using a Mask:
let mut mask = Mask::new(pixmap.width() as u32, pixmap.height() as u32).unwrap();
...
let path = path_from_line(poly.exterior())?;
mask.clear();
for interior in poly.interiors() {
let interior_path = path_from_line(interior)?;
mask.fill_path(&interior_path, FillRule::EvenOdd, true, transform);
}
mask.invert();
pixmap.fill_path(&path, paint, FillRule::EvenOdd, transform, Some(&mask));
Anyways, it's been really nice to draw a line under something I've known I've needed to do for a looooong time.