Adding a feature model

You can add and remove data on the Map using Map::getLayerList()Map::getLayerList()Map::getLayerList().

To add a feature model to the map, you:

  1. Create a FeatureLayerFeatureLayerFeatureLayer based on the model and styling information (IFeaturePainterIFeaturePainterIFeaturePainter)

  2. Add that layer to the Map’s LayerListLayerListLayerList

This code snippet demonstrates how a feature model is added to the map, configured with a custom painter:

Program: Adding a feature layer
std::shared_ptr<IFeatureModel> geometryModel = CustomerGeometryModel::create();
std::shared_ptr<FeatureLayer> geometryLayer = FeatureLayer::newBuilder()
                                                  .model(geometryModel)
                                                  .editable(true)
                                                  .editCreateGeometryProvider(CustomerGeometryModel::createEditGeometryProvider())
                                                  .build();

map->getLayerList()->add(geometryLayer);
var geometryModel = CustomerGeometryModel.Create();
var geometryLayer = FeatureLayer.NewBuilder()
    .Model(geometryModel)
    .Editable(true)
    .EditCreateGeometryProvider(CustomerGeometryModel.CreateEditGeometryProvider())
    .Build();
Map.LayerList.Add(geometryLayer);
val geometryModel = CustomerGeometryModel.create()
val geometryLayer = FeatureLayer.newBuilder()
    .model(geometryModel)
    .editable(true)
    .editCreateGeometryProvider(CustomerGeometryModel.createEditGeometryProvider())
    .build()
map.layerList.add(geometryLayer)

Styling features

Apart from a mandatory IFeatureModelIFeatureModelIFeatureModel parameter on its constructor, the FeatureLayer::BuilderFeatureLayer::BuilderFeatureLayer::Builder also accepts an optional IFeaturePainterIFeaturePainterIFeaturePainter, which you can use to set up custom styling of the model features.

Creating your own IFeaturePainterIFeaturePainterIFeaturePainter requires an implementation of two methods:

This code snippet shows an implementation of the IFeaturePainter::paintIFeaturePainter::paintIFeaturePainter::paint method:

Program: Using the feature painter
void RoadsPainter::paint(const Feature& feature, const FeaturePainterContext& context, FeatureCanvas& canvas) const {
  const std::optional<std::shared_ptr<Geometry>>& geometry = feature.findGeometry();
  if (!geometry) {
    std::cerr << "Geometry not found for the given feature: " << feature.getId() << std::endl;
    return;
  }

  std::string roadType = feature.getValue<std::string>(_roadTypePropertyPath).value_or("unknown");
  size_t detailLevel = context.getDetailLevel();

  std::map<StyleKey, LineStyle> styleMap;
  std::map<StyleKey, TextStyle> labelStyleMap;
  if (context.isFeatureStateEnabled(FeatureState::selected())) {
    styleMap = _selectedStyles;
    labelStyleMap = _selectedLabelStyles;
  } else if (context.isFeatureStateEnabled(FeatureState::hover())) {
    styleMap = _hoverStyles;
    labelStyleMap = _hoverLabelStyles;
  } else {
    styleMap = _regularStyles;
    labelStyleMap = _regularLabelStyles;
  }

  StyleKey key = std::make_pair(detailLevel, roadType);
  auto iterator = styleMap.find(key);
  LineStyle style = iterator != styleMap.end() ? iterator->second : _fallbackStyle;

  canvas.drawGeometry().geometry(*geometry).stroke(style).submit();

  auto labelIterator = labelStyleMap.find(key);
  bool foundLabel = labelIterator != labelStyleMap.end();
  std::optional<std::string> name = feature.getValue<std::string>(_namePropertyPath);
  if (foundLabel && name) {
    TextStyle labelStyle = labelIterator->second;
    canvas.drawLabel().anchor(*geometry).textStyle(labelStyle).text(*name).submit();
  }
}
public void Paint(Feature feature, FeaturePainterContext context, FeatureCanvas canvas)
{
    Geometry geometry = feature.FindGeometry();
    if (geometry == null)
    {
        Console.WriteLine("Feature [" + feature.Id + "] without geometry!");
        return;
    }

    Dictionary<StyleKey, LineStyle> styleMap;
    Dictionary<StyleKey, TextStyle> labelStyleMap;

    if (context.IsFeatureStateEnabled(FeatureState.Selected))
    {
        styleMap = SelectedStylesMap;
        labelStyleMap = SelectedLabelStylesMap;
    }
    else if (context.IsFeatureStateEnabled(FeatureState.Hover))
    {
        styleMap = HoverStylesMap;
        labelStyleMap = HoverLabelStylesMap;
    }
    else
    {
        styleMap = RegularStylesMap;
        labelStyleMap = RegularLabelStylesMap;
    }

    string type = feature.GetValue<string>(_typePropertyPath);
    var key = new StyleKey(context.DetailLevel, type);
    if (!styleMap.TryGetValue(key, out var style))
    {
        style = FallbackStyle;
    }

    canvas.DrawGeometry().Geometry(geometry).Stroke(style).Draped(true).Submit();

    if (labelStyleMap.TryGetValue(key, out var textStyle))
    {
        var name = feature.GetValue<string>(_namePropertyPath);
        if (!string.IsNullOrEmpty(name))
        {
            canvas.DrawLabel().Anchor(geometry).TextStyle(textStyle).Text(name).Submit();
        }
    }
}
override fun paint(feature: Feature, context: FeaturePainterContext, canvas: FeatureCanvas) {
    val geometry = feature.findGeometry()
    if (geometry == null) {
        Log.e("LUCIAD", "Feature [" + feature.id + "] without geometry!")
        return
    }
    val styleMap: Map<StyleKey, LineStyle>
    val labelStyleMap: Map<StyleKey, TextStyle>
    if (context.isFeatureStateEnabled(FeatureState.Selected)) {
        styleMap = SelectedStylesMap
        labelStyleMap = SelectedLabelStylesMap
    } else {
        styleMap = RegularStylesMap
        labelStyleMap = RegularLabelStylesMap
    }
    val type = feature.getValue<String>(_typePropertyPath)
    val key = StyleKey(context.detailLevel, type!!)
    val lineStyle = styleMap[key] ?: FallbackStyle
    canvas.drawGeometry().geometry(geometry).stroke(lineStyle).draped(true).submit()
    val name = feature.getValue<String>(_namePropertyPath)
    name?.let { labelName ->
        labelStyleMap[key]?.let { style ->
            canvas.drawLabel().anchor(geometry).textStyle(style).text(labelName).submit()
        }
    }
}

Visualizing geometries

You can visualize geometries with the FeatureCanvas::drawGeometryFeatureCanvas::drawGeometryFeatureCanvas::drawGeometry method. This method requires at least a GeometryGeometryGeometry and a stroke and/or fill style.

You create Feature styles through builder methods on one of the style classes. The different types of feature styles are:

Adding labels to features

You can attach icon and text labels to features with the FeatureCanvas::drawLabelFeatureCanvas::drawLabelFeatureCanvas::drawLabel method. See related article on adding labels for more information.