block by hugolpz 5939519

France_location_map.svg (Wikipedia)

Full Screen

Step 2: Topographic map. final_topo_France.json (topojson) created using makefile.

Attempt to programmatically generate geolocalized France_location_map.svg (focus: France, type: location map, geolocalised yet light, printable) following existing Wikipedia’s guidelines.

Meta: v13.08.22. Makefile: Make4b. Focus: France. Type: topographic_map.

With: countries (L0), subdivisions (L1), places (major cities). Labels for L1 & places.

This code is part of the Wikimaps team push for better wikipedia maps. An efforts for both GIS data collection and map generation for the purpose of encyclopedic cartography and free knowledge.

Sources:

1a. Base idea and tutorial: Let’s Make a Map by Mike Bostock

1b. In practice (shorter) : Making a map of germany with topojson

2a. Base introduction to Makefile Why Use Make by Mike Bostock

2b. In practice (shorter): Austria D3 TopoJSON

3a. wikimaps’ stylesheets: Wikipedia:WikiProject_Maps/Conventions

Interesting: Creating and Publishing Maps with D3, Dymo, and PhantomJS, ISO_3166-2

TODO: Conditional borders and coastlines : http://bost.ocks.org/mike/map/#displaying-boundaries

index.html

<!DOCTYPE html>
<!--    //bost.ocks.org/mike/map/-->
<meta charset="utf-8">
v. 08/13:12:30am. Last version on codio.com
<style>
svg { border: 5px solid #646464; background-color: #C6ECFF;}
path.L0 { fill:#E0E0E0;}
path.L1 { fill:#FEFEE9;}
path.L1:hover { fill: #B10000 ;}
.red { border: 5px solid red;} /* Class for tests */

.subunit-boundary {
  fill: none;
  stroke-width:1px;
  stroke: #646464;
  /* stroke-dasharray: 2,2; */
  stroke-linejoin: round;
}
.place,
.place-label {
  fill: #444;
  font-size:4px;
}
text {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 6px;
  pointer-events: none;
}
.subunit-label {
  fill: #777;
  fill-opacity: .5;
  font-size: 11px;
  font-weight: 200;
  text-anchor: middle;
}
</style>
<body>
<script src="//code.jquery.com/jquery-2.0.2.min.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/topojson.v0.min.js"></script>
<script>
// -------------- SETTINGS ------------- //
// HTML frame: dimensions & colors
var width  = 525,
    height = 525,
    color = d3.scale.category10(); // d3.scale.ordinal().domain(["000000", "FFFFFF", "baz"]).range(colorbrewer.RdBu[9]);

// Projection: New projection, center coord, scale(?):
var projection = d3.geo.mercator()
    .center([2.2, 46.4]) // jap: [139, 35.4]
    .scale(2000) // behavioral definition welcome 
    .translate([width / 2, height / 2]); //??

// SVG injection:
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

// Path
var path = d3.geo.path()
    .projection(projection)
    .pointRadius(4);

// Data (getJSON: TopoJSON)
d3.json("fra.json", showData);

// ---------- FUNCTION ------------- //
function showData(error, fra) {

// var #Coord: projection formerly here

// var #Path: formerly here
    var countries = topojson.object(fra, fra.objects.countries)
        subunits = topojson.object(fra, fra.objects.subunits),
        neighbors = topojson.neighbors(fra.objects.subunits.geometries); // coloring: full line

//Append L0 polygons
    svg.append("path")
        .datum(countries)
        .attr("d", path)

    svg.selectAll(".countries")
        .data(topojson.object(fra, fra.objects.countries).geometries)
      .enter().append("path")
        .attr("class", function(d) { return "L0 " + d.properties.name; })
        .attr("d", path)
        //.style("fill", function(d, i) { return color(d.color = d3.max(neighbors[i], function(n) { return subunits[n].color; }) + 1 | 0); })  // coloring: full line
        .on("click", click);

//Append L1 polygons
    svg.append("path")
        .datum(subunits)
        .attr("d", path)

    svg.selectAll(".subunit")
        .data(topojson.object(fra, fra.objects.subunits).geometries)
      .enter().append("path")
        .attr("class", function(d) { return "L1 " + d.properties.name; })
        .attr("d", path)
        //.style("fill", function(d, i) { return color(d.color = d3.max(neighbors[i], function(n) { return subunits[n].color; }) + 1 | 0); })  // coloring: full line
        .on("click", click);

// Function Click > Console
    function click(a){
        console.log(a.properties.name);}

//Append [what that !!!?]
    svg.append("path")
        .datum(topojson.mesh(fra, fra.objects.subunits, function(a,b) { if (a!==b || a.properties.name === "Berlin"|| a.properties.name === "Bremen"){var ret = a;}return ret;}))
        .attr("d", path)
        .attr("class", "subunit-boundary");

// Append [??]
    svg.append("path")
        .datum(topojson.object(fra, fra.objects.places))
        .attr("d", path)
        .attr("class", "place");

// Positioning: place-label
    svg.selectAll(".place-label")
        .data(topojson.object(fra, fra.objects.places).geometries)
      .enter().append("text")
        .attr("class", "place-label")
        .attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
        .attr("dy", ".35em")
        .text(function(d) { if (d.properties.name!=="Paris"&&d.properties.name!=="Bremen"){return d.properties.name;} })
        .attr("x", function(d) { return d.coordinates[0] > -1 ? 6 : -6; })
        .style("text-anchor", function(d) { return d.coordinates[0] > -1 ? "start" : "end"; });

// Positioning: subunit-label
    svg.selectAll(".subunit-label")
        .data(topojson.object(fra, fra.objects.subunits).geometries)
      .enter().append("text")
        .attr("class", function(d) { return "subunit-label " + d.properties.name; })
        .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
        // Vertical adjustment: Champagne-Ardenne-- Languedoc-Roussillon-- Haute-Normandie-  Loraine++ Île-de-france 0.5em franche-Comté-1.0em Limousin -1.0
        .attr("dy", function(d){ 
        if(d.properties.name==="Champagne-Arfranne"||d.properties.name==="Languedoc-Roussillon" || d.properties.name==="Limousin" )
            {return "1.5em"}
        else if(d.properties.name==="Haute-Normandie" )
            {return ".5em"}
        else if(d.properties.name==="Loraine"|| d.properties.name==="france-Comté")
            {return "-1.5em"}
        else if(d.properties.name==="Île-de-france" )
            {return "-.5em"}
        else{return ".2em"}}) // frafault
        .text(function(d) { return d.properties.name; });

}
</script>
<br />
<div>
    <a class="download ac-icon-download" href="javascript:javascript: (function () { var e = document.createElement('script'); if (window.location.protocol === 'https:') { e.setAttribute('src', 'https://raw.github.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js'); } else { e.setAttribute('src', '//nytimes.github.com/svg-crowbar/svg-crowbar.js'); } e.setAttribute('class', 'svg-crowbar'); document.body.appendChild(e); })();"><!--⤋--><big></big> Download</a> -- Works on Chrome. Feedback me for others web browsers ?
</div>
<br />
</body>
</html>

Makefile

fra.json: countries.json subunits.json places.json
	topojson --id-property none -p name=name -p name=NAME -o fra0813b.json -- countries.json subunits.json places.json

### FILES FILTERS & 2JSON
countries.json: ne_10m_admin_0_sovereignty.shp
	ogr2ogr -f GeoJSON -where "admin IN ('Spain', 'Italy', 'Andorra', 'Switzerland', 'Belgium', 'Netherlands', 'Luxembourg', 'Germany', 'United Kingdom')" countries.json ne_10m_admin_0_sovereignty.shp
subunits.json: ne_10m_admin_1_states_provinces_shp
	ogr2ogr -f GeoJSON -where "admin IN ('France')" subunits.json ne_10m_admin_1_states_provinces_shp.shp
places.json: ne_10m_populated_places.shp	
	ogr2ogr -f GeoJSON -where "ADM0NAME = 'France' OR SOV0NAME = 'French Republic' OR ISO_A2 = 'FR' AND FEATURECLA = 'Admin-1 region capital'" places.json ne_10m_populated_places.shp
#or "iso_a2 = 'AT' AND SCALERANK < 20" , see also sr_adm0_a3

### FILES UNZIP:
ne_10m_admin_0_sovereignty.shp: countries.zip
	unzip countries.zip
	touch ne_10m_admin_0_sovereignty.shp
ne_10m_admin_1_states_provinces_shp: subunits.zip
	unzip subunits.zip
	touch ne_10m_admin_1_states_provinces_shp.shp
ne_10m_populated_places.shp: places.zip
	unzip places.zip
	touch ne_10m_populated_places.shp

### FILES DOWNLOAD:
countries.zip:
	curl -L -o countries.zip 'http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_sovereignty.zip'
	# http://www.nacis.org/naturalearth/10m/cultural/ne_10m_admin_0_map_subunits.zip
subunits.zip:
	curl -L -o subunits.zip 'http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces_shp.zip'
places.zip:
	curl -o places.zip 'http://www.nacis.org/naturalearth/10m/cultural/ne_10m_populated_places.zip'	

clean:
	rm `ls | grep -v 'zip' | grep -v 'Makefile' `