■
万有引力シミュレータ。
wireFrame.pyを修正してその上で動かす。
…次は影をつけよう。やっぱりアレがないと動いてる感じがしない*1。
planet.py
from wireFrame import * from math import * class planet: def __init__(self): self.wf = wireFrame() self.wf.canvas.bind("<ButtonPress-1>",self.press1) self.vectors = {} self.timerTick = 100 self.G = 1.0 self.R = 4 self.wf.window.after(self.timerTick,self.moveObjects) def press1(self,event): (x,y,z) = self.wf.cnvMap(event.x,event.y) (x,y,z) = self.wf.roll3DbySettingReverse(x,y,z) obj = self.wf.createObject(['sphere',x,y,z,self.R]) self.vectors[obj['id']] = [0,0,0] def moveObjects(self): for id,obj in self.wf.objects.iteritems(): itemType = obj['itemType'] if itemType=='sphere': item,itemType,(x,y,z,r) = obj['id'],obj['itemType'],obj['coords'] for oid,other in self.wf.objects.iteritems(): if other['id']==item or other['itemType']!='sphere': continue oid,oType,(ox,oy,oz,oR) = other['id'],other['itemType'],other['coords'] xDist,yDist,zDist = x-ox,y-oy,z-oz d = pow(pow(xDist,2)+pow(yDist,2)+pow(zDist,2),1/2.0) g = 1/pow(d,2)*self.G vx,vy,vz = self.vectors[obj['id']] vx,vy,vz = vx+(ox-x)*g,vy+(oy-y)*g,vz+(oz-z)*g self.vectors[obj['id']] = [vx,vy,vz] vx,vy,vz = self.vectors[obj['id']] x,y,z = x+vx,y+vy,z+vz (rx,ry,rz) = self.wf.roll3DbySetting(x,y,z) (cx,cy) = self.wf.cnvCanvas(rx,ry,rz) self.wf.canvas.coords(item,cx-r,cy-r,cx+r,cy+r) obj['coords'] = (x,y,z,r) self.wf.window.after(self.timerTick,self.moveObjects)
修正した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()