Open spatial measurements that testify.
Scale chain → polygon → sealed receipt.
Not a cadastral survey. Roof print ≠ interior GLA.
map-ruler measure --address "Ontario Legislative Building, 111 Wellesley Street West, Toronto, ON, Canada" \
--feature roof --calibrators basemap,car_sedan --pretty
# Fence / driveway with operator vertices (GeoJSON or [[lat,lon],...])
map-ruler measure --address "..." --feature fence \
--vertices examples/ontario-demo-fence.json --pretty
# PNG overlay (rings from receipt — no second fetch when coords_latlon present)
map-ruler plot --address "Ontario Legislative Building, 111 Wellesley Street West, Toronto, ON, Canada" \
--feature roof --out receipts/ontario-demo.png --receipt-out receipts/ontario-demo.json
# Two-point car (or any known length) scale check
map-ruler measure --address "..." --feature roof \
--scale-segment "43.66250,-79.39120,43.66250,-79.39105" \
--scale-length-ft 15.5 --pretty
Map UIs draw areas. They rarely defend scale or leave a receipt.
map-ruler is the CDS metrology brick:
- Geocode (Nominatim) or accept operator lat/lon
- Pull building footprints (OSM Overpass; often Microsoft Building Footprints)
- Scale chain — basemap CRS + optional car/parking/dual-basemap protocol
- Shoelace area in local meters → sq ft
- Seal
measure-testify/receipt/v1with SHA-256
Doctrine: It doesn’t answer. It testifies.
git clone https://github.com/cjchanh/map-ruler.git && cd map-ruler
# pipx (recommended)
bash scripts/install-pipx.sh
# or: pipx install --editable '.[plot]'
# pip editable
python3 -m pip install -e '.[plot]'
# no install
PYTHONPATH=. python3 -m map_ruler measure --address "..." --prettyCore measure: zero required deps.
Plot + basemap: matplotlib + Pillow (via [plot] extra).
Network: Nominatim + Overpass (+ tile hosts when --basemap).
# Roof / building footprint near address
python3 -m map_ruler measure \
--address "Ontario Legislative Building, 111 Wellesley Street West, Toronto, ON, Canada" \
--feature roof \
--calibrators basemap,car_sedan \
--out receipts/ontario-demo.json \
--pretty
# Pin only
python3 -m map_ruler measure --lat 43.6626213 --lon -79.3910161 --feature building
# Fence / driveway — v0 returns PARTIAL + building context (no auto-trace yet)
python3 -m map_ruler measure --address "..." --feature fence| Feature | Behavior |
|---|---|
roof / building |
Closest OSM footprint to pin; GLA band heuristic |
fence / driveway |
Without --vertices: PARTIAL context. With --vertices: CLEAN length (+ area if closed) |
parcel |
Building context (parcel polygons later) |
any + --vertices |
Operator/agent path wins; seals length/area from file |
- GeoJSON
LineString/Polygon/Feature(coordinates lon,lat) [[lat, lon], ...]JSON array{"coordinates":[...], "order":"latlon"|"lonlat"}
| Id | Role |
|---|---|
basemap |
Always on — local equirectangular EN (~2% for small spans) |
car_sedan |
Protocol: 14.5–16.5 ft vehicle as image scale |
parking_stall |
Protocol: ~9×18 ft stall |
dual_basemap |
Protocol: cross-check second imagery source |
Combined uncertainty = max of chain (fail-closed, not optimistic RSS).
See schema/measure-testify-receipt-v1.json.
Status enum: CLEAN | PARTIAL | ABSTAIN | ERROR.
Primary fields:
footprint_sqft/footprint_m2gla_band_sqft(0.85–0.95 × footprint, 1-story heuristic)scale_chain[]polygon_sha256receipt_sha256mapslinks (Google satellite, OSM, Earth)
An operator-side agent skill (author tooling, kept outside this repo) wraps map-ruler for agent invocation when the operator wants a roof/fence/driveway measure with a receipt. The CLI documented above is the complete public interface — nothing in this repo depends on the skill wrapper.
# True Microsoft/OSM footprints around address
python3 -m map_ruler plot \
--address "Ontario Legislative Building, 111 Wellesley Street West, Toronto, ON, Canada" \
--out receipts/ontario-demo-roof.png \
--receipt-out receipts/ontario-demo-roof.json
# Satellite underlay
python3 -m map_ruler plot --receipt receipts/ontario-demo-roof.json \
--basemap --basemap-source esri --out receipts/ontario-demo-sat.png
# Fence path on top of context (vertices required for path)
python3 -m map_ruler plot \
--address "..." --feature fence \
--vertices examples/ontario-demo-fence.json \
--out receipts/fence.pngPlot needs matplotlib (+ Pillow for --basemap).
git clone https://github.com/cjchanh/map-ruler.git && cd map-ruler
python3 -m unittest discover -s tests -vOffline unit tests only. Live dogfood / plot need network (plot needs matplotlib).
PYTHONPATH=. python3 -m map_ruler measure \
--address "Ontario Legislative Building, 111 Wellesley Street West, Toronto, ON, Canada" \
--feature roof --calibrators basemap,car_sedan \
--out receipts/ontario-demo-roof.json --prettyMIT — see LICENSE.
Not a survey. Not legal property lines. Not assessor GLA.
Use for operator evidence, agent context, and open research.
Field tape/laser upgrades authority — record it in the scale chain later.