Published
Edited
Jan 12, 2019
Importers
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
railwayNetwork = d3.json('https://raw.githubusercontent.com/alexmasselot/swiss-transport-data/master/data/cff-network.json')
.then((d)=>{
_.each(d.connections, (cs)=>{
_.each(cs, (c, to)=> cs[to] = new FragmentedPath(c, d.stops))
})
return d
})
Insert cell
{
d3Enter()
d3Update()
}
Insert cell
Insert cell
map = {
let m = L.map(mapContainer,
{
zoomControl: false,
dragging: false,
boxZoom:false,
keyboard:false,
boxZoom:false,
scrollWheelZoom: false,
touchZoom:false
});
yield m

let osmLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(m);
m.fitBounds([
[45.90,6.0141006],
[47.7247412,10.1079157]
]);
}
Insert cell
Insert cell
svg = d3.select(map.getPanes().overlayPane)
.append('svg')
.attr('height', map.getSize().y)
.attr('width', map.getSize().x)

Insert cell
Insert cell
gStops = svg.append('g').classed('stops', true)
Insert cell
Insert cell
Insert cell
d3Enter = () => {
//gStops.selectAll('circle.stop').remove();
//gStops.selectAll('circle.stop')
// .data(_.values(railwayNetwork.stops))
// .enter()
// .append('circle')
// .classed('stop', true)
// .attr('stroke-width', 1)
// .attr('fill', 'grey')
// .attr('r', 1.5)
// .exit()
// .remove()
gRails.selectAll('line.rails').remove();
gRails.selectAll('line.rails')
.data(_.values(railwayNetwork.segments))
.enter()
.append('line')
.classed('rails', true)
.attr('stroke-width', 1)
.attr('stroke', 'black')
.exit()
.remove()
}
Insert cell
d3Update = ()=>{
//gStops.selectAll('circle.stop')
//.attr('cx', (s)=> map.latLngToLayerPoint(L.latLng(s.coords.lat, s.coords.lon)).x)
//.attr('cy', (s)=>map.latLngToLayerPoint(L.latLng(s.coords.lat, s.coords.lon)).y)
gRails.selectAll('line.rails')
.attr('x1', (segment)=> {
let coords = railwayNetwork.stops[segment.a].coords
return map.latLngToLayerPoint(L.latLng(coords.lat, coords.lon)).x
})
.attr('y1', (segment)=> {
let coords = railwayNetwork.stops[segment.a].coords
return map.latLngToLayerPoint(L.latLng(coords.lat, coords.lon)).y
})
.attr('x2', (segment)=> {
let coords = railwayNetwork.stops[segment.b].coords
return map.latLngToLayerPoint(L.latLng(coords.lat, coords.lon)).x
})
.attr('y2', (segment)=> {
let coords = railwayNetwork.stops[segment.b].coords
return map.latLngToLayerPoint(L.latLng(coords.lat, coords.lon)).y
})
.on('mouseover', (segment)=>{
console.log(railwayNetwork.stops[segment.a], railwayNetwork.stops[segment.b])
})
}
Insert cell
FragmentedPath = {
const FragmentedPath = function(stopInfos, stops){
const distTot = stopInfos[stopInfos.length-1].dist
this.nodes = _.map(stopInfos, (si) => {
return {
stop: stops[si.stopId],
dist: si.dist,
distRatio: si.dist/distTot
}
})
this.dist = distTot
}
yield FragmentedPath
FragmentedPath.prototype.stopBracket = function(ratio){
const self = this;
if(ratio <=0){
return [undefined, self.nodes[0]]
}
const iMax = self.nodes.length-1
if(ratio >= 1){
return [self.nodes[iMax], undefined]
}
const dist=ratio*self.dist
return _.chain(_.take(self.nodes, iMax))
.zip(_.tail(self.nodes))
.find((p)=> dist <= p[1].dist)
.value()
}
FragmentedPath.prototype.interpolatePosition = function(ratio){
const self = this;
const seg = self.stopBracket(ratio)
if(seg[0] === undefined){
return seg[1].stop.coords
}
if(seg[1] === undefined){
return seg[0].stop.coords
}
const r = (ratio-seg[0].distRatio)/(seg[1].distRatio-seg[0].distRatio)
return {
lat: seg[0].stop.coords.lat + r*(seg[1].stop.coords.lat-seg[0].stop.coords.lat),
lon: seg[0].stop.coords.lon + r*(seg[1].stop.coords.lon-seg[0].stop.coords.lon),
}
}
FragmentedPath.prototype.interpolatePartial = function(ratio0, ratio1){
const self = this;
const dist0 = ratio0*self.dist
const dist1 = ratio1*self.dist
const intraNodes = _.chain(self.nodes)
.dropWhile((n)=> n.dist < dist0 )
.tail()
.takeWhile((n)=> dist1 > n.dist)
.map((n)=>n.stop.coords)
.value()
return _.concat(
self.interpolatePosition(ratio0),
intraNodes,
self.interpolatePosition(ratio1)
)
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fp1_pos500 = fp1.interpolatePosition(500/fp1.dist)
Insert cell
Insert cell
fp_gl = railwayNetwork.connections['8501008']['8501120']

Insert cell
fp_gl.interpolatePartial(0.5, 0.51)
Insert cell
Insert cell
Insert cell
L = require('leaflet@1.3.4')
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more