wireFrame.py

大昔に書いたコードを読み直して(書き直して)みたくなったので

#!/usr/bin/env python

import Tkinter
import tkFileDialog
import math

class wireFrame:
    def clickOpenFile(self):
        fileName = tkFileDialog.askopenfilename()
        self.openFile(fileName)
    def cnvMap(self,x,y):
#        return (x-self.width/2,y*-1+self.height/2)
        return (x-self.width/2,(y-self.height/2)*-1,0)

    def cnvCanvas(self,x,y,z):
        interval = self.viewPoint.get()*10 / (self.viewPoint.get()*10 + float(z))
        x = x*interval
        y = y*interval
        return (x+self.width/2,(y-self.height/2)*-1)

    def roll(self,x,y,degree):
        (orgX,orgY) = (x,y)
        orgR = math.sqrt(math.pow(orgX,2)+math.pow(orgY,2))
        if orgR==0:
            return (x,y)
        orgTheta = math.atan2(orgY/orgR,orgX/orgR)
        theta = math.radians(degree)+orgTheta
        x = math.cos(theta)*orgR
        y = math.sin(theta)*orgR
        return (x,y)

    def roll3DbySetting(self,x,y,z):
        x,y = self.roll(x,y,self.zAxisRollAngle.get())
        y,z = self.roll(y,z,self.xAxisRollAngle.get())
        x,z = self.roll(x,z,self.yAxisRollAngle.get())
        return (x,y,z)

    def roll3DbySettingReverse(self,x,y,z):
        x,z = self.roll(x,z,-self.yAxisRollAngle.get())
        y,z = self.roll(y,z,-self.xAxisRollAngle.get())
        x,y = self.roll(x,y,-self.zAxisRollAngle.get())
        return (x,y,z)

    def createObject(self,item):
        '''
        item
                => ('line',startX,startY,startZ,endX,endY,endZ)
                => ('sphere',centerX,centerY,centerZ,radius)
        '''
        if item[0]=='line':
            (itemType,sx,sy,sz,ex,ey,ez) = (item[0],
                                            int(item[1]),int(item[2]),int(item[3]),
                                            int(item[4]),int(item[5]),int(item[6]))
            (rsx,rsy,rsz) = self.roll3DbySetting(sx,sy,sz)
            (rex,rey,rez) = self.roll3DbySetting(ex,ey,ez)
            (lineSx,lineSy) = self.cnvCanvas(rsx,rsy,rsz)
            (lineEx,lineEy) = self.cnvCanvas(rex,rey,rez)
            line = self.canvas.create_line(lineSx,lineSy,
                                           lineEx,lineEy,
                                           fill=self.penColor,width=self.penWidth)
            obj = dict(id=line,itemType=itemType,coords=[sx,sy,sz,ex,ey,ez])
#            self.objects.append(obj)
            self.objects[line] = obj
            return obj
        elif item[0]=='sphere':
            (itemType,x,y,z,r) = (item[0],
                                  int(item[1]),int(item[2]),int(item[3]),int(item[4]))
            (rx,ry,rz) = self.roll3DbySetting(x,y,z)
            (cx,cy) = self.cnvCanvas(rx,ry,rz)
            sphere = self.canvas.create_oval(cx-r,cy-r,cx+r,cy+r,
                                             fill=self.penColor,outline=self.penColor)
            obj = dict(id=sphere,itemType=itemType,coords=[x,y,z,r])
#            self.objects.append(obj)
            self.objects[sphere] = obj
#            print sphere,itemType,x,y,z,r
            return obj
        else:
            pass
        pass
    def clearCanvas(self):
#         for obj in self.objects:
#             item,itemType,sx,sy,sz,ex,ey,ez = obj
#             self.canvas.delete(item)
        for id in self.objects.keys():
            self.canvas.delete(id)
        self.objects = {}
    def openFile(self,fileName):
        f = open(fileName)
        for row in f:
            row = row.replace('\n','')
            if row=='':continue
            item = row.split(',')
            obj = self.createObject(item)
        f.close()

    def angleChanged(self,event):
#        for obj in self.objects:
        for id,obj in self.objects.iteritems():
            itemType = obj['itemType']
            if itemType=='line':
                item,itemType,(sx,sy,sz,ex,ey,ez) = obj['id'],obj['itemType'],obj['coords']
                (rsx,rsy,rsz) = self.roll3DbySetting(sx,sy,sz)
                (rex,rey,rez) = self.roll3DbySetting(ex,ey,ez)
                (lineSx,lineSy) = self.cnvCanvas(rsx,rsy,rsz)
                (lineEx,lineEy) = self.cnvCanvas(rex,rey,rez)
                self.canvas.coords(item,lineSx,lineSy,lineEx,lineEy)
            elif itemType=='sphere':
                item,itemType,(x,y,z,r) = obj['id'],obj['itemType'],obj['coords']
                (rx,ry,rz) = self.roll3DbySetting(x,y,z)
                (cx,cy) = self.cnvCanvas(rx,ry,rz)
                self.canvas.coords(item,cx-r,cy-r,cx+r,cy+r)
            
    def __init__(self):
        self.window = Tkinter.Tk()
        self.width = 800
        self.height = 600
        self.penColor = 'red'
        self.penWidth = 3
        self.canvas = Tkinter.Canvas(self.window,bg="white",
                                     width=self.width,height=self.height)
        self.canvas.pack()
        self.xAxisRollAngle = Tkinter.Scale(self.window, from_=0, to=360,
                                            orient=Tkinter.HORIZONTAL)
        self.xAxisRollAngle.bind("<ButtonPress-1>",self.angleChanged)
        self.xAxisRollAngle.bind("<ButtonRelease-1>",self.angleChanged)
        self.xAxisRollAngle.bind("<B1-Motion>",self.angleChanged)
        self.xAxisRollAngle.pack(side=Tkinter.LEFT);

        self.yAxisRollAngle = Tkinter.Scale(self.window, from_=0, to=360,
                                            orient=Tkinter.HORIZONTAL)
        self.yAxisRollAngle.bind("<ButtonPress-1>",self.angleChanged)
        self.yAxisRollAngle.bind("<ButtonRelease-1>",self.angleChanged)
        self.yAxisRollAngle.bind("<B1-Motion>",self.angleChanged)
        self.yAxisRollAngle.pack(side=Tkinter.LEFT);

        self.zAxisRollAngle = Tkinter.Scale(self.window, from_=0, to=360,
                                            orient=Tkinter.HORIZONTAL)
        self.zAxisRollAngle.bind("<ButtonRelease-1>",self.angleChanged)
        self.zAxisRollAngle.bind("<ButtonPress-1>",self.angleChanged)
        self.zAxisRollAngle.bind("<B1-Motion>",self.angleChanged)
        self.zAxisRollAngle.pack(side=Tkinter.LEFT);

        self.viewPoint = Tkinter.Scale(self.window, from_=1, to=100,
                                       orient=Tkinter.HORIZONTAL)
        self.viewPoint.bind("<ButtonRelease-1>",self.angleChanged)
        self.viewPoint.bind("<ButtonPress-1>",self.angleChanged)
        self.viewPoint.bind("<B1-Motion>",self.angleChanged)
        self.viewPoint.set(100)
        self.viewPoint.pack(side=Tkinter.LEFT);

        self.btnOpenFile = Tkinter.Button(self.window,text="open",command=self.clickOpenFile)
        self.btnOpenFile.pack(side=Tkinter.RIGHT)

        self.objects = {}
        
        self.window.mainloop()

if __name__=='__main__':
    wireFrame()