Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中获取两个(X,Y)坐标之间所有点的最快方法_Python_Numpy_Gis_Vectorization_Interpolation - Fatal编程技术网

在python中获取两个(X,Y)坐标之间所有点的最快方法

在python中获取两个(X,Y)坐标之间所有点的最快方法,python,numpy,gis,vectorization,interpolation,Python,Numpy,Gis,Vectorization,Interpolation,所以我有一个shapelyLineString: print np.round(shapely_intersecting_lines.coords).astype(np.int) >>> array([[ 1520, -1140], [ 1412, -973]]) 这可以解释为一个numpy数组,如上所示 我想要得到中间的所有点,也就是说,我想要得到中间线的点作为整数值。输出应如下所示: array([[ 1520, -1140], [

所以我有一个
shapely
LineString

print np.round(shapely_intersecting_lines.coords).astype(np.int) 
>>> array([[ 1520, -1140],
           [ 1412,  -973]])
这可以解释为一个
numpy
数组,如上所示

我想要得到中间的所有点,也就是说,我想要得到中间线的点作为整数值。输出应如下所示:

array([[ 1520, -1140],
       [ 1519, -1139],
       [ 1519, -1138],
       ..., 
       [ 1413,  -975],
       [ 1412,  -974],
       [ 1412,  -973]], dtype=int32)

我在早些时候发布了这篇文章,希望在
shapely
中有一个高效的解决方案。这个解决方案一开始很好,但是现在太慢了,因为我在代码中运行了50000次。在我的计算机上,每个循环大约需要0.03秒,因此需要运行一天以上。它太慢了,无法满足我的需要,我希望看看是否有人知道这方面的矢量化解决方案。

使用生成器,这样可以节省内存

import numpy as np
import math

d = np.array(
    [
        [1520,-1140],
        [1412,-973]
    ],dtype=float);
rise = d[0,1]-d[1,1];
run = d[0,0]-d[1,0];
slope = rise/run;
print slope

fromPt = d[0];
sign = 1
if (slope<0):
    sign = -1;
points = ([d[0,0]+sign*i,math.floor(d[0,1]+(sign*i*slope))] for i in xrange(1+int(math.ceil(abs(d[0,0]-d[1,0])))))
for pt in points:
    print pt
将numpy导入为np
输入数学
d=np.array(
[
[1520,-1140],
[1412,-973]
],dtype=float);
上升=d[0,1]-d[1,1];
run=d[0,0]-d[1,0];
坡度=上升/运行;
打印坡度
fromPt=d[0];
符号=1

if(slope以下是Bresenhams line算法作为生成器。如果需要列表,只需在输出上调用list():

def line(x0, y0, x1, y1):
    deltax = x1-x0
    dxsign = int(abs(deltax)/deltax)
    deltay = y1-y0
    dysign = int(abs(deltay)/deltay)
    deltaerr = abs(deltay/deltax)
    error = 0
    y = y0
    for x in range(x0, x1, dxsign):
        yield x, y
        error = error + deltaerr
        while error >= 0.5:
            y += dysign
            error -= 1
    yield x1, y1

Bresenham可能很聪明,但我很确定暴力矢量化速度更快。我已经写了两个变体-第一个更容易阅读,第二个更快(80对50)

更新修复了一个bug(感谢@Varlor)并添加了一个nd变体

import numpy as np
from timeit import timeit

def connect(ends):
    d0, d1 = np.abs(np.diff(ends, axis=0))[0]
    if d0 > d1: 
        return np.c_[np.linspace(ends[0, 0], ends[1, 0], d0+1, dtype=np.int32),
                     np.round(np.linspace(ends[0, 1], ends[1, 1], d0+1))
                     .astype(np.int32)]
    else:
        return np.c_[np.round(np.linspace(ends[0, 0], ends[1, 0], d1+1))
                     .astype(np.int32),
                     np.linspace(ends[0, 1], ends[1, 1], d1+1, dtype=np.int32)]


def connect2(ends):
    d0, d1 = np.diff(ends, axis=0)[0]
    if np.abs(d0) > np.abs(d1): 
        return np.c_[np.arange(ends[0, 0], ends[1,0] + np.sign(d0), np.sign(d0), dtype=np.int32),
                     np.arange(ends[0, 1] * np.abs(d0) + np.abs(d0)//2,
                               ends[0, 1] * np.abs(d0) + np.abs(d0)//2 + (np.abs(d0)+1) * d1, d1, dtype=np.int32) // np.abs(d0)]
    else:
        return np.c_[np.arange(ends[0, 0] * np.abs(d1) + np.abs(d1)//2,
                               ends[0, 0] * np.abs(d1) + np.abs(d1)//2 + (np.abs(d1)+1) * d0, d0, dtype=np.int32) // np.abs(d1),
                     np.arange(ends[0, 1], ends[1,1] + np.sign(d1), np.sign(d1), dtype=np.int32)]


def connect_nd(ends):
    d = np.diff(ends, axis=0)[0]
    j = np.argmax(np.abs(d))
    D = d[j]
    aD = np.abs(D)
    return ends[0] + (np.outer(np.arange(aD + 1), d) + (aD>>1)) // aD


ends = np.array([[ 1520, -1140],
                 [ 1412,  -73]])

ends_4d = np.array([[  100, -302, 101, -49],
                    [ -100,  -45, 112, 100]])

print(connect(ends))
print(connect_nd(ends_4d))


assert np.all(connect(ends)==connect2(ends))
assert np.all(connect(ends)==connect_nd(ends))
assert np.all(connect(ends)==connect(ends[:, ::-1])[:, ::-1])
assert np.all(connect(ends)==connect(ends[::-1])[::-1])

print(timeit('f(ends)', globals={'f': connect, 'ends': ends}, number=10000)*100, 'us')
print(timeit('f(ends)', globals={'f': connect2, 'ends': ends}, number=10000)*100, 'us')
print(timeit('f(ends)', globals={'f': connect_nd, 'ends': ends}, number=10000)*100, 'us')
样本输出:

[[ 1520 -1140]
 [ 1520 -1139]
 [ 1520 -1138]
 ..., 
 [ 1412   -75]
 [ 1412   -74]
 [ 1412   -73]]
[[ 100 -302  101  -49]
 [  99 -301  101  -48]
 [  98 -300  101  -48]
 ..., 
 [ -98  -47  112   99]
 [ -99  -46  112   99]
 [-100  -45  112  100]]
78.8237597000034 us
48.02509490000375 us
62.78072760001123 us

您需要。这无法正确计算“陡峭”线的点。例如,
线(0,0,2,5)
生成
(0,0)、(1,3)、(2,5)
,当它从(0,0)向上移动到(2,5)时跳过两条网格线.啊,对了,这只适用于第一个八分之一。可以在维基百科页面上找到八分之一转换:在3D中也可以这样做吗?@Varlor好的,我的第一个想法是正确的:找到差异最大的轴。使用这个差异+1作为点数,并以与2D中完全相同的方式创建坐标。两个非最长的轴在3D.Hmm中被视为相同的,所以我必须做d0,d1=np.diff(ends,axis=0)[0]+1?所以第一个np.arange生成x轴的所有点,第二个np.arange生成y轴的所有点?其他的情况是什么?你能给出一个z轴的例子吗?致以最良好的祝愿!)我得检查很多案子,不是吗?d0>d1、d0>d2等等?@Varlor你能做的最简单的事情:
d=np.max(np.abs(np.diff(ends,axis=0))
np.array([np.linspace(*e.T,d+1,dtype=np.int32),对于e-in-end.T+0.5],order='F').T