How can I reduce the number of annotations on a map?

后端 未结 6 1469
时光说笑
时光说笑 2020-12-13 11:03

I\'m coding a map view with around 900 annotations. Having this many annotations on a map make the performance suffer, so I\'d like to reduce it to about 300 at a time. The

6条回答
  •  北海茫月
    2020-12-13 11:31

    Late to the party, I know, but you may find this routine useful. It comes from this file, which is part of a FOSS project.

    /**************************************************************//**
     \brief This function looks for meetings in close proximity to each
            other, and collects them into "red markers."
     \returns an NSArray of BMLT_Results_MapPointAnnotation objects.
     *****************************************************************/
    - (NSArray *)mapMeetingAnnotations:(NSArray *)inResults ///< This is an NSArray of BMLT_Meeting objects. Each one represents a meeting.
    {
    #ifdef DEBUG
        NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations - Checking %d Meetings.", [inResults count]);
    #endif
        NSMutableArray  *ret = nil;
    
        NSInteger   displayIndex = 1;
    
        if ( [inResults count] )
            {
            NSMutableArray  *points = [[NSMutableArray alloc] init];
            for ( BMLT_Meeting *meeting in inResults )
                {
    #ifdef DEBUG
                NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations - Checking Meeting \"%@\".", [meeting getBMLTName]);
    #endif
                CLLocationCoordinate2D  meetingLocation = [meeting getMeetingLocationCoords].coordinate;
                CGPoint meetingPoint = [(MKMapView *)[self view] convertCoordinate:meetingLocation toPointToView:nil];
                CGRect  hitTestRect = CGRectMake(meetingPoint.x - BMLT_Meeting_Distance_Threshold_In_Pixels,
                                                 meetingPoint.y - BMLT_Meeting_Distance_Threshold_In_Pixels,
                                                 BMLT_Meeting_Distance_Threshold_In_Pixels * 2,
                                                 BMLT_Meeting_Distance_Threshold_In_Pixels * 2);
    
                BMLT_Results_MapPointAnnotation *annotation = nil;
    #ifdef DEBUG
                NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations - Meeting \"%@\" Has the Following Hit Test Rect: (%f, %f), (%f, %f).", [meeting getBMLTName], hitTestRect.origin.x, hitTestRect.origin.y, hitTestRect.size.width, hitTestRect.size.height);
    #endif
    
                for ( BMLT_Results_MapPointAnnotation *annotationTemp in points )
                    {
                    CGPoint annotationPoint = [(MKMapView *)[self view] convertCoordinate:annotationTemp.coordinate toPointToView:nil];
    #ifdef DEBUG
                    NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations - Comparing the Following Annotation Point: (%f, %f).", annotationPoint.x, annotationPoint.y);
    #endif
    
                    if ( !([[annotationTemp getMyMeetings] containsObject:meeting]) && CGRectContainsPoint(hitTestRect, annotationPoint) )
                        {
    #ifdef DEBUG
                        for ( BMLT_Meeting *t_meeting in [annotationTemp getMyMeetings] )
                            {
                            NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations - Meeting \"%@\" Is Close to \"%@\".", [meeting getBMLTName], [t_meeting getBMLTName]);
                            }
    #endif
                        annotation = annotationTemp;
                        }
                    }
    
                if ( !annotation )
                    {
    #ifdef DEBUG
                    NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations -This meeting gets its own annotation.");
    #endif
                    NSArray *meetingsAr = [[NSArray alloc] initWithObjects:meeting, nil];  
                    annotation = [[BMLT_Results_MapPointAnnotation alloc] initWithCoordinate:[meeting getMeetingLocationCoords].coordinate andMeetings:meetingsAr andIndex:0];
                    [annotation setDisplayIndex:displayIndex++];
                    [points addObject:annotation];
                    }
                else
                    {
    #ifdef DEBUG
                    NSLog(@"BMLTMapResultsViewController mapMeetingAnnotations -This meeting gets lumped in with others.");
    #endif
                    [annotation addMeeting:meeting];
                    }
    
                if ( annotation )
                    {
                    if ( !ret )
                        {
                        ret = [[NSMutableArray alloc] init];
                        }
    
                    if ( ![ret containsObject:annotation] )
                        {
                        [ret addObject:annotation];
                        }
                    }
                }
            }
    
        // This is the black marker.
        BMLT_Results_MapPointAnnotation *annotation = [[BMLT_Results_MapPointAnnotation alloc] initWithCoordinate:[[BMLTAppDelegate getBMLTAppDelegate] searchMapMarkerLoc] andMeetings:nil andIndex:0];
    
        if ( annotation )
            {
            [annotation setTitle:NSLocalizedString(@"BLACK-MARKER-TITLE", nil)];
            [ret addObject:annotation];
            }
    
        return ret;
    }
    

    You can see it in action in the released version of the app.

    Meetings in close proximity are gathered into red annotations, which open a list.

提交回复
热议问题