%%{init: {"themeVariables": {"edgeLabelBackground": "#000000", "clusterBkg": "transparent", "clusterBorder": "#3a3a3a"}, "flowchart": {"subGraphTitleMargin": {"top": 8, "bottom": 12}}}}%%
flowchart TB
S[surface model 2015<br/>tops of roofs and trees]:::data --> N[surface minus terrain<br/>height above the ground]:::step
T[terrain model 2015<br/>the bare ground]:::data --> N
F[G1 footprint]:::data --> M[height inside the footprint<br/>the rule: a ledger row]:::step
N --> M
M --> C{built after 2015?<br/>roll year, OSM}:::rule
C -->|no| H[measured height<br/>replaces the storey rule]:::out
C -->|yes or unknown| K[keeps its current height rule<br/>and says why]:::out
T --> G[ground slopes<br/>canal edge, rail viaduct]:::out
classDef data fill:none,stroke:#8a8a8a,color:#e6e6e6
classDef step fill:none,stroke:#8a8a8a,stroke-dasharray:4 3,color:#a6a6a6
classDef rule fill:none,stroke:#fe83cc,color:#fe83cc
classDef out fill:none,stroke:#e6e6e6,color:#e6e6e6
G1 World
The first step from the systems to a game: the built world
Asks What can a game stand on and move among, taken from the systems with nothing made up?
Found The streets and 296 building masses in one frame, with 2,783 props. 234 heights are measured, most from the city’s 2015 surface model, and 158 roofs come from its 2016 3D buildings. 14 buildings have no height in any source, and stay without one.
Stands verified: 10 tests pass. 31 decisions in the ledger, 5 of them assumptions.
Leaves out Facades, interiors and most entrances, and the roofs of the 138 buildings the 2016 model does not include. A game that shows them invents them.
In the game World: the ground and the masses (From systems to a game).
Trace ledger · run record · uses S1, S4 and S6
What G1 does
G1 reads the outputs of S1, S4 and S6, and writes them as files a game engine can load. S1 gives the ground. S4 gives the building masses, and S6 the objects and sidewalks. It does not choose an engine. Every element keeps the id of the row it came from, so a block in a game can be traced back to its building in S4 and from there to its source.
The frame
All coordinates are metres from one origin: the study area’s south-west corner, rounded down to 10 m, at (299180, 5038120) in the map projection the systems use (EPSG:32188). x points east, y north, z up. True north is kept, so the sun can be placed later. An engine converts the units and the axes it needs (W01, W02).
The files
| File | Holds | From |
|---|---|---|
| ground.geojson | 264 segments as lines and 191 junctions as points, with S1’s walk and car flags | S1 |
| blocks.geojson | 296 buildings, each a separate structure: its outline, the height of its base and top, the rule behind its height, a door, and a public-use class | S4, 2015 models |
| props.csv | 2,783 props with a game class, a position and the S6 rows behind each | S6 |
| surfaces.geojson | 487 sidewalks and 32 islands | S6 |
| areas.geojson | 879 pieces of ground by kind: green, play, plaza, parking, bike, water | OpenStreetMap (ODbL), W29 to W31 |
| flat_ground.geojson | the flat ground in 659 pieces by kind, none overlapping | W30 |
| terrain_2015.png | the ground as a 1 m grid, in centimetres above the frame’s z origin; read with terrain_2015.json | 2015 terrain model |
| heights_2015.csv | what the 2015 surface measured on each outline | 2015 models |
| roofs_2016.geojson, roofs_2016.csv | the roof faces of the 2016 parts, and per outline its parts, cover, roof form and 2016 height | 2016 3D buildings |
| ledger.csv | the 31 decisions below | G1 |
| checkpoints.csv | what a person should look at | G1 |
Heights
Since G1b, most heights are measured. The city’s 2015 surface model (ground and buildings, 1 m) minus its 2015 terrain model (bare ground) gives each pixel’s height above ground. A building’s height is the 90th percentile of those heights inside its outline, leaving out a 1 m band along the edge (W16).
| Rule | Buildings | Status |
|---|---|---|
| measured: 2015 surface minus terrain | 215 | source observation |
| measured: roof top of the 2016 3D buildings minus the 2015 terrain, where the 2015 surface cannot measure | 6 | source observation |
| measured: OpenStreetMap height, where neither city model can measure | 13 | source observation |
| storeys x a measured height per storey of the same use | 48 | assumption |
| nothing measures it and S4 has no storeys | 14 | left empty |
The 2015 surface cannot measure a building that went up later. On 61 outlines it shows no building at all, and for 17 more the tax roll dates the building 2015 or later, so what the surface shows there is the building before (W15, W17). Those buildings take, in this order, a height from the 2016 3D buildings (Roofs), an OpenStreetMap height, or the storey rule.
The two measurements agree. Where a building has both a 2015 surface height and an OpenStreetMap height, the median difference is 0.37 m and the median absolute difference 0.89 m, over 14 buildings (test report).
The first storey rule was too low. G1 first used 3.33 m per storey, the median of 27 mostly tall buildings. Measured against the 2015 surface, that rule came out 1.16 m too low on the median building, and 1.99 m off in absolute terms (143 buildings). The rule now uses a height per storey measured on 157 buildings, by use (W05):
| Use | Height per storey | Measured buildings |
|---|---|---|
| residential | 3.45 m | 90 |
| commerce | 4.32 m | 27 |
| services | 4.11 m | 21 |
| industry | 4.20 m | 8 |
| any other use | 3.75 m (all uses) | 157 |
The sources are in two slightly different datums (W18). A search for the best shift between them, within 2 m, found none: the outlines and the surface agree as they are.
Roofs
The city’s 2016 3D buildings model each building part with its roof faces. Each part goes to the G1 outline that holds the centre of its ground (W23). 202 parts fall on 158 outlines, with 13,833 roof faces between them, kept in roofs_2016.geojson as 3D faces in the frame. A face sloping less than 5 degrees is flat (W22): 122 roofs are flat, 30 mixed and 6 pitched. The other 138 outlines have no part in the 2016 model, most of them buildings finished after 2016, and their roofs stay unknown (W14).
A finding about the 2016 model. Its own height field, measuredHeight, is 4.4 m more than its roof tops stand above the 2015 terrain. Its roof tops, though, sit exactly where the 2015 surface puts them. So measuredHeight counts from a ground set lower than the street. Situ takes the 2016 roof top and subtracts the 2015 terrain (W25). Measured that way, the 2016 model agrees with the 2015 surface to a median of 0.23 m on 131 buildings, and it gives a height to 6 buildings the 2015 surface could not measure. No shift between the model and the outlines was found within 1 m (W24).
Ground
The ground is the city’s 2015 terrain model, written as a 1 m grid over everything G1 places (W13). Every street vertex, junction and prop takes its height from it, in metres above the frame’s z origin, the lowest ground in the grid (3 m above sea, W19). The terrain model stops at the edge of the Sud-Ouest borough, so 16 street elements north of it have no height, and say so.
Each building is a separate structure set on that ground (W20). Its base is the lowest ground along its outline, so no wall floats; its top is the median ground along the outline plus its height. On 10 outlines the ground drops more than 3 m below its median, at a ramp, the canal edge or an outline that is off; each is a checkpoint.
Doors and public use
No source used here records where a building’s entrance is. G1 puts a door at the point of the outline closest to the building’s access street from S4 (W07, assumption). One building has no walkable street within reach, so it has no door. For one more, S1’s Rue Barré runs through the outline, so the street file or the outline is out of date (a checkpoint).
Each block also says what S4 records of a public use (W08, assumption). This marks a building where a player could act. It does not say a door is open.
| Public use | Buildings |
|---|---|
| a place with opening hours | 49 |
| a place or an occupied commercial premise, hours unknown | 123 |
| commercial premises, all vacant | 9 |
| none recorded | 115 |
Props
S6 lists some objects twice: once from OpenStreetMap and once from Mapillary’s photo detection. G1 keeps every mapped object at its mapped position and drops a detection that S6 matched to one (W09). 2,898 S6 rows become 2,783 props. In 26 places the match is not one to one, such as one detection near two mapped crossings, and the count there is unsure. G1 lists them as checkpoints. 34 props were found only in photos, in no photo since 2023, and are marked possibly gone (W11).
| Class | Props | Class | Props | |
|---|---|---|---|---|
| tree | 971 | camera | 87 | |
| lamp | 803 | bin | 38 | |
| crossing mark | 503 | table | 31 | |
| bike rack | 110 | work zone | 29 | |
| hydrant | 104 | water | 4 | |
| seat | 101 | shelter | 2 |
The ledger
| Id | Kind | Decision | Alternative |
|---|---|---|---|
| W01 | researcher decision | origin at the area’s south-west corner, rounded down to 10 m; metres; x east, y north, z up | the engine converts units and axes |
| W02 | researcher decision | true north kept | turn the frame to the street grid |
| W03 | researcher decision | the ground is S1 as filed; no path added | add the paths S1’s checks found as a marked layer |
| W04 | source observation | OpenStreetMap heights used where the 2015 surface cannot measure (13) | none needed |
| W05 | assumption | height = storeys x the measured height per storey of the same use (48) | a height per storey by type and age |
| W06 | researcher decision | nothing measures it, no storeys: height left empty (14) | measure on site |
| W07 | assumption | door at the outline’s closest point to its access street | entrances from street photos |
| W08 | assumption | public use from S4’s places and occupied premises | a ground-floor survey |
| W09 | researcher decision | one prop per mapped object; matched detections dropped | S6’s count, one prop per detection |
| W10 | researcher decision | each S6 kind gets a game class | a finer class list |
| W11 | researcher decision | objects in no photo since 2023 placed and marked possibly gone | leave them out |
| W12 | source observation | road works keep the city’s permit dates | none needed |
| W13 | source observation | the ground follows the city’s 2015 terrain model, as a 1 m grid | a newer terrain model |
| W14 | gap | facades, materials, interiors, canopies, what is upstairs, and the roofs of 138 outlines are not in G1 | photo surveys; a newer 3D model |
| W15 | researcher decision | a building stood on its outline in 2015 when the median height above ground inside it is at least 2.5 m | another threshold; aerial photos |
| W16 | researcher decision | measured height: the 90th percentile above ground inside the outline, 1 m in from the edge | the median, or the maximum |
| W17 | researcher decision | the 2015 surface is not used where the roll dates the building 2015 or later (17) | aerial photos of each site |
| W18 | source observation | the 2015 models and the systems are in two datums; no shift between them was found within 2 m | a published transformation grid |
| W19 | researcher decision | z in metres above the lowest ground, 3 m above sea; empty where the terrain model has no triangle (16 street elements) | terrain for the neighbouring boroughs |
| W20 | researcher decision | each building is a separate structure: base at the lowest ground along its outline, top at the median ground plus its height | a base per wall |
| W21 | gap | the terrain is from 2015; later earthworks are not in it | a newer terrain model |
| W22 | researcher decision | a roof face under 5 degrees is flat; a roof is flat at 90 % flat area, pitched at 10 % or less, mixed between | a finer roof typology |
| W23 | researcher decision | the 2016 model gives a height where the 2015 surface cannot, if its parts cover half the outline and the roll gives no year after 2016 (6) | matching by overlap |
| W24 | source observation | no shift between the 2016 model and the outlines within 1 m | none needed |
| W25 | source observation | the 2016 measuredHeight counts from a lower ground; Situ uses its roof top minus the 2015 terrain | measuredHeight as given |
| W26 | researcher decision | for the greybox the engine draws the ground flat, each building standing on it at its height; the measured base, top and terrain stay in the files | the 2015 terrain |
| W27 | assumption | sidewalks and islands stand 0.15 m above the flat ground: the top of the 125 to 150 mm standard range; the 2015 models show them raised but cannot measure a curb | Montreal’s own standard, or a visit |
| W28 | researcher decision | the flat ground’s grid is turned 61.5 degrees from east, the main street direction (31 % of street centrelines within 3 degrees); streets near 40 and 56 degrees keep an angled grid; a look only | one direction per street, once road surfaces exist |
| W29 | researcher decision | where the flat ground is not street, sidewalk or building, it takes the OpenStreetMap kind: green 352, play 40, plaza 59, parking 100, bike 311, water 17 pieces; later kinds cover earlier ones, buildings cut them; each is one outer ring (holes opened by cuts, spikes removed); lines with no area are left out | the city’s park and land-use layers; a visit |
| W30 | researcher decision | the flat ground (study area + 50 m) is cut into 659 pieces, each one kind, none overlapping, exact outlines, meeting corner to corner; engines draw them at z 0 with one shared grid (two earlier ways failed: sheets overlapped, the 1 m grid stepped) | the 2015 terrain with areas draped on it, once heights return |
| W31 | assumption | bicycle paths lie at street level as bands: OSM width where mapped, else the median mapped one-way width (2.1 m), else 3.0 m for two-way paths (Ville de Montréal 2011); four city paths typed at sidewalk level stay at street level | a visit or street photos per path |
Tests
Ten checks, all PASS (report). The ground is exactly S1’s segments and junctions, once each, and moving it back by the origin gives S1’s coordinates to the centimetre. Every height is recomputed from S4 and the 2015 measurements in the order the ledger gives, and the 15 without a source stay empty. Every door sits on its outline, no further from its street than S4 measured. Every S6 row is accounted for, either as a prop or as a detection matched to one. Every height in the frame is read again from the terrain picture by a separate sampler, and no outline corner lies below its building’s base. The ledger covers every layer, and the files keep the published format: a version number, numbers stored as numbers, and missing values stored as empty (null), never as zero.
The door check failed at first. One building’s door came out 4.9 m from the street, where S4 had 1.1 m. Rue Barré runs through that outline, and the first door rule only looked at corners. The rule now places the door where the street enters the outline, and the building is a checkpoint.
Plan: G1b, the world completed
G1b fills empty fields from measurements, and replaces the storey rule wherever a measured height exists. Two city sources measure buildings: the 2015 surface and terrain models (downloaded), and the 2016 3D buildings, which also give roof shapes. Both are older than many of Griffintown’s towers, so each building says which source, if any, saw it.
| Step | Does | Needs | Done when |
|---|---|---|---|
| 1 | download and record the terrain and surface models for the area | permission, licence check | done 2026-10-22: both in the sources list with date, licence and fingerprint |
| 2 | heights as in the diagram | step 1 | done 2026-10-22: 215 heights from the surface model; every block names its height source |
| 3 | test the storey rule against the surface model | step 2 | done 2026-10-22: 3.33 m was 1.16 m too low on the median building; replaced by a measured height per storey for each use |
| 4 | terrain under the ground and the blocks | step 1 | done 2026-10-22: W13 now follows the 2015 terrain; every street vertex, junction, prop and building base has a height (W19 to W21) |
| 5 | roof shapes and a second height from the 2016 3D buildings, for the buildings they include (done 2026-10-23: 158 roofs, 6 heights) | 3D buildings 2016, Sud-Ouest tiles covering the area (downloaded) | each block has a roof shape or says none is known; where the 2015 and 2016 heights differ, both are kept and the difference reported |
| 6 | tree crowns from the 2019 canopy layer | canopy (to download) | each tree prop has a crown, or says it has none |
| 7 | entrances from street photos, for buildings with a public use | Mapillary photos | each entrance found replaces an assumed door, building by building |
| Data | Status |
|---|---|
| terrain and surface models 2015 (Ville de Montréal) | downloaded 2026-10-22; CC BY 4.0 |
| 3D buildings 2016, LOD2 with roofs (Ville de Montréal) | downloaded 2026-10-22; CC BY 4.0; the 4 of 11 Sud-Ouest tiles that cover the area, kept unchanged |
| canopy 2019 (Ville de Montréal) | found, not downloaded |
| street photos (Mapillary) | in use in S1, S3 and S6 |
What comes next
The game is now built in stages, starting in QGIS with one building (The game, stage by stage). Decisions W26 to W31 were made for the first engine plugins, withdrawn on 2026-10-28 (G7).


