Going straight ahead!

This commit is contained in:
didier committed 2024-12-31 10:29:08 -05:00
1 parent 89b07a3dc6
commit a92eee0479
10 files changed
+315 -129

No files matched your search

+4
View File
@@ -1 +1,5 @@
.direnv .direnv
result
*.duckdb
notebooks
static/data
+50
View File
@@ -0,0 +1,50 @@
INSTALL spatial;
LOAD spatial;
CREATE OR REPLACE VIEW osm_quebec AS (
SELECT
*,
'montreal' AS city
FROM
ST_READOSM (
'/nix/store/j56yncmjh7qgwa5k631vl70mdny7c5y0-data-dir/canada/quebec/montreal_quebec.osm.pbf'
)
);
CREATE OR REPLACE VIEW roads AS (
WITH
interresting_ways AS (SELECT * FROM osm_quebec
WHERE (
tags['highway'][1] = 'residential'
OR tags['highway'][1] = 'primary'
OR tags['highway'][1] = 'secondary'
OR tags['highway'][1] = 'tertiary'
)
AND city = 'montreal'),
relations AS (SELECT id,
tags,
UNNEST(refs) AS refs,
UNNEST(RANGE(LEN(refs))) as index
FROM interresting_ways),
road_points AS (SELECT osm_quebec.id AS id,
osm_quebec.lon AS lon,
osm_quebec.lat AS lat,
relations.tags AS tags,
relations.index AS relation_index,
relations.id AS relation_id
FROM relations
JOIN osm_quebec
ON osm_quebec.id = relations.refs
WHERE
osm_quebec.kind = 'node'
ORDER BY relation_id, relation_index)
SELECT
relation_id,
LIST([road_points.lat, road_points.lon]) AS points,
ANY_VALUE(tags) AS tags
FROM road_points
GROUP BY relation_id
);
COPY roads TO 'static/data/montreal.csv';
COPY roads TO 'static/data/montreal.json';
Generated
+26 -9
View File
@@ -5,11 +5,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1710146030, "lastModified": 1731533236,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1724819573, "lastModified": 1735291276,
"narHash": "sha256-GnR7/ibgIH1vhoy8cYdmXE6iyZqKqFxQSVkFgosBh6w=", "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "71e91c409d1e654808b2621f28a327acfdad8dc2", "rev": "634fd46801442d760e09493a794c4f15db2d0cbb",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -34,22 +34,39 @@
"type": "github" "type": "github"
} }
}, },
"quebec-cities-poly": {
"flake": false,
"locked": {
"lastModified": 1735484400,
"narHash": "sha256-poCHLXsdgX20cJiQVEamHkY6CpAJhbhMLJgtlFfQnKI=",
"owner": "didiercrunch",
"repo": "cities",
"rev": "c7b7612a5e8ba18831329238047a125ea5358db6",
"type": "github"
},
"original": {
"owner": "didiercrunch",
"repo": "cities",
"type": "github"
}
},
"quebec-osm-data": { "quebec-osm-data": {
"flake": false, "flake": false,
"locked": { "locked": {
"narHash": "sha256-wZnwOz49muoA1lXmXQ6LdHhVyt8vhG9Ex+6oWhts2FI=", "narHash": "sha256-Mm7tzput0a4BiUeafCtVpuzPKnT13NfU6zU7o/bJZ3k=",
"type": "file", "type": "file",
"url": "https://download.geofabrik.de/north-america/canada/quebec-240828.osm.pbf" "url": "https://static.home.all-dressed-programming.com/download.geofabrik.de/north-america/canada/quebec-241223.osm.pbf"
}, },
"original": { "original": {
"type": "file", "type": "file",
"url": "https://download.geofabrik.de/north-america/canada/quebec-240828.osm.pbf" "url": "https://static.home.all-dressed-programming.com/download.geofabrik.de/north-america/canada/quebec-241223.osm.pbf"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"quebec-cities-poly": "quebec-cities-poly",
"quebec-osm-data": "quebec-osm-data" "quebec-osm-data": "quebec-osm-data"
} }
}, },
+91 -8
View File
@@ -4,21 +4,104 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
quebec-osm-data.url = quebec-osm-data = {
"https://download.geofabrik.de/north-america/canada/quebec-240828.osm.pbf"; url =
quebec-osm-data.flake = false; "https://static.home.all-dressed-programming.com/download.geofabrik.de/north-america/canada/quebec-241223.osm.pbf";
flake = false;
};
quebec-cities-poly = {
url = "github:didiercrunch/cities";
flake = false;
};
}; };
outputs = { self, nixpkgs, flake-utils, quebec-osm-data, quebec-cities-poly }:
outputs = { self, nixpkgs, flake-utils, quebec-osm-data }:
flake-utils.lib.eachDefaultSystem (system: flake-utils.lib.eachDefaultSystem (system:
let let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
default = pkgs.hello;
poly2geojson = pkgs.rustPlatform.buildRustPackage rec {
pname = "poly2geojson";
version = "0.1.3";
src = pkgs.fetchFromGitHub {
owner = "frafra";
repo = pname;
rev = "2fbf2383765fe043d43d53b91ddbfe50c0129bb1";
hash = "sha256-BMRl6fRqQlibuGxg5hBHz7r1cvionNYEZe9YcZuL0oU=";
};
cargoHash = "sha256-pCegHF6SsCIsCQ/b+N34xTMjw2PjPB0pi30Y9sWIcV4=";
};
osmosis = pkgs.stdenv.mkDerivation {
name = "osmosis";
src = pkgs.fetchzip {
url =
"https://github.com/openstreetmap/osmosis/releases/download/0.49.2/osmosis-0.49.2.zip";
hash = "sha256-hmD/pnEEJsl2NkODon4XZcZ3ZQ7+fx/JvWTR4xrRoug=";
};
buildInputs = [ ];
buildPhase = "";
installPhase = ''
cp -r . $out
'';
};
data-dir = pkgs.stdenv.mkDerivation {
name = "data-dir";
src = ./scripts;
buildInputs = [ poly2geojson ];
buildPhase = ''
mkdir -p cities/canada/quebec
${pkgs.babashka}/bin/bb to-geojson.clj ${quebec-cities-poly}/canada/québec/* > cities.json
'';
installPhase = ''
mkdir -p $out/data
cp ${quebec-osm-data} $out/data/quebec.osm.pbf
cp cities.json $out/data
'';
};
dati = pkgs.stdenv.mkDerivation {
name = "data-dir";
src = ./scripts;
buildInputs = [ poly2geojson pkgs.jdk23 osmosis ];
buildPhase = ''
mkdir -p cities/canada/quebec
cp ${quebec-cities-poly}/canada/quebec/* cities/canada/quebec
chmod u+w cities/canada/quebec
${pkgs.babashka}/bin/bb to-geojson.clj --osm-file ${quebec-osm-data} --paths cities/canada/quebec/*.poly
'';
installPhase = ''
cp -r cities $out
'';
};
python-virtual-env = pkgs.python312.withPackages (ps: [
ps.matplotlib
ps.jupyter
ps.duckdb
ps.pandas
ps.unidecode
ps.geopy
]);
in { in {
packages = { default = default; }; packages = {
default = data-dir;
dati = dati;
poly2geojson = poly2geojson;
osmosis = osmosis;
};
devShell = pkgs.mkShell { devShell = pkgs.mkShell {
name = "spacial-data-experiments"; name = "spacial-data-experiments";
buildInputs = with pkgs; [ duckdb ]; buildInputs = with pkgs; [
duckdb
http-server
sqlfluff
poly2geojson
gdal
osmosis
python-virtual-env
];
}; };
}); });
} }
+41
View File
@@ -0,0 +1,41 @@
(require '[babashka.process :refer [shell process exec]]
'[clojure.string :as strings]
'[babashka.cli :as cli])
(defn extract-data [file]
(let [data (slurp file)
geojson (shell {:out :string :continue true :in data} "poly2geojson")
city-name (subs file
(inc (strings/last-index-of file "/"))
(strings/last-index-of file "_"))]
{:originalFile file
:geojson (some-> geojson
:out
(json/parse-string true)
:geometry
json/generate-string)
:province "québec"
:cityName city-name}))
;; ${osmosis}/bin/osmosis --read-pbf-fast file="${quebec-osm-data}" \
;; --bounding-polygon file="cities/canada/quebec/westmount_quebec.poly" \
;; --write-pbf file="cities/canada/quebec/westmount_quebec.osm.pbf"
(defn extract-osm-pbf [osm-file file]
(let [output-file (strings/replace file ".poly" ".osm.pbf")]
(println "Processing " file " file to " output-file)
(shell {:continue true}
"osmosis"
"--read-pbf-fast" (str "file=" osm-file)
"--bounding-polygon"
(str"file=" file)
"--write-pbf"
(str "file=" output-file))))
(def opts (cli/parse-opts *command-line-args* {:coerce {:paths []}}))
(doall (map
#(extract-osm-pbf (:osm-file opts) %)
(:paths opts)))
+51
View File
@@ -0,0 +1,51 @@
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
function convertCsvRow(row) {
return {
relation_id: +row.relation_id,
points: JSON.parse(row.points),
};
}
const roads = await d3.csv("./data/pincourt.csv", convertCsvRow);
const projection = d3
.geoConicConformal()
.scale(100000)
.center([-73.983028645966, 45.37425995800737]);
function drawRoad(context, road) {
if (!road || !road.points || road.points.length < 1) {
return context;
}
context.moveTo(...projection([road.points[0][0], road.points[0][1]]));
for (const datum of road.points) {
context.lineTo(...projection([datum[0], datum[1]]));
}
return context;
}
const svg = d3
.create("svg")
.attr("width", 975)
.attr("height", 610)
.attr("viewBox", [0, 0, 975, 610])
.attr("style", "max-width: 100%; height: auto;");
svg
.append("g")
.attr("transform", "translate(610,20)")
.append("text")
.text("Some title");
svg
.selectAll("path")
.data(roads)
.join("path")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-linejoin", "round")
.attr("stroke-with", 2)
.attr("d", (road) => drawRoad(d3.path(), road).toString());
container.append(svg.node());
+35
View File
@@ -0,0 +1,35 @@
import leaflet from "https://esm.sh/leaflet@1.9.4";
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
function convertCsvRow(row) {
return {
relation_id: +row.relation_id,
points: JSON.parse(row.points),
};
}
function getCenter(data) {
if (!data) {
return [51.505, -0.09]; // london
}
return data[0].points[0];
}
function addRoad(road, map) {
leaflet.polyline(road.points).addTo(map);
}
function addRoads(roads, map) {
for (const road of roads) {
addRoad(road, map);
}
}
const roads = await d3.csv("./data/montreal.csv", convertCsvRow);
const map = leaflet.map("leaflet-map").setView(getCenter(roads), 13);
leaflet
.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19 })
.addTo(map);
addRoads(roads, map);
+17 -7
View File
@@ -1,13 +1,23 @@
<!doctype html>
<!DOCTYPE html> <html style="background-color: black">
<html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<title>spacial-data-experiments</title> <title>spacial-data-experiments</title>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""
/>
</head> </head>
<body> <body style="width: 100%; text-align: center">
<div id="container"></div> <div id="container" style="background-color: white"></div>
<script type="module" src='index.js'></script>
<div id="leaflet-map" style="height: 1200px; width: 1200px"></div>
<!-- <script type="module" src="index-d3.js"></script> -->
<script type="module" src="index-leaflet.js"></script>
</body> </body>
</html> </html>
-43
View File
@@ -1,43 +0,0 @@
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
import * as topojson from "https://cdn.jsdelivr.net/npm/topojson@3/+esm";
const roadUrl = './road.json';
const road = await (await fetch(roadUrl)).json()
const projection = d3.geoConicConformal()
.scale(12000)
.center([-72.949, 46.879])
function drawRoads(context, data) {
if(!data || data.length < 1){
return context;
}
context.moveTo(...projection([data[0].lon, data[0].lat]));
for(const datum of data){
context.lineTo(...projection([datum.lon, datum.lat]));
}
return context;
}
const svg = d3.create("svg")
.attr("width", 975)
.attr("height", 610)
.attr("viewBox", [0, 0, 975, 610])
.attr("style", "max-width: 100%; height: auto;");
svg.append("g")
.attr("transform", "translate(610,20)")
.append('text').text("fuck me");
svg.append("path")
.data([road])
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-linejoin", "round")
.attr("stroke-with", 2)
.attr("d", d => drawRoads(d3.path(), d).toString());
container.append(svg.node());
-62
View File
@@ -1,62 +0,0 @@
[{"kind":"node","id":16874054,"tags":null,"refs":null,"lat":45.5292308,"lon":-74.55641920000001,"ref_roles":null,"ref_types":null,"refs_1":16874054},
{"kind":"node","id":1452900835,"tags":null,"refs":null,"lat":45.5311146,"lon":-74.5546107,"ref_roles":null,"ref_types":null,"refs_1":1452900835},
{"kind":"node","id":16874055,"tags":null,"refs":null,"lat":45.532989,"lon":-74.55260270000001,"ref_roles":null,"ref_types":null,"refs_1":16874055},
{"kind":"node","id":1452900864,"tags":null,"refs":null,"lat":45.542531000000004,"lon":-74.5416177,"ref_roles":null,"ref_types":null,"refs_1":1452900864},
{"kind":"node","id":4512670916,"tags":null,"refs":null,"lat":45.5433042,"lon":-74.54055190000001,"ref_roles":null,"ref_types":null,"refs_1":4512670916},
{"kind":"node","id":16874058,"tags":null,"refs":null,"lat":45.544044400000004,"lon":-74.5394361,"ref_roles":null,"ref_types":null,"refs_1":16874058},
{"kind":"node","id":4512670917,"tags":null,"refs":null,"lat":45.5446192,"lon":-74.53849190000001,"ref_roles":null,"ref_types":null,"refs_1":4512670917},
{"kind":"node","id":1452900866,"tags":null,"refs":null,"lat":45.545194,"lon":-74.5374298,"ref_roles":null,"ref_types":null,"refs_1":1452900866},
{"kind":"node","id":16874059,"tags":null,"refs":null,"lat":45.5461273,"lon":-74.53556760000001,"ref_roles":null,"ref_types":null,"refs_1":16874059},
{"kind":"node","id":4512670918,"tags":null,"refs":null,"lat":45.546693000000005,"lon":-74.5342433,"ref_roles":null,"ref_types":null,"refs_1":4512670918},
{"kind":"node","id":1452900868,"tags":null,"refs":null,"lat":45.547448100000004,"lon":-74.53218340000001,"ref_roles":null,"ref_types":null,"refs_1":1452900868},
{"kind":"node","id":17053331,"tags":null,"refs":null,"lat":45.548865600000006,"lon":-74.5284827,"ref_roles":null,"ref_types":null,"refs_1":17053331},
{"kind":"node","id":1452900882,"tags":null,"refs":null,"lat":45.5497377,"lon":-74.52613190000001,"ref_roles":null,"ref_types":null,"refs_1":1452900882},
{"kind":"node","id":17053333,"tags":null,"refs":null,"lat":45.5506867,"lon":-74.5239093,"ref_roles":null,"ref_types":null,"refs_1":17053333},
{"kind":"node","id":3506421397,"tags":null,"refs":null,"lat":45.551139500000005,"lon":-74.5229566,"ref_roles":null,"ref_types":null,"refs_1":3506421397},
{"kind":"node","id":1452900886,"tags":null,"refs":null,"lat":45.551902600000005,"lon":-74.5216305,"ref_roles":null,"ref_types":null,"refs_1":1452900886},
{"kind":"node","id":3506421404,"tags":null,"refs":null,"lat":45.5525632,"lon":-74.5206493,"ref_roles":null,"ref_types":null,"refs_1":3506421404},
{"kind":"node","id":3506421403,"tags":null,"refs":null,"lat":45.5540165,"lon":-74.5188466,"ref_roles":null,"ref_types":null,"refs_1":3506421403},
{"kind":"node","id":1452900890,"tags":null,"refs":null,"lat":45.5549678,"lon":-74.5178784,"ref_roles":null,"ref_types":null,"refs_1":1452900890},
{"kind":"node","id":5748462429,"tags":null,"refs":null,"lat":45.5605861,"lon":-74.51205780000001,"ref_roles":null,"ref_types":null,"refs_1":5748462429},
{"kind":"node","id":1452900894,"tags":null,"refs":null,"lat":45.562221,"lon":-74.5103639,"ref_roles":null,"ref_types":null,"refs_1":1452900894},
{"kind":"node","id":3506421401,"tags":null,"refs":null,"lat":45.5630547,"lon":-74.50927030000001,"ref_roles":null,"ref_types":null,"refs_1":3506421401},
{"kind":"node","id":1699110086,"tags":null,"refs":null,"lat":45.563304200000005,"lon":-74.5088868,"ref_roles":null,"ref_types":null,"refs_1":1699110086},
{"kind":"node","id":3506421396,"tags":null,"refs":null,"lat":45.5636285,"lon":-74.50834230000001,"ref_roles":null,"ref_types":null,"refs_1":3506421396},
{"kind":"node","id":1699110096,"tags":null,"refs":null,"lat":45.5640571,"lon":-74.5074692,"ref_roles":null,"ref_types":null,"refs_1":1699110096},
{"kind":"node","id":3506421424,"tags":null,"refs":null,"lat":45.5642687,"lon":-74.5069479,"ref_roles":null,"ref_types":null,"refs_1":3506421424},
{"kind":"node","id":1699110099,"tags":null,"refs":null,"lat":45.564606100000006,"lon":-74.50595750000001,"ref_roles":null,"ref_types":null,"refs_1":1699110099},
{"kind":"node","id":294347577,"tags":null,"refs":null,"lat":45.564881400000004,"lon":-74.50497130000001,"ref_roles":null,"ref_types":null,"refs_1":294347577},
{"kind":"node","id":17053336,"tags":null,"refs":null,"lat":45.565148300000004,"lon":-74.5033525,"ref_roles":null,"ref_types":null,"refs_1":17053336},
{"kind":"node","id":3506421438,"tags":null,"refs":null,"lat":45.565200700000005,"lon":-74.50279450000001,"ref_roles":null,"ref_types":null,"refs_1":3506421438},
{"kind":"node","id":17053337,"tags":null,"refs":null,"lat":45.5652404,"lon":-74.50223820000001,"ref_roles":null,"ref_types":null,"refs_1":17053337},
{"kind":"node","id":3506421433,"tags":null,"refs":null,"lat":45.5652534,"lon":-74.5017481,"ref_roles":null,"ref_types":null,"refs_1":3506421433},
{"kind":"node","id":3506421449,"tags":null,"refs":null,"lat":45.5652552,"lon":-74.5013563,"ref_roles":null,"ref_types":null,"refs_1":3506421449},
{"kind":"node","id":1452900897,"tags":null,"refs":null,"lat":45.5652357,"lon":-74.5007033,"ref_roles":null,"ref_types":null,"refs_1":1452900897},
{"kind":"node","id":294346765,"tags":null,"refs":null,"lat":45.565069300000005,"lon":-74.4991076,"ref_roles":null,"ref_types":null,"refs_1":294346765},
{"kind":"node","id":16874063,"tags":null,"refs":null,"lat":45.5633618,"lon":-74.4917568,"ref_roles":null,"ref_types":null,"refs_1":16874063},
{"kind":"node","id":16874064,"tags":null,"refs":null,"lat":45.5603345,"lon":-74.4790139,"ref_roles":null,"ref_types":null,"refs_1":16874064},
{"kind":"node","id":17053339,"tags":null,"refs":null,"lat":45.5579422,"lon":-74.46892840000001,"ref_roles":null,"ref_types":null,"refs_1":17053339},
{"kind":"node","id":503820619,"tags":{"highway":"motorway_junction","ref":"5"},"refs":null,"lat":45.5551072,"lon":-74.4576126,"ref_roles":null,"ref_types":null,"refs_1":503820619},
{"kind":"node","id":16874071,"tags":null,"refs":null,"lat":45.5532872,"lon":-74.4503572,"ref_roles":null,"ref_types":null,"refs_1":16874071},
{"kind":"node","id":16874073,"tags":null,"refs":null,"lat":45.552988500000005,"lon":-74.4491962,"ref_roles":null,"ref_types":null,"refs_1":16874073},
{"kind":"node","id":16874074,"tags":null,"refs":null,"lat":45.5521059,"lon":-74.44576260000001,"ref_roles":null,"ref_types":null,"refs_1":16874074},
{"kind":"node","id":16874075,"tags":null,"refs":null,"lat":45.550453700000006,"lon":-74.43921800000001,"ref_roles":null,"ref_types":null,"refs_1":16874075},
{"kind":"node","id":16874076,"tags":null,"refs":null,"lat":45.549582900000004,"lon":-74.4354764,"ref_roles":null,"ref_types":null,"refs_1":16874076},
{"kind":"node","id":4512670915,"tags":null,"refs":null,"lat":45.5494045,"lon":-74.4344518,"ref_roles":null,"ref_types":null,"refs_1":4512670915},
{"kind":"node","id":4512670914,"tags":null,"refs":null,"lat":45.549094600000004,"lon":-74.43196,"ref_roles":null,"ref_types":null,"refs_1":4512670914},
{"kind":"node","id":4512670913,"tags":null,"refs":null,"lat":45.5489424,"lon":-74.430694,"ref_roles":null,"ref_types":null,"refs_1":4512670913},
{"kind":"node","id":16874079,"tags":null,"refs":null,"lat":45.548533000000006,"lon":-74.42820760000001,"ref_roles":null,"ref_types":null,"refs_1":16874079},
{"kind":"node","id":4512670912,"tags":null,"refs":null,"lat":45.5480652,"lon":-74.4262442,"ref_roles":null,"ref_types":null,"refs_1":4512670912},
{"kind":"node","id":16874080,"tags":null,"refs":null,"lat":45.5468161,"lon":-74.4212794,"ref_roles":null,"ref_types":null,"refs_1":16874080},
{"kind":"node","id":4603837886,"tags":null,"refs":null,"lat":45.545283500000004,"lon":-74.41547650000001,"ref_roles":null,"ref_types":null,"refs_1":4603837886},
{"kind":"node","id":2028173902,"tags":null,"refs":null,"lat":45.5281766,"lon":-74.5572753,"ref_roles":null,"ref_types":null,"refs_1":2028173902},
{"kind":"node","id":16874057,"tags":null,"refs":null,"lat":45.540989800000006,"lon":-74.5434379,"ref_roles":null,"ref_types":null,"refs_1":16874057},
{"kind":"node","id":17053334,"tags":null,"refs":null,"lat":45.5533184,"lon":-74.51963570000001,"ref_roles":null,"ref_types":null,"refs_1":17053334},
{"kind":"node","id":1699110085,"tags":null,"refs":null,"lat":45.5625209,"lon":-74.5100056,"ref_roles":null,"ref_types":null,"refs_1":1699110085},
{"kind":"node","id":3506421423,"tags":null,"refs":null,"lat":45.5639343,"lon":-74.50772350000001,"ref_roles":null,"ref_types":null,"refs_1":3506421423},
{"kind":"node","id":3506421410,"tags":null,"refs":null,"lat":45.565178200000005,"lon":-74.4999356,"ref_roles":null,"ref_types":null,"refs_1":3506421410},
{"kind":"node","id":3506421445,"tags":null,"refs":null,"lat":45.5648618,"lon":-74.49801140000001,"ref_roles":null,"ref_types":null,"refs_1":3506421445},
{"kind":"node","id":16873636,"tags":null,"refs":null,"lat":45.5643016,"lon":-74.4956882,"ref_roles":null,"ref_types":null,"refs_1":16873636},
{"kind":"node","id":3506421443,"tags":null,"refs":null,"lat":45.5607385,"lon":-74.4807037,"ref_roles":null,"ref_types":null,"refs_1":3506421443},
{"kind":"node","id":16874078,"tags":null,"refs":null,"lat":45.548848500000005,"lon":-74.4299001,"ref_roles":null,"ref_types":null,"refs_1":16874078}
]