Skip to content

Instantly share code, notes, and snippets.

@ppKrauss
Last active October 29, 2019 23:19
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 ppKrauss/e6c12bf84e732ca4cbf0694808619cad to your computer and use it in GitHub Desktop.
Save ppKrauss/e6c12bf84e732ca4cbf0694808619cad to your computer and use it in GitHub Desktop.
Brazilian States: Albers vs Mercator projections
license: mit
height: 600

Comparing Brazilian maps on Albers and Mercator projections.

Topojson with brazilian states (estados brasileiros).

Projection is standard Mercator, at EPSG:4326 datum.

The polygons are simplified, making the file really small. Comparing with Albers used by IBGE's Statistical Grid.

Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Brazilian States: Albers vs Mercator projections</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<style>
#br-maps .state {
fill: #bfe;
stroke:black;
fill-opacity: 0.6;
}
#br-maps .state:hover { fill: #d78; }
/*#br-maps .state_contour {
fill: none;
stroke: black;
stroke-linejoin: round;
}*/
#br-maps rect.map_canvas {
stroke: #F00;
fill: none;
stroke-width: 4; /* 0.25 to 5 */
opacity: 0.6; /* 0 to 0.5 */
}
#br-maps .map_gridCell {
stroke: #F55;
fill: none;
stroke-width: 2; /* 0.25 to 5 */
opacity: 0.9; /* 0 to 0.5 */
}
</style>
<script>
'use strict';
// Configs and global vars
const canvas_width=420, // sugere-se 340 a 620
nX=9, nY=10;
const height=1.1111111111*canvas_width;
const cellWidth = canvas_width/nX;
const cellHeight = height/nY;
var svg1, svg2, g1, g2, path1, path2;
function ready(shp) {
var states = topojson.feature(shp, shp.objects.estados);
g1.selectAll(".estado")
.data(states.features)
.enter()
.append("path") // polygon
.attr("class", "state")
.attr("d", path1);
g2.selectAll(".estado")
.data(states.features)
.enter()
.append("path") // polygon
.attr("class", "state")
.attr("d", path2);
}
// // // AlMrCmp
// canvas configs for runAlMrCmp():
const cv_reduction = 0.7; // reduction factor
const cv_width = 960 *cv_reduction;
const cv_height = 500 *cv_reduction;
const cv_margin = 10 *cv_reduction;
const fontSize = cv_reduction<0.7? "10pt": "12pt";
function runAlMrCmp() {
const svgAlMrCmp = d3.select("#AlMrCmp")
.attr("width",cv_width)
.attr("height",cv_height)
;
const mercator = d3.geoMercator(); // Standard Mercator
const albers = d3.geoAlbers() // official Brazilian Statistical Grid
.parallels([-2,-22])
.rotate([54,0])
;
var projections = [albers,mercator];
var projLayout = [
{label:"ALBERS", color:"crimson", label_x:cv_width/30, label_y:cv_height/2},
{label:"MERCATOR",color:"steelblue", label_x:cv_width/2.8, label_y:cv_height/9}
]; // labels and positions
var g = svgAlMrCmp.selectAll("g")
.data(projections)
.enter()
.append("g")
.attr("transform", (d,i)=> `translate(${(i*cv_width/2)},0)` )
; // split canvas
d3.json("world.topojson").then(function(world) {
var brazil = topojson.feature( world,world.objects.countries ).features[210];
projections.forEach(
proj => proj.fitExtent(
[ [cv_margin,cv_margin], [cv_width/2-cv_margin, cv_width/2-cv_margin] ],
brazil
)
);
g.append("path")
.attr("d", d=> d3.geoPath(d)(brazil) )
.attr("fill","none")
.attr("stroke", (d,i) => projLayout[i].color )
.attr("stroke-width",1)
;
g.transition()
.delay(2000)
.duration(2000)
.attr("transform","translate("+cv_width/4+",0)")
;
g.append("text")
.text( (d,i) => projLayout[i].label )
.attr("x", (d,i) => projLayout[i].label_x )
.attr("y", (d,i) => projLayout[i].label_y )
.attr("fill", (d,i) => projLayout[i].color )
.style("font-size",fontSize).style("font-weight","bold")
;
});
} // \runAlMrCmp
function ONLOAD() {
svg1 = d3.select("#br-albers")
.attr("width", canvas_width)
.attr("height", height);
svg2 = d3.select("#br-mercator")
.attr("width", canvas_width)
.attr("height", height);
g1 = svg1.append("g")
g2 = svg2.append("g")
const trlte_shift = [canvas_width/71,canvas_width/28.8];
var projection1 = d3.geoConicEqualArea()
.parallels([-2,-22])
.center([0,-12])
.rotate([54,0])
.scale(canvas_width*1.414930556)
.translate([ canvas_width/2.0 - trlte_shift[0], height/2.0 - trlte_shift[1] ]);
var projection2 = d3.geoMercator()
.scale(canvas_width*1.414930556)
.center([-52, -15])
.translate([canvas_width/2 + trlte_shift[0]*3, canvas_width/2 + trlte_shift[0]*6]); // + 18, 20
path1 = d3.geoPath().projection(projection1);
path2 = d3.geoPath().projection(projection2);
d3.json("./br-states.json").then(ready); // apply path1 and path2
d3.select(self.frameElement).style("height", height + "px"); // really need this line?
g1.append("rect") // the canvas frame1
.attr("x", 0 ).attr("y", 0 )
.attr("class","map_canvas")
.attr("width",canvas_width).attr("height",height)
;
g2.append("rect") // the canvas frame2
.attr("x", 0 ).attr("y", 0 )
.attr("class","map_canvas")
.attr("width",canvas_width).attr("height",height)
;
var rectsXY = []
for (let i=0; i<nX; i++) for(let j=0; j<nY; j++)
rectsXY.push( {"x":cellWidth*i, "y":cellHeight*j} );
g1.selectAll().data( rectsXY ).enter().append("rect") // GRID
.attr("x", d=>d.x).attr("y", d=>d.y )
.attr("class","map_gridCell")
.attr("width",cellWidth).attr("height",cellHeight)
;
g2.selectAll().data( rectsXY ).enter().append("rect") // GRID
.attr("x", d=>d.x).attr("y", d=>d.y )
.attr("class","map_gridCell")
.attr("width",cellWidth).attr("height",cellHeight)
;
runAlMrCmp();
} // ONLOAD
</script>
</head>
<body onload="ONLOAD()">
<section id="br-maps">
<h3>Brazilian Topojson Map: Albers vs Mercator on grid</h3>
<p>Adapted from <a href="https://bl.ocks.org/ppKrauss/0c33364240e841fa23e78b21005f792c">bl.ocks.org/ppKrauss/0c333</a>
and <a href="https://bl.ocks.org/Andrew-Reid/0ebddf4724a1658e43da01a5feff859b">bl.ocks.org/Andrew-Reid/0ebdd</a>.
</p>
<svg id="AlMrCmp"></svg>
<table border="0">
<tr>
<td>Alberts projection:<br/><svg id="br-albers"></td>
<td>&nbsp;</td>
<td>Mercator projection:<br/><svg id="br-mercator"></td>
</tr>
</table>
</section>
<hr/>
<p align="center">
Brazilian's (IBGE) official Statistical Grid, that
<a href="https://spatialreference.org/ref/sr-org/albers-conical-equal-area-brazil-sirgas-2000/">use Albers-BR-2000</a>
<br/><img src="thumbnail.png"/>
</p>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment