Rendering Functions

The rendering plugin code must declare a single function that returns an object with one of these functions in it:

Both synchronous getGeoJSON and asynchronous getGeoJSONAsync functions return an object with GeoJSON data in the bodyproperty:

{
  contentType: "application/vnd.geo+json; charset=utf-8",
  body: geoJsonData
}

Only one of these functions must be declared. If both are present, GeoJsonDataSource throws an exception.

These functions accept a single parameter that is an object containing raw source data and provides access to various helpers and utilities.

Typically, you should use the synchronous function to convert raw data to the GeoJSON format. If your plugin can perform any asynchronous tasks, then you must implement the getGeoJSONAsync function. Examples of asynchronous tasks are HTTP requests to external APIs or usage of geometry data providers. To see a sample implementation of the Data Inspector Library's sync and async rendering functions, see Plugin Examples.

Parameters

The getGeoJSON and getGeoJSONAsync functions accept a single params parameter. It is an object with these properties in it:

  • params.decodeResult { object }: The decodeResult object provides access to raw data and has two properties:

    • partitionId {string}: partition ID
    • data { object }: raw partition data decoded by protobuf
  • params.logger { object }: The GeoJSON data source uses a logger that implements the ILogger interface and is completely set up to log information to the console. The logger provides the following functions:

    // trace
    logger.trace("Trace message");
    
    // debug
    logger.debug("Hello again log");
    
    // log
    logger.log("Hello log");
    
    // info
    logger.info("Hello again log");
    
    // warning
    logger.warn("Hello again log");
    
    // error
    logger.error("Hello again log");
    

    By default, the log level is set to Warn, and you can change it at any point after the GeoJsonDataSource instance has been created:

    // Possible log levels are: Trace = 0, Debug = 1, Log = 2, Info = 3, Warn = 4, Error = 5.
    geoJsonDataSource.renderingPluginLogger.level = LogLevel.Info;
    

    or in the plugin code:

    params.logger.level = 0;
    

    You can also pass multiple messages to any of the logger's methods:

    logger.log("Log message", "Another log message", "One more log message");
    
  • params.layer { object }: The layer object contains all layer properties. For a full list of layer properties, see Catalog2Layer.

  • params.mapUtils { object }: The mapUtils object provides a set of helpful converters that can be used while decoding data into GeoJSON. For more information, see MapUtils.

  • params.geometryDataProviders { object }: The geometryDataProviders object has async getters that are used to access various geometry data providers to map data. Currently, there are two data providers available:

    • getSegmentAnchorDataProvider: an asynchronous method whose promise resolves with a SegmentAnchorGeometryDataProvider instance.
    • getRoadSegmentsDataProvider: an asynchronous method whose promise resolves with a BaseRoadSegmentsDataProvider instance.

Referencing Source Data in GeoJSON

Rendering plugins work as converters from the source data format to GeoJSON. While a plugin can put some additional data payload to a GeoJSON feature's properties, it is not the best place to store original raw data. The intended use of properties is to configure visual styles and provide human-readable tooltips.

A proper way to provide access to source data is to map a GeoJSON feature (the output of the plugin) to a source data object (the input for the plugin). This can be done by providing the properties.protobufRef property for a feature. It contains a path to the original raw data property that this feature visualizes such as prop.someArray[34].prop2.

You can see the usage of properties.protobufRef in the above-mentioned sample plugin for visualizing HMC topology data. The source data root object has two arrays - node and segment, and the corresponding protobufRef properties are node[12] and segment[43].

If you look at the speed limit sample plugin, it generates a bit deeper path to the source data property: speed_limit[2].segment_anchor_index[137].

When you select a certain feature on the map, the Data Inspector Library's DataInspector widget highlights the selected feature and moves focus to the corresponding source data node in the DecodedPanel, as in the figure below:

Source Data Node
Figure 1. Source Data Node

Note

According to the GeoJSON specification, FeatureCollection cannot contain properties. So, for visualization needs, you can specify identical protobufRef paths for multiple features.

Data Filtering

A rendering plugin may process large amounts of data and generate a lot of GeoJSON features. As a result, you can find it hard to pinpoint specific features on the map. Fortunately, plugins provide a mechanism to implement sophisticated filtering of visualized data.

Filters are implemented by grouping features and assigning each feature a set of tags. Tags are string values that can be either unique for each feature or can be shared between multiple features. Visibility of features with certain tags can be toggled in the Data Inspector's Data Filters panel. For this panel to show up, make sure that the enableFiltering property is set to true in the configuration of the DataInspector widget.

For a demo and implementation details of feature tags, see the plugin-hmc.js file that is shipped with Data Inspector example applications. This file contains the most recent rendering plugin code for certain HERE Map Content layers.

The images below show the difference between the visualization with all the filters enabled and the visualization with a few filters disabled:

All filters enabled
Figure 2. All filters enabled
Some filters disabled
Figure 3. Some filters disabled

In their simplest form, feature tags can be applied as an array of strings for each feature. For example, the following GeoJSON has two categories for free and paid parking lots. Note that this allows features to have more than one tag assigned, putting them in multiple categories for filtering.

{
  "type": "FeatureCollection",
  "features": [
    {
        "type": "Feature",
        "properties": {
            "featureTags": ["free"]
        },
        "geometry": { ... }
    },
    {
        "type": "Feature",
        "properties": {
            "featureTags": ["paid"]
        },
        "geometry": { ... }
    },
    {
        "type": "Feature",
        "properties": {
            "featureTags": ["free", "paid"]
        },
        "geometry": { ... }
    }
  ]
}

This results in the following filters with switches in the Data Filters panel:

Data Filters Panel
Figure 4. Data Filters Panel

Tags Hierarchy

You can organize tags into a hierarchical structure for more detailed filtering of features. This is achieved by using a pipe | separator in tag names. For example, a tag Buildings|Banks creates two tags - Buildings and Banks. Banks are nested inside Buildings. If you add a Buildings|Schools tag, Schools are also nested under the parent Buildings tag. In the Data Filters panel, you can toggle all of them at once by using the parent tag or each of the tags individually:

Filters tree
Figure 5. Filters tree

Tags can have an unlimited level of hierarchy depth, for example: Buildings|Educational|Schools|Preschools.

Filters tree with deep hierarchy
Figure 6. Filters tree with deep hierarchy

Default Tags

Sometimes a plugin can generate too much geometries for users to cope with, or some information is of less importance and should be visualized optionally. In such cases, it is useful to create all geometries but visualize only a certain subset of them.

For this, FeatureCollection supports a custom defaultEnabledFeatureTags property that specifies an array of those feature tags that are enabled by default. If it is not specified, then all the features are enabled. Pass an empty array to disable all the tags. For example, if you want to visualize roads but keep unpaved ones hidden by default, you can generate the following GeoJSON:

{
  "type": "FeatureCollection",
  "features": [
      {
          "type": "Feature",
          "properties": {
              "featureTags": ["Roads|Paved"]
          },
          "geometry": { ... }
      },
      {
          "type": "Feature",
          "properties": {
              "featureTags": ["Roads|Unpaved"]
          },
          "geometry": { ... }
      }
  ],
  "defaultEnabledFeatureTags": ["Roads|Paved"]
}

Note that you still have full control over tags visibility from the Data Filters panel, defaultEnabledFeatureTags only specifies a default state for tags.

Referencing Source Data from Multiple Layers

GeoJSON plugins provide an interface that allows retrieving data from different layers belonging to different catalogs. There is no limitation of layers that can be retrieved. For a working example of how data from multiple layers can be accessed through a rendering plugin, including sample plugin code, see the DI / geojson / plugin / external / ds example in Run Example Apps.

This interface provides a set of additional properties of the params object that is passed to the getGeoJSONAsync method:

  • getDependencies():Promise<VersionInfo[]>

    Retrieves the dependencies and their versions of the currently inspected version of the catalog.

  • getPartitionDataProvider(layer,catalogHrn?,version?): Promise<PartitionDataProvider>

    Retrieves a cross-layer partition data provider for the given parameters:

    • layer: A mandatory parameter that defines the target data layer identifier from where the partition data will be retrieved. The same layer and tiling types are supported as in the Data Inspector's Partitions List (currently, versioned and volatile layers with the HEREtile or generic partitioning scheme).

    • catalogHrn: Defines the target catalog identifier. Defaults to the current catalog if not specified. If this parameter is a number, it is assumed to be the version parameter, and catalogHrn defaults to the current catalog.

    • version: Defines the version number of the target catalog to use. If catalogHrn is this catalog, the default is the currently inspected version. If catalogHrn is found from the dependencies of this catalog, the default is that version. Otherwise, the version must be given by the caller when the target layer is a versioned layer; for volatile layers it is not needed.

      The resolved layer, catalog HRN, and version used are logged to a browser console when this function is called. Nothing is shown in the Data Inspector user interface, it is up to you as a plugin developer to utilize the data.

      The function returns a promise to the PartitionDataProvider object that has the following functions (if the catalog cannot be accessed or the layer type is unsupported, the promise rejects):

    • getData(partitionId): Promise<ArrayBuffer>: Returns a promise which resolves to the ArrayBuffer with raw partition data. The promise rejects if the data cannot be accessed. The layer content type may be anything, it is up to the plugin code to interpret the bytes (for example, it may be TXT or CSV or a custom binary type).

    • getDataDecoded(partitionId, raw?): Promise<object>: Returns a promise to the partition content decoded as a JavaScript object. JSON, GeoJSON as well as protobuf content types are supported. The promise rejects with a detailed error if decoding cannot be done (for example, an unsupported content type, inability to get the schema for a protobuf layer, or a decode error). If raw is true, then the enums and longs in the protobuf data will not be converted to strings (false by default). If raw is false, then the returned object has exactly the same properties and values as the rendering plugin in the target layer would receive. This enables copy-pasting of the code from the target layer's rendering.

    • decodeProtobufData(messageName, buffer, raw?): Promise<object>: Returns a promise to a JSON object decoded from the ArrayBuffer buffer using the given messageName as the root message. The promise rejects if messageName is unknown or data cannot be decoded with it. If raw is true, then the enums and longs will not be converted to strings (false by default). The schema declaration for messageName must be in the schema package linked to the layer. For example, this function can be used to decode arbitrary protobuf data stored in an Any field.

      Partition metadata or blobs are not accessed until the getData/getDataDecoded functions are called.

      You must call getPartitionDataProvider for different layers and catalogs, store the returned PartitionDataProviders during the lifetime of the getGeoJSONAsync call, and repeatedly call the getData/getDataDecoded/decodeProtobufData methods of those when producing the GeoJSON output.

      Calls to getData/getDataDecoded do not impact what's shown in the Decoded Panel, it always shows the partition selected by the user.

Version Dependency Resolution

The Data Inspector Library has a built in mechanism for version dependency resolution between different catalogs and the corresponding versions of regional HERE Map Content (HMC) catalogs (Japan, China, or rest of the world) in the Data Inspector. This works for visualizing data like traffic or speed limits that contains no road geometry information.

For example, speed limit lines from the HMC Navigation Attributes layer must be mapped to road geometries from the HMC Topology Geometry layer. The new mechanism, in this case, aligns the versions of speed limit lines data and road geometry data to omit any errors and get the most accurate visualization. The Data Inspector reads layer dependencies and automatically retrieves geometry information from the corresponding regional HMC catalog.

Note that if you have no access permissions to the necessary HMC catalog, or the correct HMC is not defined in the dependencies of the layer to be visualized, the most recent HMC version is used by default (China or rest of the world).

For more information on how to set layer dependencies, see the CLI Developer Guide.

results matching ""

    No results matching ""