7

I have an array which describes a polyline (ordered list of connected straight segments) as follows:

points = ((0,0),
          (1,2),
          (3,4),
          (6,5),
          (10,3),
          (15,4))
points = numpy.array(points, dtype=float)

Currently, I get a list of segment distances using the following loop:

segdists = []
for seg in xrange(points.shape[0]-1):
    seg = numpy.diff(points[seg:seg+2], axis=0)
    segdists.append(numpy.linalg.norm(seg))

I would like, instead, to apply a single function call, without loops, using some native Scipy/Numpy function.

The closest thing I could get is this:

from scipy.spatial.distance import pdist
segdists = pdist(points, metric='euclidean')

but in this later case, segdists provides EVERY distance, and I want to get only the distances between adjacent rows.

Also, I'd rather avoid creating custom functions (since I already have a working solution), but instead to use more "numpythonic" use of native functions.

Hooked
  • 84,485
  • 43
  • 192
  • 261
heltonbiker
  • 26,657
  • 28
  • 137
  • 252

1 Answers1

15

Here's one way:

Use the vectorized np.diff to compute the deltas:

d = np.diff(points, axis=0)

Then use np.hypot to compute the lengths:

segdists = np.hypot(d[:,0], d[:,1])

Or use a more explicit computation:

segdists = np.sqrt((d ** 2).sum(axis=1))
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
  • After some dead-ends by myself, when you put it that way it's actually very straightforward. I've seen `hypot` being mentioned before, but googling "numpy hypot" doesn't return anything, I had to search at the numpy docs page. Thanks! – heltonbiker Nov 28 '12 at 00:40
  • Is this also possible in 3D ? – Varlor Jun 01 '17 at 10:52
  • @Varlor: Not with `hypot`, but the second version, `segdists = np.sqrt((d ** 2).sum(axis=1))`, works in 3D. – Warren Weckesser Jun 01 '17 at 12:57