在我的地图中,我必须通过URL显示kml文件中的注释。我还需要只显示多边形或圆形区域内的注释(如果用户同时绘制了两个叠加层,则需要显示两个注释)。
我见过问题How to determine if an annotation is inside of MKPolygonView (iOS),但我有两个困惑:
addAnnotation
方法中注释的坐标吗?编辑:我创建了一些代码:
-(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委托方法的实现。我看到我创建的叠加层,圆圈和多边形。我看到它们的所有注释.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 :(得分:1)
总的来说,这看起来不错,但filterAnnotations
方法存在一个问题,即如何从annotationsToFilter
数组中删除注释。
将会跳过一些注释并且永远不会通过检查。
例如:
解决此问题的一种方法是收集您想要保留在另一个数组中的注释&#34; annotationsToAdd&#34;而不是从原始中删除它们并将注释传递给addAnnotations
方法。
以下是建议的修改。我还建议在for循环之外移动viewForOverlay
个调用,因为这些引用在循环期间不会发生变化,因此无需重复调用它们。
-(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
方法中您使用变量mapview
但在filterAnnotations
mapView
V
(大写viewForOverlay
)。希望编译器会给你一个警告。
<小时/> 其他信息:
class 'MKPolygonView' does not implement the 'MKOverlay' protocol
代码...
首先,您收到的编译器警告polygonOverlay
表示变量circleOverlay
和MKPolygonView
被声明为MKCircleView
和MKPolygon
而不是{{ 1}}和MKCircle
。
其次,viewForOverlay
委托方法中的代码是错误的。它会尝试为传入的overlay
创建圆形和多边形视图,然后然后检查叠加层是什么类。它似乎也保存了对overlay view 的引用,但其余代码假定我们保留对 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;
}
您还在编辑中提到&#34;我看到了叠加层,圆圈和多边形&#34;。这听起来像是在创建多个圆形和/或多边形叠加层。在这种情况下,只有一个polygonOverlay和circleOverlay变量不起作用。
如果您确实拥有每种类型的多个叠加层,则不要存储对叠加层的引用。相反,在每个注释的filterAnnotations
方法中,循环遍历mapView.overlays
数组并在嵌套循环中执行viewForOverlay
和多边形点测试