球体表面(经度,纬度)点的凸包
Posted
技术标签:
【中文标题】球体表面(经度,纬度)点的凸包【英文标题】:Convex hull of (longitude, latitude)-points on the surface of a sphere 【发布时间】:2012-03-29 12:49:50 【问题描述】:标准凸包算法不适用于(经度、纬度)点,因为标准算法假定您需要一组笛卡尔点的包。纬度-经度点不是笛卡尔坐标,因为经度“环绕”在反子午线(+/- 180 度)。即,经度 179 以东 2 度为 -179。
因此,如果您的点集恰好跨越反子午线,您将错误地计算出环绕世界的虚假船体。
对于我可以使用标准凸包算法来纠正此问题的技巧的任何建议,或指向正确的“地球”包体算法的指针?
现在我想起来了,除了跨越反经线之外,还有更多有趣的案例需要考虑。考虑一个环绕地球的点“带”——它的凸包没有东/西边界。或者更进一步,(0,0), (0, 90), (0, -90), (90, 0), (-90, 0), (180, 0) 的凸包是什么? -- 它似乎包含了地球的整个表面,那么它的周边有哪些点?
【问题讨论】:
+1 提出了一个发人深省的好问题。 见这里:***.com/a/9612324/817828 【参考方案1】:球形凸包的所有边缘都可以被视为/视为大圆(本质上,欧几里得空间中凸包的所有边缘都可以视为线(而不是线段))。这些大圆圈中的每一个都将球体切割成两个半球。因此,您可以将每个大圆圈视为一个约束。凸包内的一个点将位于每个约束定义的每个半球上。
原始多边形的每条边都是凸包的候选边。要验证它是否确实是凸包的边缘,您只需要验证多边形的所有节点是否都位于由穿过相关边缘的两个节点的大圆定义的半球上。但是,我们仍然需要创建超过多边形凹节点的新边。
但是让我们更快捷/蛮力这个: 在多边形的每对节点之间画一个大圆圈。在两个方向上执行此操作(即连接 A 到 B 的大圆和连接 B 到 A 的大圆)。对于具有 N 个节点的多边形,您最终将得到 N^2 个大圆。这些大圆中的每一个都是一个候选约束(即凸多边形的候选边)。其中一些大圆圈将与原始多边形的边缘重叠,但大多数不会。现在,再次记住:每个大圆都是将球体约束到一个半球的约束。现在验证原始多边形的所有节点是否满足约束(即,如果所有节点都在大圆定义的半球上)。如果是,那么这个大圆就是凸包的边缘。但是,如果原始多边形的单个节点不满足约束,则它不满足,您可以丢弃这个大圆。
这样做的美妙之处在于,一旦您将纬度和经度转换为指向单位球体的笛卡尔向量,它实际上只需要点积和叉积 - 你通过叉积找到穿过球体上两点的大圆 - 如果大圆和该点的点积大于(或等于)0,则该点位于由大圆定义的半球上。 因此,即使对于具有大量边的多边形,这种蛮力方法也应该可以正常工作。
【讨论】:
【参考方案2】:这个问题前段时间已经回答过了,但我想总结一下我的研究结果。
球形凸包基本上只针对非对映点定义。假设所有点都在同一个半球上,您可以通过两种主要方式计算它们的凸包:
-
使用 gnomonic/central 投影将点投影到平面并应用平面凸包算法。见 Lin-Lin Chen, T. C. Woo, "Computational Geometry on the Sphere With Application to Automated Machining" (1992)。如果这些点位于已知的半球上,您可以硬编码将这些点投影到哪个平面上。
使平面凸包算法适应球体。参见 C. Grima 和 A. Marquez,"Computational Geometry on Surfaces: Performing Computational Geometry on the Cylinder, the Sphere, the Torus, and the Cone",Springer (2002)。这个参考似乎给出了与上面叶丽昂引用的摘要类似的方法。
作为参考,在 Python 中,我正在处理 implementation of my own,它目前仅适用于北半球的点。
另见 this question 关于数学溢出。
【讨论】:
【参考方案3】:未来书呆子:
你完全正确。我必须为我的应用程序解决与 Maxy-B 完全相同的问题。作为第一次迭代,我只是将 (lng,lat) 视为 (x,y) 并运行标准的 2D 算法。只要没有人看得太近,这工作就很好,因为我所有的数据都在连续的美国。不过,作为第二次迭代,我使用了你的方法并证明了这个概念。
这些点必须在同一个半球。事实证明,选择这个半球并非易事(它不仅仅是点的中心,正如我最初猜测的那样。)为了说明,考虑以下四个点:(0,0),(-60,0), (+60,0) 沿赤道,和 (0,90) 北极。无论您选择如何定义“中心”,它们的中心对称地位于北极,并且所有四个点都在北半球。但是,请考虑将第四点替换为 (-19, 64) 冰岛。现在他们的中心不在北极,而是不对称地拉向冰岛。然而,这四个点仍然在北半球。此外,由北极唯一定义的北半球是它们共享的唯一半球。所以计算这个“极点”变成了算法,而不是代数。
查看我的 Python 代码库: https://github.com/VictorDavis/GeoConvexHull
【讨论】:
【参考方案4】:如果您的所有点都在一个半球内(也就是说,如果您可以找到一个穿过地球中心的剖切面,将它们全部放在一侧),那么您可以从地球中心到平行于剖切面的平面。然后投影中的所有大圆都变成直线,因此投影中的凸包将映射回地球上正确的凸包。您可以通过查看“Gnomonic Projection”部分here 中的纬度线来了解纬度/经度点的错误程度(注意经度线保持笔直)。
(将地球视为球体仍然不太正确,但它是一个很好的第二近似值。我不认为穿过更现实的地球(比如WGS84)的真正最短距离路径上的点通常位于在穿过中心的平面上。也许假装它们确实比球体得到的近似值更好。)
【讨论】:
【参考方案5】:标准的凸包算法并没有被地球表面坐标的环绕所打败,而是被一个更基本的问题所打败。球体的表面(让我们忘记地球的不完全球形)不是欧几里得空间,因此欧几里得几何学不起作用,而凸包例程假设基础空间是欧几里得(给我看一个不是) t,拜托)不会工作。
球体的表面符合elliptic geometry 的概念,其中线是大圆,对映点被认为是同一个点。您已经开始体验将欧几里得的凸性概念应用于椭圆空间所产生的问题。
您可以采用的一种方法是采用geodesic convexity 的定义并实施测地线凸包例程。这看起来很毛茸茸的。它可能不会产生符合您(通常是欧几里得)期望的结果。在许多情况下,对于 3 个任意点,凸包实际上是球体的整个表面。
航海家和制图师多年来采用的另一种方法是将球体表面的一部分(包含所有点的部分)投影到欧几里得空间(这是地图投影的主题,我会的) t 麻烦你参考大量的文献)并找出投影点的凸包。将您感兴趣的区域投影到平面上并调整坐标,使其不会环绕;例如,如果您对法国感兴趣,您可以通过添加 30 度来调整所有经度,这样整个国家就由 +ve 数字协调。
在我写作时,@Li-aung Yip 的回答中提出的使用 3D 凸包算法的想法让我觉得被误导了。表面点集的 3D 凸包将包括位于球体内的点、边和面。这些实际上并不存在于球体的 2D 表面上,只会将您的困难从 2D 中不太正确的概念转变为 3D 中完全错误的概念。此外,我从我引用的 Wikipedia 文章中了解到,封闭的半球(即包括其“赤道”的半球)在球体表面的几何形状中不是凸的。
【讨论】:
我主要建议应用 3D 凸包算法作为思考的食物。如果 OP 可以提供有关他尝试使用的数据的更多信息(一个国家/地区内的点?世界上所有首都城市的列表?)那可能会有所帮助。 感谢您的精彩回答。测地线凸性非常有趣,凸性对非欧几里得上下文的其他推广也是如此。但是,对于我的迫切需要,对纬度/经度点应用一些简单的线性变换,使它们永远不会跨越反子午线就足够了。【参考方案6】:您是否可以将您的数据视为经纬度数据,而不是将其视为 3D 空间并应用3D convex hull algorithm?然后您可以通过分析 3D 凸包找到您想要的 2D 凸包。
这将使您返回到适用于笛卡尔凸包(尽管是在三个维度上)的广为人知的算法,并且不会出现坐标环绕的问题。
另外,还有这篇论文:Computing the Convex Hull of a Simple Polygon on the Sphere (1996),它似乎处理了您正在处理的一些相同问题(坐标环绕等)
【讨论】:
感谢 PDF 的链接,尽管它看起来像是演讲的摘要(PDF 本身)而不是完整的论文。 关于 3D 船体的想法 - 因为所有 3D 点(根据定义)都位于球体的表面上,所以它们 all 不会包含在生成的 3D 中凸包,无论它们在哪里?这样的船体不会提供任何信息。 是的,所有的点都将成为凸包的一部分——但考虑到 3D 凸包可能具有特定的形状(即半球)。半球可能有用。 您可以在制作 3D 船体之前添加 (0,0,0) 以抵消@High Performance Mark 提出的(有效)点。仅将具有 (0,0,0) 的船体面作为顶点,其中的一个边缘不与 (0,0,0) 相交。这些边缘投影回球体,形成原始数据集的 2D 球形外壳。但是,这仅在 (0,0,0) 位于 3D 笛卡尔外壳中时才有效;也就是说,如果所有点都在一个半球上。似乎运作良好。以上是关于球体表面(经度,纬度)点的凸包的主要内容,如果未能解决你的问题,请参考以下文章