参考文档:
参考1:https://blog.csdn.net/u013044116/article/details/49737585
参考2:https://blog.csdn.net/keneyr/article/details/83747501
算法思想:
对多边形沿y轴从0开始遍历,建立边表NET。只记录顶点的x, dx, ymax。
根据NET构建活动边表AET(activate edge table)。射线与多边形的交点坐标为(x + △x, y + 1), △x是斜率的倒数(dx)。详解见 参考1。
实现代码:
点击查看代码
# encoding=utf8
import mathimport cv2
import numpy as npclass EdgeTable:def __init__(self, x, dx, ymax):self.x = xself.dx = dxself.ymax = ymaxself.next = Nonedef fill_polys(polys):poly_x_max = float('-inf')poly_y_max = float('-inf')for poly in polys:poly_x_max = max(poly_x_max, poly[0])poly_y_max = max(poly_y_max, poly[1])poly_x_max += 1poly_y_max += 1point_count = len(polys)# build edge tablenet = [None for _ in range(poly_y_max)]for i in range(poly_y_max):for j in range(point_count):# 一个点跟前面的点形成线段 跟后边的点也形成线段if polys[j][1] == i:if polys[(j - 1 + point_count) % point_count][1] > polys[j][1]:x_ = polys[j][0]dx_ = (polys[(j - 1 + point_count) % point_count][0] - polys[j][0]) / (polys[(j - 1 + point_count) % point_count][1] - polys[j][1])ymax_ = polys[(j - 1 + point_count) % point_count][1]pnt = EdgeTable(x_, dx_, ymax_)pnt.next = net[i]net[i] = pntif polys[(j + 1 + point_count) % point_count][1] > polys[j][1]:x_ = polys[j][0]dx_ = (polys[(j + 1 + point_count) % point_count][0] - polys[j][0]) / (polys[(j + 1 + point_count) % point_count][1] - polys[j][1])ymax_ = polys[(j + 1 + point_count) % point_count][1]pnt = EdgeTable(x_, dx_, ymax_)pnt.next = net[i]net[i] = pnt# build activate edge tablebg = np.zeros((poly_x_max, poly_y_max), dtype=np.uint8)aet = EdgeTable(0, 0, 0)for i in range(poly_y_max):# 计算新的交点 更新aet表pa = aet.nextwhile pa:pa.x = pa.x + pa.dxpa = pa.next# 更新aet表之后对ate表进行排序# 断表排序 不开辟新空间pa = aetpcur = aet.nextpa.next = Nonewhile pcur:while pa.next and pcur.x >= pa.next.x:pa = pa.nextpt = pcur.nextpcur.next = pa.nextpa.next = pcurpcur = ptpa = aet# net表中的点加入到aet表中,并用插值法按x排序插入pn = net[i]pa = aetwhile pn:while pa.next and pn.x >= pa.next.x:pa = pa.nextpt = pn.nextpn.next = pa.nextpa.next = pnpn = ptpa = aet# 填充pcur = aet.nextwhile pcur and pcur.next:# 浮点数转成整数 如果dx是负数 向下取整;如果dx是正数 向上取整s = math.ceil(pcur.x) if pcur.dx > 0 else math.floor(pcur.x)e = math.ceil(pcur.next.x) if pcur.next.dx > 0 else math.floor(pcur.next.x)# for x in range(pcur.x, pcur.next.x+1):for x in range(s, e + 1):bg[x][i] = 1pcur = pcur.next# 从aet表中删除ymax==i的结点pa = aetpcur = pa.nextwhile pcur:if pcur.ymax == i:pa.next = pcur.nextdel pcurpcur = pa.nextelse:pcur = pcur.nextpa = pa.nextprint(bg)def matrix(polys):m = np.zeros((10, 10), dtype=np.uint8)for x, y in polys:m[x, y] = 1return mdef cv_fill(polys):mask = np.zeros((5, 5), dtype=np.uint8)cv2.fillPoly(mask, [np.array(polys)], 1, lineType=cv2.FILLED)return maskif __name__ == "__main__":# r = matrix([[8, 8], [2, 7], [5, 5], [2, 2], [5, 1], [9, 3]])# print(r)polys = [[2, 4], [1, 2], [3, 0], [4, 1], [3, 2], [4, 3]]fill_polys(polys)# cv_fill(polys)
结果展示: