You can configure a 2D WebGLMap with a cylindrical projection, like a Mercator projection or an equidistant cylindrical projection, to wrap around the date line. This article tells you how.

What does "wrapping around the world" mean?

This refers to the visualization of the map where the 2D map wraps around back to the other side of the world at the projection boundary (typically the 180° meridian, which roughly follows the date line). In other words, the map is repeated again beyond the projection boundary. This makes it easier to work with data near the projection boundary because users can just pan across the boundary. Without it, the user has to pan back and forth to the other side of the map. Changing the map’s projection can also alleviate this problem but that has various other consequences.

Wrapping off
Figure 1. A map that doesn’t wrap around. The projection boundary splits the cloud coverage image into 2 parts. To closely inspect it, the user needs to pan back and forth across the map.
Wrapping on
Figure 2. A map that wraps around. The user can pan across the projection boundary to closely inspect the cloud coverage.

How do I enable wrapping around the world?

Wrapping around the world is enabled by specifying wrapAroundWorld: true as an option when constructing a WebGLMap.

Program: Creating a map with wrapping enabled
const map = new WebGLMap("map", {
  reference: getReference("EPSG:3857"), // Web Mercator projection
  wrapAroundWorld: true
});

Wrapping around the world is only supported on a WebGLMap with a cylindrical projection. Examples of cylindrical projections are Mercator projections or equidistant cylindrical projections.

Limiting the number of worlds visible at one time

By default, you can only see one world width at a time. You can configure this limit with the MapNavigator.constraints API.

Program: Configuring the maximum number of visible worlds on a wrapAroundWorld map
map.mapNavigator.constraints.wrapAroundWorld = {
  maxNumberOfWorlds: 3
};

If you allow only one world width at a time, users can pan across the date line, but any point on the world will be on screen only once at most. The map part that falls off at one end becomes visible on the other side. Users can’t zoom out beyond a single world width on the screen.

If you allow more than one world, users can zoom out as far as they want. This configuration duplicates all information on all visible worlds, and might affect map performance.

What to consider when working with these maps?

Most things work out-of-the-box on this type of map. However, inspect your codebase for these API uses:

  • Pay attention when you are creating a transformation from map reference to model reference, CRS:84 for example, when using a map that is wrapped around the dateline. The map’s X coordinate might need special attention to normalize it to projection bounds. This problem is handled for you if you create your transformation using createTransformation method and by passing CreateTransformationOptions.normalizeWrapAround: map.wrapAroundWorld as option to it.

    Program: Transforming view points to the map reference without taking date line wrapping into account
    const map2LLH = createTransformation(map.reference, getReference("CRS:84"));
    const centerViewPoint = createPoint(null, [map.viewSize[0] / 2, map.viewSize[1] / 2]);
    const viewToMap = map.getViewToMapTransformation();
    const centerMapPoint = viewToMap.transform(centerViewPoint);
    const centerLLHPoint = map2LLH.transform(centerMapPoint);
    Program: Transforming view points to the map reference, taking date line wrapping into account
    const map2LLH = createTransformation(map.reference, getReference("CRS:84"), {normalizeWrapAround: map.wrapAroundWorld});
    let centerViewPoint = createPoint(null, [map.viewSize[0] / 2, map.viewSize[1] / 2]);
    const viewToMap = map.getViewToMapTransformation(LocationMode.TERRAIN);
    const centerMapPoint = viewToMap.transform(centerViewPoint);
    // the wrapAround normalization might've caused the point to be normalized to a different location on-screen
    // go back to view again, to make sure centerMapPoint matches centerViewPoint
    centerViewPoint = map.mapToViewTransformation.transform(centerMapPoint);
    const centerLLHPoint = map2LLH.transform(centerMapPoint);
  • Use of Map.mapToViewTransformation. Map.mapToViewTransformation takes multiple wrap-around worlds into account. The transformation returns a point in view if it exists. If more than one full world is visible, the returned view point is only for one of the worlds, typically the most central one.

    Map.mapToViewTransformation usage
    Figure 3. A map showing in green the pixel returned by a call to Map.mapToViewTransformation for map coordinates corresponding to Belgium. The map shows in red the pixels corresponding to Belgium on other worlds not returned by Map.mapToViewTransformation.
  • Use of Map.mapBounds. Map.mapBounds returned a bounds instance representing the visible part of the map. If the map can visualize more than one world at once, a single bounds might not be enough. Because of this, Map.mapBounds has been depecrated. Replace usages of Map.mapBounds with its newer counterpart: Map.getMapBounds(). This method returns an array of bounds instead of a single bounds instance. Additionally, it takes options to transform bounds to a target (model) reference.

    map.getMapBounds() usage
    Figure 4. The bounds in red and blue are the two distinct bounds returned by a call to Map.getMapBounds(). If Map.mapBounds had been used instead, only one of the bounds would have been returned.

Known limitations

  • The animation of MapNavigator.fit might take an unexpected detour when fitting on bounds on the other side of the dateline.

  • Clustering around the date line works as expected only when at most one world is visible.