Goal

In this tutorial, we create a feature layer that displays vector data on a LuciadRIA map. We visualize cities of the United States of America, served by a Web Feature Service (WFS).

Starting point

We take the code written in Hello World as our starting point, and expand from there.

Step 1 - Create the store for data access

You must always access vector data through a Store that links the model with the data on the server. The store is responsible for:

  • Querying the server for data

  • Updating data on the server

  • Converting the responses of the server to LuciadRIA Feature instances. It uses a Codec for this.

A Feature is a data object representing vector data in LuciadRIA.

To learn more about LuciadRIA feature models, stores and the visualization of WFS features, see Introduction to feature (vector) models and Data Formats: OGC WFS.

A store abstracts the underlying communication protocols and storage mechanism: one of your stores can connect to a REST web service, another store connects to the local storage of the browser, and a third connects to the non-persistent memory of the application. In our case, a WFS service serves the point geometries representing cities of the USA. A WFS service is accessible through a WFSFeatureStore. It exposes a utility function createFromURL that creates an instance of the WFSFeatureStore based on these arguments:

  • url: the URL pointing to the WFS service

  • featureTypeName: the name of the WFS feature type to load

  • options: an object literal that has optional settings for the store

Note that the options.codec parameter is optional. LuciadRIA reads the capabilities information of the WFS to decide which codec to use.

We connect to a WFS served by LuciadFusion. By default, LuciadRIA uses a GeoJsonCodec, which suits our requirements for this example.

The following code snippet shows you how to create a store that retrieves data from a WFS service.

import {WFSFeatureStore} from "@luciad/ria/model/store/WFSFeatureStore.js";
// ...
// Create a WFS store
const url = "https://sampleservices.luciad.com/wfs";
const featureTypeName = "cities";
WFSFeatureStore.createFromURL(url, featureTypeName).then(
    (wfsSore: WFSFeatureStore) => {
      // We will create a model based on the store
    });

Note that WFSFeatureStore.createFromURL returns a promise for a WFSFeatureStore instance.

You can check which feature types and capabilities the WFS service offers by executing a GetCapabilities request on the WFS service. In our tutorial, the URL with the GetCapabilities operation is https://sampleservices.luciad.com/wfs?REQUEST=GetCapabilities&SERVICE=WFS.

Step 2 - Create a model for the store

We create the model by wrapping the store in a FeatureModel. Its main constructor argument is the Store we created in an earlier step. This code snippet shows the creation of the FeatureModel that uses the WFS store:

import {FeatureModel} from "@luciad/ria/model/feature/FeatureModel.js";
// ...
        // Create a feature model
        const featureModel = new FeatureModel(wfsSore);

Step 3 - Create a layer for the model

We need a layer to visualize the model. For vector data in a FeatureModel, we use a FeatureLayer. Its constructor needs these parameters:

  • model: the feature model

  • options: JavaScript object containing layer-specific options. See the API reference documentation for more information.

This code snippet creates the layer:

import {FeatureLayer} from "@luciad/ria/view/feature/FeatureLayer.js";
import {LayerType} from "@luciad/ria/view/LayerType.js";
// ...
        // Create a feature layer
        const featureLayer = new FeatureLayer(featureModel, {
          label: "US Cities",
          layerType: LayerType.STATIC
        });

Step 4 - Add the layer to the map

Now we can add the layer to the map through this code snippet:

// Add a layer to the map
map.layerTree.addChild(featureLayer);

Output

Let’s put all steps of this tutorial together in a new file src/vectorData.ts. The file exposes a createCitiesLayer(map) function that expects one argument, which is our LuciadRIA map object.

vectorData.ts file
import {FeatureLayer} from "@luciad/ria/view/feature/FeatureLayer.js";
import {FeatureModel} from "@luciad/ria/model/feature/FeatureModel.js";
import {LayerType} from "@luciad/ria/view/LayerType.js";
import {Map} from "@luciad/ria/view/Map.js";
import {WFSFeatureStore} from "@luciad/ria/model/store/WFSFeatureStore.js";

export function createCitiesLayer(map: Map) {
  const url = "https://sampleservices.luciad.com/wfs";
  const featureTypeName = "cities";
  // Create a WFS store
  return WFSFeatureStore.createFromURL(url, featureTypeName).then(
      (wfsSore: WFSFeatureStore) => {
        // Create a feature model
        const featureModel = new FeatureModel(wfsSore);

        // Create a feature layer
        const featureLayer = new FeatureLayer(featureModel, {
          label: "US Cities",
          layerType: LayerType.STATIC
        });

        // Add a layer to the map
        map.layerTree.addChild(featureLayer);
      });
}

Now we can invoke the createCitiesLayer(map) function from our main module (index.ts).

The complete index.ts code after modification
import "./license-loader";
import {WMSTileSetModel}  from "@luciad/ria/model/tileset/WMSTileSetModel.js";
import {RasterTileSetLayer} from "@luciad/ria/view/tileset/RasterTileSetLayer.js";
import {createCitiesLayer} from "./vectorData.js";
import {WebGLMap} from "@luciad/ria/view/WebGLMap.js";

//Create a new map instance, and display it in the div with the "map" id
const map = new WebGLMap("map");

//Add some WMS data to the map
const server = "https://sampleservices.luciad.com/wms";
const dataSetName = "4ceea49c-3e7c-4e2d-973d-c608fb2fb07e";
WMSTileSetModel.createFromURL(server, [{layer: dataSetName}])
    .then(model => {
      //Once the data is available, create a layer for it
      const layer = new RasterTileSetLayer(model);
      //and add the layer to the map
      map.layerTree.addChild(layer);
    });

createCitiesLayer(map);

The application draws city features on the map.

vector data