Диагональная нарезка кусочков
Я хочу нарезать 2D массив массивов между 3-мя координатами, например, учитывая этот код,
[[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]]
и координаты (1,1) (3,1) (3,5), я хочу это:
[[0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0]
[0 1 1 1 0 0 0 0]
[0 1 1 1 1 1 0 0]]
любые советы и рекомендации очень ценятся.
1 ответ
Основная функция для np.tri...
семейство функций np.tri
,
Глядя на его код, мы видим, что он делает (для квадратного массива):
In [36]: np.greater_equal.outer(np.arange(4),np.arange(+1, 4+1))
Out[36]:
array([[False, False, False, False],
[ True, False, False, False],
[ True, True, False, False],
[ True, True, True, False]])
Поэкспериментируя с этим, я могу создать что-то ближе к вашему примеру:
In [39]: np.greater_equal.outer(np.arange(4),.5*np.arange(+1, 8+1))
Out[39]:
array([[False, False, False, False, False, False, False, False],
[ True, True, False, False, False, False, False, False],
[ True, True, True, True, False, False, False, False],
[ True, True, True, True, True, True, False, False]])
In [40]: _.astype(int)
Out[40]:
array([[0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0]])
Является ли это полезным подходом, зависит от того, какой общий треугольник вы хотите. Примером является вариация традиционного нижнего треугольника. Но если точки были более общими, скажите:
(1,1), (3,2), (2,6)
вам придется придумать более сложный
Основываясь на этом ответе, нам нужно проверить каждое ребро треугольника, если ребра ориентированы против часовой стрелки, мы можем проверить, лежит ли точка слева от края. Если все ребра проходят проверку - точка внутри. Если хоть один выйдет из строя - дело во внешнем.
Чтобы проверить, действительно ли точка (xp, yp)
лежит на левой стороне края (x1, y1) - (x2, y2)
, вам просто нужно рассчитать:
D = (x2 - x1) * (yp - y1) - (xp - x1) * (y2 - y1)
Если D > 0
, точка находится слева. ЕслиD < 0
, точка находится справа. ЕслиD = 0
, точка находится на линии.
Вот код:
def triangular_slicing(input, (x1, y1), (x2, y2), (x3, y3)):
for i in range(input.shape[0]):
for j in range(input.shape[1]):
D = (x2 - x1) * (j - y1) - (i - x1) * (y2 - y1)
if D >= 0:
D = (x3 - x2) * (j - y2) - (i - x2) * (y3 - y2)
if D >= 0:
D = (x1 - x3) * (j - y3) - (i - x3) * (y1 - y3)
if D >= 0:
input[i][j] = 1
return input
и вот результаты:
a = np.zeros((11, 11), dtype=np.uint)
res = triangular_slicing(a, (1,1), (6,3) , (6,9) )
[[0 0 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0 0]
[0 0 1 1 1 0 0 0 0 0 0]
[0 0 0 1 1 1 0 0 0 0 0]
[0 0 0 1 1 1 1 1 0 0 0]
[0 0 0 1 1 1 1 1 1 1 0]
[0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0]]
a = np.zeros((11, 11), dtype=np.uint)
res = triangular_slicing(a, (0,5), (8,2) , (8,8) )
[[0 0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 1 1 1 0 0 0 0]
[0 0 0 0 1 1 1 0 0 0 0]
[0 0 0 0 1 1 1 0 0 0 0]
[0 0 0 1 1 1 1 1 0 0 0]
[0 0 0 1 1 1 1 1 0 0 0]
[0 0 1 1 1 1 1 1 1 0 0]
[0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0]]