Fun changes
Some checks failed
CI / Python (lint + test) (push) Failing after 3m38s
CI / Rust (lint + test) (push) Failing after 3m32s
CI / Frontend (lint + typecheck) (push) Failing after 4m12s
Build and publish Docker image / build-and-push (push) Failing after 4m48s

This commit is contained in:
Andras Schmelczer 2026-04-04 22:59:44 +01:00
parent cd778dd088
commit 349a6c1d53
60 changed files with 1260 additions and 2600 deletions

View file

@ -4,30 +4,43 @@ import { ENUM_PALETTE } from './consts';
/**
* LayerExtension that turns polygon fills into pie charts.
* Injects a fragment shader that computes angle from each fragment's position
* to the polygon centroid, then picks a slice color from the enum palette.
*
* Works with H3HexagonLayer (hex fills) and GeoJsonLayer (postcode fills).
* Only activates on SolidPolygonLayer sublayers (fill), not PathLayer (stroke).
* Follows the canonical deck.gl v9 extension pattern:
* - defaultProps with type:'accessor' enables getSubLayerProps() to wrap
* accessors via getSubLayerAccessor(), which unwraps __source.object to
* access the original data item through CompositeLayer sublayer chains.
* - stepMode:'dynamic' handles per-instance counting automatically.
* - isEnabled() restricts to SolidPolygonLayer (fill) sublayers only.
*
* Required layer props when this extension is active:
* getCenter: (d) => [lon, lat] polygon centroid in world coordinates
* getRatios0: (d) => number[4] pie ratios for slices 0-3
* getRatios1: (d) => number[4] pie ratios for slices 4-7
* getRatios2: (d) => number[2] pie ratios for slices 8-9
* Accepts an optional custom palette in the constructor for per-feature color overrides.
*/
// Build palette as GLSL vec3 constants (normalized 0-1)
const PALETTE_GLSL = ENUM_PALETTE.map(
(c) =>
`vec3(${(c[0] / 255).toFixed(4)}, ${(c[1] / 255).toFixed(4)}, ${(c[2] / 255).toFixed(4)})`
).join(',\n ');
function paletteToGlsl(palette: [number, number, number][]): string {
return palette
.map(
(c) =>
`vec3(${(c[0] / 255).toFixed(4)}, ${(c[1] / 255).toFixed(4)}, ${(c[2] / 255).toFixed(4)})`
)
.join(',\n ');
}
export class PieHexExtension extends LayerExtension {
static extensionName = 'PieHexExtension';
static defaultProps = {
getCenter: { type: 'accessor', value: [0, 0] },
getRatios0: { type: 'accessor', value: [1, 0, 0, 0] },
getRatios1: { type: 'accessor', value: [0, 0, 0, 0] },
getRatios2: { type: 'accessor', value: [0, 0] },
};
private paletteGlsl: string;
constructor(palette?: [number, number, number][]) {
super();
this.paletteGlsl = paletteToGlsl(palette ?? ENUM_PALETTE);
}
isEnabled(layer: any): boolean {
// Only apply to fill sublayers (SolidPolygonLayer), not stroke (PathLayer)
return layer.id.endsWith('-fill');
}
@ -61,7 +74,7 @@ in vec4 vRatios0;
in vec4 vRatios1;
in vec2 vRatios2;
const vec3 pieColors[10] = vec3[10](
${PALETTE_GLSL}
${this.paletteGlsl}
);`,
'fs:DECKGL_FILTER_COLOR': `\
{
@ -98,25 +111,25 @@ const vec3 pieColors[10] = vec3[10](
if (!extension.isEnabled(this)) return;
const am = this.getAttributeManager();
if (!am) return;
am.addInstanced({
am.add({
instancePieCenter: {
size: 2,
type: 'float32',
stepMode: 'dynamic',
accessor: 'getCenter',
},
instanceRatios0: {
size: 4,
type: 'float32',
stepMode: 'dynamic',
accessor: 'getRatios0',
},
instanceRatios1: {
size: 4,
type: 'float32',
stepMode: 'dynamic',
accessor: 'getRatios1',
},
instanceRatios2: {
size: 2,
type: 'float32',
stepMode: 'dynamic',
accessor: 'getRatios2',
},
});