0

I wrote this program to calculate the 3d distance for a group of points.

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]

def dist3d((x0, y0, z0), (x1, y1, z1)):
    return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

def dist_3d(obs):
    dist_list = list()
    while len(obs) != 1:
        obs_g = [(obs[0], x) for x in obs[1:]]
        dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        obs.pop(0)
    return dist_list

The result is a list of distance lists:

test = dist_3d(points)
print test
[[4.217700795331081, 5.922339064664832, 3.554222840244929], [2.1374049685457694, 7.046453008421205], [8.107835716151763]]

The result I wish to have is the following:

[4.217700795331081, 5.922339064664832, 3.554222840244929, 2.1374049685457694, 7.046453008421205, 8.107835716151763]

P.S.: the code is not optimized because the "points" list after the function returns with only one element

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
test = dist_3d(points)
points
[(472764.07, 6191524.39, 16.0)]
double-beep
  • 5,031
  • 17
  • 33
  • 41
Gianni Spear
  • 7,033
  • 22
  • 82
  • 131

2 Answers2

1

To fix your first problem, use list.extend on this line:

dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])

as in:

          ######
dist_list.extend([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
          ######

Here is a demonstration of why that will help.


Your second problem comes from this line:

obs.pop(0)

Because obs and points both reference the same list object, calling obs.pop is the same as calling points.pop directly. In other words, each time that line is executed, an item is popped from points. In the end, this will cause points to contain only one item.

To fix this problem, make a shallow copy of points inside dist_3d:

copy = obs[:]

Then, call pop on the copy. Doing so will leave points unaffected.


Below is how the modified code will look:

import math

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]

def dist3d((x0, y0, z0), (x1, y1, z1)):
    return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

def dist_3d(obs):
    dist_list = list()
    copy = obs[:]
    while len(copy) != 1:
        obs_g = [(copy[0], x) for x in copy[1:]]
        dist_list.extend([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        copy.pop(0)
    return dist_list

And here is a sample run:

>>> import math
>>> points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
>>> def dist3d((x0, y0, z0), (x1, y1, z1)):
...     return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)
...
>>> def dist_3d(obs):
...     dist_list = list()
...     copy = obs[:]
...     while len(copy) != 1:
...         obs_g = [(copy[0], x) for x in copy[1:]]
...         dist_list.extend([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
...         copy.pop(0)
...     return dist_list
...
>>> test = dist_3d(points)
>>> print test
[4.217700795331081, 5.922339064664832, 3.554222840244929, 2.1374049685457694, 7.046453008421205, 8.107835716151763]
>>> print points
[(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
>>>
Community
  • 1
  • 1
0
import itertools

def dist_3d(obs):
    dist_list = list()
    while len(obs) != 1:
        obs_g = [(obs[0], x) for x in obs[1:]]
        dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        obs.pop(0)
    return list(itertools.chain(*dist_list))