2010-02-04 23 views
17

Koduję widok mapy z około 900 adnotacjami. Posiadanie tak wielu adnotacji na mapie powoduje pogorszenie wydajności, dlatego chciałbym zmniejszyć ją do około 300 na raz. Adnotacje reprezentują sklepy w danym kraju, więc mają tendencję do grupowania się w dużych miastach, a następnie w małych grupach 2 lub 3 w mniejszych miastach. Chcę zmniejszyć liczbę tak, aby grupy 2 lub 3 pozostały same, ale liczby w mieście są rozrzedzone (są tak blisko siebie, że nie oferują użytecznych informacji).Jak zmniejszyć liczbę adnotacji na mapie?

Na zdjęciu widać kilka dużych grup (Tokio, Nagoi i Osaka), które chcę zlikwidować. Ale z kołkami w pojedynkę lub w małych grupach, chcę się upewnić, że nie zostaną odfiltrowane. Po powiększeniu chcę pokazać brakujące szpilki.

Czy ktoś wie o jakimś dobrym kodzie, z którego mogę korzystać, aby punkty znajdujące się blisko siebie zostały wyeliminowane, ale te, które są bardziej rozłożone, pozostawiono w spokoju?

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

Odpowiedz

6

Jednym ze sposobów jest to, że przed wprowadzeniem nowego kołka należy sprawdzić, czy istnieje inny pin już umieszczone w odległości d nowego kołka. Jeśli tak jest, nie umieszczaj nowej szpilki. Musisz zmienić d na podstawie bieżącego poziomu powiększenia.

Można zmniejszyć liczbę sprawdzanych styków, biorąc pod uwagę tylko szpilki w ramce ograniczającej, której środkiem jest nowy kołek. Skrzynka może być d x d stopni na boku (z różnym w zależności od poziomu zoomu).

0

Biorąc pod uwagę, że wiele szpilek w gęsto zaludnionych obszarach będzie na tej samej ulicy, można rozważyć utworzenie "super-szpilek", które wymieniają szpilki na konkretnej ulicy, zamiast na każdym indywidualnym adresie.

-S!

5

Dwie opcje można myślę:

  • Jeśli masz interesujące pracować (np miastach), można po prostu grupa wszystkie kołki przez UM że jesteśmy najbliżej, w dolnej zoom poziomy.
  • Możesz użyć K-means clustering, aby zgrupować szpilki w klastry i reprezentować je za pomocą szpilki środkowej.
2

Oto fragment kodu, który wykonuje koordynuje MKAnnotation za, konwertować je do CGPoint względem MKMapView i rejestruje co bazowy widoku w tym CGPoint.

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

Umieść w pętli, która przechodzi przez wszystkie szpilki. Jeśli podstawowy widok jest inną instancją MKAnnotation, a następnie ukryj tę pinezkę.

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

Aby to działało poprawnie, musisz zamówić pinsArray, aby indeks 0 był czołowym pinem.

+0

Ciekawe podejście, choć nie idealne – chatur

6

Jeśli dostępna jest komercyjna biblioteka innych firm, sprawdź numer Superpin (licencja kosztuje 199 USD). Jest to framework systemu iOS, który wewnętrznie używa quadtrees do przechowywania adnotacji i wykonuje tworzenie klastrów opartych na sieci. Algorytm jest dość szybki, dołączona przykładowa aplikacja pokazuje lotniska świata (ponad 30k + adnotacje) i działa całkiem gładko na telefonie iPhone 3G.

Możesz również sprawdzić http://revolver.be/blog/mapkit-clustering-with-ios/, kolejne gotowe rozwiązanie, które jest bezpłatne dla projektów niekomercyjnych.

Zastrzeżenie: Jestem jednym z twórców Superpin

+0

Stwierdziłem, że bardzo łatwo jest zintegrować projekt rewolweru open source z moją własną aplikacją. Dzięki esad! –

0

późno do partii, wiem, ale może się okazać, to rutyna użyteczne. Pochodzi z this file, który jest częścią 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; 
} 

Możesz zobaczyć go w akcji w the released version aplikacji.

Zebrania w pobliżu gromadzą się w czerwone adnotacje, które otwierają listę.

Powiązane problemy