计算机图形学3-多边形扫描转换算法

多边形扫描转换算法

  • 效果
  • 代码

效果

首先点击几个点作为多边形顶点,按下“e”画出多边形轮廓。接下来按下“r”、“g”、“b”三个按键中的任一个选择对应颜色填充多边形。它会慢慢自上往下填充。
计算机图形学3-多边形扫描转换算法_第1张图片
计算机图形学3-多边形扫描转换算法_第2张图片
这里说明一下,代码可能还有点小问题,边数多了会填充出错

代码

import cv2
import numpy as np
import time
 
img  =  np.zeros((700, 900, 3), np.uint8)#背景
pts=[]

def draw_func(event, x, y, flags, param):
    global pts
    if event == cv2.EVENT_LBUTTONDOWN:
        print('(x:',x,',y:',y,')')
        str1 = '(x:'+ str(x) + ',y:'+ str(y) + ')'
        #cv2.putText(img,str1 , (x, y), cv2.FONT_HERSHEY_PLAIN,1.0, (0, 0, 255), thickness=1)
        cv2.circle(img,(x,y),1,(0,255,0),thickness=1)
        pts.append([x,y])

#活性边表与新边表中的节点
class Node:
    def __init__(self,xmin,ymax,k1,next=None):
        self.x=xmin#也就是x的初始值
        self.ymax=ymax
        self.k1=k1#也就是δx
        self.next=next
    def print(self):
        t=self
        while t!=None:
            print(t.x,t.ymax,t.k1,end="-->")
            t=t.next
        print()


def FillPoly(fpts,color):
    #cv2.fillPoly(img,fpts,color)
    Ymin,Ymax=1000000,0
    for pt in fpts:
        if Ymin>pt[1]:
            Ymin=pt[1]
        if Ymax<pt[1]:
            Ymax=pt[1]
    
    #构造新边表
    NET=[x for x in range(Ymax+1)]
    for i in range(len(fpts)):
        #后面一个点的序号
        j=i+1 if i<len(fpts)-1 else 0
        if fpts[i][1]>fpts[j][1]:
            ymax,ymin=fpts[i][1],fpts[j][1]
            xmin=fpts[j][0]
        else:
            ymin,ymax=fpts[i][1],fpts[j][1]
            xmin=fpts[i][0]
        #与x轴平行,跳过该边
        if fpts[i][1]==fpts[j][1]:
            continue

        if fpts[i][0]==fpts[j][0]:
            k1=0
        else:
            k1=(fpts[i][0]-fpts[j][0])/(fpts[i][1]-fpts[j][1])

        if type(NET[ymin])!=type(66):
            t=NET[ymin]
            while t.next!=None:
                t=t.next
            t.next=Node(xmin,ymax,k1)
        else:
            NET[ymin]=Node(xmin,ymax,k1)
    for i,x in enumerate(NET):
        if type(x)!=type(66):
            print(i)
            x.print()

    AET=Node(0,0,0)
    print("YY")
    for y in range(Ymin,Ymax+1):
        print(y)
        #慢慢画
        cv2.waitKey(3)
        cv2.imshow('src',img)
        #加入新边
        if type(NET[y])!=type(66):
            t=AET
            while t.next:
                t=t.next
            t.next=NET[y]
        #填充颜色
        #按x排序
        xs=[]
        t=AET
        while t.next:
            t=t.next
            xs.append(t.x)
        xs=sorted(xs)
        for i in range(1,len(xs),2):
            for x in range(int(xs[i-1]),int(xs[i])):
                cv2.circle(img,(x,y),1,color,thickness=1)
        #删除并更新边
        t=AET
        while t.next:
            ct=t.next
            ct.x+=ct.k1
            if ct.ymax==y:
                t.next=ct.next
            t=t.next
            if t==None:
                break




cv2.namedWindow('src')
cv2.setMouseCallback('src',draw_func)

while(1):
    cv2.imshow('src',img)
    code=cv2.waitKey(100)
    if code == ord('q'):#按下q退出
        break
    elif code == ord('e'):#按下该键表示画完一个多边形
        tmp=np.array(pts,np.int32)
        tmp=[tmp.reshape((-1,1,2))]
        fpts=pts
        pts=[]
        cv2.polylines(img,tmp,True,(255,255,255))
    #按下 r,g,b 填充多边形为相应的颜色
    elif code == ord('r'):
        FillPoly(fpts,(0,0,255))
    elif code == ord('g'):
        FillPoly(fpts,(0,255,0))
    elif code == ord('b'):
        FillPoly(fpts,(255,0,0))
cv2.destroyAllWindows()

你可能感兴趣的:(计算机图形学,python,图形学)