hulab / ClusterKit

An iOS map clustering framework targeting MapKit, Google Maps and Mapbox.
MIT License
512 stars 86 forks source link

Use one single clusterManager for multiple view controllers and proposes #22

Closed jacogasp closed 6 years ago

jacogasp commented 6 years ago

I have a huge amount of POIs that I can successfully show over on the map. But I also need to search all the POIs within a certain distance from the user location, in a different view.

Is it possible to create one general cluster of annotations, accessing it from different view controllers and perform a search based on the user location?

jacogasp commented 6 years ago

I think that a possible solution could be to initialize a QuadTree object that can be used as datasource for the mapView and that can provide, in another viewcontroller, the annotations near to the user location. But I don't know how to implement this, the QuadTree class is not accessible and I think there's no way tell the mapView.clusterManager which tree its should use.

maxep commented 6 years ago

Hi @JacoGasp

We need to balance the pros and cons of setting a tree to the cluster manager instead of an array of annotations.

CKQuadTree is private but you can access by importing it:

#import <ClusterKit/CKQuadTree.h>
import ClusterKit.CKQuadTree
jacogasp commented 6 years ago

I changed the target membership of CKQuadTree.h from Private to Public and added the following method to CKClusterManager.m

- (void)setQuadTree:(id<CKAnnotationTree>)quadTree {
    _tree = quadTree;
    _tree.delegate = self;
    [self updateClusters];
}

Then I can simply create a general purpose quadTree object as

var quadTree = CKQuadTree()
quadTree = CKQuadTree(annotations: annotationsArray)

and set the clusterManager of the mapView as

let algorithm = CKNonHierarchicalDistanceBasedAlgorithm()
algorithm.cellSize = 300
mapView.clusterManager.algorithm = algorithm
mapView.clusterManager.marginFactor = 1
mapView.clusterManager.setQuadTree(quadTree)

At this point it is possible to get the annotations within a certain MKMapRegion from any viewController as

 let annotationsInRect = quadTree.annotations(in: rect)

I think it's a very convenient way to access very quickly to the annotations stored into the quadTree object and reuse them for other purposes, preserving the benefits of the quadTree algorithm. The performance seems to be pretty good.