标准凸包算法不适用于(经度,纬度)点,因为标准算法假设您需要一组笛卡尔点的外壳。纬度 - 经度点不笛卡尔坐标,因为经度在“反子午线”(+/- 180度)处“环绕”。即,经度179以东两度是-179。
因此,如果您的一组点碰巧跨越反子午线,您将计算出错误地在世界各地伸展的虚假船体。
对于技巧的任何建议我可以使用标准的凸包算法进行校正,或指向正确的“地球”船体算法?
现在我想起来,有更多有趣的案例需要考虑,而不是跨越反梅迪安。考虑一个包围地球的点“带” - 它的凸包将没有东/西边界。或者甚至更进一步,{(0,0),(0,90),(0,-90),(90,0),( - 90,0),(180,0)}的凸包是什么? - 它似乎包含了地球的整个表面,所以它的周边有哪些点?
答案 0 :(得分:7)
标准凸包算法不会被地球表面上的坐标环绕,而是由一个更基本的问题所打破。球体的表面(让我们忘记地球的不太球形)不是欧几里德空间,所以欧几里德几何不起作用,凸壳体例程假设下面的空间是欧几里得(给我一个没有'请,请不要工作。
球体表面符合elliptic geometry的概念,其中直线是大圆,对映点被认为是相同的点。您已经开始体验尝试将欧几里德凸性概念应用于椭圆空间所产生的问题。
对您开放的一种方法是采用geodesic convexity的定义并实施测地柱凸体例程。看起来很毛茸茸。它可能不会产生符合您(通常是欧几里德)期望的结果。在许多情况下,对于3个任意点,凸包将成为球体的整个表面。
航海家和制图师多年来采用的另一种方法是将球体表面的一部分(包含所有点的部分)投射到欧几里德空间(这是地图投影的主题,我赢了'请参考其中的大量文献,并弄清楚投影点的凸包。将您感兴趣的区域投影到飞机上并调整坐标,使它们不会缠绕;例如,如果您对法国感兴趣,可以通过添加30度来调整所有经度,以便整个国家由+ ve数字协调。
在我写作的时候,在@ Li-aung Yip的回答中提出的使用3D凸包算法的想法让我感到误入歧途。该组曲面点的三维凸包将包括位于球体内的点,边和面。这些字面上并不存在于球体的2D表面上,只会改变您在2D中与不太正确的概念进行摔跤以及在3D中完全错误的难度。此外,我从维基百科的文章中了解到,一个封闭的半球(即包含其“赤道”的半球)在球体表面的几何形状中不是凸起的。
答案 1 :(得分:2)
您可以考虑在3D空间中应用3D convex hull algorithm而不是将您的数据视为纬度 - 经度数据吗?然后,您可以通过分析3D凸包来找到所需的2D凸包。
这将使您返回到笛卡尔凸壳的良好行进算法(虽然是三维),并且没有绕坐标的问题。
或者,有这篇论文:Computing the Convex Hull of a Simple Polygon on the Sphere (1996)似乎处理了你正在处理的一些相同的问题(协调环绕等)
答案 2 :(得分:1)
如果你的所有点都在一个半球内(也就是说,如果你能找到一个穿过地球中心的切割平面,将它们全部放在一边),那么你可以做一个中心的又名gnomic aka gnomonic投影。地球中心到平行于切割平面的平面。然后所有大圆都成为投影中的直线,因此投影中的凸包将映射回地球上正确的凸包。通过查看“Gnomonic Projection”部分here中的纬度线,您可以看到错误的纬度/经度点(注意经度线保持笔直)。
(将地球视为一个球体仍然不太正确,但它是一个很好的第二近似。我不认为在一个更真实的地球上的真正的最小距离路径上的点(比如WGS84)通常假装在一个穿过中心的平面上。也许假装它们会给你一个比用球体更好的近似值。)
答案 3 :(得分:1)
FutureNerd:
你是完全正确的。我必须为我的应用程序解决与Maxy-B完全相同的问题。作为第一次迭代,我只是将(lng,lat)视为(x,y)并运行标准的2D算法。只要没有人看得太近,这就行得很好,因为我的所有数据都在连续的美国。作为第二次迭代,我使用了你的方法并证明了这个概念。
点必须在同一个半球。事实证明,选择这个半球是非平凡的(它不仅仅是点'中心,正如我最初猜测的那样。)为了说明,请考虑以下四点:(0,0),( - 60,0), (+60,0)沿赤道,(0,90)北极。然而,你选择定义“中心”,它们的中心位于北极的对称性,所有四个点都在北半球。但是,考虑用(-19,64)冰岛代替第四点。现在他们的中心不在北极,而是不对称地朝向冰岛。然而,所有四个点仍然在北半球。此外,由北极独特定义的北半球是他们共有的唯一半球。所以计算这个“极点”变成了算法,而不是代数。
请参阅我的存储库以获取Python代码: https://github.com/VictorDavis/GeoConvexHull
答案 4 :(得分:0)
这个问题已经回答了一段时间,但是我想总结一下我的研究结果。
基本上只为非对映点定义球形凸包。假设所有点都在同一半球上,则可以通过两种主要方法来计算它们的凸包:
作为参考,在Python中,我正在研究implementation of my own,目前仅适用于北半球上的点。
另请参阅this question关于数学溢出。
答案 5 :(得分:0)
可以将球形凸包的所有边缘视为/视为大圆(部分而言,可以将欧氏空间中凸包的所有边缘视为线(而不是线段))。这些大圆圈中的每一个将球体切成两个半球。因此,您可以将每个大圆圈视为一个约束。凸包内的一个点将位于每个约束所定义的每个半球上。
原始多边形的每个边缘都是凸包的候选边缘。要验证它是否确实是凸包的边缘,您只需要验证多边形的所有节点是否在通过有问题的边缘的两个节点的大圆所定义的半球上。但是,我们仍然需要创建超过多边形凹节点的新边。
但是,让我们相当捷径/蛮力: 在多边形中的每对节点之间绘制一个大圆圈。双向执行此操作(即,将A连接到B的大圆和将B连接到A的大圆)。对于具有N个节点的多边形,您将因此得到N ^ 2个大圆。这些大圆中的每一个都是候选约束(即凸多边形的候选边)。这些大圆中的一些会与原始多边形的边缘重叠,但大多数不会。现在,请再次记住:每个大圆都是一个将球体限制到一个半球的约束。现在,验证原始多边形的所有节点是否都满足约束条件(即,如果所有节点都在大圆所定义的半球上)。如果是,则此大圆圈是凸包的边缘。但是,如果原始多边形的单个节点不满足约束条件,则不满足该约束,您可以丢弃该大圆。
这样做的好处是,一旦将经度和纬度转换为指向单位球面的笛卡尔矢量,它实际上只需要点积和叉积 -您会发现一个大圆通过其叉积穿越球体上的两个点 -如果大圆和该点的点积大于(或等于)0,则该点位于由大圆定义的半球上。 因此,即使对于具有大量边的多边形,这种蛮力方法也应该可以正常工作。