4

我正在寻找一些指导来测试 MKPolygon 是否与 MKCircle 相交。目前我正在使用:

if ([circle intersectsMapRect:[poly boundingMapRect]]) {
                    //they do intersect
   }

我发现这只会返回不准确的结果 b/c 它在我的圆圈周围画了一个矩形,从而给了我不应该出现的交叉点。

搜索该主题使我找到了Chad Saxon 的多边形-多边形相交项目。如果我能以某种方式将我的 MKCircle 转换为多边多边形,这可能会很有用 - 这可能是可能的,但最终我相信这是解决这个问题的迂回方法。

在深入研究移植我自己的自定义几何射线测试算法实现之前,我最终想知道是否有一个我忽略的简单解决方案。

4

2 回答 2

6

几个想法:

  1. 如果您使用该多边形相交项目,请注意其中有一些泄漏。我发出了一个拉取请求,修复了其中的一些(以及其他一些随机观察)。我也会谨慎采用任何视图控制器代码(因为它还有其他问题),但是如果您对它所带来的各种限制(特别是顺时针限制,这并不是真正的如果您只是确定它们是否相交,则会出现问题)。

  2. 与其将圆转换为一系列多边形,然后使用该多边形相交类,我可能会考虑一种替代方法,即您可以利用以下事实来检测与圆的相交:您可以查看相关点之间的距离多边形和圆的半径。看来问题有以下三个方面:

    • 如果多边形的任何顶点与圆心之间的距离小于圆的半径,则多边形和圆相交。

      圆内顶点

    • 多边形是否包含圆(这是一种特殊情况,多边形所有边的距离都大于圆的半径,但圆和多边形仍然明显相交)。这很容易通过检查CGPath多边形视图的 是否包含圆心来实现CGPathContainsPoint

      在此处输入图像描述

    • 唯一复杂的部分是检查多边形的任何边是否与圆相交,即多边形的边与圆心之间的最小距离小于圆的半径;

      圆内边

    为了计算每一边与圆心的距离,我可能会遍历多边形的每一边以及面向圆心的那些边(即圆心垂直于线段,这意味着一条假想线垂直于通过圆心的多边形边实际上穿过线段),您可以:

    • 计算多边形这一侧的常数ab和,以获得在多边形顶点 (x 1 , y 1 ) 和 (x 2 , y 2 )之间的线段的方程:cax + by + c = 0

    • a = (y 1 – y 2 )

    • b = (x 2 – x 1 )

    • c = (x 1 y 2 – x 2 y 1 )

    • 使用 (x 0 , y 0 ) 作为圆心计算点到直线的距离:

      abs(ax0+by0+c)/sqrt(a^2+b^2)

    • 如果该距离小于圆的半径,则您知道多边形与圆相交。

我在 github 上放了一个使用这种技术的示例项目。

于 2013-09-07T02:05:11.147 回答
1

只是为了让那些对解决方案有所了解的人,这是我编写的一个有用的 MKCircle 扩展,它检查一个点(在这种情况下是一个多边形点)是否在圆内。享受!

//MKCircle+PointInCircle.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MKCircle (PointInCircle)

-(BOOL)coordInCircle:(CLLocationCoordinate2D)coord;

@end

//MKCircle+PointInCircle.m

#import "MKCircle+PointInCircle.h"

@implementation MKCircle (PointInCircle)

-(BOOL)coordInCircle:(CLLocationCoordinate2D)coord {

    CLLocation *locFrom = [[CLLocation alloc] initWithLatitude:self.coordinate.latitude longitude:self.coordinate.longitude];
    CLLocation *locTo = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];

    double distance = [locFrom distanceFromLocation:locTo];
    BOOL isInside = (distance <= self.radius);

    return isInside;
}

@end
于 2013-09-09T17:03:12.400 回答