Python从二维数组中的矩形获取随机墙

时间:2018-08-21 09:36:42

标签: python

所以我有这种形式的矩形:

class Rect:  # used for the tunneling algorithm
    def __init__(self, x, y, w, h):
        self.x1 = x
        self.y1 = y
        self.x2 = x + w
        self.y2 = y + h

    def center(self):
        center_x = (self.x1 + self.x2) // 2
        center_y = (self.y1 + self.y2) // 2
        return center_x, center_y

    def intersect(self, other):
        # returns true if this rectangle intersects with another one
        return (self.x1 <= other.x2 and self.x2 >= other.x1 and
                self.y1 <= other.y2 and self.y2 >= other.y1)

我一直在尝试从任何墙(包括角)上取任意一点,并将其作为x,y值传递。矩形仅具有以下值:坐标x和y,宽度和高度。

通常对于任何类型的2d数组,如果要获取所有值(包括角,即使它们重复也是如此),我会这样做:

alist=[arr[0,:], arr[:,-1], arr[-1,:], arr[:,0]]

这基本上会为我提供从中选择的值,但是在这种特殊情况下,我只能使用4个值,而且我不确定如何在不必重新创建整个矩形2d数组的情况下执行此操作。

请注意,整个矩形本身位于一个更大的数组中,并且所说的坐标是从那里开始的,但我希望它尽可能独立。

2 个答案:

答案 0 :(得分:1)

如果要生成矩形的所有整数坐标,则一种方法是在CommandInvokationFailure: Failed to re-package resources. E:\sdkandroid\build-tools\27.0.3\aapt.exe package --auto-add-overlay -v -f - m -J "gen" -M "AndroidManifest.xml" -S "res" -I "E:/sdkandroid\platforms\android-28\android.jar" -F bin/resources.ap_ -- extra-packages 类中实现__getitem__方法:

Rect

这将产生任何类型的坐标范围:

def __getitem__(self, k):
    def iteritem(k, kmin, kmax):
        if isinstance(k, int):
            yield kmin + k if k >= 0 else kmax + k
        elif isinstance(k, slice):
            for i in range(k.start or kmin, k.stop or kmax, k.step or 1):
                yield i

    if isinstance(k, tuple) and len(k) == 2:
        result = []
        for i in iteritem(k[0], self.x1, self.x2):
            for j in iteritem(k[1], self.y1, self.y2):
                result.append((i, j))
        return result

左上角:

>>> r = Rect(10, 20, 5, 4)

右下角:

>>> r[0,0]
[(10, 20)]

顶行:

>>> r[-1,-1]
[(14, 23)]

所有坐标:

>>> r[0,:]
[(10, 20), (10, 21), (10, 22), (10, 23)]

边界坐标:

>>> r[:,:]
[(10, 20), (10, 21), (10, 22), (10, 23), (11, 20), (11, 21), (11, 22), (11, 23), (12, 20), (12, 21), (12, 22), (12, 23), (13, 20), (13, 21), (13, 22), (13, 23), (14, 20), (14, 21), (14, 22), (14, 23)]

答案 1 :(得分:1)

如果我理解正确,例如,您本质上想要的是如果您具有2d数组

[[ 1,  2,  3,  4,  5],
 [ 6,  7,  8,  9, 10],
 [11, 12, 13, 14, 15],
 [16, 17, 18, 19, 20],
 [21, 22, 23, 24, 25]]

然后是一个以(1,1)开始,宽度和高度为3的矩形,那么该矩形应该是:

 7  8  9
12    14
17 18 19

通过尝试获取隔离墙,我想这意味着提取[7,8,9][7, 12, 17][9, 14, 19][17, 18, 19]作为列表。

请记住,您所需的代码只需从数组中选择构成墙的那些值即可。按照您定义类的方式,我们可以看到北壁的像元以y1作为其第一索引,而其第二索引从x1x2。因此,东墙的单元格的第一个索引取值为y1y2,第二个索引为x2。等等,其他墙壁。

在代码中,以下是一种快速的解决方案:

class Rect:  # used for the tunneling algorithm
    def __init__(self, x, y, w, h):
        self.x1 = x
        self.y1 = y
        self.x2 = x + w - 1
        self.y2 = y + h - 1

    def get_wall(self, grid, wall_name):
        # `grid` is the 2d array, such as `grid[i][j]` element is in i-th row and j-th column
        # `wall_name` accepts 'east', 'west', 'north', 'south' as values

        if wall_name == 'west':
            wall = [grid[i][self.x1] for i in range(self.y1, self.y2+1)]
        if wall_name == 'east':
            wall = [grid[i][self.x2] for i in range(self.y1, self.y2+1)]
        if wall_name == 'north':
            wall = [grid[self.y1][i] for i in range(self.x1, self.x2+1)]
        if wall_name == 'south':
            wall = [grid[self.y2][i] for i in range(self.x1, self.x2+1)]

        return wall

(请注意,我在计算y2和x2值时加了-1。因为我觉得如果正方形以2开始且宽度为2,那么它以3结束而不是4结束。但这只是一个约定)

要使用我提到的示例运行代码,可以添加以下行:

grid = [[ 1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10],
        [11, 12, 13, 14, 15],
        [16, 17, 18, 19, 20],
        [21, 22, 23, 24, 25]]

rect = Rect(1,1,3,3)

# The rectangle is:
#  *  *  *  *  *
#  *  7  8  9  *
#  * 12  * 14  *
#  * 17 18 19  *
#  *  *  *  *  * 

print(rect.get_wall(grid, 'north')) # will print [7,8,9]
print(rect.get_wall(grid, 'south')) # will print [17,18,19]
print(rect.get_wall(grid, 'east'))  # will print [9,14,19]
print(rect.get_wall(grid, 'west'))  # will print [7,12,17]

最后,请注意,如果矩形超出数组范围,则此代码将失败。但是您可以通过一些简单的if案例轻松解决它。