2011-11-15 118 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