我有轨迹数据,其中每个轨迹由一系列坐标(x,y点)组成,每个轨迹由唯一ID标识。
这些轨迹位于 x-y 平面,我想将整个平面划分为相等大小的网格(方形网格)。该网格显然是不可见的,但用于将轨迹划分为子段。每当轨迹与网格线相交时,它就会分段,并成为 new_id 的新子轨迹。
我添加了一个简单的手工制作图表,以明确我的期望。
可以看到轨迹如何在网格线的交叉点处划分,并且这些段中的每一个都具有新的唯一ID。
我正在研究Python,并寻找一些python实现链接,建议,算法,甚至是伪代码。
如果有任何不清楚的地方,请告诉我。
更新
为了将平面划分为网格,单元格索引如下:
#finding cell id for each coordinate
#cellid = (coord / cellSize).astype(int)
cellid = (coord / 0.5).astype(int)
cellid
Out[] : array([[1, 1],
[3, 1],
[4, 2],
[4, 4],
[5, 5],
[6, 5]])
#Getting x-cell id and y-cell id separately
x_cellid = cellid[:,0]
y_cellid = cellid[:,1]
#finding total number of cells
xmax = df.xcoord.max()
xmin = df.xcoord.min()
ymax = df.ycoord.max()
ymin = df.ycoord.min()
no_of_xcells = math.floor((xmax-xmin)/ 0.5)
no_of_ycells = math.floor((ymax-ymin)/ 0.5)
total_cells = no_of_xcells * no_of_ycells
total_cells
Out[] : 25
由于飞机现在被分成25个单元,每个单元都有一个 cellid 。为了找到交叉点,也许我可以检查轨迹中的下一个坐标,如果 cellid 保持不变,那么轨迹的该段位于同一个单元格中并且没有与网格交叉。比如,如果x_cellid [2]大于x_cellid [0],则段与垂直网格线相交。虽然,我仍然不确定如何找到与网格线的交叉点,并在交叉点上分割轨迹,为它们提供新的id。
答案 0 :(得分:5)
这可以通过以下方式解决:
%matplotlib inline
import pylab as pl
from shapely.geometry import MultiLineString, LineString
import numpy as np
from matplotlib.collections import LineCollection
x0, y0, x1, y1 = -10, -10, 10, 10
n = 11
lines = []
for x in np.linspace(x0, x1, n):
lines.append(((x, y0), (x, y1)))
for y in np.linspace(y0, y1, n):
lines.append(((x0, y), (x1, y)))
grid = MultiLineString(lines)
x = np.linspace(-9, 9, 200)
y = np.sin(x)*x
line = LineString(np.c_[x, y])
fig, ax = pl.subplots()
for i, segment in enumerate(line.difference(grid)):
x, y = segment.xy
pl.plot(x, y)
pl.text(np.mean(x), np.mean(y), str(i))
lc = LineCollection(lines, color="gray", lw=1, alpha=0.5)
ax.add_collection(lc);
结果:
不要使用造型,自己动手:
import pylab as pl
import numpy as np
from matplotlib.collections import LineCollection
x0, y0, x1, y1 = -10, -10, 10, 10
n = 11
xgrid = np.linspace(x0, x1, n)
ygrid = np.linspace(y0, y1, n)
x = np.linspace(-9, 9, 200)
y = np.sin(x)*x
t = np.arange(len(x))
idx_grid, idx_t = np.where((xgrid[:, None] - x[None, :-1]) * (xgrid[:, None] - x[None, 1:]) <= 0)
tx = idx_t + (xgrid[idx_grid] - x[idx_t]) / (x[idx_t+1] - x[idx_t])
idx_grid, idx_t = np.where((ygrid[:, None] - y[None, :-1]) * (ygrid[:, None] - y[None, 1:]) <= 0)
ty = idx_t + (ygrid[idx_grid] - y[idx_t]) / (y[idx_t+1] - y[idx_t])
t2 = np.sort(np.r_[t, tx, tx, ty, ty])
x2 = np.interp(t2, t, x)
y2 = np.interp(t2, t, y)
loc = np.where(np.diff(t2) == 0)[0] + 1
xlist = np.split(x2, loc)
ylist = np.split(y2, loc)
fig, ax = pl.subplots()
for i, (xp, yp) in enumerate(zip(xlist, ylist)):
pl.plot(xp, yp)
pl.text(np.mean(xp), np.mean(yp), str(i))
lines = []
for x in np.linspace(x0, x1, n):
lines.append(((x, y0), (x, y1)))
for y in np.linspace(y0, y1, n):
lines.append(((x0, y), (x1, y)))
lc = LineCollection(lines, color="gray", lw=1, alpha=0.5)
ax.add_collection(lc);
答案 1 :(得分:1)
你经常问很多。一旦采用一般方法,您应该自己攻击大部分设计和编码。 Stack Overflow算法识别是合理的;要求设计和参考链接is not。
我建议您将点坐标放入列表中。使用NumPy
和SciKit
功能插入网格交叉点。您可以将段存储在列表中(无论是在数据设计中定义段的任何内容)。考虑制作一个字典,允许您通过网格坐标检索分段。例如,如果段仅由端点表示,并且点是您的类,则可能有类似这样的事情,使用每个方块的左下角作为其定义点:
grid_seg = {
(0.5, 0.5): [p0, p1],
(1.0, 0.5): [p1, p2],
(1.0, 1.0): [p2, p3],
...
}
其中p0,p1等是插值交叉点。
答案 2 :(得分:1)
每条轨迹由一系列直线段组成。因此,您需要一个例程将每个线段分成完全位于网格单元格内的部分。这种例程的基础是Digital Differential Analyzer (DDA)算法,尽管您需要修改基本算法,因为您需要每个单元格中的行的端点,而不仅仅是访问哪些单元。
你必须要注意几件事:
1)如果您正在使用浮点数,请注意步长值计算中的舍入误差,因为这些可能导致算法失败。出于这个原因,许多人选择转换为整数网格,显然会失去精度。 This是一个很好的讨论问题,有一些工作代码(虽然不是python)。
2)您需要确定一个小区周围的4个网格线中的哪一个属于该小区。一种惯例是使用底边和左边。如果您考虑一个落在网格线上的水平线段,它可以看到问题 - 它的线段属于上面的单元格还是下面的单元格?
干杯
答案 3 :(得分:1)
data = list of list of coordinates
For point_id, point_coord in enumerate(point_coord_list):
if current point & last point stayed in same cell:
append point's index to last list of data
else:
append a new empty list to data
interpolate the two points and add a new point
that is on the grid lines.
数据存储所有轨迹。数据中的每个列表都是一条轨迹。
沿x和y轴(x_cell_id
,y_cell_id
)的单元格索引可以通过将点的坐标除以单元的维度,然后舍入为整数来找到。如果当前点的单元索引与最后点的单元索引相同,则这两个点在同一单元中。 list适用于插入新点,但它不像数组那样具有内存效率。
为轨迹创建一个类可能是个好主意。或者如果坐标列表浪费太多内存,则使用内存缓冲区和稀疏数据结构而不是列表和列表以及用于x-y坐标的数组。 将新点插入数组的速度很慢,因此我们可以将另一个数组用于新点。
警告:我对下面的事情没有太多考虑。它可能有错误,有人需要填补空白。
# coord n x 2 numpy array.
# columns 0, 1 are x and y coordinate.
# row n is for point n
# cell_size length of one side of the square cell.
# n_ycells number of cells along the y axis
import numpy as np
cell_id_2d = (coord / cell_size).astype(int)
x_cell_id = cell_id_2d[:,0]
y_cell_id = cell_id_2d[:,1]
cell_id_1d = x_cell_id + y_cell_id*n_x_cells
# if the trajectory exits a cell, its cell id changes
# and the delta_cell_id is not zero.
delta_cell_id = cell_id_1d[1:] - cell_id_1d[:-1]
# The nth trajectory should contains the points from
# the (crossing_id[n])th to the (crossing_id[n + 1] - 1)th
w = np.where(delta_cell_id != 0)[0]
crossing_ids = np.empty(w.size + 1)
crossing_ids[1:] = w
crossing_ids[0] = 0
# need to interpolate when the trajectory cross cell boundary.
# probably can replace this loop with numpy functions/indexing
new_points = np.empty((w.size, 2))
for i in range(1, n):
st = coord[crossing_ids[i]]
en = coord[crossing_ids[i+1]]
# 1. check which boundary of the cell is crossed
# 2. interpolate
# 3. put points into new_points
# Each trajectory contains some points from coord array and 2 points
# in the new_points array.
要进行检索,请创建一个包含coord数组中起始点索引的稀疏数组。
如果单元格大小,线性插值可能看起来很糟糕。
For n_xcells = 4, n_ycells = 3, the grid is:
0 1 2 3 4
0 [ ][ ][ ][ ][ ]
1 [ ][ ][ ][* ][ ]
2 [ ][ ][ ][ ][ ]
[* ] has an x_index of 3 and a y_index of 1.
网格中有(n_x_cells
* n_y_cells
)个单元格。
包含轨迹的i th 点的单元格的x_index为x_cell_id[i]
,y_index为x_cell_id[i]
。我通过离散化得到这个,通过将点的xy坐标除以单元格的长度,然后截断为整数。
The cell_id_1d of the cells are the number in [ ]
0 1 2 3 4
0 [0 ][1 ][2 ][3 ][4 ]
1 [5 ][6 ][7 ][8 ][9 ]
2 [10][11][12][13][14]
cell_id_1d[i] = x_cell_id[i] + y_cell_id[i]*n_x_cells
我将i th 点的单元格索引(x_cell_id[i], y_cell_id[i])
转换为名为cell_id_1d
的单个索引。
现在,i th 和(i + 1) th 点在同一个单元格中,当且仅当(x_cell_id [i],y_cell_id [i]) ==(x_cell_id [i + 1],y_cell_id [i + 1])以及cell_id_1d [i] == cell_id [i + 1]和cell_id [i + 1] - cell_id [i] == 0. delta_cell_ids [ i] = cell_id_1d [i + 1] - cell_id [i],当且只有i th 和(i + 1) th 点相同时才为零细胞