Some visualizations animate, pulse, and flash. If you're sensitive to motion or flashing, turn on Reduce motion in your system settings.

poopdeck.gl
deck.gl Layers

QuadbinSummaryLayer

The QuadbinSummaryLayer renders the server-aggregated summary tier of an STT archive as CARTO Quadbin square cells — the Z/X/Y square-grid counterpart of H3SummaryLayer. The summary tier (built with stt-build --summary-tier quadbin) collapses raw features into one row per Quadbin cell — count plus per-column aggregates — indexed by (zoom, x, y, time-bucket) just like the raw tier. At low zooms it renders a dense point dataset as a few thousand cells instead of millions of features.

It extends SpatioTemporalLayer and reuses all of its archive/tileset plumbing, clamping to the summary tier's zoom band. Each cell renders through deck.gl's QuadkeyLayer (@deck.gl/geo-layers): the layer reads the cell id from BinaryFeatures.featureIds64, decodes the CARTO Quadbin u64 to a Bing quadkey string, and hands it to getQuadkey. Summary cells are pre-aggregated per time bucket at build time, so — like H3SummaryLayer — no per-feature TimeFilterExtension is attached.

Installation#

import { QuadbinSummaryLayer } from '@poopdeck.gl/layers';

Usage#

const layer = new QuadbinSummaryLayer({
id: 'trip-density',
data: '/data/nyc-od-quadbin/manifest.json',
currentTime,
timeWindow: 3600 * 1000,
weightProperty: 'count',
colorDomain: [1, 60], // pin the legend (recommended)
extruded: true,
elevationScale: 120,
});

Pair it with a raw-tier layer for a zoom-dependent stack, or simply use any animated layer with tier: 'auto' (the base default) — the tileset dispatches to the summary tier inside its zoom band and back to the raw tier above it, and has no effect at all on an archive with no summary tier.

Cell encoding#

The Quadbin cell id is a CARTO Quadbin u64 (header 0b100, mode bit, 5-bit zoom at bits 56–52, 52-bit left-aligned Morton x/y). ⚠️ Because the header and zoom bits live in the high half, BinaryFeatures.featureIds — a masked low 32 bits — is meaningless for every Quadbin id; featureIds64 is the only correct source, which is what this layer reads. The Rust aggregator (stt-build) encodes it and the TS quadbin-cell helper decodes it to (z, x, y) → Bing quadkey string. The encode/decode are exact mirror-images, validated against CARTO's reference value (0,0,0) → 0x480fffffffffffff.

Time inside a tile (sub-buckets)#

Identical to the H3 tier in every respect except the flag spelling — build with --summary-tier quadbin --summary-sub-buckets N and see Time inside a tile for what N bakes, how the active bucket_<k> column is selected, and what it costs.

Properties#

Inherits all properties from SpatioTemporalLayer. One base default changes: maxCacheSize is 500 (summary tiles are few but row-heavy).

PropertyTypeDefaultDescription
weightPropertystring'count'Numeric column the color ramp + extrusion height are driven by. On a sub-bucketed archive the default 'count' is replaced per frame by the active bucket_<k> column — see Time inside a tile.
colorRangeColor[]6-stopLow→high color ramp; weightProperty is quantised into its buckets.
colorDomain[number, number] | nullnull[min, max] for the ramp. Pin it for a stable legend across streaming tiles (recommended).
extrudedbooleanfalse3D extrusion.
elevationScalenumber1Meters per weight unit (only when extruded).
coveragenumber0.92Cell coverage (0..1); lower values leave gaps between cells.
onMetadataLoad(meta: ArchiveMetadata) => voidnullFired once per archive init with the decoded metadata.

Stroke & material#

Pass-throughs to deck.gl's QuadkeyLayer (→ GeoCellLayerPolygonLayer). They surface the cell outline — the underlying PolygonLayer defaults stroked: true, giving every cell an un-disable-able 1px black border, so set stroked: false for a clean heatmap-style fill — plus the extrusion lighting material. getLineColor / getLineWidth are upstream-vocabulary aliases: unlike upstream deck.gl they accept a constant value only (summary cells bake no per-cell stroke column — a function accessor or column-name string warns once and falls back to lineColor / lineWidth); when set they win over the legacy prop.

PropertyTypeDefaultDescription
filledbooleantrueFill each cell. When false, cells render outline-only (pair with stroked).
strokedbooleantrueDraw each cell's outline. Set false for a borderless heatmap-style fill.
lineColorColor[0, 0, 0, 255]Cell outline color (constant). Only takes effect when stroked.
getLineColorColor | nullnullUpstream-vocabulary alias of lineColor (constant Color only). Wins over lineColor when set.
lineWidthnumber1Cell outline width, in lineWidthUnits. Only takes effect when stroked.
getLineWidthnumber | nullnullUpstream-vocabulary alias of lineWidth (constant number only). Wins over lineWidth when set.
lineWidthUnits'meters' | 'common' | 'pixels''meters'Units for lineWidth.
lineWidthScalenumber1Multiplier applied to every outline width.
lineWidthMinPixelsnumber0Minimum outline width in pixels — clamps the outline so 1m borders stay visible at planet-scale summary zooms.
lineWidthMaxPixelsnumberNumber.MAX_SAFE_INTEGERMaximum outline width in pixels.
lineJointRoundedbooleanfalseRound the joints between outline segments.
lineMiterLimitnumber4Miter limit for mitered outline joints.
lineDashJustifiedbooleanfalseJustify dashes to segment endpoints (only meaningful with a dash array supplied via the PathStyle extension).
wireframebooleanfalseDraw the edges of extruded cells as a wireframe. Only takes effect when extruded.
materialMaterial | booleantrueLighting material for extruded cells. true for the default phong material, false to disable lighting, or a material spec {ambient, diffuse, shininess, specularColor}. Only takes effect when extruded.

Behavior notes#

  • No tier, no render: archives without a Quadbin summary tier render nothing; the layer warns once ("rebuild with stt-build --summary-tier quadbin").
  • Zoom band: clamps tile zoom to the summary tier's [minZoom, maxZoom] with 'no-overlap' refinement, identical to H3SummaryLayer.
  • Picking: hits arrive with info.object swapped for the cell's FULL aggregated columns plus cell / quadkey (the Bing quadkey string) and weight; the u64 id is decimal-stringified so JSON.stringify on it doesn't throw. info.tile / info.sourceTile carry the source tile.
  • deck.gl 9.x ships no Quadbin-native layer, so QuadkeyLayer + the u64→quadkey decode is the path; a future deck/@deck.gl/carto upgrade could swap it without touching the renderer.
  • The sublayer short id for _subLayerProps overrides is quadbins.

Source#

packages/layers/src/layers/summary/quadbin-summary-layer.ts · cell helper: quadbin-cell.ts