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:





The overall effect





Local effect

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>
    • BaseMapViewControllerMap the base class
      • AnnotationClusterViewControllerPoi point aggregation
    • PoiDetailViewControllerThe POI details list is displayed

View

  • MAAnnotationView
    • ClusterAnnotationViewCustom aggregate annotationView

Models

  • Conform to <MAAnnotation>
    • ClusterAnnotationRecord 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 Equal
  • CoordinateQuadTreeEncapsulated quadtree classes
  • QuadTreeQuadtree 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

createMAClusteringManagerandMAClusterAnimator

@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 theMAClusteringManagerThe calculated quantity is modifiedAnnotationStyle.

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.