2013-04-07 55 views
8

我在2D地圖由ndarray表示的項目中使用numpy的和Python:如何將Numpy數組切片到邊界?

map = [[1,2,3,4,5], 
     [2,3,4,2,3], 
     [2,2,2,1,2], 
     [3,2,1,2,3], 
     [4,6,5,7,4]] 
MAP_WIDTH = 5, MAP_HEIGHT = 5 

的對象具有一個元組的位置:

actor.location = (3,3) 

和一個視野範圍:

actor.range = 2 

如何編寫函數actor.view_map(map),使地圖返回演員位置周圍的區域直至範圍。例如(使用上述地圖),

range = 1 
location = (3, 2) 
=> 
[[2,3,4], 
[3,4,2], 
[2,2,1]] 

,但如果演員的範圍擴展得太遠我想要的地圖充滿了-1:

range = 1 
location = (1,1) 
[[-1,-1,-1], 
[-1, 1, 2], 
[-1, 2, 3]] 

最簡單的情況下是一系列的0,返回當前平方:

range = 0 
location = (1, 2) 
[[2]] 

如何將我的地圖切片到某個邊界?

+1

'actor.range'會有多少變化?如果它總是小於某個值(相對較小),那麼就有一個簡單的優化(用-1緩衝邊並寫一個簡單的包裝類)。 – 2013-04-07 20:54:28

+0

它將始終小於地圖寬度/高度的一半 - 但如果我在該級別向地圖添加邊界,則會將其大小加倍(?)... – sdasdadas 2013-04-07 20:56:08

+1

更接近四倍(面積==長度平方),實際上。儘管如此,如果你能夠承擔內存使用量,它會大大加快索引速度。 – 2013-04-07 20:58:25

回答

4

因此,感謝Joe Kington,我在地圖周圍添加了一個邊框(填充-1s)。

這裏是我做到了,但因爲我剛開始用的語言/庫這可能不是非常符合Python:

map = numpy.random.randint(10, size=(2 * World.MAP_WIDTH, 2 * World.MAP_HEIGHT)) 
map[0 : World.MAP_WIDTH/4, :] = -1 
map[7 * World.MAP_WIDTH/4 : 2 * World.MAP_WIDTH, :] = -1 
map[:, 0 : World.MAP_HEIGHT/4] = -1 
map[:, 7 * World.MAP_HEIGHT/4 : 2 * World.MAP_WIDTH] = -1 
+3

您可以使用函數'np.pad'在地圖上添加邊框:'np.pad(map,1,mode ='constant',constant_values = -1)' – askewchan 2013-04-08 03:18:46

+0

提示:避免使用'map'作爲變量名稱。這是python中的一個內置函數。 https://docs.python.org/3/library/functions.html#map – grisaitis 2016-03-03 17:19:42

2

這裏有一個小類Box,使使用更方便盒 -

from __future__ import division 
import numpy as np 

class Box: 
    """ B = Box(2d numpy array A, radius=2) 
     B.box(j, k) is a box A[ jk - 2 : jk + 2 ] clipped to the edges of A 
     @askewchan, use np.pad (new in numpy 1.7): 
      padA = np.pad(A, pad_width, mode="constant", edge=-1) 
      B = Box(padA, radius) 
    """ 

    def __init__(self, A, radius): 
     self.A = np.asanyarray(A) 
     self.radius = radius 

    def box(self, j, k): 
     """ b.box(j, k): square around j, k clipped to the edges of A """ 
     return self.A[ self.box_slice(j, k)] 

    def box_slice(self, j, k): 
     """ square, jk-r : jk+r clipped to A.shape """ 
      # or np.clip ? 
     r = self.radius 
     return np.s_[ max(j - r, 0) : min(j + r + 1, self.A.shape[0]), 
         max(k - r, 0) : min(k + r + 1, self.A.shape[1])] 

#............................................................................... 
if __name__ == "__main__": 
    A = np.arange(5*7).reshape((5,7)) 
    print "A:\n", A 
    B = Box(A, radius=2) 
    print "B.box(0, 0):\n", B.box(0, 0) 
    print "B.box(0, 1):\n", B.box(0, 1) 
    print "B.box(1, 2):\n", B.box(1, 2) 
+0

我還沒有機會嘗試它,但謝謝你的答覆! – sdasdadas 2013-04-08 21:30:51

+0

我喜歡這個,從我這裏得到讚揚:) – 2014-10-31 16:00:23