Said in the previous
In order to realize the aggregation display of a large number of annotation points on the map, the annotation points are dynamically arranged according to the change of the center point and the zoom ratio and complete the function of point aggregation. Now provides a point aggregation implementation method based on AUtonavi SDK.
The following are the effect pictures of the aggregation of the labeled points under the two scaling ratios:
Train of thought
Early ideas
The server computes the annotation statistics and loads the drawing on the client
In the early stage of pre-research, I considered the way to obtain data from the background and add overlay on the map. However, considering that user operations require all data to be generated and displayed in real time, which means that every time the zoom ratio and center point is changed, the server must be visited to reload the data, which is quite difficult to achieve. And the server and the client have caused a great pressure.
All data is loaded at once, and the client implementation algorithm calculates overloads as needed
When reading the API provided by Autonavi Open Platform, I found that amap Sample Center updated the point aggregation effect sample on February 10, 2017.
Its application scenario is as follows: There are too many markers to be displayed on the local map, which may lead to marker capping and performance deterioration on the interface. Using the point aggregation feature, you can solve this problem.
Principle and Implementation
architecture
Controllers
<UIViewController>
BaseMapViewController
Map the base class
AnnotationClusterViewController
Poi point aggregationPoiDetailViewController
The POI details list is displayedView
MAAnnotationView
ClusterAnnotationView
Custom aggregate annotationViewModels
Conform to <MAAnnotation>
ClusterAnnotation
Record the information of annotations, such as the array of POIS it represents, the number of POIS, and the average coordinate of POIS, and provide a judgment on whether two annotations are EqualCoordinateQuadTree
Encapsulated quadtree classesQuadTree
Quadtree basic algorithm
The core code
Point aggregation algorithm Autonavi official code (iOS) seeiOS_3D_ClusterAnnotationIn the making.
Implemented in the project
Introduction of AMap3DMap (currently in version 4.3.0)
Pod 'AMap3DMap', '~ > 4.3.0'Copy the code
Download and add MAAnnotationCluster
Add points to the map
createMAClusteringManager
andMAClusterAnimator
@property(nonatomic,strong)MAClusteringManager * clusteringManager ;
@property(nonatomic,strong)MAClusterAnimator * animator;Copy the code
Initialize the callout point group
NSMutableArray *pointAnnotations = [NSMutableArray array];Copy the code
Adds a point with location information to the array
for (int i = 0; i < [receivedData count]; i ++) {
NSDictionary *annotationDict = receivedData[i];
CGFloat lat = [[annotationDict objectForKey:@"latitude"] floatValue];
CGFloat lon = [[annotationDict objectForKey:@"longitude"] floatValue];
NSNumber *pID = [annotationDict objectForKey:@"id"];
MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];
pointAnnotation.coordinate = CLLocationCoordinate2DMake(lat, lon);
pointAnnotation.title = [pID stringValue];
[pointAnnotations addObject:pointAnnotation];
}
self.animator = [[MAClusterAnimator alloc] init];
self.clusteringManager = [[MAClusteringManager alloc] initWithAnnotations:pointAnnotations];
self.clusteringManager.delegate = self;
[self mapView:_mapView regionDidChangeAnimated:YES];Copy the code
ReceivedData can be obtained from the background or generated locally, including the longitude, latitude, and pID, that is, the unique ID of each annotation point. MapView regionDidChangeAnimated: The mapView regionDidChangeAnimated method is called automatically when the mapView region changes, the annotation is recalcated, and the annotation is called manually once during initialization so that the annotation points are loaded on the map as an aggregate.
implementationMapView regionDidChangeAnimated:
Method body
double scale = mapView.bounds.size.width / mapView.visibleMapRect.size.width; [[NSOperationQueue new] addOperationWithBlock:^{ // Get the main queue and do the UI stuff . NSArray *annatations = [NSArray array]; annatations = [self.clusteringManager clusteredAnnotationsWithinMapRect:mapView.visibleMapRect withZoomScale:scale]; [self.clusteringManager displayAnnotations:annatations onMapView:mapView]; }];Copy the code
Note: Multithreading must be used here
According to theMAClusteringManager
The calculated quantity is modifiedAnnotation
Style.
In the mapView viewForAnnotation: method
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation { static NSString *const AnnotatioViewReuseID = @"AnnotatioViewReuseID"; static NSString *const ClusterAnnotationReuseID = @"ClusterAnnotationReuseID"; static NSString *const SingleClusterAnnotationRauseID = @"SingleClusterAnnotationRauseID"; If ([annotation isannotation Cluster class :[MAAnnotationCluster class]]) {// MAAnnotationCluster *cluster = (MAAnnotationCluster) *)annotation; cluster.title = [NSString stringWithFormat:@"%zd items",[cluster.annotations count]]; MAClusterAnnotationView *clusterView = (MAClusterAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ClusterAnnotationReuseID]; if (! clusterView) { clusterView = [[MAClusterAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ClusterAnnotationReuseID]; clusterView.canShowCallout = NO; clusterView.clusterColor = ClusterColor; } clusterView.count = [((MAAnnotationCluster *)annotation).annotations count]; return clusterView; }else { if ([annotation isKindOfClass:[MAPointAnnotation class]]) { MAAnnotationView *poiAnnotationView = (MAAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotatioViewReuseID]; if ([[annotation title] isEqualToString:(NSString*)RoutePlanningViewControllerStartTitle]) { poiAnnotationView.image = [UIImage imageNamed:@""]; return poiAnnotationView; }else if([[annotation title] isEqualToString:(NSString *)RoutePlanningViewControllerDestinationTitle]) { poiAnnotationView.image = [UIImage imageNamed:@"ani"]; return poiAnnotationView; }else { MAClusterAnnotationView *clusterView = (MAClusterAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ClusterAnnotationReuseID]; if (! clusterView) { clusterView = [[MAClusterAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:SingleClusterAnnotationRauseID]; clusterView.canShowCallout = NO; clusterView.clusterColor = ClusterColor; } clusterView.count = 1; return clusterView; } }else { return nil; }}}Copy the code
In this way, the point aggregation function is realized on the basis of quadtree algorithm.