矩形裁剪算法_python3最终版

来源:互联网 发布:公司网络推广提成方案 编辑:程序博客网 时间:2024/06/05 12:58
环境准备:
Python版本是3.5.1。使用pip命令:pip install pyopengl 安装pyopengl模块
另外注意需要将opengl文件(打开文件链接,也可自行百度)复制到系统盘System32(32位系统)或SysWOW64(64位系统)目录下,不然可能或报错。我今天在学校实验室碰到了此问题,错误信息好像是glutInit函数不能使用之类的。
说明:
老师的要求是实现键盘输入和鼠标点击两种交互方式,没法子,只好封装一下函数,方便调用了。
代码:
#encoding='utf-8'#python3.5.1#author by 张政伟 2016/6/21#矩形裁剪算法from OpenGL.GLUT import *from OpenGL.GL import *import sysblue=(0.0,0.0,1.0)green=(0.0,1.0,0.0)red=(1.0,0.0,0.0)color=bluewinx=400 #窗口宽度winy=400 #窗口高度l1=[];#存储坐标class point:    x=0 #x坐标    y=0 #y坐标    pl=0 #相对于矩形裁剪区域左边,此点的位置,0为内,1为外    pt=0 #相对于矩形裁剪区域上边,此点的位置,0为内,1为外    pr=0 #相对于矩形裁剪区域右边,此点的位置,0为内,1为外    pb=0 #相对于矩形裁剪区域下边,此点的位置,0为内,1为外    def __init__(self,x,y,pl,pt,pr,pb):        self.x=x        self.y=y        self.pl=pl        self.pt=pt        self.pr=pr        self.pb=pbi=point(0,0,0,0,0,0)#函数:得到被裁剪区域顶点坐标相对于裁剪区域四条边的位置def judgePositon(i,prt,plb):    #判断左边    if(i.x<plb.x):        i.pl=1    else:        i.pl=0    #判断上边    if(i.y<prt.y):        i.pt=0    else:        i.pt=1    #判断右边    if(i.x<prt.x):        i.pr=0    else:        i.pr=1    #判断下边       if(i.y<plb.y):        i.pb=1    else:        i.pb=0def leftClip(prt,plb,*l):    l=l[0]    l2=[]    #左边裁剪    print(l[0].x)    for i in range(0,len(l)):        if(i==len(l)-1):            if(l[i].pl==0):                #都在内部,保留第二个顶点                if(l[0].pl==0):                    l2.append(l[0])                #一内一外,保留交点                else:                    k=(l[i].y-l[0].y)/(l[i].x-l[0].x)                    b=l[i].y-k*l[i].x                    x=plb.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)            else:                #一外一内,保留交点与内                if(l[0].pl==0):                    k=(l[i].y-l[0].y)/(l[i].x-l[0].x)                    b=l[i].y-k*l[i].x                    x=plb.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)                    l2.append(l[0])                #都在外部,全部舍弃                else:                    pass        else:            if(l[i].pl==0):                #都在内部,保留第二个顶点                if(l[i+1].pl==0):                    l2.append(l[i+1])                #一内一外,保留交点                else:                    k=(l[i].y-l[i+1].y)/(l[i].x-l[i+1].x)                    b=l[i].y-k*l[i].x                    x=plb.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)            else:                #一外一内,保留交点与内                if(l[i+1].pl==0):                    k=(l[i].y-l[i+1].y)/(l[i].x-l[i+1].x)                    b=l[i].y-k*l[i].x                    x=plb.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)                    l2.append(l[i+1])                #都在外部,全部舍弃                else:                     pass    return l2def topClip(prt,plb,*l):    l2=l[0]    l=[]    for i in range(0,len(l2)):        if(i==len(l2)-1):            if(l2[i].pt==0):                #都在内部,保留第二个顶点                if(l2[0].pt==0):                    l.append(l2[0])                #一内一外,保留交点                else:                    if(l2[i].x==l2[0].x):                        x=l2[i].x                        y=prt.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                    else:                             k=(l2[i].y-l2[0].y)/(l2[i].x-l2[0].x)                        b=l2[i].y-k*l2[i].x                        y=prt.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)            else:                #一外一内,保留交点与内                if(l2[0].pt==0):                    if(l2[i].x==l2[0].x):                        x=l2[i].x                        y=prt.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[0])                    else:                        k=(l2[i].y-l2[0].y)/(l2[i].x-l2[0].x)                        b=l2[i].y-k*l2[i].x                        y=prt.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[0])                #都在外部,全部舍弃                else:                    pass        else:            if(l2[i].pt==0):                #都在内部,保留第二个顶点                if(l2[i+1].pt==0):                    l.append(l2[i+1])                    #一内一外,保留交点                else:                    if(l2[i].x==l2[i+1].x):                        x=l2[i].x                        y=prt.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                    else:                            k=(l2[i].y-l2[i+1].y)/(l2[i].x-l2[i+1].x)                        b=l2[i].y-k*l2[i].x                        y=prt.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)            else:                #一外一内,保留交点与内                if(l2[i+1].pt==0):                    if(l2[i].x==l2[i+1].x):                        x=l2[i].x                        y=prt.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[i+1])                    else:                        k=(l2[i].y-l2[i+1].y)/(l2[i].x-l2[i+1].x)                        b=l2[i].y-k*l2[i].x                        y=prt.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[i+1])                #都在外部,全部舍弃                else:                    pass    return ldef rightClip(prt,plb,*l):    l=l[0]    l2=[]    for i in range(0,len(l)):        if(i==len(l)-1):            if(l[i].pr==0):                #都在内部,保留第二顶点                if(l[0].pr==0):                    l2.append(l[0])                #一内一外,保留交点                else:                    k=(l[i].y-l[0].y)/(l[i].x-l[0].x)                    b=l[i].y-k*l[i].x                    x=prt.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)            else:                #一外一内,保留交点与内                if(l[0].pr==0):                    k=(l[i].y-l[0].y)/(l[i].x-l[0].x)                    b=l[i].y-k*l[i].x                    x=prt.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)                    l2.append(l[0])                #都在外部,全部舍弃                else:                    pass        else:            if(l[i].pr==0):                #都在内部,保留第二顶点                if(l[i+1].pr==0):                    l2.append(l[i+1])                #一内一外,保留交点                else:                    k=(l[i].y-l[i+1].y)/(l[i].x-l[i+1].x)                    b=l[i].y-k*l[i].x                    x=prt.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)            else:                #一外一内,保留交点与内                if(l[i+1].pr==0):                    k=(l[i].y-l[i+1].y)/(l[i].x-l[i+1].x)                    b=l[i].y-k*l[i].x                    x=prt.x                    y=x*k+b                    temp=point(x,y,0,0,0,0)                    l2.append(temp)                    l2.append(l[i+1])                #都在外部,全部舍弃                else:                    pass    return l2def bottomClip(prt,plb,*l):    l2=l[0]    l=[]    for i in range(0,len(l2)):        if(i==len(l2)-1):            if(l2[i].pb==0):                #都在内部,保留第二顶点                if(l2[0].pb==0):                    l.append(l2[0])                #一内一外,保留交点                else:                    if(l2[i].x==l2[0].x):                        x=l2[i].x                        y=plb.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                    else:                        k=(l2[i].y-l2[0].y)/(l2[i].x-l2[0].x)                        b=l2[i].y-k*l2[i].x                        y=plb.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)            else:                #一外一内,保留交点内                if(l2[0].pb==0):                    if(l2[i].x==l2[0].x):                        x=l2[i].x                        y=plb.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[0])                    else:                        k=(l2[i].y-l2[0].y)/(l2[i].x-l2[0].x)                        b=l2[i].y-k*l2[i].x                        y=plb.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[0])                #都在外部,全部舍弃                else:                    pass        else:            if(l2[i].pb==0):                #都在内部,保留第二顶点                if(l2[i+1].pb==0):                    l.append(l2[i+1])                #一内一外,保留交点                else:                    if(l2[i].x==l2[i+1].x):                        x=l2[i].x                        y=plb.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                    else:                        k=(l2[i].y-l2[i+1].y)/(l2[i].x-l2[i+1].x)                        b=l2[i].y-k*l2[i].x                        y=plb.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)            else:                #一外一内,保留交点与内                if(l2[i+1].pb==0):                    if(l2[i].x==l2[i+1].x):                        x=l2[i].x                        y=plb.y                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[i+1])                    else:                        k=(l2[i].y-l2[i+1].y)/(l2[i].x-l2[i+1].x)                        b=l2[i].y-k*l2[i].x                        y=plb.y                        if k!=0:                            x=(y-b)/k                        temp=point(x,y,0,0,0,0)                        l.append(temp)                        l.append(l2[i+1])                #都在外部,全部舍弃                else:                    pass    return l#窗口左上角为(0,0),而PyOpengl画图以窗口中心为(0,0)且最大x坐标与y坐标都是100。#因此需要将鼠标获取的坐标转换成PyOpengl画图坐标。def translate(point):    a=winx/2    b=winy/2    if point.x < a and point.y < b:        point.x=(point.x/a)*100-100        point.y=100-(point.y/b)*100    elif point.x > a and point.y < b:        point.x=((point.x-a)/a)*100        point.y=100-(point.y/b)*100    elif point.x < a and point.y > b:        point.x=(point.x/a)*100-100        point.y=((point.y-b)/b)*100*(-1)    else:        point.x=((point.x-a)/a)*100        point.y=((point.y-b)/b)*100*(-1)def display():    glClearColor(0.0,0.0,0.0,0.0)  #背景色=黑色,RGBA全为0    glClear(GL_COLOR_BUFFER_BIT)   #清除颜色缓冲区    glColor3fv(color)              #设置下面绘制物体的颜色    #f表示参数类型为浮点类型,v表示接受的参数为数组形式    #glRectf(-10.0,-20.0,20.0,10.0) #画填充矩形    #绘制坐标系    glColor3f(1.0, 1.0, 1.0)      glBegin(GL_LINES)     glVertex2f(0.0, 0.0)      glVertex2f(0.0, 95.0)    glVertex2f(0.0, 95.0)    glVertex2f(4.0, 92.0)    glVertex2f(0.0, 95.0)    glVertex2f(-4.0, 92.0)    glVertex2f(0.0, 0.0)      glVertex2f(0.0, -95.0)    glVertex2f(0.0, 0.0)      glVertex2f(95.0,0.0)    glVertex2f(95.0,0.0)    glVertex2f(92.0,4.0)    glVertex2f(95.0,0.0)    glVertex2f(92.0,-4.0)    glVertex2f(0.0, 0.0)      glVertex2f(-95.0,0.0)        glEnd()    glColor3f(0.0,0.0,1.0)    glBegin(GL_POINTS);    glVertex2i(0,0);    glEnd();    glFlush()def reshape(winx,winy):    glViewport(0,0,winx,winy)      #定义相对视窗大小(像素范围)    glMatrixMode(GL_PROJECTION)    #选择投影矩阵    glLoadIdentity()               #读取规范化的单位矩阵    glOrtho(-100.0,100.0, -100.0,100.0, 0.0,100.0)                                   #定义空间坐标系范围    glMatrixMode(GL_MODELVIEW)     #选择模型视图矩阵    glLoadIdentity()def key(key,mousex,mousey):    global color    if(key==b'q'):                 #按下q按键时        print('退出')        glutDestroyWindow(winid)   #根据ID结束窗口        sys.exit()    elif(key==b'e'):        l1.clear()        print('初始化界面')        glutPostRedisplay()        #重绘,将调用display    elif(key==b'g'):        #以绿线画裁剪后图形并输出裁剪后坐标        if l1[0].x<l1[1].x:             #矩形裁剪区域:左下点的坐标            plb=point(l1[0].x,l1[0].y,0,0,0,0)            #矩形裁剪区域:右上点的坐标            prt=point(l1[1].x,l1[1].y,0,0,0,0)        else:            #矩形裁剪区域:左下点的坐标            plb=point(l1[1].x,l1[1].y,0,0,0,0)            #矩形裁剪区域:右上点的坐标            prt=point(l1[0].x,l1[0].y,0,0,0,0)        #输出        print('裁剪区域左下点坐标:')        print(plb.x,plb.y)        print('裁剪区域右上点坐标:')        print(prt.x,prt.y)        #被裁剪区域顶点坐标        l=l1[2:]        #调用函数,完全初始化被裁减区域顶点坐标        for i in l1:            judgePositon(i,prt,plb)        #测试输出被裁剪区域顶点坐标        print("init:")        for i in l:            print(i.x,i.y,i.pl,i.pt,i.pr,i.pb)        #左边裁剪        #调用左边裁减函数        l=leftClip(prt,plb,l)        #初始化左裁剪后顶点坐标相对裁剪区域的位置        for i in l:            judgePositon(i,prt,plb)        #输出左裁剪后顶点坐标        print("leftClip:")        for i in l:            print(i.x,i.y,i.pl,i.pt,i.pr,i.pb)        #上边裁剪        #调用上边裁剪函数        l=topClip(prt,plb,l)        #初始化上裁剪后顶点坐标相对裁剪区域的位置        for i in l:            judgePositon(i,prt,plb)        #输出上裁剪后顶点坐标        print("topClip:")        for i in l:            print(i.x,i.y,i.pl,i.pt,i.pr,i.pb)        #右边裁剪        #调用右边裁剪函数        l=rightClip(prt,plb,l)        #初始化右裁剪后顶点坐标相对裁剪区域的位置        for i in l:            judgePositon(i,prt,plb)        #输出右裁剪后顶点坐标        print("rightClip:")        for i in l:            print(i.x,i.y,i.pl,i.pt,i.pr,i.pb)        #下边裁剪        #调用下边裁剪函数        l=bottomClip(prt,plb,l)        #初始化下裁剪后顶点坐标相对裁剪区域的位置        for i in l:            judgePositon(i,prt,plb)        #输出下裁剪后顶点坐标        print("bottomClip:")        for i in l:            print(i.x,i.y,i.pl,i.pt,i.pr,i.pb)        #以绿线画裁剪后区域        color=green        glColor3fv(color)         print('以绿线画被裁剪多边形')        for i in range(0,len(l)):            if(i==len(l)-1):                glBegin(GL_LINES) #画线                  glVertex2f(l[i].x,l[i].y)                glVertex2f(l[0].x,l[0].y)                  glEnd()                glFlush()            else:                glBegin(GL_LINES) #画线                  glVertex2f(l[i].x,l[i].y)                glVertex2f(l[i+1].x,l[i+1].y)                  glEnd()                glFlush()            elif(key==b'r'):#以红色画矩形裁剪窗口        color=red        glColor3fv(color)         print('以红线画矩形裁剪窗口')        glBegin(GL_LINES) #画线          glVertex2f(l1[0].x,l1[0].y)        glVertex2f(l1[0].x,l1[1].y)                glVertex2f(l1[0].x,l1[1].y)         glVertex2f(l1[1].x,l1[1].y)                glVertex2f(l1[1].x,l1[1].y)        glVertex2f(l1[1].x,l1[0].y)        glVertex2f(l1[1].x,l1[0].y)        glVertex2f(l1[0].x,l1[0].y)        glEnd()        glFlush()    elif(key==b'b'):        color=blue        glColor3fv(color)         print('以蓝线画被裁剪多边形')        for i in range(2,len(l1)):            if(i==len(l1)-1):                glBegin(GL_LINES) #画线                  glVertex2f(l1[i].x,l1[i].y)                glVertex2f(l1[2].x,l1[2].y)                  glEnd()                glFlush()            else:                glBegin(GL_LINES) #画线                  glVertex2f(l1[i].x,l1[i].y)                glVertex2f(l1[i+1].x,l1[i+1].y)                  glEnd()                glFlush()    elif(key==b'k'):        print('请输入左下点x坐标:')        lx=float(input())        print('请输入左下点y坐标:')        ly=float(input())        print('请输入右下点x坐标:')        rx=float(input())        print('请输入右下点y坐标:')        ry=float(input())        l1.clear()        plb=point(lx,ly,0,0,0,0)        prt=point(rx,ry,0,0,0,0)        l1.append(plb)        l1.append(prt)        #矩形顶点坐标        for i in l1:            print(i.x,i.y)        print("输入被裁剪多边形顶点个数:")        n=int(input())        for i in range(0,n):            print('请输入第%d个顶点x坐标' %(i+1))            tempX=float(input())            print('请输入第%d点y坐标' %(i+1))            tempY=float(input())            temp=point(tempX,tempY,0,0,0,0)            l1.append(temp)        print('按\'r\'键绘制裁剪区域。')        print('按\'b\'键绘制被裁剪区域')        print('按\'g\'键绘制被裁剪后区域')def mouse(button,state,x,y):    #鼠标左键按下    if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN:        glColor3fv(color)        temp=point(x,y,0,0,0,0)        translate(temp)        l1.append(temp)print('使用说明:')print('1.鼠标点击:')print('请用鼠标点击确定矩形裁剪区域左下点与右下点坐标,按\'r\'键绘制裁剪区域')print('请用鼠标点击确定被裁剪区域坐标,按\'b\'键绘制被裁剪区域')print('按\'g\'键绘制被裁剪后区域')print('按\'e\'键初始化界面')print('按\'q\'键退出程序')print('按\'k\'键从命令行输入坐标绘图裁剪')glutInit(sys.argv)glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA)glutInitWindowSize(winx,winy)glutInitWindowPosition(100,100)winid=glutCreateWindow(b"main")    #建立窗口的ID返回到winidglutDisplayFunc(display)glutReshapeFunc(reshape)glutKeyboardFunc(key)glutMouseFunc(mouse)glutMainLoop()


0 0
原创粉丝点击