HERE iOS SDK Developer's Guide

Marker Clustering

You can use marker clustering to reduce the visual overload caused by too much markers being displayed on the map at once. With this feature, markers that are close together are automatically replaced by numbered cluster markers to indicate that multiple map markers are represented.

Figure 1. Cluster Markers

Showing Cluster Markers

You can enable cluster markers on a map by using a NMAClusterLayer and adding map markers to it. All markers that are on a layer are automatically clustered based on a grid-based clustering algorithm that depends on the map zoom level.

The following steps demonstrates how to use the NMAClusterLayer class:

  1. Create map markers as normal:
    NMAMapMarker *mm =
      [NMAMapMarker
        mapMarkerWithGeoCoordinates:[NMAGeoCoordinates geoCoordinatesWithLatitude:54.54
          longitude:13.23]
        image:[UIImage imageNamed:@"marker@1x.png"]];
    
  2. Create a ClusterLayer object.
    NMAClusterLayer *cl = [[NMAClusterLayer alloc] init];
  3. Add markers to the cluster layer, instead of the map directly.
    [cl addMarker:mm];
    You can also add an NSArray of NMAMapMarker instead of setting just adding a single marker by using the addMarkers: method.
  4. Add the cluster layer to the map.
    [activeMapView addClusterLayer:cl];
    Note: The order of these two steps are not important. You can also add the cluster layer to the map first and add markers to the cluster layer afterwards.
  5. To remove a marker or collection or markers from the cluster layer again, call:
    [cl removeMarker:mm];

You can also retrieve all markers on a cluster layer with the markers property in NMAClusterLayer. This is useful in the case where you would like to remove all markers by using the removeMarkers: method.

Theming

You can customize clusters by assigning a NMAClusterTheme object to the NMAClusterLayer. Every theme consists of several styles, where a cluster style defines the look of marker cluster objects at a particular density. Cluster density is an indication of how many markers a cluster represents.

Figure 2. A Cluster with Density of 7

There are three available cluster styles that you can use with a NMAClusterTheme:

  • Default cluster style - the predefined markers behavior. This is the default style that is used if you do not set a theme. It is also used for ranges that are not covered by your own theme.
  • NMABasicClusterStyle - similar to the default style, but you can change the fill color, text color, and stroke color for the markers.
  • NMAImageClusterStyle - use your own bitmap image as a marker.

To set a style, use the setStyle:forDensityRange: method in NMAClusterTheme. For example, if you want red for all clusters between density 10 to 19, and green for 20 to 30, and the default blue for all other cases, you can use NMABasicClusterStyle as follows:

  1. Create a style with a red circle and a style with a green one:
    NMABasicClusterStyle *redStyle = [NMABasicClusterStyle style];
    redStyle.fillColor = [UIColor redColor];
    NMABasicClusterStyle *greenStyle = [NMABasicClusterStyle style];
    greenStyle.fillColor = [UIColor greenColor];
    
  2. Create a new theme and add those styles to the theme with defining the density ranges they should be used for:
    NMAClusterTheme *theme = [[NMAClusterTheme alloc] init];
    [theme setStyle:redStyle forDensityRange:NSMakeRange(10, 9)];
    [theme setStyle:greenStyle forDensityRange:NSMakeRange(20, 10)];
    
    Note: Make sure that density ranges do not overlap, or otherwise the setStyle:forDensityRange: returns NO.
  3. Finally, add this theme to the cluster layer you use:
    cl.theme = theme;

To use your own image as a cluster icon, set an UIImage to an NMAImageClusterStyle instance before setting the style to the cluster theme. For example:

NMAImageClusterStyle *imageStyle =
  [NMAImageClusterStyle
    styleWithUIImage:[UIImage imageNamed:@"cluster-icon.png"]];

NMAClusterTheme *theme = [[NMAClusterTheme alloc] init];
  [theme setStyle:imageStyle forDensityRange:NSMakeRange(2, 8)];
  cl.theme = theme;

Although you can only set one theme per layer, you can mix styles for different densities in a single theme. For example, you can set a NMABasicClusterStyle from density of 10 to 19 and an NMAImageClusterStyle from 20 to 30. The default theme applies for all other densities that are not covered by the custom themes.

Cluster Marker Events

Cluster markers are similar to normal markers on the map. You can also use map object gesture delegates in a similar manner as normal map markers. For example:

  1. Set an NMAMapView delegate:
    self.mapView.delegate = self;
  2. Implement mapView:didSelectObjects: to get the map click event.
    - (void)mapView:(NMAMapView *)mapView didSelectObjects:(NSArray *)objects
    {
      for (NMAClusterViewObject *object in objects) {
        if ([object isKindOfClass:[NMAClusterViewObject class]]) {
          NSLog(@"Cluster of %d markers", object.markers.count);
        }
      }
    }

Working with Clusters

The HERE SDK also provides a few other ways for you to interact with marker clusters. You can get all markers inside one specific cluster by using NMAClusterViewObject, which is a proxy object class representing a cluster. For example:

NMAGeoCoordinates *coordinates =
  [NMAGeoCoordinates geoCoordinatesWithLatitude:0 longitude:0]; // Your coordinates
NSArray *objects =
  [self.mapView objectsAtPoint:[self.mapView pointFromGeoCoordinates:coordinates]];

for (NMAClusterViewObject *object in objects) {
    if ([object isKindOfClass:[NMAClusterViewObject class]]) {
      NSArray *clusterMarkers = object.markers; // Your clustered markers
    }
  }

You can also retrieve the bounding box around all markers that are in a cluster marker by calling the following:

NMAClusterViewObject *cluster;
NMAGeoBoundingBox *boundingBox = cluster.boundingBox;