Giter Club home page Giter Club logo

Comments (1)

kylebarron avatar kylebarron commented on June 18, 2024 1

The steps required for a new layer type are:

  1. Add JavaScript support for the layer type to https://github.com/geoarrow/deck.gl-layers, ensuring that you're using deck.gl's support for binary attributes. For an example you can see the PR for the GeoArrowTextLayer.
  2. Add a new layer model in the JavaScript bindings of lonboard to sync layer state from Python and pass it into @geoarrow/deck.gl-layers. E.g.

    lonboard/src/model/layer.ts

    Lines 576 to 662 in cc40061

    export class ScatterplotModel extends BaseArrowLayerModel {
    static layerType = "scatterplot";
    protected radiusUnits: GeoArrowScatterplotLayerProps["radiusUnits"] | null;
    protected radiusScale: GeoArrowScatterplotLayerProps["radiusScale"] | null;
    protected radiusMinPixels:
    | GeoArrowScatterplotLayerProps["radiusMinPixels"]
    | null;
    protected radiusMaxPixels:
    | GeoArrowScatterplotLayerProps["radiusMaxPixels"]
    | null;
    protected lineWidthUnits:
    | GeoArrowScatterplotLayerProps["lineWidthUnits"]
    | null;
    protected lineWidthScale:
    | GeoArrowScatterplotLayerProps["lineWidthScale"]
    | null;
    protected lineWidthMinPixels:
    | GeoArrowScatterplotLayerProps["lineWidthMinPixels"]
    | null;
    protected lineWidthMaxPixels:
    | GeoArrowScatterplotLayerProps["lineWidthMaxPixels"]
    | null;
    protected stroked: GeoArrowScatterplotLayerProps["stroked"] | null;
    protected filled: GeoArrowScatterplotLayerProps["filled"] | null;
    protected billboard: GeoArrowScatterplotLayerProps["billboard"] | null;
    protected antialiasing: GeoArrowScatterplotLayerProps["antialiasing"] | null;
    protected getRadius: GeoArrowScatterplotLayerProps["getRadius"] | null;
    protected getFillColor: GeoArrowScatterplotLayerProps["getFillColor"] | null;
    protected getLineColor: GeoArrowScatterplotLayerProps["getLineColor"] | null;
    protected getLineWidth: GeoArrowScatterplotLayerProps["getLineWidth"] | null;
    constructor(model: WidgetModel, updateStateCallback: () => void) {
    super(model, updateStateCallback);
    this.initRegularAttribute("radius_units", "radiusUnits");
    this.initRegularAttribute("radius_scale", "radiusScale");
    this.initRegularAttribute("radius_min_pixels", "radiusMinPixels");
    this.initRegularAttribute("radius_max_pixels", "radiusMaxPixels");
    this.initRegularAttribute("line_width_units", "lineWidthUnits");
    this.initRegularAttribute("line_width_scale", "lineWidthScale");
    this.initRegularAttribute("line_width_min_pixels", "lineWidthMinPixels");
    this.initRegularAttribute("line_width_max_pixels", "lineWidthMaxPixels");
    this.initRegularAttribute("stroked", "stroked");
    this.initRegularAttribute("filled", "filled");
    this.initRegularAttribute("billboard", "billboard");
    this.initRegularAttribute("antialiasing", "antialiasing");
    this.initVectorizedAccessor("get_radius", "getRadius");
    this.initVectorizedAccessor("get_fill_color", "getFillColor");
    this.initVectorizedAccessor("get_line_color", "getLineColor");
    this.initVectorizedAccessor("get_line_width", "getLineWidth");
    }
    layerProps(): Omit<GeoArrowScatterplotLayerProps, "id"> {
    return {
    data: this.table,
    ...(this.radiusUnits && { radiusUnits: this.radiusUnits }),
    ...(this.radiusScale && { radiusScale: this.radiusScale }),
    ...(this.radiusMinPixels && { radiusMinPixels: this.radiusMinPixels }),
    ...(this.radiusMaxPixels && { radiusMaxPixels: this.radiusMaxPixels }),
    ...(this.lineWidthUnits && { lineWidthUnits: this.lineWidthUnits }),
    ...(this.lineWidthScale && { lineWidthScale: this.lineWidthScale }),
    ...(this.lineWidthMinPixels && {
    lineWidthMinPixels: this.lineWidthMinPixels,
    }),
    ...(this.lineWidthMaxPixels && {
    lineWidthMaxPixels: this.lineWidthMaxPixels,
    }),
    ...(this.stroked && { stroked: this.stroked }),
    ...(this.filled && { filled: this.filled }),
    ...(this.billboard && { billboard: this.billboard }),
    ...(this.antialiasing && { antialiasing: this.antialiasing }),
    ...(this.getRadius && { getRadius: this.getRadius }),
    ...(this.getFillColor && { getFillColor: this.getFillColor }),
    ...(this.getLineColor && { getLineColor: this.getLineColor }),
    ...(this.getLineWidth && { getLineWidth: this.getLineWidth }),
    };
    }
    render(): GeoArrowScatterplotLayer {
    return new GeoArrowScatterplotLayer({
    ...this.baseLayerProps(),
    ...this.layerProps(),
    });
    }
    }
  3. Add a new Python class in the Python part of lonboard to pass data from Python into JavaScript. E.g.

    lonboard/lonboard/_layer.py

    Lines 409 to 599 in cc40061

    class ScatterplotLayer(BaseArrowLayer):
    """The `ScatterplotLayer` renders circles at given coordinates.
    **Example:**
    ```py
    import geopandas as gpd
    from lonboard import Map, ScatterplotLayer
    # A GeoDataFrame with Point geometries
    gdf = gpd.GeoDataFrame()
    layer = ScatterplotLayer.from_geopandas(
    gdf,
    get_fill_color=[255, 0, 0],
    )
    m = Map(layers=[layer])
    ```
    """
    _layer_type = traitlets.Unicode("scatterplot").tag(sync=True)
    table = PyarrowTableTrait(
    allowed_geometry_types={EXTENSION_NAME.POINT, EXTENSION_NAME.MULTIPOINT}
    )
    radius_units = traitlets.Unicode("meters", allow_none=True).tag(sync=True)
    """
    The units of the radius, one of `'meters'`, `'common'`, and `'pixels'`. See [unit
    system](https://deck.gl/docs/developer-guide/coordinate-systems#supported-units).
    - Type: `str`, optional
    - Default: `'meters'`
    """
    radius_scale = traitlets.Float(allow_none=True, min=0).tag(sync=True)
    """
    A global radius multiplier for all points.
    - Type: `float`, optional
    - Default: `1`
    """
    radius_min_pixels = traitlets.Float(allow_none=True, min=0).tag(sync=True)
    """
    The minimum radius in pixels. This can be used to prevent the circle from getting
    too small when zoomed out.
    - Type: `float`, optional
    - Default: `0`
    """
    radius_max_pixels = traitlets.Float(allow_none=True, min=0).tag(sync=True)
    """
    The maximum radius in pixels. This can be used to prevent the circle from getting
    too big when zoomed in.
    - Type: `float`, optional
    - Default: `None`
    """
    line_width_units = traitlets.Unicode("meters", allow_none=True).tag(sync=True)
    """
    The units of the line width, one of `'meters'`, `'common'`, and `'pixels'`. See
    [unit
    system](https://deck.gl/docs/developer-guide/coordinate-systems#supported-units).
    - Type: `str`, optional
    - Default: `'meters'`
    """
    line_width_scale = traitlets.Float(allow_none=True, min=0).tag(sync=True)
    """
    A global line width multiplier for all points.
    - Type: `float`, optional
    - Default: `1`
    """
    line_width_min_pixels = traitlets.Float(allow_none=True, min=0).tag(sync=True)
    """
    The minimum line width in pixels. This can be used to prevent the stroke from
    getting too thin when zoomed out.
    - Type: `float`, optional
    - Default: `0`
    """
    line_width_max_pixels = traitlets.Float(allow_none=True, min=0).tag(sync=True)
    """
    The maximum line width in pixels. This can be used to prevent the stroke from
    getting too thick when zoomed in.
    - Type: `float`, optional
    - Default: `None`
    """
    stroked = traitlets.Bool(allow_none=True).tag(sync=True)
    """
    Draw the outline of points.
    - Type: `bool`, optional
    - Default: `False`
    """
    filled = traitlets.Bool(allow_none=True).tag(sync=True)
    """
    Draw the filled area of points.
    - Type: `bool`, optional
    - Default: `True`
    """
    billboard = traitlets.Bool(allow_none=True).tag(sync=True)
    """
    If `True`, rendered circles always face the camera. If `False` circles face up (i.e.
    are parallel with the ground plane).
    - Type: `bool`, optional
    - Default: `False`
    """
    antialiasing = traitlets.Bool(allow_none=True).tag(sync=True)
    """
    If `True`, circles are rendered with smoothed edges. If `False`, circles are
    rendered with rough edges. Antialiasing can cause artifacts on edges of overlapping
    circles.
    - Type: `bool`, optional
    - Default: `True`
    """
    get_radius = FloatAccessor()
    """
    The radius of each object, in units specified by `radius_units` (default
    `'meters'`).
    - Type: [FloatAccessor][lonboard.traits.FloatAccessor], optional
    - If a number is provided, it is used as the radius for all objects.
    - If an array is provided, each value in the array will be used as the radius
    for the object at the same row index.
    - Default: `1`.
    """
    get_fill_color = ColorAccessor()
    """
    The filled color of each object in the format of `[r, g, b, [a]]`. Each channel is a
    number between 0-255 and `a` is 255 if not supplied.
    - Type: [ColorAccessor][lonboard.traits.ColorAccessor], optional
    - If a single `list` or `tuple` is provided, it is used as the filled color for
    all objects.
    - If a numpy or pyarrow array is provided, each value in the array will be used
    as the filled color for the object at the same row index.
    - Default: `[0, 0, 0, 255]`.
    """
    get_line_color = ColorAccessor()
    """
    The outline color of each object in the format of `[r, g, b, [a]]`. Each channel is
    a number between 0-255 and `a` is 255 if not supplied.
    - Type: [ColorAccessor][lonboard.traits.ColorAccessor], optional
    - If a single `list` or `tuple` is provided, it is used as the outline color
    for all objects.
    - If a numpy or pyarrow array is provided, each value in the array will be used
    as the outline color for the object at the same row index.
    - Default: `[0, 0, 0, 255]`.
    """
    get_line_width = FloatAccessor()
    """
    The width of the outline of each object, in units specified by `line_width_units`
    (default `'meters'`).
    - Type: [FloatAccessor][lonboard.traits.FloatAccessor], optional
    - If a number is provided, it is used as the outline width for all objects.
    - If an array is provided, each value in the array will be used as the outline
    width for the object at the same row index.
    - Default: `1`.
    """
    @traitlets.validate(
    "get_radius", "get_fill_color", "get_line_color", "get_line_width"
    )
    def _validate_accessor_length(self, proposal):
    if isinstance(proposal["value"], (pa.ChunkedArray, pa.Array)):
    if len(proposal["value"]) != len(self.table):
    raise traitlets.TraitError("accessor must have same length as table")
    return proposal["value"]
  4. Add a page to the API documentation: https://github.com/developmentseed/lonboard/blob/main/docs/api/layers/scatterplot-layer.md

In the case of H3 support specifically, deck.gl has an H3ClusterLayer which clusters points into H3 cells on the frontend and an H3HexagonLayer which renders hexagons from h3 cell id input. I assume in this case you're referring to the latter one. I already added GeoArrowH3HexagonLayer to @geoarrow/deck.gl-layers, so in this case we only need steps 2-4.

from lonboard.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.