我正在编写一个包含大约900个注释的地图视图。在地图上有这么多注释会使性能受损,所以我想一次将它减少到大约300个。注释代表一个国家的商店,因此它们倾向于在主要城市周围聚集很多,然后在小城镇中以2或3个小组聚集。我想减少数字,以便让2或3组成为一体,但城市中的数字会变薄(它们非常接近,因此它们没有提供有用的信息)。
在图片中你可以看到有几个大团体(东京,名古屋和大阪),我想要减肥。但是对于自己或小组的引脚,我想确保它们不被过滤。放大后,我想显示丢失的针脚。
有没有人知道我可以使用的一些好的代码,以便消除那些靠近在一起的点,但更多的分散是单独留下的?
alt text http://img.skitch.com/20100204-jpde6wugc94nn692k7m36gmqf1.jpg
答案 0 :(得分:6)
一种方法是在放置新引脚之前,检查是否已将另一个引脚放置在新引脚的距离d内。如果有,请不要放置新引脚。您需要根据当前缩放级别改变d。
通过仅考虑以新引脚为中心的边界框中的引脚,可以减少要检查的引脚数。盒子的侧面可以是d x d度(d根据缩放级别而变化)。
答案 1 :(得分:6)
如果可以选择商业第三方图书馆,请查看Superpin(许可证费用为199美元)。它是一个iOS框架,内部使用四叉树进行注释存储并执行基于网格的聚类。该算法非常快,包含的示例应用程序显示了世界上的机场(超过30k +注释),并且它在3G iPhone上运行得相当顺畅。
您可能还想查看http://revolver.be/blog/mapkit-clustering-with-ios/,这是另一个现成的解决方案,对于非商业项目是免费的。
免责声明:我是Superpin开发者之一
答案 2 :(得分:5)
我能想到的两个选择:
答案 3 :(得分:2)
这是一个代码片段,它采用MKAnnotation的坐标,将其转换为相对于MKMapView的CGPoint,并记录该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是最前面的引脚。
答案 4 :(得分:0)
考虑到人口密集区域中的许多引脚将位于同一条街道上,您可以考虑制作“超级引脚”,列出特定街道上的引脚,而不是每个地址。
-S!
答案 5 :(得分: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中看到它。
近距离的会议被收集到红色注释中,打开一个列表。