Skip to content

Instantly share code, notes, and snippets.

@espinielli
Last active August 29, 2015 13:59
Show Gist options
  • Save espinielli/10587361 to your computer and use it in GitHub Desktop.
Save espinielli/10587361 to your computer and use it in GitHub Desktop.
Eurocontrol member states
espinielli
mbostock

A map of Eurocontrol member states. Hover with the mouse on members countries to get name, adhesion date and flag.

Select bounding box for Europe

I tried various bounding boxes:

	WOEID: 24865675
	Centroid Location (lat/lon): 52.976181, 7.857840
	Bounding Box:
		NE 81.008797, 39.869301
		SW 27.636311, -31.266001

I did decide to use

	N = 71°
	E = -11°
	W = 35°
    S = 34°

and then applied Mike's stackoverflow answer to find scale and translate values in order to center according to my map dimensions and above bounding box.

Reduce GeoJSON data to Europe (and surrounding countries)

I tried some ogr2ogr below but lacking time I resolved to use the data from Mike Bostock's World Atlas and reacheable via his TopoJSON Examples' gist

Countries in Europe (in bounding box):

ogr2ogr -f GeoJSON \
	-where "SCALERANK = 0"
	-spat -31.266001 27.636311 39.869301 81.008797 \
	europe.json \
	data/ne_10m_admin_0_countries/ne_10m_admin_0_countries.shp

And capitals:

ogr2ogr -f GeoJSON \
	-where "FEATURECLA = 'Admin-0 capital'" \
	-spat -31.266001 27.636311 39.869301 81.008797 \
	data/ne_10m_populated_places/ne_10m_populated_places.shp

For now I stick with world list...

id date iso2
8 1 Apr 2002 AL
51 1 Mar 2006 AM
40 1 May 1993 AT
56 13 Dec 1960 BE
70 1 Mar 2004 BA
100 1 Jun 1997 BG
191 1 Mar 1997 HR
196 1 Jan 1991 CY
-1 1 Jan 1991 XK
203 1 Jan 1996 CZ
208 1 Aug 1994 DK
246 1 Jan 2001 FI
250 13 Dec 1960 FR
268 1 Jan 2014 GE
276 13 Dec 1960 DE
300 1 Sep 1988 GR
348 1 Jul 1992 HU
372 1 Jan 1965 IE
380 1 Apr 1996 IT
428 1 Jan 2011 LV
440 1 Sep 2006 LT
442 13 Dec 1960 LU
470 1 Jul 1989 MT
498 1 Mar 2000 MD
492 1 Dec 1997 MC
499 1 Jul 2007 ME
528 13 Dec 1960 NL
578 1 Mar 1994 NO
616 1 Sep 2004 PL
620 1 Jan 1986 PT
642 1 Sep 1996 RO
688 1 Jul 2005 RS
703 1 Jan 1997 SK
705 1 Oct 1995 SI
724 1 Jan 1997 ES
752 1 Dec 1995 SE
756 1 Jul 1992 CH
807 1 Nov 1998 MK
792 1 Mar 1989 TR
804 1 May 2004 UA
826 13 Dec 1960 GB
233 1 Jan 2015 EE
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: none;
stroke-width: .5px;
stroke-opacity: .5;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
.country {
fill: #ccc;
}
.country.eurocontrol {
fill: rgb(51,154,205);
}
.country-label {
fill: #fff;
fill-opacity: 1.0;
font-size: 20px;
font-weight: 300;
text-anchor: middle;
}
#loading {
text-align: center;
position: absolute;
padding-left: 200px;
padding-top: 100px;
height: 20px;
font-size: 30px;
}
#tooltip {
position: absolute;
width: auto;
height: auto;
padding: 2px 2px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
pointer-events: none;
background-color: #bbb;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0 0 0 0;
padding: 2px 2px;
font-family: sans-serif;
font-size: 14px;
}
#countryflag {
display: block;
max-width: 120px;
max-height: 100px;
width: auto;
height: auto;
}
#coordinates {
position: absolute;
text-align: left;
font-size: 12px;
font-family:Arial,Helvetica,sans-serif
}
.hidden{
display: none;
}
</style>
<body>
<div id="tooltip" class="hidden">
<p id="countryname"></p>
<p id="adhesiondate"></p>
<img id="countryflag">
</div>
<div id="map">
<div id="loading">Loading...</div>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://keithcirkel.co.uk/jwerty/jwerty.js"></script>
<script>
var width = 960,
height = 600;
// // ############### scaling and translating ###############
// from http://stackoverflow.com/questions/14492284/#answer-14691788
// var N = 71,
// E = -11,
// W = 35,
// S = 34,
// europe = { "type": "Polygon",
// "coordinates": [
// [
// [E, N],
// [W, N],
// [W, S],
// [E, S]
// ] ]
// };
// // find proper scale and translation from bounds of europe polygon
// var projection = d3.geo.azimuthalEqualArea().scale(1).translate([0,0]).clipAngle(180 - 1e-3).precision(0.1);
// var path = d3.geo.path().projection(projection);
// var b = path.bounds(europe),
// s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
// t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
// console.log("scale="+s);
// console.log("translate="+t);
// // #######################################################
var s = 987,
t = [262, 1187];
var projection = d3.geo.azimuthalEqualArea().scale(s).translate(t).clipAngle(180 - 1e-3).precision(1),
path = d3.geo.path().projection(projection);
var graticule = d3.geo.graticule();
var loading = d3.select("#loading");
var svg = d3.select("#map").append("svg")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("#tooltip").classed("hidden", true),
countryname = d3.select("#countryname"),
adhesiondate = d3.select("#adhesiondate"),
countryflag = d3.select("#countryflag"),
format = d3.format(" 2.2f");
svg.on("mousemove", function() {
// update tooltip position
tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");
return true;
});
var logo = svg.append("g");
logo.append("image")
.attr("xlink:href",
"http://upload.wikimedia.org/wikipedia/commons/b/b2/Eurocontrol_logo_2010.svg")
.attr("x", 40)
.attr("y", 160)
.attr("width", 100)
.attr("height", 100)
.attr("preserveAspectRatio", "xMinYMin");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
queue()
.defer(d3.json, "/mbostock/raw/4090846/world-50m.json")
.defer(d3.tsv, "/mbostock/raw/4090846/world-country-names.tsv")
.defer(d3.tsv, "/espinielli/raw/5107491/world-country-flags.tsv")
.defer(d3.tsv, "eurocontrol_members.tsv")
.await(ready);
function ready(error, world, names, flags, members) {
if (error) return console.error(error);
loading.classed("hidden", true);
var land = topojson.feature(world, world.objects.land),
countries = topojson.feature(world, world.objects.countries).features,
borders = topojson.mesh(world, world.objects.countries,function(a, b) { return a.id !== b.id; }),
eurocontrol = d3.set();
for (var i = members.length - 1; i >= 0; i--) {
eurocontrol.add(members[i].id);
};
countries.forEach(function(d) {
names.some(function(n) {
if (d.id == n.id) return d.name = n.name;
});
});
countries.forEach(function(d) {
members.some(function(n) {
if (d.id == n.id) {
d.adhesion = n.date;
return d.iso2 = n.iso2;
}
});
});
countries.forEach(function(d) {
flags.some(function(n) {
if (d.id == n.id) return d.flag = n.url;
});
});
var country = svg.selectAll(".country")
.data(countries)
.enter().insert("path", ".graticule")
.attr("class", function(d) {return (eurocontrol.has(d.id)? "country eurocontrol": "country");})
.attr("d", path)
.text(function(d) { return d.id;})
.on("mouseover", function(d,i) {
d3.select(this).style({'stroke-opacity':1,'stroke':'#F00'});
// http://stackoverflow.com/questions/17917072/#answer-17917341
// d3.select(this.parentNode.appendChild(this)).style({'stroke-opacity':1,'stroke':'#F00'});
if (eurocontrol.has(d.id)) {
tooltip.classed("hidden", false);
countryname.text(d.name);
adhesiondate.text("(" + d.adhesion + ")");
countryflag.attr("src", d.flag);
}
})
.on("mouseout", function(d) {
this.style.stroke = "none";
tooltip.classed("hidden", true);
})
.on("mousedown.log", function(d) {
console.log("id=" + d.id + "; name=" + d.name + "; centroid=[" + path.centroid(d) + "] px.");
});;
// add ISO2 label
// svg.selectAll(".eurocontrol")
// .append("text")
// .attr("class", function(d) { return "country-label " + d.iso2; })
// .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
// .attr("z-index", 1000)
// .attr("dy", ".35em")
// .text(function(d) { return d.iso2;});
svg.insert("path", ".graticule")
.datum(land)
.attr("class", "land")
.attr("d", path);
svg.insert("path", ".graticule")
.datum(borders)
.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