This document describes the overall strategy behind crossify
's algorithms.
At a glance, crossify
generates lines that connect sidewalks across street
intersections. Some of these crossings may be crosswalks, or entirely unmarked:
such information is treated as metadata to be added later as attributes of
the crossings generated by crossify
.
Given a streets dataset and sidewalks dataset, crossify attempts to draw one crossing per street in an intersection, given that there are appropriate sidewalks on either side. It accomplishes this in an N-step process:
-
Streets are split when they share a node (point) and are at the same z-level. Streets are also joined end-to-end at all other locations. Note: this step is not actually implemented yet, so datasets are assumed to have been appropriately split in advance.
-
Intersections are identified as shared nodes with more than 2 streets from step one.
-
Intersections are grouped based on proximity, as some may be complex (e.g. 6-way intersections, boulevards). The street segment(s) connecting each intersection node are ignored. All further logic happens on a per-intersection group basis.
-
Create a buffer of 10 meters (by default) around the intersection's node(s) and do an intersection operation on the streets/sidewalks: all streets and sidewalks are clipped at 10 meters from an intersection node. In most cases, this will mean that all streets and sidewalks are cut off by a 30-meter radius circle. If necessary, streets are temporarily extended to be 30 meters long. Idea: possibly use polygonized street data? Idea: use voronoi polygons?
-
Select all incoming streets and split the buffer by them. This aids the algorithm in ensure a connection across the street, guaranteeing each end of a crossing connects to left or right.
-
Extend 'up' each street in 1-meter increments, finding the closest sidewalk on each side. Only extend at most half-way down the street.
-
If each sidewalk side differs too much in length, the entire crossing is discarded. The problem this is attempting to solve is one where incoming streets have a very acute angle, and we don't want to select the sidewalk on the opposite side.
-
Choose the first 1-meter increment node that's relatively straight. Can abort generating any further 1-meter increment nodes for this street.
-
Make that crossing truly straight - connect each side with a straight line.
-
If the option is set, the first and last ~1 meter of the crossing is converted to a short line of 'sidewalk'. The point where a 1-meter segment of new sidewalk meets a crossing is where a curb interface should eventually be annotated.
There are many ways that these strategies could be improved. Here's a list of ideas:
-
Generate crossings automatically for long sidewalk stretches so that the pedestrian network remains well-connected even with missing data.
-
Generate half-crossings where sidewalks end, so they are more appropriately connected to the street network.
-
Add option to generate crossing lines from street node metadata, e.g. OpenStreetMap's highway=crossing data.