Public
Edited
Sep 8, 2023
Insert cell
Insert cell
Insert cell
mapContainer = html`<div style="height:500px"></div>`
Insert cell
countries = FileAttachment("countries.fgb")
Insert cell
Insert cell
wasmTable = flatgeobuf.readFlatGeobuf(
new Uint8Array(await countries.arrayBuffer())
)
Insert cell
Insert cell
table = {
const jsRecordBatches = [];
for (let i = 0; i < wasmTable.numBatches; ++i) {
const wasmRecordBatch = wasmTable.recordBatch(0).intoFFI();
const jsRecordBatch = arrowJsFfi.parseRecordBatch(
wasmMemory.buffer,
wasmRecordBatch.arrayAddr(),
wasmRecordBatch.schemaAddr(),
true
);
jsRecordBatches.push(jsRecordBatch);
wasmRecordBatch.free();
}

return new apacheArrow.Table(jsRecordBatches);
}
Insert cell
{
const recordBatch = table.batches[0];
const geometryColumnIdx = 2;

const geometryColumn = recordBatch.getChildAt(geometryColumnIdx);
const geometryOffsets = geometryColumn.data[0].valueOffsets;
const polygonOffsets = geometryColumn.getChildAt(0).data[0].valueOffsets;
const ringOffsets = geometryColumn.getChildAt(0).getChildAt(0)
.data[0].valueOffsets;
const flatCoordinateArray = geometryColumn
.getChildAt(0)
.getChildAt(0)
.getChildAt(0)
.getChildAt(0).data[0].values;

const resolvedPolygonOffsets = new Int32Array(polygonOffsets.length);
for (let i = 0; i < resolvedPolygonOffsets.length; ++i) {
// Perform the lookup into the ringOffsets array using the polygonOffsets array
resolvedPolygonOffsets[i] = ringOffsets[polygonOffsets[i]];
}

// This is a total hack to show anything interesting.
// Change color according to vertex index :joy:
const fillColors = new Float32Array(flatCoordinateArray.length * 4);
for (let i = 0; i < flatCoordinateArray.length; ++i) {
fillColors[i * 4] = 0;
fillColors[i * 4 + 1] = i / flatCoordinateArray.length;
fillColors[i * 4 + 2] = i / flatCoordinateArray.length;
fillColors[i * 4 + 3] = 100 / 255;
}

console.log(polygonOffsets.length);
const data = {
// Number of geometries (here exploding multi polygons)
length: polygonOffsets.length,
// Indices into coordinateArray where each polygon starts
startIndices: resolvedPolygonOffsets,
// Flat coordinates array
attributes: {
getPolygon: { value: flatCoordinateArray, size: 2 },
getFillColor: { value: fillColors, size: 4 }
}
};

const layer = new deck.SolidPolygonLayer({
// This is an Observable hack - changing the id will force the layer to refresh when the cell reevaluates
id: `layer-${Date.now()}`,
data,
// Skip normalization for binary data
_normalize: false,
// Counter-clockwise winding order
_windingOrder: "CCW",
// getFillColor: [0, 100, 60, 100],
getLineColor: [0, 0, 0, 255]
});

deckglMap.setProps({ layers: [layer] });
}
Insert cell
deckglMap = {
// This is an Observable hack: clear previously generated content
mapContainer.innerHTML = "";

return new deck.DeckGL({
// The HTML container to render into
container: mapContainer,
map: mapboxgl,
mapStyle:
"https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json",

// Viewport settings
initialViewState: {
longitude: 0,
latitude: 0,
zoom: 1,
pitch: 0,
bearing: 0
},
controller: true
});
}
Insert cell
// Load the @geoarrow/flatgeobuf-wasm library
flatgeobuf = {
const flatgeobufModule = await import(
"https://unpkg.com/@geoarrow/flatgeobuf-wasm@0.1.0/esm/index.js"
);
// Need to await the default export first to initialize the WebAssembly code
await flatgeobufModule.default();
return flatgeobufModule;
}
Insert cell
deck = require.alias({
h3: {}
})("deck.gl@8.9.27/dist.min.js")
Insert cell
wasmMemory = flatgeobuf._memory()
Insert cell
mapboxgl = require("mapbox-gl@1.6.0/dist/mapbox-gl.js")
Insert cell
apacheArrow = require("apache-arrow@12")
Insert cell
arrowJsFfi = require.alias({
"apache-arrow": apacheArrow
})("arrow-js-ffi@0.3.0")
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