Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@
"peerDependencies": {
"@deck.gl/aggregation-layers": "^8.9.23",
"@deck.gl/core": "^8.9.23",
"@deck.gl/geo-layers": "^8.9.23",
"@deck.gl/layers": "^8.9.23",
"@math.gl/polygon": "^3.6.2",
"apache-arrow": "^13.0.0"
},
"devDependencies": {
"@deck.gl/aggregation-layers": "^8.9.23",
"@deck.gl/core": "^8.9.23",
"@deck.gl/geo-layers": "^8.9.23",
"@deck.gl/layers": "^8.9.23",
"@math.gl/polygon": "^3.6.2",
"@rollup/plugin-terser": "^0.4.3",
Expand Down
4 changes: 3 additions & 1 deletion src/arc-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export type GeoArrowArcLayerProps = Omit<

/** Properties added by GeoArrowArcLayer */
type _GeoArrowArcLayerProps = {
data?: arrow.Table;
data: arrow.Table;

/**
* Method called to retrieve the source position of each object.
Expand Down Expand Up @@ -139,6 +139,8 @@ export class GeoArrowArcLayer<
}
}

// Note: below we iterate over table batches anyways, so this layer won't
// work as-is if data/table is null
validatePointType(sourcePosition.type);
validatePointType(targetPosition.type);
if (table) {
Expand Down
234 changes: 234 additions & 0 deletions src/column-layer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import {
CompositeLayer,
CompositeLayerProps,
DefaultProps,
GetPickingInfoParams,
Layer,
LayersList,
} from "@deck.gl/core/typed";
import { ColumnLayer } from "@deck.gl/layers/typed";
import type { ColumnLayerProps } from "@deck.gl/layers/typed";
import * as arrow from "apache-arrow";
import {
assignAccessor,
getGeometryVector,
getPointChild,
isPointVector,
validateColorVector,
validatePointType,
validateVectorAccessors,
} from "./utils.js";
import {
ColorAccessor,
FloatAccessor,
GeoArrowPickingInfo,
PointVector,
} from "./types.js";
import { EXTENSION_NAME } from "./constants.js";
import { getPickingInfo } from "./picking.js";

/** All properties supported by GeoArrowColumnLayer */
export type GeoArrowColumnLayerProps = Omit<
ColumnLayerProps<arrow.Table>,
| "data"
| "getPosition"
| "getFillColor"
| "getLineColor"
| "getElevation"
| "getLineWidth"
> &
_GeoArrowColumnLayerProps &
CompositeLayerProps;

/** Properties added by GeoArrowColumnLayer */
type _GeoArrowColumnLayerProps = {
data: arrow.Table;

/**
* Method called to retrieve the position of each column.
* @default object => object.position
*/
getPosition?: PointVector;

/**
* Fill color value or accessor.
* @default [0, 0, 0, 255]
*/
getFillColor?: ColorAccessor;

/**
* Line color value or accessor.
*
* @default [0, 0, 0, 255]
*/
getLineColor?: ColorAccessor;

/**
* The elevation of each cell in meters.
* @default 1000
*/
getElevation?: FloatAccessor;

/**
* The width of the outline of the column, in units specified by `lineWidthUnits`.
*
* @default 1
*/
getLineWidth?: FloatAccessor;

/**
* If `true`, validate the arrays provided (e.g. chunk lengths)
* @default true
*/
_validate?: boolean;
};

// Remove data and getPosition from the upstream default props
const {
data: _data,
getPosition: _getPosition,
..._defaultProps
} = ColumnLayer.defaultProps;

const defaultProps: DefaultProps<GeoArrowColumnLayerProps> = {
..._defaultProps,
_validate: true,
};

/**
* Render extruded cylinders (tessellated regular polygons) at given
* coordinates.
*/
export class GeoArrowColumnLayer<
ExtraProps extends {} = {}
> extends CompositeLayer<Required<GeoArrowColumnLayerProps> & ExtraProps> {
static defaultProps = defaultProps;
static layerName = "GeoArrowColumnLayer";

getPickingInfo(params: GetPickingInfoParams): GeoArrowPickingInfo {
return getPickingInfo(params, this.props.data);
}

renderLayers(): Layer<{}> | LayersList | null {
const { data: table } = this.props;

const pointVector = getGeometryVector(table, EXTENSION_NAME.POINT);
if (pointVector !== null) {
return this._renderLayersPoint(pointVector);
}

const geometryColumn = this.props.getPosition;
if (isPointVector(geometryColumn)) {
return this._renderLayersPoint(geometryColumn);
}

throw new Error("geometryColumn not point");
}

_renderLayersPoint(
geometryColumn: PointVector
): Layer<{}> | LayersList | null {
const { data: table } = this.props;

if (this.props._validate) {
const vectorAccessors: arrow.Vector[] = [geometryColumn];
for (const accessor of [
this.props.getFillColor,
this.props.getLineColor,
this.props.getLineWidth,
this.props.getElevation,
]) {
if (accessor instanceof arrow.Vector) {
vectorAccessors.push(accessor);
}
}

validatePointType(geometryColumn.type);
validateVectorAccessors(table, vectorAccessors);

if (this.props.getFillColor instanceof arrow.Vector) {
validateColorVector(this.props.getFillColor);
}
if (this.props.getLineColor instanceof arrow.Vector) {
validateColorVector(this.props.getLineColor);
}
}

const layers: ColumnLayer[] = [];
for (
let recordBatchIdx = 0;
recordBatchIdx < table.batches.length;
recordBatchIdx++
) {
const geometryData = geometryColumn.data[recordBatchIdx];
const flatCoordsData = getPointChild(geometryData);
const flatCoordinateArray = flatCoordsData.values;

const props: ColumnLayerProps = {
// @ts-expect-error used for picking purposes
recordBatchIdx,

id: `${this.props.id}-geoarrow-column-${recordBatchIdx}`,

diskResolution: this.props.diskResolution,
radius: this.props.radius,
angle: this.props.angle,
vertices: this.props.vertices,
offset: this.props.offset,
coverage: this.props.coverage,
elevationScale: this.props.elevationScale,
filled: this.props.filled,
stroked: this.props.stroked,
extruded: this.props.extruded,
wireframe: this.props.wireframe,
flatShading: this.props.flatShading,
radiusUnits: this.props.radiusUnits,
lineWidthUnits: this.props.lineWidthUnits,
lineWidthScale: this.props.lineWidthScale,
lineWidthMinPixels: this.props.lineWidthMinPixels,
lineWidthMaxPixels: this.props.lineWidthMaxPixels,
material: this.props.material,

data: {
length: geometryData.length,
attributes: {
getPosition: {
value: flatCoordinateArray,
size: geometryData.type.listSize,
},
},
},
};

assignAccessor({
props,
propName: "getFillColor",
propInput: this.props.getFillColor,
chunkIdx: recordBatchIdx,
});
assignAccessor({
props,
propName: "getLineColor",
propInput: this.props.getLineColor,
chunkIdx: recordBatchIdx,
});
assignAccessor({
props,
propName: "getElevation",
propInput: this.props.getElevation,
chunkIdx: recordBatchIdx,
});
assignAccessor({
props,
propName: "getLineWidth",
propInput: this.props.getLineWidth,
chunkIdx: recordBatchIdx,
});

const layer = new ColumnLayer(this.getSubLayerProps(props));
layers.push(layer);
}

return layers;
}
}
Loading