在 Objective-C 中实现一个简单的地理围栏

Posted

技术标签:

【中文标题】在 Objective-C 中实现一个简单的地理围栏【英文标题】:implementing a simple geofence in objective-C 【发布时间】:2011-04-01 06:59:59 【问题描述】:

我正在尝试实现一些简单的地理围栏算法,该算法基本上执行以下操作:

    假设我有两个点A和B(每个点都有一个纬度和经度 地球上的价值)。 我可以画一条从 A 点到 B 点的直线 我可以围绕这条线设置一个长方形的周长(见图 更清楚)

我想要做的如下,如果手机当前位置在这个红色范围之外,那么它会触发一些东西,基本上是一个代表。周长大小应该能够调整为百分比大小,因此 5% 将是围绕线的小周长,而 70% 将是围绕线的大周长。请注意,周长应该是矩形,而不是带半径的圆形。我猜在构建这个过程中会涉及到一堆 if 语句......如果有人能想出一个简单而优雅的解决方案(如果我能在 Objective-C 中看到代码会很棒),那就太棒了.或者任何指导也会有所帮助

【问题讨论】:

你这样做是不是太简单了?即只是将纬度和经度视为x,y坐标?还是您做得正确,即将经纬度转换为三维坐标并计算直线的大圆? 我猜将其转换为 3d 坐标会更好,对吧?因此,如果可以将其整合到这个想法中,那么我希望看到 是的,这样会更好,但我怀疑几何形状会很困难。 【参考方案1】:

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

至于经纬度到平面x、y坐标的转换,最简单的解决方案是使用Map Kit使用墨卡托投影。更多信息请查看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 米的精度半径,就好像当前位置是精确的一样进行计算,而忽略计算的微小误差。如果矩形更小(比如 50m),您也可以像当前位置一样进行计算,但是误报概率会更高(例如,有时您会被检测为在矩形中,而您会站在外面)。

或者您可能想寻求“完美”解决方案并进行圆矩形相交,这更复杂,不仅可能导致“是”和“否”答案,而且“以这种准确性无法确定您是否是矩形内部或外部”。

【讨论】:

无论如何要将我得到的半径整合到这个计算中? iphone 如何使用显着的LocationChanges 为您返回半径范围?它只是一个随机变量吗? 这假设这条线是水平的......这不会按照你原来的帖子工作......加上原来的帖子提到纬度和经度,这也被忽略了...... 这对于问题来说过于复杂,并且如果线的方向不正确则不起作用。我的解决方案是找到距您所在位置的最短点并计算阈值距离,这种解决方案更简单、更准确(因为它对旋转具有弹性)。 @Simon 此解决方案不假定线条是水平的,它适用于任何线条方向。【参考方案2】:

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

现在,鉴于您可以在一条线上从用户点(当前位置)找到最近的点,您可以检查他们的位置与最近点之间的距离是否在您感兴趣的阈值之内,如果超过它,那么他们位于线路周围区域的“外部”。

【讨论】:

有意思,这个公式我其实是在高中学的……涉及到很多数学和计算,不过我还是会考虑的 你看链接了吗?这为您提供了与直线相切的点,然后使用以下命令获取距离....maths.abdn.ac.uk/~igc/tch/ma1002/revision/node9.html 数学很简单(奇怪!):)

以上是关于在 Objective-C 中实现一个简单的地理围栏的主要内容,如果未能解决你的问题,请参考以下文章

如何在iphone中实现前向地理编码

如何在objective-c的pickerView中实现多次转换

在 Objective-C 中实现纯虚方法

如何在 iOS Objective-c 中实现交互式远程通知

在 UITableView Objective-C 中实现 UISearchController

在 Objective-C 中实现 singleTap 和 doubleTap