Public
Edited
Jan 22, 2024
1 fork
Importers
7 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const context = DOM.context2d(width, height, 1);
reproject.context(context)(planets[planet]);
return context.canvas;
}
Insert cell
reproject = geoRasterReproject()
.projection(projection.fitSize([width, height], {type: "Sphere"}))
.size([width, height]);
Insert cell
function geoRasterReproject(){
let context,
projection,
size;

// See: https://bl.ocks.org/mbostock/4329423
function reproject(image){
const dx = image.width, dy = image.height, w = size[0], h = size[1];
context.drawImage(image, 0, 0, dx, dy);
const sourceData = context.getImageData(0, 0, dx, dy).data,
target = context.createImageData(w, h),
targetData = target.data;
for (let y = 0, i = -1; y < h; ++y) {
for (let x = 0; x < w; ++x) {
const p = projection.invert([x, y]), lambda = p[0], phi = p[1];
if (lambda > 180 || lambda < -180 || phi > 90 || phi < -90) { i += 4; continue; }
let q = ((90 - phi) / 180 * dy | 0) * dx + ((180 + lambda) / 360 * dx | 0) << 2;
targetData[++i] = sourceData[q];
targetData[++i] = sourceData[++q];
targetData[++i] = sourceData[++q];
targetData[++i] = 255;
}
}
context.clearRect(0, 0, w, h);
context.putImageData(target, 0, 0);
}
reproject.context = function(_){
return arguments.length ? (context = _, reproject) : context;
}

reproject.projection = function(_){
return arguments.length ? (projection = _, reproject) : projection;
}
reproject.size = function(_){
return arguments.length ? (size = _, reproject) : size;
}
return reproject;
}
Insert cell
Insert cell
Insert cell
Earth = FileAttachment("earth.jpg").image();
Insert cell
Mars = FileAttachment("mars.jpg").image();
Insert cell
Moon = FileAttachment("moon.jpg").image();
Insert cell
Insert cell
projection = {
const options = {
"Stereographic": d3.geoStereographic(),
"Orthographic": d3.geoOrthographic(),
"Natural Earth 1": d3.geoNaturalEarth1(),
"Equal Earth": d3.geoEqualEarth(),
"Mercator": d3.geoMercator(),
"Azimuthal Equal Area": d3.geoAzimuthalEqualArea(),
"Gnomic": d3.geoGnomonic(),
"Conic Equal Area": d3.geoConicEqualArea(),
"Conic Equidistant": d3.geoConicEquidistant(),
"Equal Earth": d3.geoEqualEarth(),
"Equirectangular": d3.geoEquirectangular(),
}
return options[selected].rotate([lon, 0, 0]);
}
Insert cell
height = fitWidth(projection);
Insert cell
function fitWidth(projection) {
const [[x0, y0], [x1, y1]] = d3.geoPath(projection.fitWidth(width, {type: "Sphere"})).bounds({type: "Sphere"});
const dy = Math.ceil(y1 - y0), l = Math.min(Math.ceil(x1 - x0), dy);
projection.scale(projection.scale() * (l - 1) / l).precision(0.2);
return dy;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more