Using Cesium for display of remote parquet.
parquet
spatial
recipe
This page renders points from an iSamples parquet file on cesium using point primitives.
WarningHeads up: first interaction may be slow
The first click or query can take a few seconds while the in‑browser database engine initializes and the remote Parquet file is fetched and indexed. Subsequent interactions are much faster because both the browser and DuckDB cache metadata and column chunks, so later queries reuse what was already loaded.
Code
= {
db const instance = await DuckDBClient.of();
await instance.query(`create view nodes as select * from read_parquet('${parquet_path}')`)
return instance;
}
async function loadData(query, params = [], waiting_id = null, key = "default") {
// latest-only guard per key
._latest = loadData._latest || new Map();
loadDataconst requestToken = Symbol();
._latest.set(key, requestToken);
loadData
// Get loading indicator
const waiter = waiting_id ? document.getElementById(waiting_id) : null;
if (waiter) waiter.hidden = false;
try {
// Run the (slow) query
const _results = await db.query(query, params);
// Ignore stale responses
if (loadData._latest.get(key) !== requestToken) return null;
return _results;
catch (error) {
} if (waiter && loadData._latest.get(key) === requestToken) {
.innerHTML = `<pre>${error}</pre>`;
waiter
}return null;
finally {
} // Hide the waiter (if there is one) only if latest
if (waiter && loadData._latest.get(key) === requestToken) {
.hidden = true;
waiter
}
}
}
= {
locations // get the content form the parquet file
const query = `SELECT pid, latitude, longitude FROM nodes WHERE otype='GeospatialCoordLocation'`;
const data = await loadData(query, [], "loading_1", "locations");
// Clear the existing PointPrimitiveCollection
.points.removeAll();
content//content.points = new Cesium.PointPrimitiveCollection();
// create point primitives for cesium display
const scalar = new Cesium.NearFarScalar(1.5e2, 2, 8.0e6, 0.2);
const color = Cesium.Color.PINK;
const point_size = 4;
for (const row of data) {
.points.add({
contentid: row.pid,
// https://cesium.com/learn/cesiumjs/ref-doc/Cartesian3.html#.fromDegrees
position: Cesium.Cartesian3.fromDegrees(
.longitude, //longitude
row.latitude, //latitude
row0,//randomCoordinateJitter(10.0, 10.0), //elevation, m
,
)pixelSize: point_size,
color: color,
scaleByDistance: scalar,
;
})
}.enableTracking();
contentreturn data;
}
function createShowPrimitive(viewer) {
return function(movement) {
// Get the point at the mouse end position
const selectPoint = viewer.viewer.scene.pick(movement.endPosition);
// Clear the current selection, if there is one and it is different to the selectPoint
if (viewer.currentSelection !== null) {
//console.log(`selected.p ${viewer.currentSelection}`)
if (Cesium.defined(selectPoint) && selectPoint !== viewer.currentSelection) {
console.log(`selected.p 2 ${viewer.currentSelection}`)
.currentSelection.primitive.pixelSize = 4;
viewer.currentSelection.primitive.outlineColor = Cesium.Color.TRANSPARENT;
viewer.currentSelection.outlineWidth = 0;
viewer.currentSelection = null;
viewer
}
}
// If selectPoint is valid and no currently selected point
if (Cesium.defined(selectPoint) && selectPoint.hasOwnProperty("primitive")) {
//console.log(`showPrimitiveId ${selectPoint.id}`);
//const carto = Cesium.Cartographic.fromCartesian(selectPoint.primitive.position)
.pointLabel.position = selectPoint.primitive.position;
viewer.pointLabel.label.show = true;
viewer//viewer.pointLabel.label.text = `id:${selectPoint.id}, ${carto}`;
.pointLabel.label.text = `${selectPoint.id}`;
viewer.primitive.pixelSize = 20;
selectPoint.primitive.outlineColor = Cesium.Color.YELLOW;
selectPoint.primitive.outlineWidth = 3;
selectPoint.currentSelection = selectPoint;
viewerelse {
} .pointLabel.label.show = false;
viewer
}
}
}
class CView {
constructor(target) {
this.viewer = new Cesium.Viewer(
, {
targettimeline: false,
animation: false,
baseLayerPicker: false,
fullscreenElement: target,
terrain: Cesium.Terrain.fromWorldTerrain()
;
})this.currentSelection = null;
this.point_size = 1;
this.n_points = 0;
// https://cesium.com/learn/cesiumjs/ref-doc/PointPrimitiveCollection.html
this.points = new Cesium.PointPrimitiveCollection();
this.viewer.scene.primitives.add(this.points);
this.pointLabel = this.viewer.entities.add({
label: {
show: false,
showBackground: true,
font: "14px monospace",
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(15, 0),
// this attribute will prevent this entity clipped by the terrain
disableDepthTestDistance: Number.POSITIVE_INFINITY,
text:"",
,
};
})
this.pickHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
// Can also do this rather than wait for the points to be generated
//this.pickHandler.setInputAction(createShowPrimitive(this), Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.selectHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.selectHandler.setInputAction((e) => {
const selectPoint = this.viewer.scene.pick(e.position);
if (Cesium.defined(selectPoint) && selectPoint.hasOwnProperty("primitive")) {
= selectPoint.id;
mutable clickedPointId
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
}
enableTracking() {
this.pickHandler.setInputAction(createShowPrimitive(this), Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
}
= new CView("cesiumContainer");
content
async function getGeoRecord(pid) {
if (pid === null || pid ==="" || pid == "unset") {
return "unset";
}const q = `SELECT row_id, pid, otype, latitude, longitude FROM nodes WHERE otype='GeospatialCoordLocation' AND pid=?`;
const rows = await loadData(q, [pid], "loading_geo", "geo");
return rows && rows.length ? rows[0] : null;
}
async function get_samples_1(pid) {
if (pid === null || pid ==="" || pid == "unset") {
return [];
}const q = `
SELECT DISTINCT
s.pid as sample_id,
s.label as sample_label,
s.name as sample_name,
event.pid as event_id,
event.label as event_label,
'direct_event_location' as location_path
FROM nodes s
JOIN nodes e1 ON s.row_id = e1.s AND e1.p = 'produced_by'
JOIN nodes event ON e1.o[1] = event.row_id
JOIN nodes e2 ON event.row_id = e2.s AND e2.p = 'sample_location'
JOIN nodes g ON e2.o[1] = g.row_id
WHERE s.otype = 'MaterialSampleRecord'
AND event.otype = 'SamplingEvent'
AND g.otype = 'GeospatialCoordLocation'
AND g.pid = ?
`;
const result = await loadData(q, [pid], "loading_s1", "samples_1");
return result ?? [];
}
async function get_samples_2(pid) {
if (pid === null || pid ==="" || pid == "unset") {
return [];
}const q = `
SELECT DISTINCT
s.pid as sample_id,
s.label as sample_label,
s.name as sample_name,
event.pid as event_id,
event.label as event_label,
site.label as site_name,
'via_site_location' as location_path
FROM nodes s
JOIN nodes e1 ON s.row_id = e1.s AND e1.p = 'produced_by'
JOIN nodes event ON e1.o[1] = event.row_id
JOIN nodes e2 ON event.row_id = e2.s AND e2.p = 'sampling_site'
JOIN nodes site ON e2.o[1] = site.row_id
JOIN nodes e3 ON site.row_id = e3.s AND e3.p = 'site_location'
JOIN nodes g ON e3.o[1] = g.row_id
WHERE s.otype = 'MaterialSampleRecord'
AND event.otype = 'SamplingEvent'
AND site.otype = 'SamplingSite'
AND g.otype = 'GeospatialCoordLocation'
AND g.pid = ?
`;
const result = await loadData(q, [pid], "loading_s2", "samples_2");
return result ?? [];
}
async function locationUsedBy(rowid){
if (rowid === undefined || rowid === null) {
return [];
}const q = `select pid, otype from nodes where row_id in (select nodes.s from nodes where list_contains(nodes.o, ?));`;
return db.query(q, [rowid]);
}
= "unset";
mutable clickedPointId // Loading flags to control UI clearing while fetching
= false;
mutable geoLoading = false;
mutable s1Loading = false;
mutable s2Loading
// Precompute selection-driven data with loading flags
= {
selectedGeoRecord = true;
mutable geoLoading try {
return await getGeoRecord(clickedPointId);
finally {
} = false;
mutable geoLoading
}
}
= {
selectedSamples1 = true;
mutable s1Loading try {
return await get_samples_1(clickedPointId);
finally {
} = false;
mutable s1Loading
}
}
= {
selectedSamples2 = true;
mutable s2Loading try {
return await get_samples_2(clickedPointId);
finally {
} = false;
mutable s2Loading
}
}
md`Retrieved ${pointdata.length} locations from ${parquet_path}.`;
Loading…
Code
= {
viewof pointdata const data_table = Inputs.table(locations, {
header: {
row_id:"Row ID",
pid: "PID",
latitude: "Latitude",
longitude: "Longitude"
,
};
})return data_table;
}
The click point ID is “”.
Loading selected location…
1 getGeoRecord (selected)
Code
= clickedPointId
pid = selectedGeoRecord; testrecord