2010-02-04 48 views
17

我使用約900個註釋編碼地圖視圖。在地圖上有這麼多註釋會使性能受到影響,所以我希望一次將它減少到300個左右。這些註釋代表一個國家的商店,因此它們傾向於在主要城市周圍聚集,然後在小城鎮中以2或3個小組進行聚集。我想減少這些數字,以便讓2或3個小組獨立存在,但城市中的數字變少了(他們之間的距離非常近以至於他們沒有提供有用的信息)。如何減少地圖上註釋的數量?

在圖片中,您可以看到有幾個大型團體(東京,名古屋和大阪),我想精簡它們。但是憑藉自己或小團隊的針腳,我想確保他們不會被過濾。放大後,我想顯示丟失的針腳。

有沒有人知道我可以使用的一些好的代碼,這樣就可以消除靠近在一起的點,但是更加分散的點是獨立的?

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

回答

6

一種方法是,將一個新的銷前,檢查是否有已放置新的PIN碼的距離d內的另一針。如果有的話,不要放置新的引腳。您需要根據當前縮放級別改變d。

通過僅考慮以新引腳爲中心的邊界框中的引腳,可以減少檢查的引腳數量。該框可以是一邊d x d度(根據縮放級別而變化)。

0

考慮到人口稠密地區的許多插銷將位於同一條街道上,您可以考慮製作「超級插針」,以列出特定街道上的插針,而不是每個地址。

-S!

我能想到的
5

兩個選項:

  • 如果你有興趣百分點(例如,市)工作,你可以簡單地組中的所有引腳通過他們最親近的人,可以降低放大的POI水平。
  • 您可以使用K-means clustering將引腳分組爲集羣並用中點引腳表示它們。
2

下面是一段代碼片段,它接受MKAnnotation的座標,將它轉換爲CGMap相對於MKMapView,並記錄該CGPoint的底層視圖。

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

把它放在循環遍歷所有的引腳。如果底層視圖是另一個MKAnnotation實例,則隱藏該引腳。

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

爲使此功能正常工作,您需要訂購pinsArray以便索引0是最前面的引腳。

+0

有趣的方法,雖然不完美 – chatur 2012-01-10 09:39:23

6

如果一個商業的第三方庫是一個選項,檢查出Superpin(許可證費用199美元)。它是一個iOS框架,內部使用四叉樹作爲註釋存儲並執行基於網格的聚類。該算法速度相當快,包含的示例應用程序顯示了世界各地的機場(超過30k +註釋),並且在3G iPhone上運行得非常流暢。

您可能還想檢查另一個現成的解決方案http://revolver.be/blog/mapkit-clustering-with-ios/,該解決方案對於非商業項目是免費的。

免責聲明:我的Superpin開發商

+0

我發現將開源左輪手槍項目集成到我自己的應用程序中非常容易。謝謝esad! – 2012-03-19 12:48:58

0

遲到了,我知道一個,但你會發現這個程序非常有用。它來自this file,它是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; 
} 

您可以在應用程序的the released version中看到它的行動。

近距離會議會聚成紅色註釋,打開一個列表。