Styling 3D features in Giro3D

By Wednesday October 23rd, 2024NewsFR

This article covers features released with version 0.38 of Giro3D.

Giro3D 0.38 introduced a Style API for representing features in 3D.

What are 3D features?

OGC features (simple feature) can be represented in Giro3D in two ways: draped and non-draped.

Draped features are rasterized on a Map entity and use OpenLayers styles.

A polygon draped over terrain using the Map entity

A polygon draped over terrain using the Map entity

Non-draped features are represented as 3D objects (lines, points, polygons, polyhedrons…) and allow for the visualization of features that have their own altitude or volume (e.g., buildings).

Non-draped features are represented by the FeatureCollection entity.

Draped features are rasterized

Draped features are rasterized

Non-draped features are vector objects

Non-draped features are vector objects

Why choose non-draped features?

Compared to their draped (and therefore rasterized) counterparts, 3D features offer several advantages (but also some disadvantages).

Advantages

  • Allows the representation of volumes. This is, of course, the main advantage, as rasterized features are inherently 2D objects. Thus, it's possible to represent buildings, volumes such as no-fly zones, etc.

  • Better visual quality. The absence of rasterization ensures perfect visual quality, as the features are represented as vector objects without the approximations introduced by rasterization.

  • Lower memory usage. Without rasterization, video memory usage is significantly reduced, as vector data is much lighter.

Disadvantages

  • More complex to use. Compared to their 2D counterparts, 3D features are less intuitive to handle, especially when facing typical display issues (e.g., Z-fighting).

  • A less rich API than its 2D counterpart. It’s not (yet) possible to specify multiple styles per feature, as you can in OpenLayers, for example, to add colored borders to lines (by combining two styles). We hope to evolve this and add multi-style support.

  • Doesn’t follow the terrain. The main advantage of draped features is that they perfectly follow the terrain (see the image above). Such results are not achievable with non-draped features.

How to style these 3D features?

The new Style API is inspired by the OpenLayers API, adapted to the constraints of 3D spaces. You can specify line and surface colors, opacity, line thickness, and symbols to use for Point type features.

Bus lines represented by 3D features

Bus lines represented by 3D features

The API

A feature's style is represented by the FeatureStyle object, which contains a point style (PointStyle), a line style (StrokeStyle), and a surface style (FillStyle).

Symbols are displayed as billboards

Symbols are displayed as billboards

Dynamic styles

It’s possible to assign a different style to a feature based on its attributes. For example, you can change the color of a polygon when the feature is clicked or hovered over by the mouse.

Let’s look at an example.

function polygonStyle(feature) {
  const clicked = feature.get("clicked");

  let color;

  if (clicked) {
    color = "yellow";
  } else {
    color = "blue";
  }

  return {
    fill: color,
  };
}

Later, we can modify this feature's attribute using the OpenLayers API, then notify the FeatureCollection that the styles need to be recalculated.

feature.set("clicked", true);

featureCollection.updateStyles();
3 different styles for the same feature

3 different styles for the same feature

Polygon extrusion

This feature is not strictly part of the Style API, as it modifies geometries rather than their style. Nevertheless, it’s worth mentioning here.

A very common use case is to represent buildings based on their ground footprint (which is generally a 2D Polygon or MultiPolygon). We can use the extrusionOffset callback from the FeatureCollection entity to specify the extrusion distance for the polygon.

In the following example, we retrieve the height attribute from the feature to use as an extrusion distance.

function extrusionOffset(feature) {
    const height = feature.get('height');

    return height;
}

const entity = new FeatureCollection({
    ...
    extrusionOffset,
    ...
});
Extruded polygons from IGN's BD TOPO

Extruded polygons from IGN's BD TOPO

Conclusion

The FeatureCollection entity allows you to display both 2D and 3D features, including volumes (buildings, arbitrary polyhedrons), symbols, and lines. Dynamic styles enhance interactivity with features and help users navigate complex scenes.

Sébastien Guimmara

Author Sébastien Guimmara

More posts by Sébastien Guimmara