Public
Edited
Apr 26, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof mapboxMap = {
const container = html`<div style="height:500px; width: 800px">`;
yield container;

const terrain_tile_urls = [];

const map = new mapboxgl.Map({
container: container,
style: "mapbox://styles/mapbox/satellite-v9",
zoom: 18,
center: [148.9819, -35.3981],
pitch: 60,
transformRequest: (url, resourceType) => {
if (url.includes("mapbox.mapbox-terrain-dem-v1/")) {
// it's a request to the terrain source!
terrain_tile_urls.push(url.replace(".webp", ".png"));
}
},
antialias: true
});
map.addControl(new mapboxgl.NavigationControl());

map.on("idle", () => console.log(terrain_tile_urls));

const tb = (window.tb = new Threebox.Threebox(
map,
map.getCanvas().getContext("webgl"),
{
realSunlight: true,
sky: true,
terrain: showTerrain.length ? true : false,
enableSelectingObjects: true,
enableTooltips: true
}
));

let model;
// parameters to ensure the model is georeferenced correctly on the map
const modelOrigin = [148.9819, -35.39847];

let date = new Date(); //new Date(2020, 7, 14, 0, 39); // change this UTC date time to show the shadow view
let time =
date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds();

container.value = date;

viewof timeSlider.addEventListener("input", () => {
time = +viewof timeSlider.value;
date.setHours(Math.floor(time / 60 / 60));
date.setMinutes(Math.floor(time / 60) % 60);
date.setSeconds(time % 60);
container.value = date;
container.dispatchEvent(new Event("input", { bubbles: true }));
map.triggerRepaint();
});

async function createCustomLayer(layerName, origin) {
// create model url
// see https://observablehq.com/@vicapow/example-of-loading-and-modifying-a-glb-file
const url = await FileAttachment("34M_17.glb").url();

let model;
//create the layer
let customLayer3D = {
id: layerName,
type: "custom",
renderingMode: "3d",
onAdd: function (map, gl) {
// Attribution, no License specified: Model by https://github.com/nasa/
// https://nasa3d.arc.nasa.gov/detail/jpl-vtad-dsn34
let options = {
type: "gltf",
// IMPORTANT - DO NOT REMOVE
// the mtl option MUST be present, it just needs a URL that returns a 200 status code
// if you uncommented / delete the mtl option the actual object won't load
// Thanks @mootari for debugging this
mtl: "https://cdn.jsdelivr.net/npm/threebox-plugin@2.2.7/examples/models/radar/",
obj: url,
units: "meters",
scale: 333.22,
rotation: { x: 90, y: 180, z: 0 },
anchor: "center"
};

if (showTerrain.length) {
// query height of location
origin.push(
map.queryTerrainElevation(origin, { exaggerated: false })
);
console.log(
map.queryTerrainElevation(origin, {
exaggerated: false
})
);
console.log(
map.queryTerrainElevation([148.974, -35.42486], {
exaggerated: false
})
);

console.log(
map.queryTerrainElevation([148.9526, -35.4069], {
exaggerated: false
})
);
}
tb.loadObj(options, function (model) {
model.setCoords(origin);
model.addTooltip("A radar in the middle of nowhere", true);
tb.add(model);
model.castShadow = true;
tb.lights.dirLight.target = model;
});
},
render: function (gl, matrix) {
tb.setSunlight(date, origin); //set Sun light for the given datetime and lnglat
tb.update();
}
};
return customLayer3D;
}

map.on("load", async function () {
const customLayer = await createCustomLayer("3d-model", modelOrigin);
map.addLayer(customLayer);
});

invalidation.then(() => map.remove());
}
Insert cell
exampleTile = "https://api.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/13/7485/4958.png?sku=101ea8jyi7Tn7&access_token=pk.eyJ1IjoidG9mZmkiLCJhIjoiY2lvMDBxMzR3MDB1eHZza2x4NGI2YjI5OSJ9.IEaNA05pWbT92nOu-lEOYw"
Insert cell
imgBlob = await fetch(exampleTile).then((res) => res.arrayBuffer())
Insert cell
terrain = mapboxTerrainToGrid(parsedImg)
Insert cell
Insert cell
martini = new Martini(parsedImg.width - 1)
Insert cell
tile = martini.createTile(terrain)
Insert cell
mesh = tile.getMesh(10)
Insert cell
parsedImg = {
return new Promise(async (resolve, reject) => {
new png.PNG({ filterType: 4 }).parse(
await fetch(exampleTile).then((res) => res.arrayBuffer()),
function (error, image) {
if (error) {
return;
}
resolve(image);
}
);
});
}
Insert cell
fastPNG = import("https://cdn.skypack.dev/fast-png@6.1.0?min")
Insert cell
Martini = require("@mapbox/martini@0.2.0/martini.min.js")
Insert cell
Delatin = (await import("https://unpkg.com/delatin@0.2.0/index.js?module"))
.default
Insert cell
val = getData(parsedImg)
Insert cell
tin = {
const tin = new Delatin(val.data, val.width, val.height);
tin.run(10);
return tin;
}
Insert cell
tin.getMaxError()
Insert cell
bayHills = {
return new Promise(async (resolve, reject) => {
new png.PNG({ filterType: 4 }).parse(
await FileAttachment("14-2625-6369.png").arrayBuffer(),
function (error, image) {
if (error) {
return;
}
resolve(image);
}
);
});
}
Insert cell
png = require("pngjs@7.0.0/browser.js")
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