diff --git a/package-lock.json b/package-lock.json index 03db2d0..138bfe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7036,7 +7036,7 @@ }, "packages/deck.gl-layers": { "name": "@geoarrow/deck.gl-layers", - "version": "0.4.0-beta.4", + "version": "0.4.0-beta.5", "license": "MIT", "dependencies": { "@geoarrow/geoarrow-js": "^0.3.0", diff --git a/packages/deck.gl-layers/package.json b/packages/deck.gl-layers/package.json index ec88f98..19c8cf5 100644 --- a/packages/deck.gl-layers/package.json +++ b/packages/deck.gl-layers/package.json @@ -1,6 +1,6 @@ { "name": "@geoarrow/deck.gl-layers", - "version": "0.4.0-beta.5", + "version": "0.4.0-beta.6", "type": "module", "description": "", "source": "src/index.ts", diff --git a/packages/deck.gl-layers/src/index.ts b/packages/deck.gl-layers/src/index.ts index ed25cc3..2ef131f 100644 --- a/packages/deck.gl-layers/src/index.ts +++ b/packages/deck.gl-layers/src/index.ts @@ -11,6 +11,9 @@ export { GeoArrowArcLayer } from "./layers/arc-layer.js"; export type { GeoArrowColumnLayerProps } from "./layers/column-layer.js"; export { GeoArrowColumnLayer } from "./layers/column-layer.js"; +export type { GeoArrowGeohashLayerProps } from "./layers/geohash-layer.js"; +export { GeoArrowGeohashLayer } from "./layers/geohash-layer.js"; + export type { GeoArrowH3HexagonLayerProps } from "./layers/h3-hexagon-layer.js"; export { GeoArrowH3HexagonLayer } from "./layers/h3-hexagon-layer.js"; @@ -26,6 +29,9 @@ export { GeoArrowPointCloudLayer } from "./layers/point-cloud-layer.js"; export type { GeoArrowPolygonLayerProps } from "./layers/polygon-layer.js"; export { GeoArrowPolygonLayer } from "./layers/polygon-layer.js"; +export type { GeoArrowS2LayerProps } from "./layers/s2-layer.js"; +export { GeoArrowS2Layer } from "./layers/s2-layer.js"; + export type { GeoArrowScatterplotLayerProps } from "./layers/scatterplot-layer.js"; export { GeoArrowScatterplotLayer } from "./layers/scatterplot-layer.js"; diff --git a/packages/deck.gl-layers/src/layers/geohash-layer.ts b/packages/deck.gl-layers/src/layers/geohash-layer.ts new file mode 100644 index 0000000..fb1ccdb --- /dev/null +++ b/packages/deck.gl-layers/src/layers/geohash-layer.ts @@ -0,0 +1,157 @@ +import { + CompositeLayer, + CompositeLayerProps, + DefaultProps, + GetPickingInfoParams, + Layer, + LayersList, +} from "@deck.gl/core"; +import type { GeohashLayerProps } from "@deck.gl/geo-layers"; +import { GeohashLayer } from "@deck.gl/geo-layers"; +import * as arrow from "apache-arrow"; + +import { ColorAccessor, FloatAccessor, GeoArrowPickingInfo } from "../types"; +import { assignAccessor, extractAccessorsFromProps } from "../utils/utils"; +import { GeoArrowExtraPickingProps, getPickingInfo } from "../utils/picking"; +import { validateAccessors } from "../utils/validate"; + +/** All properties supported by GeoArrowGeohashLayer */ +export type GeoArrowGeohashLayerProps = Omit< + GeohashLayerProps, + | "data" + | "getGeohash" + | "getFillColor" + | "getLineColor" + | "getLineWidth" + | "getElevation" +> & + _GeoArrowGeohashLayerProps & + // Omit & + CompositeLayerProps; + +/** Props added by the GeoArrowGeohashLayer */ +type _GeoArrowGeohashLayerProps = { + data: arrow.RecordBatch; + + /** + * Called for each data object to retrieve the quadkey string identifier. + */ + getGeohash: arrow.Data; + + /** Fill color accessor. + * @default [0, 0, 0, 255] + */ + getFillColor?: ColorAccessor; + + /** Stroke color accessor. + * @default [0, 0, 0, 255] + */ + getLineColor?: ColorAccessor; + + /** + * Line width value of accessor. + * @default 1 + */ + getLineWidth?: FloatAccessor; + + /** + * Elevation value of accessor. + * + * Only used if `extruded: true`. + * + * @default 1000 + */ + getElevation?: FloatAccessor; + + /** + * If `true`, validate the arrays provided (e.g. chunk lengths) + * @default true + */ + _validate?: boolean; +}; + +// Remove data from the upstream default props +const { + // @ts-expect-error https://github.com/visgl/deck.gl/issues/9854 + data: _data, + getGeohash: _getGeohash, + ..._defaultProps +} = GeohashLayer.defaultProps; + +// Default props added by us +const ourDefaultProps = { + _validate: true, +}; + +// Type errors from https://github.com/visgl/deck.gl/issues/9854 +// // @ts-expect-error getFillColor +const defaultProps: DefaultProps = { + // ..._polygonDefaultProps, + ..._defaultProps, + ...ourDefaultProps, +}; + +export class GeoArrowGeohashLayer< + ExtraProps extends {} = {}, +> extends CompositeLayer { + static defaultProps = defaultProps; + static layerName = "GeoArrowGeohashLayer"; + + getPickingInfo( + params: GetPickingInfoParams & { + sourceLayer: { props: GeoArrowExtraPickingProps }; + }, + ): GeoArrowPickingInfo { + return getPickingInfo(params, this.props.data); + } + + renderLayers(): Layer<{}> | LayersList | null { + return this._renderLayer(); + } + + _renderLayer(): Layer<{}> | LayersList | null { + const { data: batch, getGeohash } = this.props; + + if (this.props._validate) { + validateAccessors(this.props, batch); + } + + // Exclude manually-set accessors + const [accessors, otherProps] = extractAccessorsFromProps(this.props, [ + "getGeohash", + ]); + const GeohashVector = new arrow.Vector([getGeohash]); + + const props: GeohashLayerProps = { + // Note: because this is a composite layer and not doing the rendering + // itself, we still have to pass in our defaultProps + ...ourDefaultProps, + ...otherProps, + + // type errors from https://github.com/visgl/deck.gl/issues/9854 + // @ts-expect-error until above issue fixed. + id: `${this.props.id}-geoarrow-geohash`, + + data: { + // type errors from https://github.com/visgl/deck.gl/issues/9854 + // // @ts-expect-error passed through to enable use by function accessors + data: batch, + length: batch.numRows, + }, + // We must load back to pure JS strings / bigint + getGeohash: (_, objectInfo) => { + return GeohashVector.get(objectInfo.index)!; + }, + }; + + for (const [propName, propInput] of Object.entries(accessors)) { + assignAccessor({ + props, + propName, + propInput, + }); + } + + return new GeohashLayer(this.getSubLayerProps(props)); + } +} diff --git a/packages/deck.gl-layers/src/layers/s2-layer.ts b/packages/deck.gl-layers/src/layers/s2-layer.ts new file mode 100644 index 0000000..5f93264 --- /dev/null +++ b/packages/deck.gl-layers/src/layers/s2-layer.ts @@ -0,0 +1,157 @@ +import { + CompositeLayer, + CompositeLayerProps, + DefaultProps, + GetPickingInfoParams, + Layer, + LayersList, +} from "@deck.gl/core"; +import type { S2LayerProps } from "@deck.gl/geo-layers"; +import { S2Layer } from "@deck.gl/geo-layers"; +import * as arrow from "apache-arrow"; + +import { ColorAccessor, FloatAccessor, GeoArrowPickingInfo } from "../types"; +import { assignAccessor, extractAccessorsFromProps } from "../utils/utils"; +import { GeoArrowExtraPickingProps, getPickingInfo } from "../utils/picking"; +import { validateAccessors } from "../utils/validate"; + +/** All properties supported by GeoArrowS2Layer */ +export type GeoArrowS2LayerProps = Omit< + S2LayerProps, + | "data" + | "getS2Token" + | "getFillColor" + | "getLineColor" + | "getLineWidth" + | "getElevation" +> & + _GeoArrowS2LayerProps & + // Omit & + CompositeLayerProps; + +/** Props added by the GeoArrowS2Layer */ +type _GeoArrowS2LayerProps = { + data: arrow.RecordBatch; + + /** + * Called for each data object to retrieve the quadkey string identifier. + */ + getS2Token: arrow.Data; + + /** Fill color accessor. + * @default [0, 0, 0, 255] + */ + getFillColor?: ColorAccessor; + + /** Stroke color accessor. + * @default [0, 0, 0, 255] + */ + getLineColor?: ColorAccessor; + + /** + * Line width value of accessor. + * @default 1 + */ + getLineWidth?: FloatAccessor; + + /** + * Elevation value of accessor. + * + * Only used if `extruded: true`. + * + * @default 1000 + */ + getElevation?: FloatAccessor; + + /** + * If `true`, validate the arrays provided (e.g. chunk lengths) + * @default true + */ + _validate?: boolean; +}; + +// Remove data from the upstream default props +const { + data: _data, + getS2Token: _getPentagon, + ..._defaultProps +} = S2Layer.defaultProps; + +// Default props added by us +const ourDefaultProps = { + _validate: true, +}; + +// @ts-expect-error getFillColor +const defaultProps: DefaultProps = { + // ..._polygonDefaultProps, + ..._defaultProps, + ...ourDefaultProps, +}; + +export class GeoArrowS2Layer extends CompositeLayer< + GeoArrowS2LayerProps & ExtraProps +> { + static defaultProps = defaultProps; + static layerName = "GeoArrowS2Layer"; + + getPickingInfo( + params: GetPickingInfoParams & { + sourceLayer: { props: GeoArrowExtraPickingProps }; + }, + ): GeoArrowPickingInfo { + return getPickingInfo(params, this.props.data); + } + + renderLayers(): Layer<{}> | LayersList | null { + return this._renderLayer(); + } + + _renderLayer(): Layer<{}> | LayersList | null { + const { data: batch, getS2Token } = this.props; + + if (this.props._validate) { + validateAccessors(this.props, batch); + } + + // Exclude manually-set accessors + const [accessors, otherProps] = extractAccessorsFromProps(this.props, [ + "getS2Token", + ]); + const s2Vector = new arrow.Vector([getS2Token]); + + const props: S2LayerProps = { + // Note: because this is a composite layer and not doing the rendering + // itself, we still have to pass in our defaultProps + ...ourDefaultProps, + ...otherProps, + + id: `${this.props.id}-geoarrow-S2`, + + data: { + // @ts-expect-error passed through to enable use by function accessors + data: batch, + length: batch.numRows, + }, + // We must load back to pure JS strings / bigint + getS2Token: (_, objectInfo) => { + const value = s2Vector.get(objectInfo.index)!; + if (typeof value === "string") { + return value; + } else { + return value.toString(16); + } + }, + }; + + for (const [propName, propInput] of Object.entries(accessors)) { + assignAccessor({ + props, + propName, + propInput, + }); + } + + return new S2Layer(this.getSubLayerProps(props)); + } +}