Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single annotation exists in multiple clusters? #43

Open
solomon-gumball opened this issue Jan 23, 2018 · 5 comments
Open

Single annotation exists in multiple clusters? #43

solomon-gumball opened this issue Jan 23, 2018 · 5 comments

Comments

@solomon-gumball
Copy link

I've been attempting to integrate ClusterKit into our app but it seems at certain zoom levels a single annotation may exist in multiple clusters which looks strange. Here is a gif illustrating the issue:

clusteringissue

Here you can see that there are just 3 annotations, but when I zoom out to a certain level it goes from clusters of 2 and 1 to clusters of 2 and 2 and then when zooming out more it goes to one cluster of 3. There are actually only 3 annotations so it seems they are mistakenly sharing an annotation at a specific zoom level.

The code I've added so far is pretty straightforward and follows your example quite closely.

I add the algorithm with a custom cell size:

    CKNonHierarchicalDistanceBasedAlgorithm *algorithm = [CKNonHierarchicalDistanceBasedAlgorithm new];
    algorithm.cellSize = 200;
    _mapView.clusterManager.algorithm = algorithm;
    _mapView.clusterManager.marginFactor = 1;

Creating MKAnnotationViews and setting the annotation:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }

    MKAnnotationView *mapAnnotationView = nil;
    mapAnnotationView = (GWTicketsGroupedByLocationPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pinAllTicketsAnnotationIdentifier];
    if ([annotation isKindOfClass:CKCluster.class]) {
        return [[GroupedGigAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinAllTicketsAnnotationIdentifier];
    }

    [mapAnnotationView setAnnotation:annotation];

    return mapAnnotationView;
}

and updating the clusters when region changes:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    [_mapView.clusterManager updateClustersIfNeeded];
}

Is there something wrong with the distance based algorithm or am I doing something incorrectly?

@vijayradke
Copy link

Any resolution of the issue?

@solomon-gumball
Copy link
Author

@vijayradke Yea. Used a different library lol

@vijayradke
Copy link

May I know which one you used?

@solomon-gumball
Copy link
Author

I used CCHMapClusterController. It doesn't have the nice pin location animations but it works and it's easy to use.

@ZalyalovIldar
Copy link

Just fix this with next line of codes:

Add open orderedSet to CKCluster.h:

- (NSMutableOrderedSet<id<MKAnnotation>> *) orderedSet;

In realisation CKCluster.m just return _annotations:

- (NSMutableOrderedSet<id<MKAnnotation>> *) orderedSet {
    return _annotations;
}

And inside CKClusterManager.m update private method:

- (void)updateMapRect:(MKMapRect)visibleMapRect animated:(BOOL)animated {
    if (!self.tree || MKMapRectIsNull(visibleMapRect) || MKMapRectIsEmpty(visibleMapRect)) {
        return;
    }
    
    MKMapRect clusterMapRect = MKMapRectWorld;
    if (self.marginFactor != kCKMarginFactorWorld) {
        clusterMapRect = MKMapRectInset(visibleMapRect,
                                        -self.marginFactor * visibleMapRect.size.width,
                                        -self.marginFactor * visibleMapRect.size.height);
    }
    
    double zoom = self.map.zoom;
    CKClusterAlgorithm *algorithm = (zoom < self.maxZoomLevel)? self.algorithm : [CKClusterAlgorithm new];
    NSArray *clusters = [algorithm clustersInRect:clusterMapRect zoom:zoom tree:self.tree];
    
   //------HERE the moment that delete all duplicates from clusters 
    for (CKCluster* cluster in clusters) {
        for (CKCluster* secondCluster in clusters) {
            
            if (![secondCluster isEqualToCluster:cluster] && [secondCluster intersectsCluster:cluster]) {
                
                NSMutableSet<id<MKAnnotation>> *secondSet = secondCluster.orderedSet.set.mutableCopy;
                
                [cluster.orderedSet minusSet:secondSet];
            }
        }
    }
    //---------------------------------------
    NSMutableSet *newClusters = [NSMutableSet setWithArray:clusters];
    NSMutableSet *oldClusters = [NSMutableSet setWithSet:_clusters];
    
    [oldClusters minusSet:newClusters];
    [newClusters minusSet:_clusters];
    
    if (visibleMapRect.size.width > _visibleMapRect.size.width) {
        [self collapse:oldClusters.allObjects to:newClusters.allObjects in:visibleMapRect];
        
    } else if (visibleMapRect.size.width < _visibleMapRect.size.width) {
        [self expand:newClusters.allObjects from:oldClusters.allObjects in:visibleMapRect];
        
    } else {
        [self.map addClusters:newClusters.allObjects];
        [self.map removeClusters:oldClusters.allObjects];
    }
    
    [_clusters minusSet:oldClusters];
    [_clusters unionSet:newClusters];
    
    _visibleMapRect = visibleMapRect;
}

Not optimised but although work perfectly.

dubraf pushed a commit to dubraf/ClusterKit that referenced this issue Dec 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants