Domanda

Sono la codifica di un guarda la mappa con circa 900 annotazioni. Avendo questo molti annotazioni su una mappa rendere le prestazioni soffrire, quindi mi piacerebbe ridurlo a circa 300 alla volta. Le annotazioni stanno rappresentando negozi in un paese, in modo che tendono a raggrupparsi intorno a un sacco grandi città, poi in piccoli gruppi di 2 o 3 nelle città più piccole. Voglio ridurre il numero in modo che i gruppi di 2 o 3 vengono lasciati soli, ma i numeri della città sono assottigliata (sono così vicini che offrono alcuna informazione utile).

Nell'immagine si può vedere che ci sono un paio di grandi gruppi (Tokyo, Nagoya e Osaka), che voglio fuori sottile. Ma con i perni in quanto tali o in piccoli gruppi, voglio fare in modo che non vengono filtrati. Una volta che lo zoom avanti, voglio mostrare i perni mancanti.

Qualcuno sa di qualche buon codice che posso usare, in modo che i punti che sono vicini tra loro vengono eliminati, ma quelli più sparsi vengono lasciati soli?

alt text http://img.skitch.com/20100204-jpde6wugc94nn692k7m36gmqf1.jpg

È stato utile?

Soluzione

Un approccio è che, prima di effettuare un nuovo perno, verificare se c'è un altro perno già collocato a breve distanza d del nuovo perno. Se c'è, non collocare il nuovo perno. È necessario variare d in base al livello di zoom corrente.

È possibile ridurre il numero di pin di controllare contro i soli perni in un riquadro centrata sulla nuova spina. La scatola può essere d x d gradi su un lato (con d variabile basati sul livello di zoom).

Altri suggerimenti

Se una libreria commerciale di terze parti è un'opzione, controlla Superpin (licenza costa $ 199). E 'un quadro IOS che utilizza internamente quadtree per l'immagazzinamento annotazioni ed esegue il clustering basato sulla griglia. L'algoritmo è abbastanza veloce, l'applicazione di esempio incluso sta mostrando aeroporti del mondo (più di 30k + annotazioni) ed è in esecuzione abbastanza liscia su un iPhone 3G.

Si consiglia inoltre di controllare http://revolver.be/blog/mapkit -clustering-con-ios / , un'altra soluzione pronta all'uso, che è gratuito per i progetti non-commerciale.

Disclaimer: io sono uno degli sviluppatori Superpin

Due opzioni mi viene in mente:

  • Se si dispone di punti di interesse con cui lavorare (Ad esempio, le città), si può semplicemente di gruppo tutti i pin da parte del POI che sono più vicini al, nel livello basso di zoom.
  • È possibile utilizzare K-means ai pin di gruppo in cluster e rappresentarli con un perno punto medio.

Ecco un frammento di codice che prende le coordinate di un MKAnnotation, convertirlo in un CGPoint rispetto al MKMapView, e registra qual è la vista sottostante a tale CGPoint.

CGPoint pinPoint = [mapView convertCoordinate:pinView.annotation.coordinate toPointToView:mapView];
NSLog(@"pointing to %@", [[mapView hitTest:pinPoint withEvent:nil] description]);

Metti che all'interno di un ciclo che consente di scorrere tutti i vostri piedini. Se la vista sottostante è un altro esempio MKAnnotation, quindi nascondere tale perno.

if([[mapView hitTest:pinPoint withEvent:nil] isKindOfClass:[FFMapPinView class]])
    pinView.hidden = YES;

Per farlo funzionare correttamente, è necessario il pinsArray da ordinare in modo che l'indice 0 è il pin in primo piano.

Considerando che molti perni in aree densamente popolate saranno sulla stessa strada, si potrebbe considerare la possibilità di "pin super" che elencano i perni su una strada particolare, invece che su ogni singolo indirizzo.

-S!

in ritardo alla festa, lo so, ma si possono trovare utile questa routine. Viene da questo file , che fa parte della un progetto FOSS .

/**************************************************************//**
 \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;
}

È possibile vederlo in azione in la versione rilasciata del app.

Le riunioni in prossimità vengono raccolti in annotazioni rosse, che aprono una lista.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top