![]() |
OCMapView 1.0
Simple and easy to use clustering mapView.
|
00001 // 00002 // OCAlgorythms.m 00003 // openClusterMapView 00004 // 00005 // Created by Botond Kis on 15.07.11. 00006 // 00007 00008 #import "OCAlgorithms.h" 00009 #import "OCAnnotation.h" 00010 #import "OCDistance.h" 00011 #import "OCGrouping.h" 00012 #import <math.h> 00013 00014 @implementation OCAlgorithms 00015 00016 #pragma mark - bubbleClustering 00017 00018 // Bubble clustering with iteration 00019 + (NSArray*) bubbleClusteringWithAnnotations:(NSArray *) annotationsToCluster andClusterRadius:(CLLocationDistance)radius grouped:(BOOL) grouped{ 00020 00021 // memory 00022 [annotationsToCluster retain]; 00023 00024 // return array 00025 NSMutableArray *clusteredAnnotations = [[NSMutableArray alloc] init]; 00026 00027 // Clustering 00028 for (id <MKAnnotation> annotation in annotationsToCluster) { 00029 // flag for cluster 00030 BOOL isContaining = NO; 00031 00032 // If it's the first one, add it as new cluster annotation 00033 if([clusteredAnnotations count] == 0){ 00034 OCAnnotation *newCluster = [[OCAnnotation alloc] initWithAnnotation:annotation]; 00035 [clusteredAnnotations addObject:newCluster]; 00036 00037 // check group 00038 if (grouped && [annotation respondsToSelector:@selector(groupTag)]) { 00039 newCluster.groupTag = ((id <OCGrouping>)annotation).groupTag; 00040 } 00041 00042 [newCluster release]; 00043 } 00044 else { 00045 for (OCAnnotation *clusterAnnotation in clusteredAnnotations) { 00046 // If the annotation is in range of the Cluster add it to it 00047 if(isLocationNearToOtherLocation([annotation coordinate], [clusterAnnotation coordinate], radius)){ 00048 00049 // check group 00050 if (grouped && [annotation respondsToSelector:@selector(groupTag)]) { 00051 if (![clusterAnnotation.groupTag isEqualToString:((id <OCGrouping>)annotation).groupTag]) 00052 continue; 00053 } 00054 00055 isContaining = YES; 00056 [clusterAnnotation addAnnotation:annotation]; 00057 break; 00058 } 00059 } 00060 00061 // If the annotation is not in a Cluster make it to a new one 00062 if (!isContaining){ 00063 OCAnnotation *newCluster = [[OCAnnotation alloc] initWithAnnotation:annotation]; 00064 [clusteredAnnotations addObject:newCluster]; 00065 00066 // check group 00067 if (grouped && [annotation respondsToSelector:@selector(groupTag)]) { 00068 newCluster.groupTag = ((id <OCGrouping>)annotation).groupTag; 00069 } 00070 00071 [newCluster release]; 00072 } 00073 } 00074 } 00075 00076 NSMutableArray *returnArray = [[NSMutableArray alloc] init]; 00077 00078 // whipe all empty or single annotations 00079 for (OCAnnotation *anAnnotation in clusteredAnnotations) { 00080 if ([anAnnotation.annotationsInCluster count] <= 1) { 00081 [returnArray addObject:[anAnnotation.annotationsInCluster lastObject]]; 00082 } 00083 else{ 00084 [returnArray addObject:anAnnotation]; 00085 } 00086 } 00087 00088 // memory 00089 [annotationsToCluster release]; 00090 [clusteredAnnotations release]; 00091 00092 return [returnArray autorelease]; 00093 } 00094 00095 00096 // Grid clustering with predefined size 00097 + (NSArray*) gridClusteringWithAnnotations:(NSArray *) annotationsToCluster andClusterRect:(MKCoordinateSpan)tileRect grouped:(BOOL) grouped{ 00098 00099 // memory 00100 [annotationsToCluster retain]; 00101 00102 // return array 00103 NSMutableDictionary *clusteredAnnotations = [[NSMutableDictionary alloc] init]; 00104 00105 // iterate through all annotations 00106 for (id <MKAnnotation> annotation in annotationsToCluster) { 00107 00108 // calculate grid coordinates of the annotation 00109 int row = ([annotation coordinate].longitude+180.0)/tileRect.longitudeDelta; 00110 int column = ([annotation coordinate].latitude+90.0)/tileRect.latitudeDelta; 00111 00112 NSString *key = [NSString stringWithFormat:@"%d%d",row,column]; 00113 00114 00115 // get the cluster for the calculated coordinates 00116 OCAnnotation *clusterAnnotation = [[clusteredAnnotations objectForKey:key] retain]; 00117 00118 // if there is none, create one 00119 if (clusterAnnotation == nil) { 00120 clusterAnnotation = [[OCAnnotation alloc] init]; 00121 00122 CLLocationDegrees lon = row * tileRect.longitudeDelta + tileRect.longitudeDelta/2.0 - 180.0; 00123 CLLocationDegrees lat = (column * tileRect.latitudeDelta) + tileRect.latitudeDelta/2.0 - 90.0; 00124 clusterAnnotation.coordinate = CLLocationCoordinate2DMake(lat, lon); 00125 00126 // check group 00127 if (grouped && [annotation respondsToSelector:@selector(groupTag)]) { 00128 clusterAnnotation.groupTag = ((id <OCGrouping>)annotation).groupTag; 00129 } 00130 00131 [clusteredAnnotations setValue:clusterAnnotation forKey:key]; 00132 } 00133 00134 // check group 00135 if (grouped && [annotation respondsToSelector:@selector(groupTag)]) { 00136 if (![clusterAnnotation.groupTag isEqualToString:((id <OCGrouping>)annotation).groupTag]) 00137 continue; 00138 } 00139 00140 // add annotation to the cluster 00141 [clusterAnnotation addAnnotation:annotation]; 00142 [clusterAnnotation release]; 00143 } 00144 00145 // return array 00146 NSMutableArray *returnArray = [[NSMutableArray alloc] init]; 00147 00148 // whipe all empty or single annotations 00149 for (OCAnnotation *anAnnotation in [clusteredAnnotations allValues]) { 00150 if ([anAnnotation.annotationsInCluster count] <= 1) { 00151 [returnArray addObject:[anAnnotation.annotationsInCluster lastObject]]; 00152 } 00153 else{ 00154 [returnArray addObject:anAnnotation]; 00155 } 00156 } 00157 00158 // memory 00159 [annotationsToCluster release]; 00160 [clusteredAnnotations release]; 00161 00162 return [returnArray autorelease]; 00163 } 00164 00165 @end