Mapbox-gl-native: Clustering Issues: Wrong Point Count / Disappearing Clusters

Created on 12 Dec 2016  路  6Comments  路  Source: mapbox/mapbox-gl-native

Platform: iOS 10.1
Mapbox SDK version: 3.4.0-beta.4

I notice some weird behaviour of the point count in clusters and I don't know if I have implemented something wrong. In the first example you see how the cluster suddenly disappears, in the second example you see that the point count displays a wrong number.

Example 1: Cluster suddenly disappears

clustering_fail1

Example 2: Point Count displays wrong number

clustering_fail2

Clustering options

var options = [MGLGeoJSONSourceOption : Any]()
options[.clustered] = true
options[.clusterRadius] = 50
options[.maximumZoomLevelForClustering] = 11.0

Style layer definition

let clusterLayers = [
  ClusterLayer(count: 30, color: Colors.FlatAlizarin, size: 20),
  ClusterLayer(count: 20, color: Colors.FlatCarrot, size: 18),
  ClusterLayer(count: 10, color: Colors.FlatSunFlower, size: 15),
  ClusterLayer(count: 0, color: Colors.FlatEmerald, size: 12)
]

for index in 0..<clusterLayers.count {
    let gtePredicate = NSPredicate(format: "%K >= %@", argumentArray: ["point_count", clusterLayers[index].count])
    let allPredicate = index == 0 ?
        gtePredicate :
        NSCompoundPredicate(andPredicateWithSubpredicates: [gtePredicate, NSPredicate(format: "%K < %@", argumentArray: ["point_count", clusterLayers[index - 1].count])])

    let circleBorder = MGLCircleStyleLayer(identifier: "cluster-\(index)-border", source: geoJSONSourceClustered)
    circleBorder.circleColor = MGLStyleValue(rawValue: UIColor.white)
    circleBorder.circleRadius = MGLStyleValue(rawValue: clusterLayers[index].size.multiplying(by: 1.1))
    circleBorder.predicate = allPredicate
    circleBorder.maximumZoomLevel = 11.0
    mapView.style().add(circleBorder)

    let cluster = MGLCircleStyleLayer(identifier: "cluster-\(index)", source: geoJSONSourceClustered)
    cluster.circleColor = MGLStyleValue(rawValue: clusterLayers[index].color)
    cluster.circleRadius = MGLStyleValue(rawValue: clusterLayers[index].size)
    cluster.predicate = allPredicate
    cluster.maximumZoomLevel = 11.0
    mapView.style().add(cluster)
}

let clusterPointCount = MGLSymbolStyleLayer(identifier: "clusterPointCount", source: geoJSONSourceClustered)
clusterPointCount.textField = MGLStyleValue(rawValue: "{point_count}")
clusterPointCount.textColor = MGLStyleValue(rawValue: UIColor.white)
clusterPointCount.maximumZoomLevel = 11.0
mapView.style().add(clusterPointCount)
iOS support

Most helpful comment

Or better ["==", "cluster", true]

All 6 comments

Here's another example (loading may takes long because of gif size):

clustering_fail3

Your example does not create any layer that would include unclustered, unitary points, so when you reach a zoom level where unitary points get split off from a cluster, they "disappear". The way clustering works, unclustered points don't have a point_count property, and filters like "point_count >= 0" evaluate to true only if there actually is a point_count property. You need to create a separate layer with the filter ["!has", "point_count"] to show them, as in this GL JS example.

Or better ["==", "cluster", true]

@jfirebaugh or @mourner
Would it be possible from one of you to write a small code snippet on how to implement this with Swift? 馃槉

Edit: My above example wasn't complete, I actually have another layer which has a minimumZoomLevel of 11.0 (which is the maximumZoomLevel of the cluster layers), but I still encounter the same problem.

Alright, I just did it by myself. The predicate for the unclustered layer needs to be like the following

layer.predicate = NSPredicate(format: "%K != YES", argumentArray: ["cluster"])

Works perfectly! 馃憤

Or better ["==", "cluster", true]

Very nice, thanks!

Was this page helpful?
0 / 5 - 0 ratings