使用Objective-C实现简单的地理围栏

3
我正在尝试实现一个简单的地理围栏算法,基本上做到以下几点:
1. 假设我有两个点A和B(每个点都有地球上的纬度和经度值)。 2. 我可以从点A到点B画一条直线。 3. 我可以在该线周围设置一个边界,它是一个矩形(更多的明确细节请参见下面的图片)。
如果手机当前位置在这个红色区域之外,则会触发某些操作,基本上是委托。边界大小应该能够调整为百分比大小,因此5%将是线周围的小范围,而70%将是线周围的大范围。请注意,边界应该是一个矩形,而不是半径为圆形。我猜在构建这个过程中会有很多if语句...如果有人能想出一个简单而优雅的解决方案(最好可以看到objective-C代码),那就太棒了。或者任何指导也将有所帮助。

你是在简单地处理吗?即将纬度和经度视为x,y坐标吗?还是你正在正确地处理,即将纬度和经度转换为三维坐标,并计算直线的大圆弧? - JeremyP
我猜将其转换为三维坐标会更好,对吗?如果可以将其集成到这个想法中,那么我想看看。 - aherlambang
是的,这样可能会更好,但我怀疑几何形状会非常困难。 - JeremyP
2个回答

1

您可以从矩形的四个点创建路径,然后使用CGPathContainsPoint检查当前位置是否在路径内。

至于将纬度和经度转换为平面x、y坐标,最简单的解决方案是使用Map Kit使用Mercator投影。请查看Understanding Map Geometry以获取更多信息。

以下是一个示例:

// create four rectangle points from A, B
dx = (B.x - A.x) * 0.05; // 5% of the A-B length
dy = (B.y - A.y) * 0.05;

// topmost corner, above B
points[0].x = B.x + dx - dy;
points[0].y = B.y + dy + dx;

//rightmost corner, to the right from B
points[1].x = B.x + dx + dy;
points[1].y = B.y + dy - dx;

...


CGMutablePathRef path = CGPathCreateMutable(); 

CGPathMoveToPoint(path, NULL, points[0].x, points[0].y);
CGPathAddLineToPoint(path, NULL, points[1].x, points[1].y);
CGPathAddLineToPoint(path, NULL, points[2].x, points[2].y);
CGPathAddLineToPoint(path, NULL, points[3].x, points[3].y);

CGPathCloseSubpath(path);

// convert latitude, longitude to planar coordinates
MKMapPoint location = MKMapPointForCoordinate([newLocation coordinate]);

BOOL inside = CGPathContainsPoint(path, NULL, CGPointMake(location.x, location.y), YES);

CGPathRelease(path);

注意: 该代码期望当前位置是一个点,而实际上它是一个点和精度半径的组合,这实际上是一个圆。这让事情有些复杂,因为现在你需要定义如何处理当当前位置不是确切已知的情况,但你只知道它在圆内某个位置。如果矩形很大(比如说5公里),那么你可以简单地要求精度半径小于50米,就像当前位置是精确的一样进行计算,并忽略计算的小不准确性。如果矩形较小(比如说50米),你也可以像当前位置是精确的一样进行计算,但假阳性的概率会更高(例如,有时你会被检测为在矩形内,而实际上你是站在外面的)。
或者你可能想采用“完美”的解决方案,使用圆-矩形相交算法,这更加复杂,并且可能不仅得到YES和NO答案,还可能得到“以此精度无法确定您是否在矩形内部或外部”的答案。

有没有办法将我得到的半径集成到这个计算中? - aherlambang
假设该线是水平的...这与您最初的帖子不符...另外,原帖提到的纬度和经度也被忽略了... - Simon Lee
这个方案对于问题来说过于复杂,而且如果线条方向不正确就无法工作。我的解决方案是找到离你位置最近的点并计算一个阈值距离,更简单、更准确(因为它对旋转具有弹性)。 - Simon Lee
@Simon 这个解决方案是否过于复杂取决于问题本身。点到线的距离确实比这个简单,但仅当您需要点到线的距离时才是如此(这是完全可能的)。在这种情况下,点到线的距离会在矩形的拐角处出现问题,在其最简单的形式中,它适用于带有圆角的矩形。无论如何,我认为答案并没有错(也就是说不应该被贬低)。 - Jan Soltis
@EquinoX 在locationManager:didUpdateToLocation:fromLocation方法中,你应该能够通过newLocation.horizontalAccuracy获取到精度半径。 - Jan Soltis
显示剩余6条评论

1

您需要找到距离用户位置最近的主A-B线上的点。请查看以下链接获取更多信息... Point Line

现在,假设您可以从用户点(当前位置)找到线上的最近点,则可以检查其位置与最近点之间的距离是否在您感兴趣的阈值范围内,如果超出,则表示他们“超出”该线周围的区域。


有趣,我在高中就学习了那个公式...其中涉及了很多数学和计算,但我仍然会考虑它。 - aherlambang
你看过链接了吗?那个链接给出了切线上的点,然后使用以下方法来获取距离... http://www.maths.abdn.ac.uk/~igc/tch/ma1002/revision/node9.html - Simon Lee
数学非常简单(奇怪!) :) - Simon Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接