Authored by Thomas Rasch

o Finer control over the clustering by separating clusterAreaSize and clusterMarkerSize

@@ -84,7 +84,7 @@ typedef enum { @@ -84,7 +84,7 @@ typedef enum {
84 NSMutableSet *visibleAnnotations; 84 NSMutableSet *visibleAnnotations;
85 RMQuadTree *quadTree; 85 RMQuadTree *quadTree;
86 BOOL enableClustering, positionClusterMarkersAtTheGravityCenter; 86 BOOL enableClustering, positionClusterMarkersAtTheGravityCenter;
87 - CGSize clusterMarkerSize; 87 + CGSize clusterMarkerSize, clusterAreaSize;
88 88
89 id <RMTileSource> tileSource; 89 id <RMTileSource> tileSource;
90 RMTileCache *tileCache; // Generic tile cache 90 RMTileCache *tileCache; // Generic tile cache
@@ -125,6 +125,7 @@ typedef enum { @@ -125,6 +125,7 @@ typedef enum {
125 @property (nonatomic, assign) BOOL enableClustering; 125 @property (nonatomic, assign) BOOL enableClustering;
126 @property (nonatomic, assign) BOOL positionClusterMarkersAtTheGravityCenter; 126 @property (nonatomic, assign) BOOL positionClusterMarkersAtTheGravityCenter;
127 @property (nonatomic, assign) CGSize clusterMarkerSize; 127 @property (nonatomic, assign) CGSize clusterMarkerSize;
  128 +@property (nonatomic, assign) CGSize clusterAreaSize;
128 129
129 @property (nonatomic, readonly) RMProjection *projection; 130 @property (nonatomic, readonly) RMProjection *projection;
130 @property (nonatomic, readonly) id <RMMercatorToTileProjection> mercatorToTileProjection; 131 @property (nonatomic, readonly) id <RMMercatorToTileProjection> mercatorToTileProjection;
@@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
110 @synthesize screenScale; 110 @synthesize screenScale;
111 @synthesize tileCache; 111 @synthesize tileCache;
112 @synthesize quadTree; 112 @synthesize quadTree;
113 -@synthesize enableClustering, positionClusterMarkersAtTheGravityCenter, clusterMarkerSize; 113 +@synthesize enableClustering, positionClusterMarkersAtTheGravityCenter, clusterMarkerSize, clusterAreaSize;
114 @synthesize adjustTilesForRetinaDisplay; 114 @synthesize adjustTilesForRetinaDisplay;
115 115
116 #pragma mark - 116 #pragma mark -
@@ -148,6 +148,7 @@ @@ -148,6 +148,7 @@
148 [self setQuadTree:[[[RMQuadTree alloc] initWithMapView:self] autorelease]]; 148 [self setQuadTree:[[[RMQuadTree alloc] initWithMapView:self] autorelease]];
149 enableClustering = positionClusterMarkersAtTheGravityCenter = NO; 149 enableClustering = positionClusterMarkersAtTheGravityCenter = NO;
150 clusterMarkerSize = CGSizeMake(100.0, 100.0); 150 clusterMarkerSize = CGSizeMake(100.0, 100.0);
  151 + clusterAreaSize = CGSizeMake(150.0, 150.0);
151 152
152 [self setTileCache:[[[RMTileCache alloc] init] autorelease]]; 153 [self setTileCache:[[[RMTileCache alloc] init] autorelease]];
153 [self setTileSource:newTilesource]; 154 [self setTileSource:newTilesource];
@@ -1536,7 +1537,11 @@ @@ -1536,7 +1537,11 @@
1536 boundingBox.size.width += 2*boundingBoxBuffer; 1537 boundingBox.size.width += 2*boundingBoxBuffer;
1537 boundingBox.size.height += 2*boundingBoxBuffer; 1538 boundingBox.size.height += 2*boundingBoxBuffer;
1538 1539
1539 - NSArray *annotationsToCorrect = [quadTree annotationsInProjectedRect:boundingBox createClusterAnnotations:self.enableClustering withClusterSize:RMProjectedSizeMake(self.clusterMarkerSize.width * self.metersPerPixel, self.clusterMarkerSize.height * self.metersPerPixel) findGravityCenter:self.positionClusterMarkersAtTheGravityCenter]; 1540 + NSArray *annotationsToCorrect = [quadTree annotationsInProjectedRect:boundingBox
  1541 + createClusterAnnotations:self.enableClustering
  1542 + withProjectedClusterSize:RMProjectedSizeMake(self.clusterAreaSize.width * self.metersPerPixel, self.clusterAreaSize.height * self.metersPerPixel)
  1543 + andProjectedClusterMarkerSize:RMProjectedSizeMake(self.clusterMarkerSize.width * self.metersPerPixel, self.clusterMarkerSize.height * self.metersPerPixel)
  1544 + findGravityCenter:self.positionClusterMarkersAtTheGravityCenter];
1540 NSMutableSet *previousVisibleAnnotations = [[NSMutableSet alloc] initWithSet:visibleAnnotations]; 1545 NSMutableSet *previousVisibleAnnotations = [[NSMutableSet alloc] initWithSet:visibleAnnotations];
1541 1546
1542 for (RMAnnotation *annotation in annotationsToCorrect) 1547 for (RMAnnotation *annotation in annotationsToCorrect)
@@ -76,6 +76,10 @@ typedef enum { @@ -76,6 +76,10 @@ typedef enum {
76 76
77 // Returns all annotations that are either inside of or intersect with boundingBox 77 // Returns all annotations that are either inside of or intersect with boundingBox
78 - (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox; 78 - (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox;
79 -- (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox createClusterAnnotations:(BOOL)createClusterAnnotations withClusterSize:(RMProjectedSize)clusterSize findGravityCenter:(BOOL)findGravityCenter; 79 +- (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox
  80 + createClusterAnnotations:(BOOL)createClusterAnnotations
  81 + withProjectedClusterSize:(RMProjectedSize)clusterSize
  82 + andProjectedClusterMarkerSize:(RMProjectedSize)clusterMarkerSize
  83 + findGravityCenter:(BOOL)findGravityCenter;
80 84
81 @end 85 @end
@@ -25,7 +25,12 @@ @@ -25,7 +25,12 @@
25 - (void)addAnnotation:(RMAnnotation *)annotation; 25 - (void)addAnnotation:(RMAnnotation *)annotation;
26 - (void)removeAnnotation:(RMAnnotation *)annotation; 26 - (void)removeAnnotation:(RMAnnotation *)annotation;
27 27
28 -- (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox toMutableArray:(NSMutableArray *)someArray createClusterAnnotations:(BOOL)createClusterAnnotations withClusterSize:(RMProjectedSize)clusterSize findGravityCenter:(BOOL)findGravityCenter; 28 +- (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox
  29 + toMutableArray:(NSMutableArray *)someArray
  30 + createClusterAnnotations:(BOOL)createClusterAnnotations
  31 + withProjectedClusterSize:(RMProjectedSize)clusterSize
  32 + andProjectedClusterMarkerSize:(RMProjectedSize)clusterMarkerSize
  33 + findGravityCenter:(BOOL)findGravityCenter;
29 34
30 - (void)removeUpwardsAllCachedClusterAnnotations; 35 - (void)removeUpwardsAllCachedClusterAnnotations;
31 36
@@ -363,7 +368,12 @@ @@ -363,7 +368,12 @@
363 return clusteredAnnotations; 368 return clusteredAnnotations;
364 } 369 }
365 370
366 -- (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox toMutableArray:(NSMutableArray *)someArray createClusterAnnotations:(BOOL)createClusterAnnotations withClusterSize:(RMProjectedSize)clusterSize findGravityCenter:(BOOL)findGravityCenter 371 +- (void)addAnnotationsInBoundingBox:(RMProjectedRect)aBoundingBox
  372 + toMutableArray:(NSMutableArray *)someArray
  373 + createClusterAnnotations:(BOOL)createClusterAnnotations
  374 + withProjectedClusterSize:(RMProjectedSize)clusterSize
  375 + andProjectedClusterMarkerSize:(RMProjectedSize)clusterMarkerSize
  376 + findGravityCenter:(BOOL)findGravityCenter
367 { 377 {
368 if (createClusterAnnotations) 378 if (createClusterAnnotations)
369 { 379 {
@@ -455,16 +465,17 @@ @@ -455,16 +465,17 @@
455 averageX /= (double)enclosedAnnotationsCount; 465 averageX /= (double)enclosedAnnotationsCount;
456 averageY /= (double) enclosedAnnotationsCount; 466 averageY /= (double) enclosedAnnotationsCount;
457 467
458 - double halfClusterWidth = clusterSize.width / 2.0, halfClusterHeight = clusterSize.height / 2.0; 468 + double halfClusterMarkerWidth = clusterMarkerSize.width / 2.0,
  469 + halfClusterMarkerHeight = clusterMarkerSize.height / 2.0;
459 470
460 - if (averageX - halfClusterWidth < boundingBox.origin.x)  
461 - averageX = boundingBox.origin.x + halfClusterWidth;  
462 - if (averageX + halfClusterWidth > boundingBox.origin.x + boundingBox.size.width)  
463 - averageX = boundingBox.origin.x + boundingBox.size.width - halfClusterWidth;  
464 - if (averageY - halfClusterHeight < boundingBox.origin.y)  
465 - averageY = boundingBox.origin.y + halfClusterHeight;  
466 - if (averageY + halfClusterHeight > boundingBox.origin.y + boundingBox.size.height)  
467 - averageY = boundingBox.origin.y + boundingBox.size.height - halfClusterHeight; 471 + if (averageX - halfClusterMarkerWidth < boundingBox.origin.x)
  472 + averageX = boundingBox.origin.x + halfClusterMarkerWidth;
  473 + if (averageX + halfClusterMarkerWidth > boundingBox.origin.x + boundingBox.size.width)
  474 + averageX = boundingBox.origin.x + boundingBox.size.width - halfClusterMarkerWidth;
  475 + if (averageY - halfClusterMarkerHeight < boundingBox.origin.y)
  476 + averageY = boundingBox.origin.y + halfClusterMarkerHeight;
  477 + if (averageY + halfClusterMarkerHeight > boundingBox.origin.y + boundingBox.size.height)
  478 + averageY = boundingBox.origin.y + boundingBox.size.height - halfClusterMarkerHeight;
468 479
469 // TODO: anchorPoint 480 // TODO: anchorPoint
470 clusterMarkerPosition = RMProjectedPointMake(averageX, averageY); 481 clusterMarkerPosition = RMProjectedPointMake(averageX, averageY);
@@ -515,13 +526,13 @@ @@ -515,13 +526,13 @@
515 } 526 }
516 527
517 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, northWestBoundingBox)) 528 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, northWestBoundingBox))
518 - [northWest addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withClusterSize:clusterSize findGravityCenter:findGravityCenter]; 529 + [northWest addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withProjectedClusterSize:clusterSize andProjectedClusterMarkerSize:clusterMarkerSize findGravityCenter:findGravityCenter];
519 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, northEastBoundingBox)) 530 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, northEastBoundingBox))
520 - [northEast addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withClusterSize:clusterSize findGravityCenter:findGravityCenter]; 531 + [northEast addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withProjectedClusterSize:clusterSize andProjectedClusterMarkerSize:clusterMarkerSize findGravityCenter:findGravityCenter];
521 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, southWestBoundingBox)) 532 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, southWestBoundingBox))
522 - [southWest addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withClusterSize:clusterSize findGravityCenter:findGravityCenter]; 533 + [southWest addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withProjectedClusterSize:clusterSize andProjectedClusterMarkerSize:clusterMarkerSize findGravityCenter:findGravityCenter];
523 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, southEastBoundingBox)) 534 if (RMProjectedRectIntersectsProjectedRect(aBoundingBox, southEastBoundingBox))
524 - [southEast addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withClusterSize:clusterSize findGravityCenter:findGravityCenter]; 535 + [southEast addAnnotationsInBoundingBox:aBoundingBox toMutableArray:someArray createClusterAnnotations:createClusterAnnotations withProjectedClusterSize:clusterSize andProjectedClusterMarkerSize:clusterMarkerSize findGravityCenter:findGravityCenter];
525 536
526 @synchronized (annotations) 537 @synchronized (annotations)
527 { 538 {
@@ -616,16 +627,16 @@ @@ -616,16 +627,16 @@
616 627
617 - (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox 628 - (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox
618 { 629 {
619 - return [self annotationsInProjectedRect:boundingBox createClusterAnnotations:NO withClusterSize:RMProjectedSizeMake(0.0, 0.0) findGravityCenter:NO]; 630 + return [self annotationsInProjectedRect:boundingBox createClusterAnnotations:NO withProjectedClusterSize:RMProjectedSizeMake(0.0, 0.0) andProjectedClusterMarkerSize:RMProjectedSizeMake(0.0, 0.0) findGravityCenter:NO];
620 } 631 }
621 632
622 -- (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox createClusterAnnotations:(BOOL)createClusterAnnotations withClusterSize:(RMProjectedSize)clusterSize findGravityCenter:(BOOL)findGravityCenter 633 +- (NSArray *)annotationsInProjectedRect:(RMProjectedRect)boundingBox createClusterAnnotations:(BOOL)createClusterAnnotations withProjectedClusterSize:(RMProjectedSize)clusterSize andProjectedClusterMarkerSize:(RMProjectedSize)clusterMarkerSize findGravityCenter:(BOOL)findGravityCenter
623 { 634 {
624 NSMutableArray *annotations = [NSMutableArray array]; 635 NSMutableArray *annotations = [NSMutableArray array];
625 636
626 @synchronized (self) 637 @synchronized (self)
627 { 638 {
628 - [rootNode addAnnotationsInBoundingBox:boundingBox toMutableArray:annotations createClusterAnnotations:createClusterAnnotations withClusterSize:clusterSize findGravityCenter:findGravityCenter]; 639 + [rootNode addAnnotationsInBoundingBox:boundingBox toMutableArray:annotations createClusterAnnotations:createClusterAnnotations withProjectedClusterSize:clusterSize andProjectedClusterMarkerSize:clusterMarkerSize findGravityCenter:findGravityCenter];
629 } 640 }
630 641
631 return annotations; 642 return annotations;
@@ -92,6 +92,10 @@ @@ -92,6 +92,10 @@
92 mapView.enableClustering = YES; 92 mapView.enableClustering = YES;
93 mapView.positionClusterMarkersAtTheGravityCenter = YES; 93 mapView.positionClusterMarkersAtTheGravityCenter = YES;
94 94
  95 + UIImage *clusterMarkerImage = [UIImage imageNamed:@"marker-blue.png"];
  96 + mapView.clusterMarkerSize = clusterMarkerImage.size;
  97 + mapView.clusterAreaSize = CGSizeMake(clusterMarkerImage.size.width * 1.25, clusterMarkerImage.size.height * 1.25);
  98 +
95 center.latitude = 47.5635; 99 center.latitude = 47.5635;
96 center.longitude = 10.20981; 100 center.longitude = 10.20981;
97 101