Published
Edited
Aug 13, 2019
Insert cell
Insert cell
Insert cell





Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
firstName = "Ambika"
Insert cell
lastName = "Yadav"
Insert cell
handle = "akibmay"
Insert cell
sphere = ({type: "Sphere"})
Insert cell
geodesic = {
const φ = 1.618033988749895;
const ρ = 180 / Math.PI;

const vertices = [
[1,φ,0], [-1,φ,0], [1,-φ,0], [-1,-φ,0],
[0,1,φ], [0,-1,φ], [0,1,-φ], [0,-1,-φ],
[φ,0,1], [-φ,0,1], [φ,0,-1], [-φ,0,-1]
];

const faces = [
[0,1,4], [1,9,4], [4,9,5], [5,9,3], [2,3,7],
[3,2,5], [7,10,2], [0,8,10], [0,4,8], [8,2,10],
[8,4,5], [8,5,2], [1,0,6], [11,1,6], [3,9,11],
[6,10,7], [3,11,7], [11,6,7], [6,0,10], [9,1,11]
].map(face => face.map(i => vertices[i]));

function interpolate([x0, y0, z0], [x1, y1, z1], t) {
return [
x0 + t * (x1 - x0),
y0 + t * (y1 - y0),
z0 + t * (z1 - z0)
];
}

function project([x, y, z]) {
return [
Math.atan2(y, x) * ρ,
Math.acos(z / Math.sqrt(x * x + y * y + z * z)) * ρ - 90
];
}

return function(n) {
n = n | 0;
const subfaces = [];
for (const [f0, f1, f2] of faces) {
let f10, f20 = interpolate(f0, f1, 1 / n);
let f11, f21 = interpolate(f0, f2, 1 / n);
subfaces.push([f0, f20, f21]);
for (let i = 1; i < n; ++i) {
f10 = f20, f20 = interpolate(f0, f1, (i + 1) / n);
f11 = f21, f21 = interpolate(f0, f2, (i + 1) / n);
for (let j = 0; j <= i; ++j) {
subfaces.push([
interpolate(f10, f11, j / i),
interpolate(f20, f21, j / (i + 1)),
interpolate(f20, f21, (j + 1) / (i + 1))
]);
}
for (let j = 0; j < i; ++j) {
subfaces.push([
interpolate(f10, f11, j / i),
interpolate(f20, f21, (j + 1) / (i + 1)),
interpolate(f10, f11, (j + 1) / i)
]);
}
}
}
return subfaces.map(f => f.map(project));
};
}
Insert cell
// Your D3 code goes here.
// The function badgeCode gets called below to generate the previews.
function badgeCode(g, context, frameNumber) {
// g: a <g>, i.e. d3.select(... the node)
// context: a canvas context, useful for doing canvas drawing
// frameNumber: a number that represents the frame (1, 2, … 10) for psuedo-animation. --> this animates everything.
// width & height are available via the environment, as is d3
// Note: the <g> is drawn on top of the <canvas>
context.fillStyle = "#34495e";
context.fillRect(0, 0, width, height);
let faces = geodesic(Math.floor(frameNumber/2)+1);
function drawTriangle([p0, p1, p2]) {
context.moveTo(...p0);
context.lineTo(...p1);
context.lineTo(...p2);
context.closePath();
}
let projectionWidth = width;
let projectionHeight = height/2;
let projection = d3.geoOrthographic()
.rotate([0, -40])
.fitExtent([[2, 2], [projectionWidth - 50, projectionHeight - 50]], sphere)
// .translate(projectionHeight)

// context.translate(0, projectionHeight/2);
const triangles = faces
.map((d, i) => (d = d.map(projection), d.index = i, d))
.filter(d => d3.polygonArea(d) < 0);
for (const t of triangles) {
t[0][1] += projectionHeight/2 + 70;
t[1][1] += projectionHeight/2 + 70;
t[2][1] += projectionHeight/2 + 70;
context.beginPath();
drawTriangle(t);
context.fillStyle = d3.interpolateRainbow(faces[t.index][0][0] / 360);
context.fill();
}
}
Insert cell
isTextLight = true
Insert cell
import {preview, animation, download, width, height, d3}
with {firstName, lastName, handle, isTextLight, badgeCode}
from "b93171820ba3f268"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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