Public
Edited
Jan 17
Insert cell
Insert cell
Insert cell
Insert cell
cells = {
const position = [];
const triangles = [];
const lines = [];
const color = [];

for (const boundary of h3CellBoundaries) {
const coords = boundary.map(([lat, lon]) => polarToCartesian(lon, lat, 1));

const offset = position.length;

const colorValue = coords.length === 6 ? [1, 1, 1] : [0, 0, 0];
coords.forEach(() => color.push(...colorValue));

position.push(...coords);

const range = d3.range(offset, offset + coords.length - 1);
range.forEach((d, i) => {
triangles.push(offset);
triangles.push(offset + i + 1);
triangles.push(offset + (((i + 1) % (coords.length - 1)) + 1));
});

const [, ...tail] = range;
range.forEach((d, i) => {
lines.push(offset + i + 1);
lines.push(offset + ((i + 1) % (coords.length - 1)) + 1);
});
}

return {
position: gl.regl.buffer(position),
triangles: gl.regl.elements({
primitive: "triangles",
count: triangles.length, // Use the exact length of triangles array
data: triangles
}),
lines: gl.regl.elements({
primitive: "lines", // Correct primitive type for lines
count: lines.length, // Use the exact length of lines array
data: lines
}),
color: gl.regl.buffer(color)
};
}
Insert cell
Insert cell
Insert cell
drawCells = gl.regl({
vert: `
precision mediump float;

attribute vec3 position;
attribute vec3 color;
varying vec3 vColor;

uniform mat4 model, view, projection;

void main () {
vColor = color;
gl_Position = projection * view * model * vec4(position, 1.0);
}
`,
frag: `
precision mediump float;

varying vec3 vColor;

void main () {
gl_FragColor = vec4(vColor, 0.5);
}
`,
attributes: {
position: gl.regl.prop("position"),
color: gl.regl.prop("color")
},
uniforms: {
model: gl.regl.prop("model")
},
elements: gl.regl.prop("elements")
})
Insert cell
drawLines = gl.regl({
vert: `
precision mediump float;

attribute vec3 position;

uniform mat4 model, view, projection;

void main () {
gl_Position = projection * view * model * vec4(position, 1.0);
}
`,
frag: `
precision mediump float;

void main () {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.6);
}
`,
attributes: {
position: gl.regl.prop("position"),
color: gl.regl.prop("color")
},
uniforms: {
model: gl.regl.prop("model")
},
elements: gl.regl.prop("elements")
})
Insert cell
setupCamera = gl.regl({
context: {
projection: (context, props) =>
mat4.perspective(
[],
Math.PI / 4,
context.viewportWidth / context.viewportHeight,
0.01,
0.92 *
Math.sqrt(
Math.pow(3 * Math.cos(props.time), 2) +
Math.pow(3 * Math.sin(props.time), 2)
)
),

view: (context, props) =>
mat4.lookAt(
[],
[3 * Math.cos(props.time), -3 * Math.sin(props.time), 0],
[0, 0, 0],
[0, 0, 1]
)
},

uniforms: {
view: gl.regl.context("view"),
projection: gl.regl.context("projection")
}
})
Insert cell
function draw(time) {
gl.regl.clear({
color: [1, 1, 1, 1],
depth: 1
});

setupCamera({ time }, () => {
const model = mat4.identity([]);

let { position, triangles, lines, color } = cells;

drawCells({
model,
position,
color,
elements: triangles
});

drawLines({
model,
position,
color,
elements: lines
});

// drawGraticule(
// graticule.map((points) => ({
// model,
// position: points,
// count: points.length
// }))
// );
});
}
Insert cell
draw(now / 2000)
Insert cell
function polarToCartesian(lon0, lat0, R) {
const lat = lat0 * Math.PI / 180
const lon = lon0 * Math.PI / 180
const x = R * Math.cos(lat) * Math.cos(lon)
const y = R * Math.cos(lat) * Math.sin(lon)
const z = R * Math.sin(lat)

return [x, y, z];
}
Insert cell
Insert cell
drawGraticule = gl.regl({
vert: `
precision mediump float;

attribute vec3 position;
uniform mat4 model, view, projection;

void main () {
gl_Position = projection * view * model * vec4(position, 1);
}
`,
frag: `
precision mediump float;

void main () {
gl_FragColor = vec4(0, 0, 0, 0.1);
}
`,
attributes: {
position: gl.regl.prop("position")
},
uniforms: {
model: gl.regl.prop("model"),
view: gl.regl.context("view"),
projection: gl.regl.context("projection")
},
primitive: "line loop",
count: gl.regl.prop("count")
})
Insert cell
Insert cell
countries = {
const world = await fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-10m.json")
.then(res => res.json())
return topojson.feature(world, world.objects.countries)
}
Insert cell
// h3Cells = {
// return countries.features
// .map((feature) => {
// return geojson2h3.featureToH3Set(feature, 3);
// })
// .flat()
// .map((cell) => [h3.cellToLatLng(cell), ...h3.cellToBoundary(cell)]);
// }
Insert cell
h3Cells = FileAttachment("h3World-res3.json").json()
Insert cell
Insert cell
Insert cell
compacted = h3.compactCells(h3Cells)
Insert cell
geojson2h3 = require("https://bundle.run/geojson2h3@1.2.0")
Insert cell
Plot.geo(countries.features[0], {}).plot()
Insert cell
baseCells = h3
.getRes0Cells()
.map((cell) => [h3.cellToLatLng(cell), ...h3.cellToBoundary(cell)])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
h3 = require("h3-js@4")
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