Added the autoplater stuff and a debug function

master
Travis Howse 2011-09-08 20:15:53 +10:00
parent 2704c88dd1
commit 71a15c220d
1 changed files with 360 additions and 250 deletions

610
plater.py
View File

@ -3,262 +3,372 @@ import wx,time,random,threading,os,math
import stltool import stltool
class stlwrap: class stlwrap:
def __init__(self,obj,name=None): def __init__(self,obj,name=None):
self.obj=obj self.obj=obj
self.name=name self.name=name
if name is None: if name is None:
self.name=obj.name self.name=obj.name
def __repr__(self): def __repr__(self):
return self.name return self.name
class showstl(wx.Window): class showstl(wx.Window):
def __init__(self,parent,size,pos): def __init__(self,parent,size,pos):
wx.Window.__init__(self,parent,size=size,pos=pos) wx.Window.__init__(self,parent,size=size,pos=pos)
self.l=wx.ListCtrl(self,style=wx.LC_LIST,size=(300,130),pos=(0,size[1]-130)) self.l=wx.ListCtrl(self,style=wx.LC_LIST,size=(300,130),pos=(0,size[1]-130))
self.eb=wx.Button(self,label="Export",pos=(300,size[1]-130)) self.eb=wx.Button(self,label="Export",pos=(300,size[1]-130))
self.sb=wx.Button(self,label="Snap to Z=0",pos=(300,size[1]-100)) self.sb=wx.Button(self,label="Snap to Z=0",pos=(300,size[1]-105))
self.cb=wx.Button(self,label="Put at 100,100",pos=(300,size[1]-70)) self.cb=wx.Button(self,label="Put at 100,100",pos=(300,size[1]-80))
self.db=wx.Button(self,label="Delete",pos=(300,size[1]-40)) self.db=wx.Button(self,label="Delete",pos=(300,size[1]-55))
self.eb.Bind(wx.EVT_BUTTON,self.export) self.ab=wx.Button(self,label="Auto",pos=(300,size[1]-30))
self.sb.Bind(wx.EVT_BUTTON,self.snap) self.eb.Bind(wx.EVT_BUTTON,self.export)
self.cb.Bind(wx.EVT_BUTTON,self.center) self.sb.Bind(wx.EVT_BUTTON,self.snap)
self.db.Bind(wx.EVT_BUTTON,self.delete) self.cb.Bind(wx.EVT_BUTTON,self.center)
#self.SetBackgroundColour((0,0,0)) self.db.Bind(wx.EVT_BUTTON,self.delete)
#wx.FutureCall(200,self.paint) self.ab.Bind(wx.EVT_BUTTON,self.autoplate)
self.i=0 #self.SetBackgroundColour((0,0,0))
self.previ=0 #wx.FutureCall(200,self.paint)
self.Bind(wx.EVT_MOUSEWHEEL,self.rot) self.i=0
self.Bind(wx.EVT_MOUSE_EVENTS,self.move) self.previ=0
self.Bind(wx.EVT_PAINT,self.repaint) self.Bind(wx.EVT_MOUSEWHEEL,self.rot)
#self.s=stltool.stl("sphere.stl").scale([2,1,1]) self.Bind(wx.EVT_MOUSE_EVENTS,self.move)
self.triggered=0 self.Bind(wx.EVT_PAINT,self.repaint)
self.models={} #self.s=stltool.stl("sphere.stl").scale([2,1,1])
self.basedir="." self.triggered=0
self.initpos=None self.models={}
self.prevsel=-1 self.basedir="."
self.initpos=None
self.prevsel=-1
def center(self,event): def center(self,event):
i=self.l.GetFirstSelected() i=self.l.GetFirstSelected()
if i != -1: if i != -1:
m=self.models[self.l.GetItemText(i)] m=self.models[self.l.GetItemText(i)]
m.offsets=[100,100,m.offsets[2]] m.offsets=[100,100,m.offsets[2]]
self.Refresh() self.Refresh()
def snap(self,event): def snap(self,event):
i=self.l.GetFirstSelected() i=self.l.GetFirstSelected()
if i != -1: if i != -1:
m=self.models[self.l.GetItemText(i)] m=self.models[self.l.GetItemText(i)]
m.offsets[2]=-1.0*min(m.facetsminz)[0] m.offsets[2]=-1.0*min(m.facetsminz)[0]
#print m.offsets[2] #print m.offsets[2]
self.Refresh() self.Refresh()
def delete(self,event): def delete(self,event):
i=self.l.GetFirstSelected() i=self.l.GetFirstSelected()
if i != -1: if i != -1:
del self.models[self.l.GetItemText(i)] del self.models[self.l.GetItemText(i)]
self.l.DeleteItem(i) self.l.DeleteItem(i)
self.l.Select(self.l.GetItemCount()-1) self.l.Select(self.l.GetItemCount()-1)
self.Refresh() self.Refresh()
def export(self,event): def export(self,event):
dlg=wx.FileDialog(self,"Pick file to save to",self.basedir,style=wx.FD_SAVE) dlg=wx.FileDialog(self,"Pick file to save to",self.basedir,style=wx.FD_SAVE)
dlg.SetWildcard("STL files (;*.stl;)") dlg.SetWildcard("STL files (;*.stl;)")
if(dlg.ShowModal() == wx.ID_OK): if(dlg.ShowModal() == wx.ID_OK):
name=dlg.GetPath() name=dlg.GetPath()
facets=[] facets=[]
for i in self.models.values(): for i in self.models.values():
r=i.rot r=i.rot
o=i.offsets o=i.offsets
if r != 0: if r != 0:
i=i.rotate([0,0,-r]) i=i.rotate([0,0,-r])
if o != [0,0,0]: if o != [0,0,0]:
i=i.translate([o[0],-o[1],o[2]]) i=i.translate([o[0],-o[1],o[2]])
facets+=i.facets facets+=i.facets
stltool.emitstl(name,facets,"plater_export") stltool.emitstl(name,facets,"plater_export")
print "wrote ",name print "wrote ",name
def testingloadfile(self,name):
def right(self,event): print name
dlg=wx.FileDialog(self,"Open file to print",self.basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) if not(os.path.exists(name)):
dlg.SetWildcard("STL files (;*.stl;)") return
if(dlg.ShowModal() == wx.ID_OK): path = os.path.split(name)[0]
name=dlg.GetPath() self.basedir=path
if not(os.path.exists(name)): t=time.time()
return #print name
path = os.path.split(name)[0] if name.lower().endswith(".stl"):
self.basedir=path newname=name
t=time.time() c=1
#print name while newname in self.models:
if name.lower().endswith(".stl"): newname=name+"(%d)"%c
newname=name c+=1
c=1 self.models[newname]=stltool.stl(name)
while newname in self.models: self.models[newname].offsets=[0,0,0]
newname=name+"(%d)"%c self.models[newname].rot=0
c+=1 minx,miny,minz,maxx,maxy,maxz=(10000,10000,10000,0,0,0)
self.models[newname]=stltool.stl(name) for i in self.models[newname].facets:
self.models[newname].offsets=[0,0,0] for j in i[1]:
self.models[newname].rot=0 if j[0]<minx:
minx,miny,minz,maxx,maxy,maxz=(10000,10000,10000,0,0,0) minx=j[0]
for i in self.models[newname].facets: if j[1]<miny:
for j in i[1]: miny=j[1]
if j[0]<minx: if j[2]<minz:
minx=j[0] minz=j[2]
if j[1]<miny: if j[0]>maxx:
miny=j[1] maxx=j[0]
if j[2]<minz: if j[1]>maxy:
minz=j[2] maxy=j[1]
if j[0]>maxx: if j[2]>maxz:
maxx=j[0] maxz=j[2]
if j[1]>maxy: self.models[newname].dims=[minx,maxx,miny,maxy,minz,maxz]
maxy=j[1] #if minx<0:
if j[2]>maxz: # self.models[newname].offsets[0]=-minx
maxz=j[2] #if miny<0:
self.models[newname].dims=[minx,maxx,miny,maxy,minz,maxz] # self.models[newname].offsets[1]=-miny
#if minx<0: self.models[newname].bitmap=wx.EmptyBitmap(800,800,32)
# self.models[newname].offsets[0]=-minx dc=wx.MemoryDC()
#if miny<0: dc.SelectObject(self.models[newname].bitmap)
# self.models[newname].offsets[1]=-miny dc.SetBackground(wx.Brush((0,0,0,0)))
self.models[newname].bitmap=wx.EmptyBitmap(800,800,32) dc.SetBrush(wx.Brush((0,0,0,255)))
dc=wx.MemoryDC() #dc.DrawRectangle(-1,-1,10000,10000)
dc.SelectObject(self.models[newname].bitmap) dc.SetBrush(wx.Brush(wx.Colour(128,255,128)))
dc.SetBackground(wx.Brush((0,0,0,0))) dc.SetPen(wx.Pen(wx.Colour(128,128,128)))
dc.SetBrush(wx.Brush((0,0,0,255))) m=self.models[newname]
#dc.DrawRectangle(-1,-1,10000,10000) #m.offsets=[10,10,0]
dc.SetBrush(wx.Brush(wx.Colour(128,255,128))) print m.offsets,m.dims
dc.SetPen(wx.Pen(wx.Colour(128,128,128))) scale=2
m=self.models[newname] for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))):
#m.offsets=[10,10,0] dc.DrawPolygon([wx.Point(400+scale*p[0],(400+scale*p[1])) for p in i[1]])
print m.offsets,m.dims #if(time.time()-t)>5:
scale=2 # break
for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))): dc.SelectObject(wx.NullBitmap)
dc.DrawPolygon([wx.Point(400+scale*p[0],(400+scale*p[1])) for p in i[1]]) m.bitmap.SetMask(wx.Mask(m.bitmap,wx.Colour(0,0,0,255)))
#if(time.time()-t)>5:
# break #print time.time()-t
dc.SelectObject(wx.NullBitmap) self.l.Append([stlwrap(self.models[newname],newname)])
m.bitmap.SetMask(wx.Mask(m.bitmap,wx.Colour(0,0,0,255))) i=self.l.GetFirstSelected()
if i != -1:
#print time.time()-t self.l.Select(i,0)
self.l.Append([stlwrap(self.models[newname],newname)])
i=self.l.GetFirstSelected() self.l.Select(self.l.GetItemCount()-1)
if i != -1: self.Refresh()
self.l.Select(i,0)
def autoplate(self,event):
self.l.Select(self.l.GetItemCount()-1) print "Autoplating"
self.Refresh()
#print time.time()-t self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\big_gear.stl')
self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\big_gear.stl')
def move(self,event): self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\big_gear.stl')
if event.ButtonUp(wx.MOUSE_BTN_LEFT): self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\big_gear.stl')
if(self.initpos is not None): self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\prusabits\\stl\\x-end-idler.stl')
i=self.l.GetFirstSelected() self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\prusabits\\stl\\x-end-idler.stl')
if i != -1: self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\prusabits\\stl\\x-end-idler.stl')
p=event.GetPositionTuple() self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\prusabits\\stl\\pla-bushing.stl')
#print (p[0]-self.initpos[0]),(p[1]-self.initpos[1]) self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\prusabits\\stl\\pla-bushing.stl')
t=time.time() self.testingloadfile('C:\\Users\\tjhowse\\reprap\\models\\top.stl')
m=self.models[self.l.GetItemText(i)] separation = 2
m.offsets=[m.offsets[0]+0.5*(p[0]-self.initpos[0]),m.offsets[1]-0.5*(p[1]-self.initpos[1]),m.offsets[2]] bedsize = [200,200,100]
#self.models[self.l.GetItemText(i)]=self.models[self.l.GetItemText(i)].translate([0.5*(p[0]-self.initpos[0]),0.5*(p[1]-self.initpos[1]),0]) cursor = [0,0,0]
#print time.time()-t newrow = 0
self.Refresh() for i in self.models:
self.initpos=None x = abs(self.models[i].dims[0] - self.models[i].dims[1])
elif event.ButtonDown(wx.MOUSE_BTN_RIGHT): y = abs(self.models[i].dims[2] - self.models[i].dims[3])
self.right(event) centre = [x/2, y/2]
elif event.Dragging(): centreoffset = [self.models[i].dims[0] + centre[0], self.models[i].dims[2] + centre[1]]
if self.initpos is None: if (newrow == 0) or (newrow < y):
self.initpos=event.GetPositionTuple() newrow = y
self.Refresh() #To the person who works out why the offsets are applied differently here:
dc=wx.ClientDC(self) # Good job, it confused the hell out of me.
p=event.GetPositionTuple() self.models[i].offsets[0] = cursor[0] + centre[0] - centreoffset[0]
dc.DrawLine(self.initpos[0],self.initpos[1],p[0],p[1]) self.models[i].offsets[1] = cursor[1] + centre[1] + centreoffset[1]
#print math.sqrt((p[0]-self.initpos[0])**2+(p[1]-self.initpos[1])**2) cursor[0] += x+separation
if cursor[0] >= bedsize[0]:
del dc cursor[0] = 0
else: cursor[1] += newrow+separation
event.Skip() newrow = 0
self.models[i].offsets[0] = cursor[0] + centre[0] - centreoffset[0]
self.models[i].offsets[1] = cursor[1] + centre[1] + centreoffset[1]
def rotateafter(self): cursor[0] += x+separation
if(self.i!=self.previ): if (cursor[1]+y) >= bedsize[1]:
i=self.l.GetFirstSelected() print "Bed full, sorry sir :("
if i != -1: self.Refresh()
#o=self.models[self.l.GetItemText(i)].offsets return
self.models[self.l.GetItemText(i)].rot+=5*(self.i-self.previ) self.Refresh()
#self.models[self.l.GetItemText(i)].offsets=o
self.previ=self.i
self.Refresh()
def cr(self): def right(self,event):
time.sleep(0.01) dlg=wx.FileDialog(self,"Open file to print",self.basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
wx.CallAfter(self.rotateafter) dlg.SetWildcard("STL files (;*.stl;)")
self.triggered=0 if(dlg.ShowModal() == wx.ID_OK):
name=dlg.GetPath()
def rot(self, event): if not(os.path.exists(name)):
z=event.GetWheelRotation() return
s=self.l.GetFirstSelected() path = os.path.split(name)[0]
if self.prevsel!=s: self.basedir=path
self.i=0 t=time.time()
self.prevsel=s #print name
if z > 0: if name.lower().endswith(".stl"):
self.i-=1 newname=name
else: c=1
self.i+=1 while newname in self.models:
if not self.triggered: newname=name+"(%d)"%c
self.triggered=1 c+=1
threading.Thread(target=self.cr).start() self.models[newname]=stltool.stl(name)
self.models[newname].offsets=[0,0,0]
def repaint(self,event): self.models[newname].rot=0
dc=wx.PaintDC(self) minx,miny,minz,maxx,maxy,maxz=(10000,10000,10000,0,0,0)
self.paint(dc=dc) for i in self.models[newname].facets:
for j in i[1]:
def paint(self,coord1="x",coord2="y",dc=None): if j[0]<minx:
coords={"x":0,"y":1,"z":2} minx=j[0]
if dc is None: if j[1]<miny:
dc=wx.ClientDC(self) miny=j[1]
offset=[0,0] if j[2]<minz:
scale=2 minz=j[2]
dc.SetPen(wx.Pen(wx.Colour(100,100,100))) if j[0]>maxx:
for i in xrange(20): maxx=j[0]
dc.DrawLine(0,i*scale*10,400,i*scale*10) if j[1]>maxy:
dc.DrawLine(i*scale*10,0,i*scale*10,400) maxy=j[1]
dc.SetPen(wx.Pen(wx.Colour(0,0,0))) if j[2]>maxz:
for i in xrange(4): maxz=j[2]
dc.DrawLine(0,i*scale*50,400,i*scale*50) self.models[newname].dims=[minx,maxx,miny,maxy,minz,maxz]
dc.DrawLine(i*scale*50,0,i*scale*50,400) #if minx<0:
dc.SetBrush(wx.Brush(wx.Colour(128,255,128))) # self.models[newname].offsets[0]=-minx
dc.SetPen(wx.Pen(wx.Colour(128,128,128))) #if miny<0:
t=time.time() # self.models[newname].offsets[1]=-miny
dcs=wx.MemoryDC() self.models[newname].bitmap=wx.EmptyBitmap(800,800,32)
for m in self.models.values(): dc=wx.MemoryDC()
b=m.bitmap dc.SelectObject(self.models[newname].bitmap)
#print b dc.SetBackground(wx.Brush((0,0,0,0)))
im=b.ConvertToImage() dc.SetBrush(wx.Brush((0,0,0,255)))
#print im #dc.DrawRectangle(-1,-1,10000,10000)
imgc = wx.Point( im.GetWidth()/2,im.GetHeight()/2 ) dc.SetBrush(wx.Brush(wx.Colour(128,255,128)))
#print math.radians(5*(self.i-self.previ)) dc.SetPen(wx.Pen(wx.Colour(128,128,128)))
im= im.Rotate( math.radians(m.rot), imgc, 0) m=self.models[newname]
bm=wx.BitmapFromImage(im) #m.offsets=[10,10,0]
dcs.SelectObject(bm) print m.offsets,m.dims
bsz=bm.GetSize() scale=2
dc.Blit(scale*m.offsets[0]-bsz[0]/2,400-(scale*m.offsets[1]+bsz[1]/2),bsz[0],bsz[1],dcs,0,0,useMask=1) for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))):
#for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))): dc.DrawPolygon([wx.Point(400+scale*p[0],(400+scale*p[1])) for p in i[1]])
# dc.DrawPolygon([wx.Point(offset[0]+scale*m.offsets[0]+scale*p[0],400-(offset[1]+scale*m.offsets[1]+scale*p[1])) for p in i[1]]) #if(time.time()-t)>5:
#if(time.time()-t)>5: # break
# break dc.SelectObject(wx.NullBitmap)
del dc m.bitmap.SetMask(wx.Mask(m.bitmap,wx.Colour(0,0,0,255)))
#print time.time()-t
#s.export() #print time.time()-t
self.l.Append([stlwrap(self.models[newname],newname)])
i=self.l.GetFirstSelected()
if i != -1:
self.l.Select(i,0)
self.l.Select(self.l.GetItemCount()-1)
self.Refresh()
#print time.time()-t
def move(self,event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT):
if(self.initpos is not None):
i=self.l.GetFirstSelected()
if i != -1:
p=event.GetPositionTuple()
#print (p[0]-self.initpos[0]),(p[1]-self.initpos[1])
t=time.time()
m=self.models[self.l.GetItemText(i)]
m.offsets=[m.offsets[0]+0.5*(p[0]-self.initpos[0]),m.offsets[1]-0.5*(p[1]-self.initpos[1]),m.offsets[2]]
#self.models[self.l.GetItemText(i)]=self.models[self.l.GetItemText(i)].translate([0.5*(p[0]-self.initpos[0]),0.5*(p[1]-self.initpos[1]),0])
#print time.time()-t
self.Refresh()
self.initpos=None
elif event.ButtonDown(wx.MOUSE_BTN_RIGHT):
self.right(event)
elif event.Dragging():
if self.initpos is None:
self.initpos=event.GetPositionTuple()
self.Refresh()
dc=wx.ClientDC(self)
p=event.GetPositionTuple()
dc.DrawLine(self.initpos[0],self.initpos[1],p[0],p[1])
#print math.sqrt((p[0]-self.initpos[0])**2+(p[1]-self.initpos[1])**2)
del dc
else:
event.Skip()
def rotateafter(self):
if(self.i!=self.previ):
i=self.l.GetFirstSelected()
if i != -1:
#o=self.models[self.l.GetItemText(i)].offsets
self.models[self.l.GetItemText(i)].rot+=5*(self.i-self.previ)
#self.models[self.l.GetItemText(i)].offsets=o
self.previ=self.i
self.Refresh()
def cr(self):
time.sleep(0.01)
wx.CallAfter(self.rotateafter)
self.triggered=0
def rot(self, event):
z=event.GetWheelRotation()
s=self.l.GetFirstSelected()
if self.prevsel!=s:
self.i=0
self.prevsel=s
if z > 0:
self.i-=1
else:
self.i+=1
if not self.triggered:
self.triggered=1
threading.Thread(target=self.cr).start()
def repaint(self,event):
dc=wx.PaintDC(self)
self.paint(dc=dc)
def paint(self,coord1="x",coord2="y",dc=None):
coords={"x":0,"y":1,"z":2}
if dc is None:
dc=wx.ClientDC(self)
offset=[0,0]
scale=2
dc.SetPen(wx.Pen(wx.Colour(100,100,100)))
for i in xrange(20):
dc.DrawLine(0,i*scale*10,400,i*scale*10)
dc.DrawLine(i*scale*10,0,i*scale*10,400)
dc.SetPen(wx.Pen(wx.Colour(0,0,0)))
for i in xrange(4):
dc.DrawLine(0,i*scale*50,400,i*scale*50)
dc.DrawLine(i*scale*50,0,i*scale*50,400)
dc.SetBrush(wx.Brush(wx.Colour(128,255,128)))
dc.SetPen(wx.Pen(wx.Colour(128,128,128)))
t=time.time()
dcs=wx.MemoryDC()
for m in self.models.values():
b=m.bitmap
#print b
im=b.ConvertToImage()
#print im
imgc = wx.Point( im.GetWidth()/2,im.GetHeight()/2 )
#print math.radians(5*(self.i-self.previ))
im= im.Rotate( math.radians(m.rot), imgc, 0)
bm=wx.BitmapFromImage(im)
dcs.SelectObject(bm)
bsz=bm.GetSize()
dc.Blit(scale*m.offsets[0]-bsz[0]/2,400-(scale*m.offsets[1]+bsz[1]/2),bsz[0],bsz[1],dcs,0,0,useMask=1)
#for i in m.facets:#random.sample(m.facets,min(100000,len(m.facets))):
# dc.DrawPolygon([wx.Point(offset[0]+scale*m.offsets[0]+scale*p[0],400-(offset[1]+scale*m.offsets[1]+scale*p[1])) for p in i[1]])
#if(time.time()-t)>5:
# break
del dc
#print time.time()-t
#s.export()
class stlwin(wx.Frame): class stlwin(wx.Frame):
def __init__(self,size=(400,530)): def __init__(self,size=(400,530)):
wx.Frame.__init__(self,None,title="Right-click to add a file",size=size) wx.Frame.__init__(self,None,title="Right-click to add a file",size=size)
self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO)) self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO))
self.SetClientSize(size) self.SetClientSize(size)
self.s=showstl(self,(400,530),(0,0)) self.s=showstl(self,(400,530),(0,0))
if __name__ == '__main__': if __name__ == '__main__':
app = wx.App(False) app = wx.App(False)
main = stlwin() main = stlwin()
main.Show() main.Show()
app.MainLoop() app.MainLoop()