首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从一个点列表中计算相对向量,从一个点到另一个点

如何从一个点列表中计算相对向量,从一个点到另一个点
EN

Stack Overflow用户
提问于 2019-04-09 08:19:14
回答 2查看 673关注 0票数 1

我在(x,y)对中有一个点列表,它表示代理列表的位置。例如,给定3个代理,有3对点,我将其存储如下:

代码语言:javascript
运行
复制
points = np.array([[x1, y1],
                   [x2, y2],
                   [x3, y3]])

我想计算一个后续数组,即一个代理到每个其他代理之间的相对位置,而不是它本身。因此,使用上面的数据,我想使用数组relative_positions生成数组pointspoints可以有N的位置(我可以在任何时候有超过50-100个代理).

因此,使用上面描述的points,我希望生成输出:

代码语言:javascript
运行
复制
relative_positions = [[x2-x1, y2-y1],
                      [x3-x1, y3-y1],
                      [x1-x2, y1-y2],
                      [x3-x2, y3-y2],
                      [x1-x3, y1-y3],
                      [x2-x3, y2-y3]]

例如,给定作为numpy数组存储的四个代理位置:

代码语言:javascript
运行
复制
agent_points = np.array([[10, 1],
                         [30, 3],
                         [25, 10],
                         [5, 5]])

我想要生成输出:

代码语言:javascript
运行
复制
relative_positions = [[30-10,  3-1],
                      [25-10, 10-1],
                      [5-10,   5-1],
                      [10-30,  1-3],
                      [25-30, 10-3],
                      [5-30,   5-3],
                      [10-25, 1-10],
                      [30-25, 3-10],
                      [5-25,  5-10],
                      [10-5,   1-5],
                      [30-5,   3-5],
                      [25-5,  10-5]]

我怎样才能有效地做到这一点呢?我考虑过只计算每一个可能的差异,并移除0的情况(当它是从代理到其自身的相对位置时),但是我不认为这是一种“纯”的方法,因为我可能会意外地删除刚好处于同一点(或非常接近)的代理。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-09 08:40:10

方法#1

使用a输入数组,您可以-

代码语言:javascript
运行
复制
d = (a-a[:,None,:])
valid_mask = ~np.eye(len(a),dtype=bool)
out = d[valid_mask]

基本上,我们将a扩展到3D,使第一个轴成为outer-broadcastable,然后对其2D版本执行减法,从而产生mxmx2形状的输出,而ma.shape[0]。按示意图-

代码语言:javascript
运行
复制
a[:, None, :]    :  4 x 1 x 2
a                :      4 x 2
output           :  4 x 4 x 2

More info

另一种创建valid_mask的方法是-

代码语言:javascript
运行
复制
r = np.arange(len(a))
valid_mask = r[:,None] != r

方法#2

我们将利用np.lib.stride_tricks.as_strided3D数组(沿前两个轴)获得一个无对角线掩码,因此我们将在这里使用它来掩盖差异数组d。这个掩码生成是受2D数组问题(如发布的here )的启发,对于3D情况,如下所示-

代码语言:javascript
运行
复制
def nodiag_view3D(a):
    m = a.shape[0]
    p,q,r = a.strides
    return np.lib.stride_tricks.as_strided(a[:,1:], shape=(m-1,m,2), strides=(p+q,q,r))

为了解决我们的问题,应该是-

代码语言:javascript
运行
复制
d = (a-a[:,None,:])
out = nodiag_view3D(d).reshape(-1,a.shape[1])

展示approach#2在#1上是如何改进的

代码语言:javascript
运行
复制
In [96]: a = np.random.rand(5000,2)

In [97]: d = (a-a[:,None,:])

In [98]: %%timeit
    ...: valid_mask = ~np.eye(len(a),dtype=bool)
    ...: out = d[valid_mask]
1 loop, best of 3: 763 ms per loop

In [99]: %%timeit
    ...: r = np.arange(len(a))
    ...: valid_mask = r[:,None] != r
    ...: out = d[valid_mask]
1 loop, best of 3: 767 ms per loop

In [100]: %timeit nodiag_view3D(d).reshape(-1,a.shape[1])
10 loops, best of 3: 177 ms per loop
票数 2
EN

Stack Overflow用户

发布于 2019-04-09 08:30:57

虽然我没有一个numpy特定的解决方案(我肯定它存在),但是双循环和id检查可以很好地完成这个任务。不过,如果points增长的话,还需要一些时间。

代码语言:javascript
运行
复制
points = [
    [x1, y1],
    [x2, y2],
    [x3, y3]
]

relative_positions = []
for point1 in points:
    for point2 in point:
        if id(point1) != id(point2):
            relative_positions.append([CALC_HERE_OR_FUNCTION])
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55588122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档