Skip to content

Instantly share code, notes, and snippets.

@Fil

Fil/README.md Secret

Last active January 6, 2016 15:33
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 Fil/df0afe191dc666d9d2c0 to your computer and use it in GitHub Desktop.
Save Fil/df0afe191dc666d9d2c0 to your computer and use it in GitHub Desktop.
Three-Axis Bottomley Rotation

D3 3.0 supports three-axis rotation for geographic projections. This example demonstrates rotating lambda (λ), phi (φ) and gamma (γ) in three side-by-side bottomley projections.

forked from mbostock's block: Three-Axis Rotation

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.title {
display: inline-block;
font-size: 48px;
line-height: 90px;
text-align: center;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
var π = Math.PI, halfπ=π/2;
function bottomleyRaw(ψ) {
function forward(λ, φ) {
var ρ = halfπ - φ,
η = ρ ? λ * Math.sin(ψ) * Math.sin(ρ) / ρ : ρ;
return [
ρ * Math.sin(η) / Math.sin(ψ),
halfπ - ρ * Math.cos(η)
];
}
forward.invert = function(x, y) {
var x1 = x * Math.sin(ψ),
y1 = halfπ - y;
var ρ = Math.sqrt( x1 * x1 + y1 * y1 ),
η = Math.atan( x1 / y1 );
return [
(ρ ? ρ / Math.sin(ρ) : 1) * η / Math.sin(ψ),
halfπ - ρ
];
};
return forward;
}
(d3.geo.bottomley = function() {
var ψ = π/6,
mutate = d3.geo.projectionMutator(bottomleyRaw),
projection = mutate(ψ);
projection.variant = function(_) {
if (!arguments.length) return ψ;
return mutate(ψ = _);
};
return projection;
}).raw = bottomleyRaw;
var diameter = 960 / 3,
radius = diameter >> 1,
velocity = .01,
then = Date.now();
var projection = d3.geo.bottomley()
.scale(radius/2 - 2)
.translate([radius, radius])
//.clipAngle(90)
.precision(0);
d3.select("body").selectAll(".title")
.data(["λ", "φ", "γ"])
.enter().append("div")
.attr("class", "title")
.style("width", diameter + "px")
.text(function(d) { return d; });
var canvas = d3.select("body").selectAll("canvas")
.data(d3.range(3))
.enter().append("canvas")
.attr("width", diameter)
.attr("height", diameter);
var path = d3.geo.path()
.projection(projection);
d3.json("https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-110m.json", function(error, world) {
if (error) throw error;
var land = topojson.feature(world, world.objects.land),
globe = {type: "Sphere"};
d3.timer(function() {
var angle = velocity * (Date.now() - then);
canvas.each(function(i) {
var rotate = [0, 0, 0], context = this.getContext("2d");
rotate[i] = angle, projection.rotate(rotate);
context.clearRect(0, 0, diameter, diameter);
context.beginPath(), path.context(context)(land), context.fill();
context.beginPath(), path(globe), context.stroke();
});
});
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment