Skip to content

Instantly share code, notes, and snippets.

@Andrew-Reid
Last active March 17, 2017 02:16
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 Andrew-Reid/56cbf086b64406aaf81b630426bad5e9 to your computer and use it in GitHub Desktop.
Save Andrew-Reid/56cbf086b64406aaf81b630426bad5e9 to your computer and use it in GitHub Desktop.
Azimuthal Equidistant Raster Reprojection

This bl.ock is a response to a question on reprojecting rasters in d3. The approach is covered in this answer: Stack Overflow answer.

It assumes a geographic projection that projects the earth on to a disc, so that one can calculate the radius of the disc and trim the image to this area. This is required as the d3 projection function is not one to one.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #222;
}
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500;
var projection = d3.geoAzimuthalEquidistant()
.scale(65)
.precision(.1);
var edge = {};
var center = {};
edge.x = projection([180 - 1e-6, 0])[0];
edge.y = projection([180 - 1e-6, 0])[1];
center.x = width/2;
center.y = height/2;
var radius = Math.pow( Math.pow(center.x - edge.x,2) + Math.pow(center.y - edge.y,2) , 0.5 )
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
var image = new Image;
image.onload = onload;
image.src = "readme-blue-marble.jpg";
function onload() {
var dx = image.width,
dy = image.height;
context.drawImage(image, 0, 0, dx, dy);
var sourceData = context.getImageData(0, 0, dx, dy).data,
target = context.createImageData(width, height),
targetData = target.data;
for (var y = 0, i = -1; y < height; ++y) {
for (var x = 0; x < width; ++x) {
var p = projection.invert([x, y]), λ = p[0], φ = p[1];
if (Math.pow( Math.pow(center.x-x,2) + Math.pow(center.y-y,2), 0.5) < radius) {
if ( λ > 180 || λ < -180 || φ > 90 || φ < -90 ) { i += 4; continue; }
var q = ((90 - φ) / 180 * dy | 0) * dx + ((180 + λ) / 360 * dx | 0) << 2;
targetData[++i] = sourceData[q];
targetData[++i] = sourceData[++q];
targetData[++i] = sourceData[++q];
targetData[++i] = 255;
}
else {
targetData[++i] = 0;
targetData[++i] = 0;
targetData[++i] = 0;
targetData[++i] = 0;
}
}
}
context.clearRect(0, 0, width, height);
context.putImageData(target, 0, 0);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment