2011-11-15 88 views
1

在我的地圖中,我必須通過URL顯示來自kml文件的註釋。我還需要僅顯示多邊形或圓形區域內的註釋(如果用戶同時繪製了兩個疊加層,則都需要顯示這兩個註釋)。僅在疊加層內顯示註釋

我已經看到了問題How to determine if an annotation is inside of MKPolygonView (iOS),但我有兩個困惑:

  1. 關於註釋座標,我應該用註釋的座標從addAnnotation方法?
  2. 在上述問題中創建了一個新的疊加層,但我在其他地方創建了兩個不同的疊加層。所以我的問題是:什麼是最適合放這個代碼(或類似的東西)的地方?

編輯:我已經創建了一些代碼:

-(IBAction)showKmlData:(id)sender 
{ 
NSString *path = [[NSBundle mainBundle] pathForResource:@"KMLGenerator" ofType:@"kml"]; 

kml = [[KMLParser parseKMLAtPath:path] retain]; 

NSArray *annotationsImmut = [kml points]; 
//[mapview addAnnotations:annotations]; not anymore 
NSMutableArray *annotations = [annotationsImmut mutableCopy]; 
[self filterAnnotations:annotations]; 

MKMapRect flyTo = MKMapRectNull; 

for (id <MKAnnotation> annotation in annotations) { 
    MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate); 
    MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0); 
    if (MKMapRectIsNull(flyTo)) { 
     flyTo = pointRect; 
    } else { 
     flyTo = MKMapRectUnion(flyTo, pointRect); 
    } 
} 

mapview.visibleMapRect = flyTo; 
} 


-(void)filterAnnotations:(NSMutableArray *)annotationsToFilter { 

for (int i=0; i<[annotationsToFilter count]; i++) { 

    CLLocationCoordinate2D mapCoordinate = [[annotationsToFilter objectAtIndex:i] coordinate]; 

    MKMapPoint mapPoint = MKMapPointForCoordinate(mapCoordinate); 

    MKPolygonView *polygonView = 
     (MKPolygonView *)[mapView viewForOverlay:polygonOverlay]; 

    MKCircleView *circleView = 
     (MKCircleView *)[mapView viewForOverlay:circleOverlay]; 

    CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint]; 
    CGPoint circleViewPoint = [circleView pointForMapPoint:mapPoint]; 

    BOOL mapCoordinateIsInPolygon = 
     CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO); 

    BOOL mapCoordinateIsInCircle = 
     CGPathContainsPoint(circleView.path, NULL, circleViewPoint, NO); 

     if(mapCoordinateIsInPolygon || mapCoordinateIsInCircle) 
      [annotationsToFilter removeObjectAtIndex:i]; 
} 
[mapView addAnnotations:annotationsToFilter]; 
} 

編輯NR 2這是我實現viewForOverlay委託method.I看到我創建的疊加層,圓形和多邊形。我看到他們的所有annotations.ALL,這些內部和外部的覆蓋...

-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay 
{ 
    MKCircleView* circleView = [[[MKCircleView alloc] initWithOverlay:overlay] autorelease]; 
circleOverlay = circleView; 
    circleView.fillColor = [UIColor blueColor]; 
    circleView.strokeColor = [UIColor blueColor]; 
    circleView.lineWidth = 5.0; 
    circleView.alpha = 0.20; 

    MKPolygonView *polygonView = [[[MKPolygonView alloc] initWithOverlay:overlay] autorelease]; 
polygonOverlay = polygonView; 
    polygonView.fillColor = [UIColor blueColor]; 
    polygonView.strokeColor = [UIColor blueColor]; 
    polygonView.lineWidth = 5.0; 
    polygonView.alpha = 0.20; 


if ([overlay isKindOfClass:[MKCircle class]]) 
{ 
    return circleView; 
} 

else 
    return polygonView; 

}

+0

因此,您添加了兩個疊加層,並且您想要檢查列表中的哪個座標位於疊加層內?在鏈接的問題中,它不會創建新的疊加層 - 只需獲取對現有疊加層視圖的引用即可。 – Anna

+0

哦,現在我明白了。但是註釋怎麼樣? kml文件只返回註釋,如何檢查它們是否在覆蓋內? – Hari

+0

創建覆蓋圖,然後遍歷kml中的座標併爲每個座標執行該邏輯。嘗試一下,如果有任何問題,請發佈代碼。 – Anna

回答

1

總的來說,這看起來不錯,但filterAnnotations方法存在問題,如何從annotationsToFilter陣列中刪除註釋。

會發生什麼是一些註釋將被跳過,並且永遠不會通過檢查。

例如:

  • 假設有5個註解(0 = A,1 = B,2 = C,3 = d,4 = E)
  • 的for循環開始於索引0和「A」符合刪除條件
  • 從陣列中刪除「A」,現在其他註釋向下移動一個索引,因此在刪除陣列後:(0 = B,1 = C,2 = D ,3 = E)
  • 現在for循環轉到下一個索引,它是1(因此註釋C被選中)
  • 所以標註B被跳過,而從來沒有檢查到解決這個問題是收集你想保持在另一個數組註釋

單向「annotationsToAdd」,而不是從原來的刪除它們,並通過annotationsToAdd到addAnnotations方法。

以下是建議的修改。我還建議將viewForOverlay調用移到for循環之外,因爲這些引用在循環中不會更改,所以不需要重複調​​用它們。

-(void)filterAnnotations:(NSMutableArray *)annotationsToFilter 
{ 
    NSMutableArray *annotationsToAdd = [NSMutableArray array]; 

    //Get a reference to the overlay views OUTSIDE the for-loop since 
    //they will remain constant so there's no need to keep calling 
    //viewForOverlay repeatedly... 
    MKPolygonView *polygonView = (MKPolygonView *)[mapView viewForOverlay:polygonOverlay]; 

    MKCircleView *circleView = (MKCircleView *)[mapView viewForOverlay:circleOverlay]; 

    for (int i=0; i < [annotationsToFilter count]; i++) 
    { 
     //get a handy reference to the annotation at the current index... 
     id<MKAnnotation> currentAnnotation = [annotationsToFilter objectAtIndex:i]; 

     CLLocationCoordinate2D mapCoordinate = [currentAnnotation coordinate]; 

     MKMapPoint mapPoint = MKMapPointForCoordinate(mapCoordinate); 

     CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint]; 
     CGPoint circleViewPoint = [circleView pointForMapPoint:mapPoint]; 

     BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO); 

     BOOL mapCoordinateIsInCircle = CGPathContainsPoint(circleView.path, NULL, circleViewPoint, NO); 

     if (!mapCoordinateIsInPolygon && !mapCoordinateIsInCircle) 
      //Note the reversed if-condition because now 
      //we are finding annotations we want to KEEP 
     { 
      [annotationsToAdd addObject:currentAnnotation]; 
     } 
    } 

    [mapView addAnnotations:annotationsToAdd]; 
} 

另外,我注意到,在showKmlData方法,你使用的是可變mapviewfilterAnnotationsmapView(大寫V)。希望編譯器會給你一個警告。


附加信息:
根據您的意見,您添加到您的問題 viewForOverlay代碼...

首先,編譯器警告class 'MKPolygonView' does not implement the 'MKOverlay' protocol你得到暗示變量polygonOverlaycircleOverlay被宣佈爲MKPolygonViewMKCircleView而不是MKPolygonMKCircle

二,viewForOverlay委託方法中的代碼是錯誤的。它試圖爲overlay傳入的任何東西創建一個圓和多邊形視圖,然後檢查覆蓋圖是什麼類。它似乎也保存了對覆蓋圖視圖的引用,但其餘代碼假定我們保留對覆蓋圖MKOverlay對象 - 而不是MKOverlayView)的引用。

請嘗試以下變化...

//polygonOverlay and circleOverlay should be declared as MKOverlay objects... 
@property (nonatomic, retain) MKPolygon *polygonOverlay; 
@property (nonatomic, retain) MKCircle *circleOverlay; 

//save a reference to them when you call addOverlay... 
self.polygonOverlay = [MKPolygon polygonWithCoordinates:polyCoords count:coordsCount]; 
[mapView addOverlay:polygonOverlay]; 
self.circleOverlay = [MKCircle circleWithCenterCoordinate:cirleCenter radius:circleRadius]; 
[mapView addOverlay:circleOverlay]; 

//the viewForOverlay delegate method... 
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay 
{ 
    if ([overlay isKindOfClass:[MKCircle class]]) 
    { 
     MKCircleView* circleView = [[[MKCircleView alloc] initWithOverlay:overlay] autorelease]; 
     circleView.fillColor = [UIColor blueColor]; 
     circleView.strokeColor = [UIColor blueColor]; 
     circleView.lineWidth = 5.0; 
     circleView.alpha = 0.20; 
     return circleView; 
    } 
    else 
     if ([overlay isKindOfClass:[MKPolygon class]]) 
     { 
      MKPolygonView *polygonView = [[[MKPolygonView alloc] initWithOverlay:overlay] autorelease]; 
      polygonView.fillColor = [UIColor blueColor]; 
      polygonView.strokeColor = [UIColor blueColor]; 
      polygonView.lineWidth = 5.0; 
      polygonView.alpha = 0.20; 
      return polygonView; 
     } 

    return nil; 
} 

你還別說在你的編輯說:「我看到了疊加,圓形和多邊形」。這聽起來像你正在創建多個圓和/或多邊形覆蓋。在這種情況下,只有一個polygonOverlay和circleOverlay變量不起作用。

如果您確實有多個每種類型的疊加層,則不要存儲對疊加層的引用。相反,在filterAnnotations方法中,每個註釋都使用,通過mapView.overlays數組循環並在嵌套循環中執行viewForOverlay和點多邊形測試。

+0

非常感謝!您的修改非常好,感謝您注意'filterAnnotations'方法中的問題。變量mapview/mapView的問題是一個打字錯誤,但您是對的,我沒有注意到它。一如既往你有很大的幫助。再次感謝! – Hari

+0

只是一個問題:'MKPolygonView * polygonView =(MKPolygonView *)[mapView viewForOverlay:polygonOverlay]';'我得到一個警告說明:'類'MKPolygonView'沒有實現'MKOverlay'協議, 。它可能是什麼? – Hari

+0

這很奇怪,因爲MKPolygonView不應該實現該協議。嘗試做一個清潔和重新構建。如果還有其他編譯器錯誤或警告,請修復這些錯誤或警告,這可能會導致此錯誤消失。 – Anna