Public
Edited
Oct 5
Insert cell
Insert cell
//if you want to use a different file use the file upload thing and change this to file.json()
boundsfile = lebanon
Insert cell
viewof file = Inputs.file({ label: "Upload geoJSON" })
Insert cell
//get tiles needed at specific zoom (this kind of affects detail of your resulting image? but mostly it affects how slowly it loads lol)
xyz_tiles = xyz(bounds, 9)
Insert cell
california = FileAttachment("california.geojson").json()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
levels = 18
Insert cell
canvasMap = {
// generic water color: "rgb(1, 134,160)"
let ctx = DOM.context2d(width, height);
// const path = d3.geoPath(projection, ctx);
// ctx.fillStyle = "rgb(1, 134,160)";
// ctx.fillRect(0, 0, width, height);
// ctx.save();
// ctx.beginPath(), path(boundsfile), ctx.clip();

xyz_tiles.map((t, i) => {
let tile = new Image();
tile.src = base64[i];
ctx.drawImage(
tile,
projection(tile_bbox[i].coordinates[0][0])[0],
projection(tile_bbox[i].coordinates[0][0])[1],
tileScale,
tileScale
);
});
ctx.save();
ctx.strokeStyle = "rgb(0,0,0)";
ctx.beginPath(),
path(turf.rewind(langata_cemetery_outline, { reverse: true })),
ctx.stroke();

return ctx.canvas;
}
Insert cell
langata01 = FileAttachment("langata01.geojson").json()
Insert cell
diamantina = FileAttachment("diamantina.geojson").json()
Insert cell
langata_cemetery_outline = FileAttachment("langata_cemetery_outline.geojson").json()
Insert cell
tileScale = projected[3][0] - projected[0][0] + 1
Insert cell
width = 600
Insert cell
selected = canvasMap
Insert cell
tileSize = selected.width
Insert cell
gridSize = tileSize
Insert cell
Insert cell
Insert cell
size = Math.sqrt(terrain.length)
Insert cell
heightExtent = d3.extent(terrain)
Insert cell
Insert cell
Insert cell
Insert cell
xScale = d3.scaleLinear().domain([0, size]).range([-10, 10])
Insert cell
yScale = d3.scaleLinear().domain([0, size]).range([-10, 10])
Insert cell
zScale = d3.scaleLinear().domain(heightExtent).range([0, terrainExaggeration])
Insert cell
edges = Object.assign({
top: terrainMatrix[0],
bottom: terrainMatrix[terrainMatrix.length - 1],
left: terrainMatrix.map((r) => r[0]),
right: terrainMatrix.map((r) => r[terrainMatrix.length - 1])
})
Insert cell
parameters = Object.assign({ ...worldParameters, ...perspectiveParameters })
Insert cell
projectedIsobands = {
const shapes = [];

isolines.forEach((lvl, i) => {
//lvl.lines.forEach((isoline) => {
//const lvl = isolines[levelIndex]
lvl.lines.forEach((isoline) => {
let entity = simplify(
isoline.map((d) => {
return { x: d[0], y: d[1] };
}),
lineSimplification
).map((c) => {
let copy = [xScale(c.x), yScale(c.y), zScale(lvl.threshold), 1];

return copy;
});

entity.closed = true;
entity.fillColor = "none";
entity.strokeWidth = 0.5;
entity.level = i;
entity.elevation = lvl.threshold;

shapes.push(entity);
});
});

return processScene(shapes, parameters);
}
Insert cell
scene = {
let scene = [];
let scale = 0.075;

//const allRings = []
isolines.forEach((lvl, i) => {
//lvl.lines.forEach((isoline) => {
//const lvl = isolines[levelIndex]
lvl.lines.forEach((isoline) => {
let entity = simplify(
isoline.map((d) => {
return { x: d[0], y: d[1] };
}),
lineSimplification
).map((c) => {
let copy = [xScale(c.x), yScale(c.y), zScale(lvl.threshold), 1];

return copy;
});

entity.closed = true;
entity.fillColor = "#fff";
entity.strokeWidth = 0.5;
entity.groupname = `group${lvl.threshold}`;

scene.push(entity);
});
});

// scene.push(label);

// const east = [[14, 0, terrainExaggeration / 2, 1]];
// east.text = "E";
// east.textAnchor = "middle";

// const west = [[-14, 0, terrainExaggeration / 2, 1]];
// west.text = "W";
// west.textAnchor = "middle";

// const south = [[0, 14, terrainExaggeration / 2, 1]];
// south.text = "S";
// south.textAnchor = "middle";

// const north = [[0, -14, terrainExaggeration / 2, 1]];
// north.text = "N";
// north.textAnchor = "middle";

// scene.push(north);
// scene.push(south);
// scene.push(east);
// scene.push(west);

return scene;
}
Insert cell
processedScene = {
var t0 = performance.now();
const result = processScene(scene, parameters);
var t1 = performance.now();

console.log(`processor: ${t1 - t0}`);

return result;
}
Insert cell
processedscene_layer = d3
.nest()
.key((d) => d.groupname)
.entries(processedScene)
.map((m) => {
m.values.flat();
return m;
})
Insert cell
anaglyphRenderer = (processedScene) => {
var t0 = performance.now();

const leftLayer = [];
const rightLayer = [];

const behindProjectionPlane = (item) => {
return item.map((points) => {
points.map((d) => d[0][2]).find((d) => d <= 0) === undefined &&
points.map((d) => d[1][2]).find((d) => d <= 0) === undefined;
});

return true;
};

let allLeftPath = "";
let allRightPath = "";

const svgStuff = processedscene_layer.map((m) => {
leftLayer.push(
svg`<g id=${m.key}>${m.values
.filter(behindProjectionPlane)
.map((item) => {
const leftPath =
"M " +
item.map((p) => `${p[0][0]} ${p[0][1]}`).join(" L ") +
(item.closed ? " Z" : "");
const rightPath =
"M " +
item.map((p) => `${p[1][0]} ${p[1][1]}`).join(" L ") +
(item.closed ? " Z" : "");

// allLeftPath += ' ' + leftPath
// allRightPath += ' ' + rightPath

return svg`<path d="${leftPath}" fill="${
item.fillColor ? item.fillColor : "none"
}" stroke="black" stroke-width="${
item.strokeWidth ? item.strokeWidth : 1
}"/>`;
})}</g>`
);
});

// if (allLeftPath !== '') {
// leftLayer.push(svg`<path d="${allLeftPath}" fill="white" stroke="${colors.left}" stroke-width="1" style="mix-blend-mode: multiply;" />`)
// }

// if (allRightPath !== '') {
// rightLayer.push(svg`<path d="${allRightPath}" fill="white" stroke="${colors.right}" stroke-width="1" style="mix-blend-mode: multiply;" />`)
// }

var t1 = performance.now();

console.log(`renderer: ${t1 - t0}`);

return svg`<g>
<g transform="translate(${tileSize / 2},${
tileSize / 2
})" style="mix-blend-mode: multiply;">
${rightLayer}
</g>
<g transform="translate(${tileSize / 2},${
tileSize / 2
})" style="mix-blend-mode: multiply;">
${leftLayer}
</g>
</g>`;
}
Insert cell
import {
renderer,
processScene
} with { height } from "@tonyhschu/anaglyph-pipeline-in-gpujs"
Insert cell
import { rasterize } from "@mbostock/saving-svg"
Insert cell
Insert cell
Insert cell
height = 600
Insert cell
Insert cell
Insert cell
Insert cell
zoomed_bbox = turf.bboxPolygon(
turf.bbox(
turf.buffer(turf.bboxPolygon(turf.bbox(boundsfile)), 0, {
unit: "miles"
})
)
)
Insert cell
site = zoomed_bbox
Insert cell
bounds = [
site.geometry.coordinates[0][0],
site.geometry.coordinates[0][2]
]
Insert cell
rewind = turf.rewind(site, { reverse: true })
Insert cell
ctr = turf.center(site)
Insert cell
projection = d3
.geoMercator()
.center(ctr.geometry.coordinates)
.translate([0, 0])
//.scale(Math.pow(2, 21) / (2 * Math.PI))
.fitSize([width, height], rewind)
Insert cell
Insert cell
projected = tile_bbox[0].coordinates[0].map((t) => projection(t))
Insert cell
xyz_tiles
Insert cell
tile_bbox = xyz_tiles.map((t) => tilebelt.tileToGeoJSON([t.x, t.y, t.z]))
Insert cell
base64 = Promise.all(
xyz_tiles.map(async (t) => {
let image = await canvas(t);
return await image.toDataURL();
})
)
Insert cell
canvas = async (t) => {
let img = new Image();
img.crossOrigin = "anonymous";
img.src = url(t);
await new Promise((resolve) => img.addEventListener("load", resolve));
let ctx = DOM.canvas(img.width, img.height).getContext("2d");
ctx.drawImage(img, 0, 0);
return ctx.canvas;
}
Insert cell
canvas(xyz_tiles[0])
Insert cell
url = (t) =>
`https://api.mapbox.com/v4/mapbox.terrain-rgb/${t.z}/${t.x}/${t.y}.png?access_token=${mapbox}`
Insert cell
sfbay = FileAttachment("sfbay.geojson").json()
Insert cell
Insert cell
Protobuf = require("pbf@3/dist/pbf.js")
Insert cell
d3 = require("d3-geo@1", "d3-selection@1", "d3-fetch@1", "d3-tile@0.0", "d3-scale@2.1.2", "d3-collection@latest", "d3-array@3", "d3")
Insert cell
path = d3.geoPath(projection)
Insert cell
turf = require("@turf/turf@latest")
Insert cell
vt = require('https://bundle.run/@mapbox/vector-tile@1.3.1')
Insert cell
import { Polygon, PI } from "@makio135/utilities"
Insert cell
xyz = require("https://bundle.run/xyz-affair@0.9.1")
Insert cell
map7 = FileAttachment("map(7).geojson").json()
Insert cell
map1 = FileAttachment("map (1).geojson").json()
Insert cell
tilebelt = import("https://cdn.skypack.dev/@mapbox/tilebelt@1.0.2?min")
Insert cell
mapbox = "pk.eyJ1IjoibGlmZXdpbm5pbmciLCJhIjoiY2t6bXA2dWZlMmtzbTJ2bjJ0ZTdwYnoyNyJ9.cF_Xt3B9htHIUD0lAKXaRg"
Insert cell
MarchingSquares = import(
"https://unpkg.com/marchingsquares@1.3.3/dist/marchingsquares-esm.js?module"
)
Insert cell
simplify = require("simplify-js")
Insert cell
import { view } from "@tomlarkworthy/view"
Insert cell
bingham = FileAttachment("bingham.geojson").json()
Insert cell
af = FileAttachment("af.geojson").json()
Insert cell
langata02 = FileAttachment("langata02.geojson").json()
Insert cell
lebanon = FileAttachment("lebanon.json").json()
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more