I am noticing an unexplained behaviour when comparing scipy’s (0.9.0) and matplotlib’s (1.0.1) Delaunay triangulation routines. My points are UTM coordinates stored in numpy.array([[easting, northing], [easting, northing], [easting, northing]]). Scipy’s edges are missing some of my points, while matplotlib’s are all there. Is there a fix, or am I doing something wrong?
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
This behavior of
scipy.spatial.Delaunaymight be connected with the impresicion of the floating point arithmetic.As you may know,
scipy.spatial.Delaunayuses Cqhulllibrary to calculate Delaunay triangulation.Qhull, in its turn, is the implementation ofQuickhullalgorithm, 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 –
Quickhullcannot 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.