Skip to content

Instantly share code, notes, and snippets.

@memoryfull
Last active August 28, 2015 01:12
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 memoryfull/12c57c2061ea2c2e04c3 to your computer and use it in GitHub Desktop.
Save memoryfull/12c57c2061ea2c2e04c3 to your computer and use it in GitHub Desktop.
Stereographic Cylindrical projections of interest

A demonstration of a Stereographic Cylindrical projection of Braun (x=cosφ0×λ; y=(1+cosφ0)×tan(φ/2), where λ is the longitude, φ is the latitude, φ0 is standard parallel) under various φ0.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #fcfcfa;
height: 500px;
position: relative;
width: 960px;
}
#projection-menu {
position: absolute;
right: 10px;
top: 10px;
}
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill {
fill: #fff;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: #222;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
</style>
<select id="projection-menu"></select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-geo-projection/0.2.9/d3.geo.projection.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script>
//
var width = 960,
height = 500;
// Stereographic Cylindrical projections of interest
var options = [
{name: "Braun, 1867 (φ0=0)", projection: d3.geo.cylindricalStereographic().parallel(0).scale(120)},
{name: "Gall's, 1855 (φ0=45)", projection: d3.geo.cylindricalStereographic().parallel(45).scale(120*(1+Math.cos(45)))},
{name: "Kamenetskiy I, 1929 (φ0=55)", projection: d3.geo.cylindricalStereographic().parallel(55).scale(120*(1+Math.cos(55)))},
{name: "Kamenetskiy II, 1937 (φ0=30)", projection: d3.geo.cylindricalStereographic().parallel(30).scale(120*(1+Math.cos(30)))}
];
// Subsequent code is from http://bl.ocks.org/mbostock/3711652
options.forEach(function(o) {
o.projection.rotate([0, 0]).center([0, 0]);
});
var interval = setInterval(loop, 1500),
i = 0,
n = options.length - 1;
var projection = options[i].projection;
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);
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);
d3.json("/mbostock/raw/4090846/world-110m.json", function(error, world) {
if (error) throw error;
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
});
var menu = d3.select("#projection-menu")
.on("change", change);
menu.selectAll("option")
.data(options)
.enter().append("option")
.text(function(d) { return d.name; });
function loop() {
var j = Math.floor(Math.random() * n);
menu.property("selectedIndex", i = j + (j >= i));
update(options[i]);
}
function change() {
clearInterval(interval);
update(options[this.selectedIndex]);
}
function update(option) {
svg.selectAll("path").transition()
.duration(750)
.attrTween("d", projectionTween(projection, projection = option.projection));
}
function projectionTween(projection0, projection1) {
return function(d) {
var t = 0;
var projection = d3.geo.projection(project)
.scale(1)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
function project(λ, φ) {
λ *= 180 / Math.PI, φ *= 180 / Math.PI;
var p0 = projection0([λ, φ]), p1 = projection1([λ, φ]);
return [(1 - t) * p0[0] + t * p1[0], (1 - t) * -p0[1] + t * -p1[1]];
}
return function(_) {
t = _;
return path(d);
};
};
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment