次のアプローチをテストして、十分に高速かどうかを確認する必要があります。まず、すべての緯度と経度を次のように変更して、グリッドに (おそらく分数の) インデックスを作成する必要があります。
idx_lats = (data_lats - lat_grid_start) / lat_grid step
idx_lons = (data_lons - lon_grid_start) / lon_grid step
次に、ポリゴンを三角形に分割します。任意の凸多角形の場合、多角形の中心をすべての三角形の 1 つの頂点として取得し、次に多角形の頂点を連続したペアとして取得できます。しかし、多角形がすべて四角形の場合は、最初の頂点に 0、1、2、2 番目の頂点に 0、2、3 を使用して、それらを 2 つの三角形のみに分割する方が速くなります。
特定の点が三角形の内側にあるかどうかを知るために、ここで説明されている重心座標アプローチを使用します。この最初の関数は、一連の点が三角形の内側にあるかどうかをチェックします。
def check_in_triangle(x, y, x_tri, y_tri) :
A = np.vstack((x_tri[0], y_tri[0]))
lhs = np.vstack((x_tri[1:], y_tri[1:])) - A
rhs = np.vstack((x, y)) - A
uv = np.linalg.solve(lhs, rhs)
# Equivalent to (uv[0] >= 0) & (uv[1] >= 0) & (uv[0] + uv[1] <= 1)
return np.logical_and(uv >= 0, axis=0) & (np.sum(uv, axis=0) <= 1)
頂点によって三角形が与えられると、三角形のバウンディング ボックス内の格子点で上記の関数を実行することにより、その内部の格子点を取得できます。
def lattice_points_in_triangle(x_tri, y_tri) :
x_grid = np.arange(np.ceil(np.min(x_tri)), np.floor(np.max(x_tri)) + 1)
y_grid = np.arange(np.ceil(np.min(y_tri)), np.floor(np.max(y_tri)) + 1)
x, y = np.meshgrid(x_grid, y_grid)
x, y = x.reshape(-1), y.reshape(-1)
idx = check_in_triangle(x, y, x_tri, y_tri)
return x[idx], y[idx]
四角形の場合は、この最後の関数を 2 回呼び出すだけです。
def lattice_points_in_quadrilateral(x_quad, y_quad) :
return map(np.concatenate,
zip(lattice_points_in_triangle(x_quad[:3], y_quad[:3]),
lattice_points_in_triangle(x_quad[[0, 2, 3]],
y_quad[[0, 2, 3]])))
サンプル データに対してこのコードを実行すると、2 つの空の配列が返されます。これは、四角形の点の順序が驚くべきものであるためです。インデックス 0 と 1 は一方の対角線を定義し、2 と 3 は他方を定義します。上記の関数は、頂点がポリゴンの周りに並べられることを期待していました。実際にこれとは別の方法で処理を行っている場合は、2 番目の呼び出しをlattice_points_in_triangle
insideに変更しlattice_points_in_quadrilateral
て、使用されるインデックス[0, 1, 3]
が[0, 2, 3]
.
そして今、その変更で:
>>> idx_lats = (data_lats - (-180) ) / 0.25
>>> idx_lons = (data_lons - (-90) ) / 0.25
>>> lattice_points_in_quadrilateral(idx_lats, idx_lons)
[array([952]), array([955])]
グリッドの解像度を 0.1 に変更した場合:
>>> idx_lats = (data_lats - (-180) ) / 0.1
>>> idx_lons = (data_lons - (-90) ) / 0.1
>>> lattice_points_in_quadrilateral(idx_lats, idx_lons)
[array([2381, 2380, 2381, 2379, 2380, 2381, 2378, 2379, 2378]),
array([2385, 2386, 2386, 2387, 2387, 2387, 2388, 2388, 2389])]
タイミングに関しては、このアプローチは、私のシステムでは、ニーズに対して約 10 倍遅くなります。
In [8]: %timeit lattice_points_in_quadrilateral(idx_lats, idx_lons)
1000 loops, best of 3: 269 us per loop
つまり、20秒以上見ています。80,000 ポリゴンを処理します。