Priority: 4
Context
The Cesium 3D globe currently renders 6.7M+ individual PointPrimitives. This works but loads everything at once. H3 enables zoom-adaptive level-of-detail (LOD) rendering.
Data Files on R2
| File |
URL |
Size |
| Wide + H3 |
https://pub-a18234d962364c22a50c787b7ca09fa5.r2.dev/isamples_202601_wide_h3.parquet |
292 MB |
| Facet cross-tab |
https://pub-a18234d962364c22a50c787b7ca09fa5.r2.dev/isamples_202601_facet_cross.parquet |
1 KB |
H3 columns: h3_res4 (BIGINT), h3_res6 (BIGINT), h3_res8 (BIGINT). Pre-computed as integers — no H3 extension needed for grouping/filtering.
File to Modify
tutorials/parquet_cesium_isamples_wide.qmd
Current Behavior
Renders all points at once using Cesium PointPrimitiveCollection:
- Loads data in chunks (25K points per batch)
- Color-coded by source (SESAR=blue, OpenContext=green, GEOME=orange, Smithsonian=purple)
- Works but initial load is heavy
Desired Changes
1. Switch to H3 file
Update parquet URL:
const wide_url = "https://pub-a18234d962364c22a50c787b7ca09fa5.r2.dev/isamples_202601_wide_h3.parquet";
2. Add zoom-adaptive LOD
Query different H3 resolutions based on camera height:
// Determine H3 resolution from zoom level
function getH3ResForHeight(height) {
if (height > 5000000) return 4; // Continental view
if (height > 500000) return 6; // Regional view
return 8; // Local view
}
// On camera move, re-query with appropriate resolution
viewer.camera.changed.addEventListener(async () => {
const height = viewer.camera.positionCartographic.height;
const h3Res = getH3ResForHeight(height);
const clusters = await db.query(`
SELECT
h3_res${h3Res} as hex_id,
COUNT(*) as n,
AVG(latitude) as lat,
AVG(longitude) as lon,
MODE(n) as dominant_source
FROM read_parquet('${wide_url}')
WHERE otype = 'MaterialSampleRecord' AND h3_res${h3Res} IS NOT NULL
GROUP BY h3_res${h3Res}
`);
// Render as sized/colored points
// Point radius proportional to log(count)
// Color by dominant source
});
3. Keep original point rendering as toggle
Add a UI toggle: "Clustered view" (H3 LOD, default) vs "All points" (existing behavior). This lets users see both approaches.
4. Show cluster count in tooltip
When hovering over an H3 cluster point, show: count, dominant source, H3 cell ID.
Important Notes
- The h3_res4/6/8 columns are pre-computed BIGINT values — you do NOT need the H3 DuckDB extension for filtering/grouping
- You only need the H3 extension if you want to convert cell IDs back to boundaries (for rendering hex outlines)
- For point-based cluster rendering, just use AVG(lat), AVG(lon) per cell — no extension needed
- DuckDB-WASM may not support the H3 community extension — design for graceful fallback
Acceptance Criteria
Priority: 4
Context
The Cesium 3D globe currently renders 6.7M+ individual PointPrimitives. This works but loads everything at once. H3 enables zoom-adaptive level-of-detail (LOD) rendering.
Data Files on R2
https://pub-a18234d962364c22a50c787b7ca09fa5.r2.dev/isamples_202601_wide_h3.parquethttps://pub-a18234d962364c22a50c787b7ca09fa5.r2.dev/isamples_202601_facet_cross.parquetH3 columns:
h3_res4(BIGINT),h3_res6(BIGINT),h3_res8(BIGINT). Pre-computed as integers — no H3 extension needed for grouping/filtering.File to Modify
tutorials/parquet_cesium_isamples_wide.qmdCurrent Behavior
Renders all points at once using Cesium PointPrimitiveCollection:
Desired Changes
1. Switch to H3 file
Update parquet URL:
2. Add zoom-adaptive LOD
Query different H3 resolutions based on camera height:
3. Keep original point rendering as toggle
Add a UI toggle: "Clustered view" (H3 LOD, default) vs "All points" (existing behavior). This lets users see both approaches.
4. Show cluster count in tooltip
When hovering over an H3 cluster point, show: count, dominant source, H3 cell ID.
Important Notes
Acceptance Criteria