scipy.spatial.Delaunay 中附近的点被遗漏
在比较 scipy 的(0.9.0)和 matplotlib 的(1.0.1)Delaunay 三角测量例程时,我注意到无法解释的行为。我的点是存储在 numpy.array([[easting, Northing], [easting, Northing], [easting, Northing]]) 中的 UTM 坐标。 Scipy 的边缘缺少我的一些观点,而 matplotlib 的边缘都在那里。有解决办法吗,还是我做错了什么?
import scipy
import numpy
from scipy.spatial import Delaunay
import matplotlib.delaunay
def delaunay_edges(points):
d = scipy.spatial.Delaunay(points)
s = d.vertices
return numpy.vstack((s[:,:2], s[:,1:], s[:,::-2]))
def delaunay_edges_matplotlib(points):
cens, edges, tri, neig = matplotlib.delaunay.delaunay(points[:,0], points[:,1])
return edges
points = numpy.array([[500000.25, 6220000.25],[500000.5, 6220000.5],[500001.0, 6220001.0],[500002.0, 6220003.0],[500003.0, 6220005.0]])
edges1 = delaunay_edges(points)
edges2 = delaunay_edges_matplotlib(points)
numpy.unique(edges1).shape # Some points missing, presumably nearby ones
numpy.unique(edges2).shape # Includes all points
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
scipy.spatial.Delaunay 的这种行为可能与浮点运算的印象有关。
您可能知道,
scipy.spatial.Delaunay
使用 Cqhull
库来计算 Delaunay 三角剖分。Qhull
又是Quickhull
算法,作者在本文论文 (1) 。您可能也知道计算机中使用的浮点运算是使用 IEEE 754 标准执行的(您可以在 维基百科)。根据标准,每个有限数最简单地由三个整数描述:s
= 符号(零或一),c
= 有效数字(或“系数”) ,q
= 指数。用于表示这些整数的位数随数据类型的不同而变化。因此,很明显,浮点数在数值轴上的分布密度并不是恒定的——数字越大,分布越松散。即使使用谷歌计算器也可以看到 - 你可以从 3333333333333334 中减去 3333333333333333 和 获取 0 。发生这种情况是因为 3333333333333333 和 3333333333333334 都四舍五入为相同的浮点数。现在,了解了舍入误差后,我们可能需要阅读论文 (1) 的第 4 章,标题为使用印象进行复制。本章描述了一种处理舍入误差的算法:
这就是可能发生的情况 - Quickhull 无法区分两个附近的点,因此它合并了两个面,从而成功消除了其中一个面。为了消除这些错误,您可以尝试移动坐标原点:
这会将计算移动到浮点数相当密集的区域。
This behavior of
scipy.spatial.Delaunay
might be connected with the impresicion of the floating point arithmetic.As you may know,
scipy.spatial.Delaunay
uses Cqhull
library to calculate Delaunay triangulation.Qhull
, in its turn, is the implementation ofQuickhull
algorithm, which is in details described by the authors in this paper (1). You as well may know that floating-point arithmetic used in computers is carried out using IEEE 754 standard (you can read about it in Wikipedia, for instance). According to the standard, each finite number is most simply described by three integers:s
= a sign (zero or one),c
= a significand (or 'coefficient'),q
= an exponent. The number of bits used to represent these integers varies with data type. So, it's obvious, that the density of floating point number distribution on nummerical axis is not constant - the greater numbers, the more loosely they are distributed. It can be seen even with Google calculator - you can subtract 3333333333333333 from 3333333333333334 and get 0. That happens because 3333333333333333 and 3333333333333334 both are rounded to the same floating point number.Now, knowing about rounding errors, we might want to read chapter 4 of the paper (1), entitled Copying with impresicion. In this chapter, an algorithm of dealing with rounding errors is described:
So that's what might happens -
Quickhull
cannot distinguish between 2 nearby points, so it merges two facets, thus successfully eliminating one of them. To eliminate these errors, you can, for instance, try to move your coordinate origin:This moves computations to the region where floating point numbers are reasonably dense.