Skip to content

Instantly share code, notes, and snippets.

@jasondavies
Forked from mbostock/.block
Created September 22, 2012 17:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jasondavies/3766821 to your computer and use it in GitHub Desktop.
Save jasondavies/3766821 to your computer and use it in GitHub Desktop.
Stereographic Blue Marble
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body { padding: 0px 230px; background: #000; }
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://raw.github.com/d3/d3-plugins/master/geo/projection/projection.js"></script>
<canvas id="canvas" width="540" height="500" style="width: 1080px; height: 1000px"></canvas>
<script>
var width = 500 / 2,
height = 500 / 2;
var projection = d3.geo.stereographic()
.scale(50)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var x = d3.scale.linear()
.domain([180, -180])
.range([0, width * 2]);
var y = d3.scale.linear()
.domain([90, -90])
.range([height * 2, 0]);
var image = new Image;
image.onload = onload;
image.src = "readme-world.jpeg";
function onload() {
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
sourceWidth = image.width,
sourceHeight = image.height;
context.drawImage(image, 0, 0, sourceWidth, sourceHeight);
var source = context.getImageData(0, 0, sourceWidth, sourceHeight).data,
out = context.createImageData(width, height),
data = out.data,
interpolate = bilinear(function(x, y, offset) {
return source[(y * sourceWidth + x) * 4 + offset];
});
context.clearRect(0, 0, sourceWidth, sourceHeight);
refresh();
d3.select(window).on("mousemove", function() {
var p = d3.mouse(canvas);
projection.rotate([x.invert(p[0]), y.invert(p[1])]);
refresh();
});
function refresh() {
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var i = (y * width + x) * 4,
location = projection.invert([x, y]),
sx = (180 + location[0]) / 360 * sourceWidth,
sy = (90 - location[1]) / 180 * sourceHeight;
data[i++] = interpolate(sx, sy, 0);
data[i++] = interpolate(sx, sy, 1);
data[i++] = interpolate(sx, sy, 2);
data[i++] = 0xff;
}
}
context.putImageData(out, 0, 0);
}
}
function bilinear(f) {
return function(x, y, o) {
var x0 = Math.floor(x),
y0 = Math.floor(y),
x1 = Math.ceil(x),
y1 = Math.ceil(y);
if (x0 === x1 || y0 === y1) return f(x0, y0, o);
return (f(x0, y0, o) * (x1 - x) * (y1 - y)
+ f(x1, y0, o) * (x - x0) * (y1 - y)
+ f(x0, y1, o) * (x1 - x) * (y - y0)
+ f(x1, y1, o) * (x - x0) * (y - y0)) / ((x1 - x0) * (y1 - y0));
};
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment