Published
Edited
Jun 3, 2020
2 forks
1 star
Insert cell
Insert cell
md `## Boring stuff setting up tiles`
Insert cell
Insert cell
projection = d3.geoMercator()
.center([-73.9888682,40.6916651]) //https://github.com/d3/d3-geo#projection_center, does what it says on the tin
.scale((1 << 22) / (2 * Math.PI)) // this number is actually 333772.1072150545. Why is it this number? I am assuming this has something to do with projecting from a...circle? Because we're dividing by tau?
//https://github.com/d3/d3-geo#projection_scale
.translate([width / 2, height / 2]) //https://github.com/d3/d3-geo#projection_translate. this feature defaults to translating the center point of your map against a 960x500 area svg? I don't really know why that size. What we have here will translate our map's center to the exact center of the div.
.precision(0) //https://github.com/d3/d3-geo#projection_precision, d3 uses something called adaptive sampling to improve rendering and performance (see https://bl.ocks.org/mbostock/3795544), this definitely falls into "I sort of understand this math, Mike" territory
Insert cell
Insert cell
tile = d3.tile() // based on the following parameters, which tiles will I need to fetch?
.size([width, height]) //it's going to fill this space
.scale(projection.scale() * 2 * Math.PI) // again, I am not 100% sure I know what's going oin
.translate(projection([0, 0])) //don't change anything from the projection
Insert cell
tiles = Promise.all(tile().map(async d => {
d.data = await d3.json(`https://tile.nextzen.org/tilezen/vector/v1/256/all/${d.z}/${d.x}/${d.y}.json?api_key=ztkh_UPOQRyakWKMjH_Bzg`); // map the tiles returned by tile() to the tile API endpoint
return d; // look at the different items that are part of the output data!! so many
}))
Insert cell
Insert cell
roads = tiles.map(t => t.data.roads.features.filter(f => f.properties.kind != "ferry" && f.properties.kind != "rail" )).filter(m => m.length > 0).flat()
Insert cell
md `## for each road in tile, identify overlaps`
Insert cell
test = function(){
let index = []
roads.forEach(function(r){
let obj = {}
obj.name = r.properties.name
obj.points = []
obj.id = r.properties.id
roads.forEach(function(ki,i){
if (ki.properties.id != r.properties.id && ki.properties.name !== undefined && r.properties.name !== undefined){
let int = turf.lineIntersect(r, ki);
if (int.features.length > 0) {
int.features.forEach(function(inter){
if (inter.properties){
inter.properties.intersection = ki.properties.name
inter.properties.ID = ki.properties.id
obj.points.push(inter)
}
})
index.push(obj)
}
}
}
)
})
return index}();
Insert cell
Insert cell
makePoints = function(){
let arr = [];
for (var i = 0; i < test.length; i++){
let obj = test[i].points[0];
arr.push(obj);
}
let geojson = {};
geojson.type = "FeatureCollection";
geojson.features = arr;
return geojson;
}();
Insert cell
md `## Turning the points into Lines`
Insert cell
makeLineString = function(){
let arr = []
for (var i = 0; i < test.length; i++) {
for(var j = 0; j < test[i].points.length; j++){
if (test[i].points[j+1] !== undefined){
let obj = {}
obj.type= "Feature",
obj.properties = {};
obj.properties.path = `${test[i].points[j].properties.intersection} and ${test[i].points[j+1].properties.intersection}`
obj.geometry = {};
obj.geometry.type = "LineString";
obj.geometry.coordinates= [test[i].points[j].geometry.coordinates, test[i].points[j+1].geometry.coordinates]
arr.push(obj)
}
}
} let geojson = {};
geojson.type = "FeatureCollection";
geojson.features = arr;
return geojson;
}()
Insert cell
d3colors = d3.quantize(d3.interpolateHcl("cyan", "hotpink"), 10)
Insert cell
map = svg`<svg viewBox="0 0 ${width} ${height}" style="width:100%;height:auto; id = "map"">
${tiles.map(d => svg`
<path fill="papayawhip" d="${path(d.data.water)}"></path>
<path fill="none" stroke="#ccc" stroke-width="0.75" d="${path(d.data.roads)}"></path
<path fill="green" stroke="pink" stroke-width="1" d=${path(d.data.pois)}"></path>
`)}
${makeLineString.features.map(d => svg `<path stroke = "${d3colors[Math.floor(Math.random()*d3colors.length)]}" stroke-width="3" d="${path(d)}"></path>`)}
${makePoints.features.map(d => svg `<path fill="orange" d="${path(d)}"></path>`)}
</svg>`
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more