17

我正在编写一个包含大约 900 个注释的地图视图。在地图上有这么多注释会使性能受到影响,所以我想一次将它减少到大约 300 个。注释代表一个国家的商店,因此它们往往聚集在主要城市周围,然后在小城镇中以 2 或 3 人为一组。我想减少数字,以便让 2 或 3 人一组,但城市中的数字变稀了(它们靠得太近,没有提供有用的信息)。

在图像中,您可以看到我想要精简的几个大群体(东京、名古屋和大阪)。但是对于他们自己或小组的别针,我想确保它们不会被过滤。放大后,我想显示丢失的图钉。

有谁知道我可以使用的一些好的代码,以便消除靠近的点,但留下更分散的点?

替代文字 http://img.skitch.com/20100204-jpde6wugc94nn692k7m36gmqf1.jpg

4

6 回答 6

6

如果可以选择商业第三方库,请查看Superpin(许可证费用为 199 美元)。它是一个 iOS 框架,内部使用四叉树进行注释存储并执行基于网格的聚类。该算法非常快,包含的示例应用程序显示了世界上的机场(超过 30k+ 注释),并且在 3G iPhone 上运行非常流畅。

您可能还想查看http://revolver.be/blog/mapkit-clustering-with-ios/,这是另一种现成的解决方案,对非商业项目是免费的。

免责声明:我是 Superpin 开发人员之一

于 2011-09-29T03:53:15.110 回答
6

一种方法是在放置新引脚之前,检查是否有另一个引脚已经放置在新引脚的距离 d 内。如果有,不要放置新引脚。您需要根据当前缩放级别改变 d。

您可以通过仅考虑以新引脚为中心的边界框中的引脚来减少您检查的引脚数。该框的一侧可以是 dxd 度(d 根据缩放级别而变化)。

于 2010-02-04T15:13:55.093 回答
5

我能想到的两个选择:

  • 如果您有兴趣点(例如,城市),您可以简单地按它们最接近的 POI 以较低的缩放级别对所有图钉进行分组。
  • 您可以使用K-means 聚类将引脚分组到集群中,并用中点引脚表示它们。
于 2010-02-08T10:47:48.880 回答
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 是最前面的引脚。

于 2010-10-11T21:30:34.050 回答
0

我知道派对迟到了,但你可能会发现这个例程很有用。它来自这个文件,它是FOSS 项目的一部分。

/**************************************************************//**
 \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;
}

您可以在应用程序的已发布版本中看到它的实际效果。

近距离的会议被收集到红色注释中,打开一个列表。

于 2012-04-22T15:00:28.753 回答
0

考虑到人口稠密地区的许多大头针将位于同一条街道上,您可以考虑制作“超级大头针”来列出特定街道上的大头针,而不是在每个单独的地址上。

-S!

于 2010-02-04T16:22:31.377 回答