odin_geolayer

odin_geolayer is a generic application domain crate to display and post-process configured GeoJSON files that are stored within the server file system (usually in ODIN_ROOT/data/odin_geolayer/ - see odin_build for details about the server filesytem structure). It is supposed to work with arbitrary GeoJSON that was generated by external tools but allows to configure display specific attributes and Javascript functions that are used to control rendering on a per-file basis.

The odin_geolayer crate itself only defines a GeoLayerService and its odin_server::SpaService implementation. The main function of this micro service is to add a server route for mapping requests to its data directory in use, and to provide the two primary assets: the geolayer.js JS module and its geolayer_config.js companion (see Client Code).

JS module configuration

The geolayer_config.js asset defines which GeoJSON sources can be displayed. It is presented to the user in form of a tree list in the "Geo Layers" UI Window. While this is an ordinary Javascript source it has to define an exported config object with a source property that holds a list of GeoJSON entries:

export const config = {
    layer: {
        name:"/overlay/annotation",
        description:"static map overlays with symbolic data",
        show: true,
    },
    
    sources: [
        { pathName: "utilities/powerlines/ca", // ① display path for UI window
            file: './hifld/Electric_Power_Transmission_Lines-CA-100122.geojson', // ② relative file path of GeoJSON resource
            info: 'HIFLD Electric Power Transmission Lines in CA 10/01/2022', // informal
            date: '10/01/2022', // informal
            render: { strokeWidth: 1.5, stroke: "#48D1CC", fill: "#48D1CC" } // ③ render options
        },
        { pathName: 'utilities/substations/ca',
            file: './hifld/Electric_Substations-CA-100122.geojson',
            info: 'HIFLD electric substations in CA 10/01/2022',
            date: '10/01/2022',
            render: { markerSymbol: 's' }
        },
        { pathName: 'emergency/fire_stations/ca',
            file: './hifld/Fire_Stations-CA-100122.geojson.gz',
            info: 'HIFLD fire stations in CA 10/01/2022',
            date: '10/01/2022',
            render: { markerSymbol: './asset/odin_geolayer/firestation.png', markerColor: 'red' }  // ③ render options with marker symbol
        },
        ...
        { pathName: 'boundaries/counties/CA',
            file: './hifld/CA_County_Boundaries.geojson',
            info: 'California county boundaries',
            date: '10/01/2022',
            render: { stroke: 'yellow', strokeWidth: 2, module: './county_boundaries.js' } // ④ render options with post-proc module
        }
    ]
    render: { // default render options
            stroke: '#48D1CC',
            stroke:  '#48D1CC',
            strokeWidth: 2,
            fill: '#48D1CC',
            markerColor: 'cyan',
            markerSize: 32,
            module: './extsym.js'
    }
};

(1) The pathName property of an entry specifies the tree list entry in the UI Window. It follows a normal filesystem scheme of path elements separated by '/'. The heading path elements (e.g. utilities/powerlines) can be used to categorize the entries. There are no constraints of how to organize entries - categories can be chosen at will.

(2) The file property contains a relative file path that is used to locate the resource on the server. It is not presented to the user and hence does not have to be readable. Note this property can also include path elements preceeding the filename, to organize such files within the server data directory. The file property is relative to the server data directory (which is not known by the client side).

(3) Each entry can have its own render options, including

  • stroke - a color name (or CSS color specification string) for lines/outlines
  • strokeWidth for lines/outlines
  • fill - fill color to use for polygons
  • markerSymbol - specification of how to display markers. Either a single letter that is drawn within the marker symbol or an image filename to use instead of the default marker
  • markerColor - symbol color to use

(4) Render options can include a module property that specifies a Javascript file which should be used to post-process the GeoJSON before it is rendered by Cesium. This is required if rendering should include GeoJSON feature properties such as names, or rendering should use a different geometric type (e.g. a polyline instead of a polygon). Render modules have to define an exported render() function like so:

...
export function render (entityCollection, opts) {
    for (const e of entityCollection.values) {
        let props = e.properties;

        if (e.polygon) {
            // get feature properties that are display relevant
            let name = getPropValue(props,'NAMELSAD');
            let lat = getPropValue(props,'INTPTLAT');
            let lon = getPropValue(props,'INTPTLON');

            // add/modify Cesium.Entity display properties
            if (name && lat && lon) {
                e.position = Cesium.Cartesian3.fromDegrees(lon, lat);

                e.label = {
                    text: name,
                    fillColor: opts.stroke,
                    ...
                };
            }
        }
        ...
    }
}

function getPropValue(props,key) { // local helper functions
    let p = props[key];
    return p ? p._value : undefined; // note that p is a Cesium.Entity property (data has to be extracted from `_value`)
}

See the odin_geolayer/assets/ directory for more examples. Rendering modules are normal module assets following the lookup rules defined in odin_build.

Tools

The odin_geolayer crate contains a show_geolayer binary with a server that has a GeoLayerService. This binary allows to specify the geolayer data directory to use with a --data_dir <path> command line option and hence is useful to test geolayer_config.js scripts. The default data directory is ODIN_ROOT/data/odin_geolayer/.