Going straight ahead!
This commit is contained in:
1 parent
89b07a3dc6
commit
a92eee0479
10 files changed
+315
-129
No files matched your search
@@ -1 +1,5 @@
|
|||||||
.direnv
|
.direnv
|
||||||
|
result
|
||||||
|
*.duckdb
|
||||||
|
notebooks
|
||||||
|
static/data
|
||||||
@@ -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
@@ -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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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 = {
|
||||||
outputs = { self, nixpkgs, flake-utils, quebec-osm-data }:
|
url = "github:didiercrunch/cities";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
outputs = { self, nixpkgs, flake-utils, quebec-osm-data, quebec-cities-poly }:
|
||||||
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
|
||||||
|
];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -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)))
|
||||||
@@ -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());
|
||||||
@@ -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
@@ -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>
|
||||||
@@ -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());
|
|
||||||
@@ -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}
|
|
||||||
]
|
|
||||||
Reference in new issue
Block a user