这里有很多问题,但主要的问题是如何创建一个给定角的填充菱形的 numpy 数组。我会回答这个问题,并留下其他问题,例如创建随机菱形等。
要填充凸多边形,可以找到由后续角指定的线并填充该线的上方或下方,然后and
所有填充的区域在一起。
import numpy as np
import matplotlib.pyplot as plt
# given two (non-vertical) points, A and B,
# fill above or below the line connecting them
def fill(A, B, fill_below=True, xs=10, ys=12):
# the equation for a line is y = m*x + b, so calculate
# m and b from the two points on the line
m = (B[1]-A[1])/(B[0]-A[0]) # m = (y2 - y1)/(x2 - x1) = slope
b = A[1] - m*A[0] # b = y1 - m*x1 = y intercept
# for each points of the grid, calculate whether it's above, below, or on
# the line. Since y = m*x + b, calculating m*x + b - y will give
# 0 when on the line, <0 when above, and >0 when below
Y, X = np.mgrid[0:ys, 0:xs]
L = m*X + b - Y
# select whether, >=0 is True, or, <=0 is True, to determine whether to
# fill above or below the line
op = np.greater_equal if fill_below else np.less_equal
return op(L, 0.0)
这是一个简单的低分辨率菱形
r = fill((0, 3), (3, 8), True) & \
fill((3, 8), (7, 4), True) & \
fill((7,4), (5,0), False) & \
fill((5,0), (0,3), False)
plt.imshow(r, cmap='Greys', interpolation='nearest', origin='lower')
也就是说,上图是以下填充的and-ing结果:
fig, ax = plt.subplots(1, 4, figsize=(10, 3))
fill_params = [((0, 3), (3, 8), True), ((3, 8), (7, 4), True), ((7, 4), (5, 0), False), ((5, 0), (0, 3), False)]
for p, ax in zip(fill_params, ax):
ax.imshow(fill(*p), cmap="Greys", interpolation='nearest', origin='lower')
或者,可以做高分辨率,并且它可以有多个侧面(尽管我认为它必须是凸面的)。
r = fill((0, 300), (300, 800), True, 1000, 1200) & \
fill((300, 800), (600,700), True, 1000, 1200) & \
fill((600, 700), (700, 400), True, 1000, 1200) & \
fill((700,400), (500,0), False, 1000, 1200) & \
fill((500,0), (100,100), False, 1000, 1200) & \
fill((100, 100), (0,300), False, 1000, 1200)
plt.imshow(r, cmap='Greys', interpolation='nearest', origin='lower')
显然,有一些事情需要改进,比如不重复线的第二个点和新线的第一个点,但我想让这一切保持干净和简单(而且,为了填充工作,这些点只需要定义一条线并且不需要是一个角,因此在某些情况下这种更通用的方法可能更可取)。此外,目前需要指定是在线上方还是下方填充,并且可以通过多种方式计算,但在生成菱形时可能是最简单的。