From af3a8e9d480b152ab3a9f437117e0f6de629acd6 Mon Sep 17 00:00:00 2001 From: Pepito Go-Oco Date: Wed, 13 Jan 2016 16:15:20 +0800 Subject: [PATCH 1/3] Clean up newlines --- .../CCHMapClusterController.m | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/CCHMapClusterController/CCHMapClusterController.m b/CCHMapClusterController/CCHMapClusterController.m index d6ee90c..c7f1c5f 100644 --- a/CCHMapClusterController/CCHMapClusterController.m +++ b/CCHMapClusterController/CCHMapClusterController.m @@ -77,7 +77,7 @@ - (instancetype)initWithMapView:(MKMapView *)mapView _visibleAnnotationsMapTree = [[CCHMapTree alloc] initWithNodeCapacity:NODE_CAPACITY minLatitude:WORLD_MIN_LAT maxLatitude:WORLD_MAX_LAT minLongitude:WORLD_MIN_LON maxLongitude:WORLD_MAX_LON]; _backgroundQueue = [[NSOperationQueue alloc] init]; _backgroundQueue.maxConcurrentOperationCount = 1; // sync access to allAnnotationsMapTree & visibleAnnotationsMapTree - + if ([mapView.delegate isKindOfClass:CCHMapViewDelegateProxy.class]) { CCHMapViewDelegateProxy *delegateProxy = (CCHMapViewDelegateProxy *)mapView.delegate; [delegateProxy addDelegate:self]; @@ -85,7 +85,7 @@ - (instancetype)initWithMapView:(MKMapView *)mapView } else { _mapViewDelegateProxy = [[CCHMapViewDelegateProxy alloc] initWithMapView:mapView delegate:self]; } - + // Keep strong reference to default instance because public property is weak id clusterer = [[CCHCenterOfMassMapClusterer alloc] init]; _clusterer = clusterer; @@ -93,10 +93,10 @@ - (instancetype)initWithMapView:(MKMapView *)mapView id animator = [[CCHFadeInOutMapAnimator alloc] init]; _animator = animator; _strongAnimator = animator; - + [self setReuseExistingClusterAnnotations:YES]; } - + return self; } @@ -136,9 +136,9 @@ - (void)cancelAllClusterOperations - (void)addAnnotations:(NSArray *)annotations withCompletionHandler:(void (^)())completionHandler { [self cancelAllClusterOperations]; - + [self.allAnnotations addObjectsFromArray:annotations]; - + [self.backgroundQueue addOperationWithBlock:^{ BOOL updated = [self.allAnnotationsMapTree addAnnotations:annotations]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -154,9 +154,9 @@ - (void)addAnnotations:(NSArray *)annotations withCompletionHandler:(void (^)()) - (void)removeAnnotations:(NSArray *)annotations withCompletionHandler:(void (^)())completionHandler { [self cancelAllClusterOperations]; - + [self.allAnnotations minusSet:[NSSet setWithArray:annotations]]; - + [self.backgroundQueue addOperationWithBlock:^{ BOOL updated = [self.allAnnotationsMapTree removeAnnotations:annotations]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -172,7 +172,7 @@ - (void)removeAnnotations:(NSArray *)annotations withCompletionHandler:(void (^) - (void)updateAnnotationsWithCompletionHandler:(void (^)())completionHandler { [self cancelAllClusterOperations]; - + CCHMapClusterOperation *operation = [[CCHMapClusterOperation alloc] initWithMapView:self.mapView cellSize:self.cellSize marginFactor:self.marginFactor @@ -185,7 +185,7 @@ - (void)updateAnnotationsWithCompletionHandler:(void (^)())completionHandler operation.animator = self.animator; operation.clusterControllerDelegate = self.delegate; operation.clusterController = self; - + if (completionHandler) { operation.completionBlock = ^{ dispatch_async(dispatch_get_main_queue(), ^{ @@ -193,9 +193,9 @@ - (void)updateAnnotationsWithCompletionHandler:(void (^)())completionHandler }); }; }; - + [self.backgroundQueue addOperation:operation]; - + // Debugging if (self.isDebuggingEnabled) { double cellMapSize = [CCHMapClusterOperation cellMapSizeForCellSize:self.cellSize withMapView:self.mapView]; @@ -207,7 +207,7 @@ - (void)updateAnnotationsWithCompletionHandler:(void (^)())completionHandler - (void)updateDebugPolygonsInGridMapRect:(MKMapRect)gridMapRect withCellMapSize:(double)cellMapSize { MKMapView *mapView = self.mapView; - + // Remove old polygons for (id overlay in mapView.overlays) { if ([overlay isKindOfClass:CCHMapClusterControllerDebugPolygon.class]) { @@ -217,11 +217,11 @@ - (void)updateDebugPolygonsInGridMapRect:(MKMapRect)gridMapRect withCellMapSize: } } } - + // Add polygons outlining each cell CCHMapClusterControllerEnumerateCells(gridMapRect, cellMapSize, ^(MKMapRect cellMapRect) { // cellMapRect.origin.x -= MKMapSizeWorld.width; // fixes issue when view port spans 180th meridian - + MKMapPoint points[4]; points[0] = MKMapPointMake(MKMapRectGetMinX(cellMapRect), MKMapRectGetMinY(cellMapRect)); points[1] = MKMapPointMake(MKMapRectGetMaxX(cellMapRect), MKMapRectGetMinY(cellMapRect)); @@ -249,10 +249,10 @@ - (void)selectAnnotation:(id)annotation andZoomToRegionWithLatitud if (!existingAnnotation) { return; } - + // Deselect annotations [self deselectAllAnnotations]; - + // Zoom to annotation self.annotationToSelect = annotation; MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, latitudinalMeters, longitudinalMeters); @@ -281,7 +281,7 @@ - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { self.regionChanging = NO; - + // Deselect all annotations when zooming in/out. Longitude delta will not change // unless zoom changes (in contrast to latitude delta). BOOL hasZoomed = !fequal(mapView.region.span.longitudeDelta, self.regionSpanBeforeChange.longitudeDelta); From 8930d3f8e6504b90f5cf884b93850a02a0fbd997 Mon Sep 17 00:00:00 2001 From: Pepito Go-Oco Date: Wed, 13 Jan 2016 16:15:59 +0800 Subject: [PATCH 2/3] Change hasZoomed criteria to use zoomLevel --- .../CCHMapClusterController.m | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/CCHMapClusterController/CCHMapClusterController.m b/CCHMapClusterController/CCHMapClusterController.m index c7f1c5f..598e805 100644 --- a/CCHMapClusterController/CCHMapClusterController.m +++ b/CCHMapClusterController/CCHMapClusterController.m @@ -62,7 +62,9 @@ @interface CCHMapClusterController() @end -@implementation CCHMapClusterController +@implementation CCHMapClusterController { + double _zoomLevelBeforeChange; +} - (instancetype)initWithMapView:(MKMapView *)mapView { @@ -274,6 +276,7 @@ - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)annotation - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { + _zoomLevelBeforeChange = self.zoomLevel; self.regionSpanBeforeChange = mapView.region.span; self.regionChanging = YES; } @@ -284,37 +287,37 @@ - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated // Deselect all annotations when zooming in/out. Longitude delta will not change // unless zoom changes (in contrast to latitude delta). - BOOL hasZoomed = !fequal(mapView.region.span.longitudeDelta, self.regionSpanBeforeChange.longitudeDelta); + BOOL hasZoomed = fabs(self.zoomLevel - _zoomLevelBeforeChange) > 0.001; if (hasZoomed) { [self deselectAllAnnotations]; - } - - // Update annotations - [self updateAnnotationsWithCompletionHandler:^{ - if (self.annotationToSelect) { - // Map has zoomed to selected annotation; search for cluster annotation that contains this annotation - CCHMapClusterAnnotation *mapClusterAnnotation = CCHMapClusterControllerClusterAnnotationForAnnotation(self.mapView, self.annotationToSelect, mapView.visibleMapRect); - self.annotationToSelect = nil; - - if (CCHMapClusterControllerCoordinateEqualToCoordinate(self.mapView.centerCoordinate, mapClusterAnnotation.coordinate)) { - // Select immediately since region won't change - [self.mapView selectAnnotation:mapClusterAnnotation animated:YES]; - } else { - // Actual selection happens in next call to mapView:regionDidChangeAnimated: - self.mapClusterAnnotationToSelect = mapClusterAnnotation; - - // Dispatch async to avoid calling regionDidChangeAnimated immediately - dispatch_async(dispatch_get_main_queue(), ^{ - // No zooming, only panning. Otherwise, annotation might change to a different cluster annotation - [self.mapView setCenterCoordinate:mapClusterAnnotation.coordinate animated:NO]; - }); + + // Update annotations + [self updateAnnotationsWithCompletionHandler:^{ + if (self.annotationToSelect) { + // Map has zoomed to selected annotation; search for cluster annotation that contains this annotation + CCHMapClusterAnnotation *mapClusterAnnotation = CCHMapClusterControllerClusterAnnotationForAnnotation(self.mapView, self.annotationToSelect, mapView.visibleMapRect); + self.annotationToSelect = nil; + + if (CCHMapClusterControllerCoordinateEqualToCoordinate(self.mapView.centerCoordinate, mapClusterAnnotation.coordinate)) { + // Select immediately since region won't change + [self.mapView selectAnnotation:mapClusterAnnotation animated:YES]; + } else { + // Actual selection happens in next call to mapView:regionDidChangeAnimated: + self.mapClusterAnnotationToSelect = mapClusterAnnotation; + + // Dispatch async to avoid calling regionDidChangeAnimated immediately + dispatch_async(dispatch_get_main_queue(), ^{ + // No zooming, only panning. Otherwise, annotation might change to a different cluster annotation + [self.mapView setCenterCoordinate:mapClusterAnnotation.coordinate animated:NO]; + }); + } + } else if (self.mapClusterAnnotationToSelect) { + // Map has zoomed to annotation + [self.mapView selectAnnotation:self.mapClusterAnnotationToSelect animated:YES]; + self.mapClusterAnnotationToSelect = nil; } - } else if (self.mapClusterAnnotationToSelect) { - // Map has zoomed to annotation - [self.mapView selectAnnotation:self.mapClusterAnnotationToSelect animated:YES]; - self.mapClusterAnnotationToSelect = nil; - } - }]; + }]; + } } @end From ddf333666d89f488cb177036fb9309d9b11579cb Mon Sep 17 00:00:00 2001 From: Pepito Go-Oco Date: Fri, 15 Jan 2016 14:58:15 +0800 Subject: [PATCH 3/3] Increase zoom change threshold --- CCHMapClusterController/CCHMapClusterController.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CCHMapClusterController/CCHMapClusterController.m b/CCHMapClusterController/CCHMapClusterController.m index 598e805..c3c3838 100644 --- a/CCHMapClusterController/CCHMapClusterController.m +++ b/CCHMapClusterController/CCHMapClusterController.m @@ -42,6 +42,7 @@ #define WORLD_MAX_LAT 85 #define WORLD_MIN_LON -180 #define WORLD_MAX_LON 180 +#define ZOOM_EPSILON 0.002 #define fequal(a, b) (fabs((a) - (b)) < __FLT_EPSILON__) @@ -287,8 +288,9 @@ - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated // Deselect all annotations when zooming in/out. Longitude delta will not change // unless zoom changes (in contrast to latitude delta). - BOOL hasZoomed = fabs(self.zoomLevel - _zoomLevelBeforeChange) > 0.001; + BOOL hasZoomed = fabs(self.zoomLevel - _zoomLevelBeforeChange) > ZOOM_EPSILON; if (hasZoomed) { + NSLog(@"Zoom 𝛥: %f", fabs(self.zoomLevel - _zoomLevelBeforeChange)); [self deselectAllAnnotations]; // Update annotations