Skip to content

Instantly share code, notes, and snippets.

@tomgp
Forked from mbostock/.block
Last active December 21, 2015 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomgp/6293758 to your computer and use it in GitHub Desktop.
Save tomgp/6293758 to your computer and use it in GitHub Desktop.
Snowden's Route

A fork of Mike Bostock's Snowden route map, adding visualisation of route direction and information about flights known to have been taken vs those not taken (or atleast not known to have been taken)

Oliver O’Brien’s original analysis of Snowden Route Maps.

Mike Bostock's map

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #fcfcfa;
}
.stroke {
fill: none;
stroke: #999;
stroke-width: 3px;
}
.fill {
fill: #fff;
}
.graticule {
fill: none;
stroke: #ddd;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: #ddd;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
.points circle {
fill: #fff;
stroke: red;
stroke-width: 2px;
}
.points text {
font: 11px sans-serif;
text-anchor: middle;
text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}
.route {
fill: none;
stroke: red;
stroke-width: 3px;
}
.possible-route {
stroke-dasharray:5, 5;
fill: none;
stroke: red;
stroke-width: 3px;
}
.arrowHead{
fill:red;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
var width = 960,
height = 570;
var places = {
HNL: [-157 - 55 / 60 - 21 / 3600, 21 + 19 / 60 + 07 / 3600],
HKG: [113 + 54 / 60 + 53 / 3600, 22 + 18 / 60 + 32 / 3600],
SVO: [37 + 24 / 60 + 53 / 3600, 55 + 58 / 60 + 22 / 3600],
HAV: [-82 - 24 / 60 - 33 / 3600, 22 + 59 / 60 + 21 / 3600],
CCS: [-66 - 59 / 60 - 26 / 3600, 10 + 36 / 60 + 11 / 3600],
UIO: [-78 - 21 / 60 - 31 / 3600, 0 + 06 / 60 + 48 / 3600]
};
var routes = {
known:[
[ places.HNL, places.HKG ],
[ places.HKG, places.SVO ]
],
possible:[
[ places.SVO, places.HAV ],
[ places.HAV, places.CCS ],
[ places.CCS, places.UIO ]
]
};
var projection = d3.geo.kavrayskiy7()
.scale(170)
.rotate([-40, 0])
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path);
d3.select("defs")
.append("marker")
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", 0)
.attr("markerWidth", 4)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5")
.attr("class","arrowHead");
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
for(var i=0;i<routes.known.length;i++){
svg.append("path")
.datum({
type:"LineString",
coordinates:routes.known[i]
})
.attr("class", "route")
.attr("d", path)
.attr("marker-end", "url(#arrow)");
}
for(var i=0;i<routes.possible.length;i++){
svg.append("path")
.datum({
type:"LineString",
coordinates:routes.possible[i]
})
.attr("class", "possible-route")
.attr("d", path)
.attr("marker-end", "url(#arrow)");
}
var point = svg.append("g")
.attr("class", "points")
.selectAll("g")
.data(d3.entries(places))
.enter().append("g")
.attr("transform", function(d) { return "translate(" + projection(d.value) + ")"; });
point.append("circle")
.attr("r", 4.5);
point.append("text")
.attr("y", 10)
.attr("dy", ".71em")
.text(function( d ) { return d.key; });
d3.json("/mbostock/raw/4090846/world-50m.json", function(error, world) {
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
svg.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "boundary")
.attr("d", path);
});
d3.select(self.frameElement).style("height", height + "px");
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment