From bfd0b378a50d372ee4fb9e4f4fdf68c299a7c4b4 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Saura Date: Thu, 26 Sep 2013 01:42:44 +0200 Subject: [PATCH] Tests compiling Replath --- Software/Replath/README.md | 5 + .../lib.linux-x86_64-2.7/reprap}/__init__.py | 92 +- .../build/lib.linux-x86_64-2.7/reprap}/ffm.py | 0 .../lib.linux-x86_64-2.7/reprap}/gopython.py | 0 .../lib.linux-x86_64-2.7/reprap}/hershey.py | 0 .../reprap}/shapeplotter.py | 4 +- .../lib.linux-x86_64-2.7/reprap}/snap.py | 3 +- .../lib.linux-x86_64-2.7/reprap}/toolpath.py | 0 .../pyRepRap/build/scripts-2.7/reprapcontrol | 169 ++++ .../build/scripts-2.7/wxreprapcontrol | 24 + Software/Replath/pyRepRap/reprap/__init__.py | 92 +- .../Replath/pyRepRap/reprap/shapeplotter.py | 4 +- Software/Replath/pyRepRap/reprap/snap.py | 3 +- Software/Replath/pyRepRap/reprap/toolpath.py | 182 ++++ .../lib.linux-x86_64-2.7/replath/__init__.py | 3 + .../replath/baseplotters.py | 138 +++ .../replath/controlpanels.py | 237 +++++ .../lib.linux-x86_64-2.7/replath/plugins.py | 80 ++ .../replath/preferences.py | 81 ++ .../lib.linux-x86_64-2.7/replath/wxpygame.py | 138 +++ .../Replath/replath/build/scripts-2.7/replath | 867 ++++++++++++++++++ Software/Replath/replath/fullplot.bmp | Bin 0 -> 171194 bytes Software/Replath/replath/replath/plugins.py | 2 +- Software/Replath/replath/scripts/replath | 2 +- 24 files changed, 2025 insertions(+), 101 deletions(-) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/__init__.py (93%) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/ffm.py (100%) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/gopython.py (100%) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/hershey.py (100%) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/shapeplotter.py (99%) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/snap.py (98%) rename Software/Replath/{reprap Recovered => pyRepRap/build/lib.linux-x86_64-2.7/reprap}/toolpath.py (100%) create mode 100755 Software/Replath/pyRepRap/build/scripts-2.7/reprapcontrol create mode 100755 Software/Replath/pyRepRap/build/scripts-2.7/wxreprapcontrol create mode 100644 Software/Replath/pyRepRap/reprap/toolpath.py create mode 100644 Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/__init__.py create mode 100644 Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/baseplotters.py create mode 100644 Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/controlpanels.py create mode 100644 Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/plugins.py create mode 100644 Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/preferences.py create mode 100644 Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/wxpygame.py create mode 100755 Software/Replath/replath/build/scripts-2.7/replath create mode 100644 Software/Replath/replath/fullplot.bmp diff --git a/Software/Replath/README.md b/Software/Replath/README.md index b08e23c..9779bd1 100644 --- a/Software/Replath/README.md +++ b/Software/Replath/README.md @@ -1,3 +1,8 @@ +Dependencies +-- +sudo apt-get install potrace +(among others) + Author -- pyRepRap and Replath by Stefan Blanke ( and ) diff --git a/Software/Replath/reprap Recovered/__init__.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/__init__.py similarity index 93% rename from Software/Replath/reprap Recovered/__init__.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/__init__.py index b61a670..8358b4d 100644 --- a/Software/Replath/reprap Recovered/__init__.py +++ b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/__init__.py @@ -215,7 +215,6 @@ def _getNotification(serialPort): class extruderClass: - tempScaler = 0 """Used to control a RepRap thermoplast extruder. An instance is automatically created in the reprap module, so for basic use just use reprap.extruder rather than defining a new one @@ -229,10 +228,8 @@ class extruderClass: self.hb = 20 # Variable Preference self.hm = 1.66667 # Variable Preference self.absZero = 273.15 # Static, K - #self.rz = 29000 # Variable Preference - self.rz = 353700 # Variable Preference - #self.beta = 3480 # Variable Preference - self.beta = 4267 # Variable Preference + self.rz = 29000 # Variable Preference + self.beta = 3480 # Variable Preference self.vdd = 5.0 # Static, volts self.cap = 0.0000001 # Variable Preference @@ -261,7 +258,7 @@ class extruderClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [int(direction), int(speed)] ) ##no command being sent, whats going on? p.send() else: - raise _RepRapError("Invalid direction or speed value") + raise RepRapError("Invalid direction or speed value") def _calculateResistance(self, picTemp, calibrationPicTemp): """Calculate resistance from pic timer value""" @@ -330,7 +327,6 @@ class extruderClass: self._autoTempRange() rawHeat, calibration = self._getRawTemp() while rawHeat == 255 or rawHeat == 0: - # TODO very bad as will hang in what should be a tight loop time.sleep(0.1) self._autoTempRange() res = self._calculateResistance( rawHeat, calibration ) @@ -338,7 +334,7 @@ class extruderClass: #print rawHeat, res, temp return round(temp, 1) #there is no point returning more points than this - def setTemp(self, temperature, null): + def setTemp(self, temperature): """Set the extruder target temperature (degrees Celsius)""" self.requestedTemperature = temperature #if(math.abs(self.requestedTemperature - extrusionTemp) > 5): @@ -480,7 +476,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_FORWARD, int(speed)] ) p.send() else: - raise _RepRapError("Invalid speed value") + raise RepRapError("Invalid speed value") def backward(self, speed = None): """Spin axis backward at given speed (0-255) @@ -494,7 +490,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_REVERSE, int(speed)] ) p.send() else: - raise _RepRapError("Invalid speed value") + raise RepRapError("Invalid speed value") def getSensors(self): """Debug only. Returns raw PIC port bytes)""" @@ -522,7 +518,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOS, posMSB, posLSB] ) p.send() else: - raise _RepRapError("Invalid position value") + raise RepRapError("Invalid position value") def free(self): """Power off coils on stepper""" @@ -566,7 +562,7 @@ class axisClass: if not notif.dataBytes[0] == CMD_SEEK: raise _RepRapError("Expected seek notification") else: - raise _RepRapError("Invalid speed or position value") + raise RepRapError("Invalid speed or position value") def homeReset(self, speed = None, waitArrival = True): """Go to 0 position. If waitArrival is True, funtion waits until reset is compete to return""" @@ -582,7 +578,7 @@ class axisClass: if not notif.dataBytes[0] == CMD_HOMERESET: raise _RepRapError("Expected home reset notification") else: - raise _RepRapError("Invalid speed value") + raise RepRapError("Invalid speed value") def setNotify(self): """Set axis to notify on arrivals""" @@ -595,7 +591,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SYNC, int(syncMode)] ) p.send() else: - raise _RepRapError("Invalid sync mode") + raise RepRapError("Invalid sync mode") def _DDA( self, seekTo, slaveDelta, speed = False, waitArrival = True): """Set DDA mode""" @@ -615,18 +611,17 @@ class axisClass: """Set stepper motor power (0-100%)""" power = int( float(power) * 0.63 ) if power >=0 and power <=0x3F: - #p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits) - p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, power] ) # This is a value from 0 to 63 (6 bits) + p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits) p.send() else: - raise _RepRapError("Invalid power value") + raise RepRapError("Invalid power value") def setSpeed(self, speed): """Set axis move speed (0-255)""" if speed >= 0 and speed <= 0xFF: self.speed = speed else: - raise _RepRapError("Invalid speed value") + raise RepRapError("Invalid speed value") def setStepsPerMM(self, spmm): """Set axis steps per millimeter""" @@ -672,17 +667,12 @@ class cartesianClass: if not waitArrival: print "WARNING : Reseting all axies at the same time is unstable. suggest using waitArrival = True option." #z is done first so we don't break anything we just made - if self.z.active: - if self.z.homeReset( speed = speed, waitArrival = waitArrival ): - print "Z Reset" - - if self.x.active: - if self.x.homeReset( speed = speed, waitArrival = waitArrival ): - print "X Reset" - - if self.y.active: - if self.y.homeReset( speed = speed, waitArrival = waitArrival ): - print "Y Reset" + if self.z.homeReset( speed = speed, waitArrival = waitArrival ): + print "Z Reset" + if self.x.homeReset( speed = speed, waitArrival = waitArrival ): + print "X Reset" + if self.y.homeReset( speed = speed, waitArrival = waitArrival ): + print "Y Reset" # TODO add a way to collect all three notifications (in whatever order) then check they are all there. this will allow symultanious axis movement and use of waitArrival # This requires snap receiver to search packets rather than just returning oldest one. probably need to do this anyway @@ -766,36 +756,21 @@ class cartesianClass: def stop(self): """Stop all motors (but retain current)""" - if self.x.active: - self.x.forward(0) - - if self.y.active: - self.y.forward(0) - - if self.z.active: - self.z.forward(0) + self.x.forward(0) + self.y.forward(0) + self.z.forward(0) def free(self): """Free all motors (no current on coils)""" - if self.x.active: - self.x.free() - - if self.y.active: - self.y.free() - - if self.z.active: - self.z.free() + self.x.free() + self.y.free() + self.z.free() def setPower(self, power): """Set stepper power (0-100)""" - if self.x.active: - self.x.setPower(power) - - if self.y.active: - self.y.setPower(power) - - if self.z.active: - self.z.setPower(power) + self.x.setPower(power) + self.y.setPower(power) + self.z.setPower(power) #def lockout(): #keep sending power down commands to all board every second @@ -803,14 +778,9 @@ class cartesianClass: def setSpeed(self, speed): """Set axies move speed (0-255)""" self.speed = speed - if self.x.active: - self.x.setSpeed(speed) - - if self.y.active: - self.y.setSpeed(speed) - - if self.z.active: - self.z.setSpeed(speed) + self.x.setSpeed(speed) + self.y.setSpeed(speed) + self.z.setSpeed(speed) def setStepsPerMM(self, spmm): """Set axies steps per millimeter""" diff --git a/Software/Replath/reprap Recovered/ffm.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/ffm.py similarity index 100% rename from Software/Replath/reprap Recovered/ffm.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/ffm.py diff --git a/Software/Replath/reprap Recovered/gopython.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/gopython.py similarity index 100% rename from Software/Replath/reprap Recovered/gopython.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/gopython.py diff --git a/Software/Replath/reprap Recovered/hershey.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/hershey.py similarity index 100% rename from Software/Replath/reprap Recovered/hershey.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/hershey.py diff --git a/Software/Replath/reprap Recovered/shapeplotter.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/shapeplotter.py similarity index 99% rename from Software/Replath/reprap Recovered/shapeplotter.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/shapeplotter.py index 341cf31..3ea282d 100644 --- a/Software/Replath/reprap Recovered/shapeplotter.py +++ b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/shapeplotter.py @@ -167,10 +167,10 @@ def circleStroke(x1, y1, x2, y2, radius, resolution, fillDensity = False ): # reversing these point lets locus be drawn in one continual motion poly.addPoint( toolpath.Point(x2 - rsintheta, y2 + rcostheta) ) poly.addPoint( toolpath.Point(x1 - rsintheta, y1 + rcostheta) ) - poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution) ) + poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution, fillDensity = False) ) poly.addPoint( toolpath.Point(x1 + rsintheta, y1 - rcostheta) ) poly.addPoint( toolpath.Point(x2 + rsintheta, y2 - rcostheta) ) - poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution) ) + poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution, fillDensity = False) ) return poly def fill(polygon, fillDensity): diff --git a/Software/Replath/reprap Recovered/snap.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/snap.py similarity index 98% rename from Software/Replath/reprap Recovered/snap.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/snap.py index 466e6c0..2143548 100644 --- a/Software/Replath/reprap Recovered/snap.py +++ b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/snap.py @@ -23,7 +23,6 @@ along with pyRepRap. If not, see . import serial, exceptions, threading, time -from __init__ import _RepRapError SYNC_BYTE = 0x54 @@ -45,7 +44,7 @@ def openSerial( port = 0, rate = 19200, tout = 60 ): try: serialPort = serial.Serial( port, rate, timeout = tout ) except: - raise _RepRapError("You do not have permissions to use the serial port, try running as root") + raise RepRapError("You do not have permissions to use the serial port, try running as root") def closeSerial(): diff --git a/Software/Replath/reprap Recovered/toolpath.py b/Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/toolpath.py similarity index 100% rename from Software/Replath/reprap Recovered/toolpath.py rename to Software/Replath/pyRepRap/build/lib.linux-x86_64-2.7/reprap/toolpath.py diff --git a/Software/Replath/pyRepRap/build/scripts-2.7/reprapcontrol b/Software/Replath/pyRepRap/build/scripts-2.7/reprapcontrol new file mode 100755 index 0000000..b5f40c2 --- /dev/null +++ b/Software/Replath/pyRepRap/build/scripts-2.7/reprapcontrol @@ -0,0 +1,169 @@ +#!/usr/bin/python +import serial, reprap, time, sys + +reprap.openSerial( 0, 19200, 60 ) + +# these devices are present in network +reprap.cartesian.x.active = True +reprap.cartesian.y.active = True +reprap.cartesian.z.active = True +reprap.extruder.active = True +reprap.cartesian.x.setNotify() +reprap.cartesian.y.setNotify() +reprap.cartesian.z.setNotify() +reprap.cartesian.x.limit = 2700 +reprap.cartesian.y.limit = 2500 +reprap.cartesian.y.limit = 2000 + +def printHelp(): + print "\nreprapcontrol command [args]" + print " Commands:" + print " stop Stop all axies" + print " reset Send all axies to home" + print " pos Print current position" + print " goto [x] [y] [z] Go to specified position" + print " power [0 to 63] Set power level" + print " speed [0 to 255] Set steper speed" + print " go Test routine" + print " free Power off steper motors" + print " run [x/y] [speed] Spin motor forwards" + print " runb [x/y] [speed] Spin motor backwards" + print " step [x/y/z] Step motor forward" + print " stepb [x/y/z] Step motor backwards" + +def printPos(): + x, y, z = reprap.cartesian.getPos() + print "Location [" + str(x) + ", " + str(y) + ", " + str(z) + "]" + +print "================================================================" + +if len(sys.argv) < 2: + printHelp() + + + +########### Cartesian control commands ######### + +# Stop all steppers +if sys.argv[1] == "stop": + reprap.cartesian.stop() + +# Reset all axies +elif sys.argv[1] == "reset": + reprap.cartesian.homeReset( waitArrival = True, speed = 220 ) + +# Print current positon +elif sys.argv[1] == "pos": + printPos() + +# Goto a specific location +elif sys.argv[1] == "goto": + reprap.cartesian.seek( ( int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]) ), speed = 200, waitArrival = True) + +# Set stepper power (%) +elif sys.argv[1] == "power": + reprap.cartesian.setPower( int( sys.argv[2] ) ) # This is a value from 0 to 63 (6 bits) + +# Free motors (switch off all coils) +elif sys.argv[1] == "free": + reprap.cartesian.free() + +# Test routine +elif sys.argv[1] == "go": + reprap.cartesian.seek( (1000, 1000, 0), 200, True ) + time.sleep(2) + reprap.cartesian.seek( (500, 1000, 0), 200, True ) + time.sleep(2) + reprap.cartesian.seek( (500, 500, 0), 200, True ) + time.sleep(2) + reprap.cartesian.seek( (10, 10, 0), 200, True ) + + + +############## control of individual steppers ############# + +# Spin stepper forwards +elif sys.argv[1] == "run": # run axis + if sys.argv[2] == "x": + reprap.cartesian.x.forward( int(sys.argv[3]) ) + elif sys.argv[2] == "y": + reprap.cartesian.y.forward( int(sys.argv[3]) ) + elif sys.argv[2] == "z": + reprap.cartesian.z.forward( int(sys.argv[3]) ) + +# Spin stepper backwards +elif sys.argv[1] == "runb": #runb axis + if sys.argv[2] == "x": + reprap.cartesian.x.backward( int(sys.argv[3]) ) + elif sys.argv[2] == "y": + reprap.cartesian.y.backward( int(sys.argv[3]) ) + elif sys.argv[2] == "z": + reprap.cartesian.z.backward( int(sys.argv[3]) ) + +# Step motor forwards +elif sys.argv[1] == "step": + if sys.argv[2] == "x": + reprap.cartesian.x.forward1() + elif sys.argv[2] == "y": + reprap.cartesian.y.forward1() + elif sys.argv[2] == "z": + reprap.cartesian.z.forward1() + +# Step motor backwards +elif sys.argv[1] == "stepb": + if sys.argv[2] == "x": + reprap.cartesian.x.backward1() + elif sys.argv[2] == "y": + reprap.cartesian.y.backward1() + elif sys.argv[2] == "z": + reprap.cartesian.z.backward1() + + + +################# control of extruder ##################### + +# Test extrder motor +elif sys.argv[1] == "motor": + nn = 0 + while 1: + if nn > 0: + nn = 0 + else: + nn = 150 + reprap.extruder.setMotor(reprap.CMD_REVERSE, nn) + time.sleep(1) + +elif sys.argv[1] == "getinfo": + mtype = reprap.extruder.getModuleType() + version = reprap.extruder.getVersion() + print "module", mtype, "version", version + +elif sys.argv[1] == "heat": + reprap.extruder.setHeat(255, 255, 255, 255) + +#setHeat(self, lowHeat, highHeat, tempTarget, tempMax + +elif sys.argv[1] == "temp": + print "Temp is ", reprap.extruder.getTemp() + + + +############### scan network for devices ################### + +# Scan snap network +elif sys.argv[1] == "scan": + reprap.scanNetwork() + +# Test comms +elif sys.argv[1] == "test": + reprap.testComms() + + +else: + printHelp() + +reprap.closeSerial() + + + + diff --git a/Software/Replath/pyRepRap/build/scripts-2.7/wxreprapcontrol b/Software/Replath/pyRepRap/build/scripts-2.7/wxreprapcontrol new file mode 100755 index 0000000..7461290 --- /dev/null +++ b/Software/Replath/pyRepRap/build/scripts-2.7/wxreprapcontrol @@ -0,0 +1,24 @@ +#!/usr/bin/python +import wx, reprap, reprap.controlpanels + +if __name__ == "__main__": + # TODO put try here with message if failes + reprap.openSerial( 0, 19200, 60 ) + reprap.cartesian.x.active = True + reprap.cartesian.y.active = True + reprap.cartesian.z.active = True + reprap.extruder.active = True + reprap.cartesian.x.setNotify() + reprap.cartesian.y.setNotify() + reprap.cartesian.z.setNotify() + reprap.cartesian.setPower(70) + reprap.cartesian.setSpeed(220) + + app = wx.PySimpleApp(0) + wx.InitAllImageHandlers() + frame_main = reprap.controlpanels.MainControlFrame(None, -1, "") + app.SetTopWindow(frame_main) + frame_main.Show() + app.MainLoop() + + reprap.closeSerial() diff --git a/Software/Replath/pyRepRap/reprap/__init__.py b/Software/Replath/pyRepRap/reprap/__init__.py index 8358b4d..b61a670 100644 --- a/Software/Replath/pyRepRap/reprap/__init__.py +++ b/Software/Replath/pyRepRap/reprap/__init__.py @@ -215,6 +215,7 @@ def _getNotification(serialPort): class extruderClass: + tempScaler = 0 """Used to control a RepRap thermoplast extruder. An instance is automatically created in the reprap module, so for basic use just use reprap.extruder rather than defining a new one @@ -228,8 +229,10 @@ class extruderClass: self.hb = 20 # Variable Preference self.hm = 1.66667 # Variable Preference self.absZero = 273.15 # Static, K - self.rz = 29000 # Variable Preference - self.beta = 3480 # Variable Preference + #self.rz = 29000 # Variable Preference + self.rz = 353700 # Variable Preference + #self.beta = 3480 # Variable Preference + self.beta = 4267 # Variable Preference self.vdd = 5.0 # Static, volts self.cap = 0.0000001 # Variable Preference @@ -258,7 +261,7 @@ class extruderClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [int(direction), int(speed)] ) ##no command being sent, whats going on? p.send() else: - raise RepRapError("Invalid direction or speed value") + raise _RepRapError("Invalid direction or speed value") def _calculateResistance(self, picTemp, calibrationPicTemp): """Calculate resistance from pic timer value""" @@ -327,6 +330,7 @@ class extruderClass: self._autoTempRange() rawHeat, calibration = self._getRawTemp() while rawHeat == 255 or rawHeat == 0: + # TODO very bad as will hang in what should be a tight loop time.sleep(0.1) self._autoTempRange() res = self._calculateResistance( rawHeat, calibration ) @@ -334,7 +338,7 @@ class extruderClass: #print rawHeat, res, temp return round(temp, 1) #there is no point returning more points than this - def setTemp(self, temperature): + def setTemp(self, temperature, null): """Set the extruder target temperature (degrees Celsius)""" self.requestedTemperature = temperature #if(math.abs(self.requestedTemperature - extrusionTemp) > 5): @@ -476,7 +480,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_FORWARD, int(speed)] ) p.send() else: - raise RepRapError("Invalid speed value") + raise _RepRapError("Invalid speed value") def backward(self, speed = None): """Spin axis backward at given speed (0-255) @@ -490,7 +494,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_REVERSE, int(speed)] ) p.send() else: - raise RepRapError("Invalid speed value") + raise _RepRapError("Invalid speed value") def getSensors(self): """Debug only. Returns raw PIC port bytes)""" @@ -518,7 +522,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOS, posMSB, posLSB] ) p.send() else: - raise RepRapError("Invalid position value") + raise _RepRapError("Invalid position value") def free(self): """Power off coils on stepper""" @@ -562,7 +566,7 @@ class axisClass: if not notif.dataBytes[0] == CMD_SEEK: raise _RepRapError("Expected seek notification") else: - raise RepRapError("Invalid speed or position value") + raise _RepRapError("Invalid speed or position value") def homeReset(self, speed = None, waitArrival = True): """Go to 0 position. If waitArrival is True, funtion waits until reset is compete to return""" @@ -578,7 +582,7 @@ class axisClass: if not notif.dataBytes[0] == CMD_HOMERESET: raise _RepRapError("Expected home reset notification") else: - raise RepRapError("Invalid speed value") + raise _RepRapError("Invalid speed value") def setNotify(self): """Set axis to notify on arrivals""" @@ -591,7 +595,7 @@ class axisClass: p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SYNC, int(syncMode)] ) p.send() else: - raise RepRapError("Invalid sync mode") + raise _RepRapError("Invalid sync mode") def _DDA( self, seekTo, slaveDelta, speed = False, waitArrival = True): """Set DDA mode""" @@ -611,17 +615,18 @@ class axisClass: """Set stepper motor power (0-100%)""" power = int( float(power) * 0.63 ) if power >=0 and power <=0x3F: - p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits) + #p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits) + p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, power] ) # This is a value from 0 to 63 (6 bits) p.send() else: - raise RepRapError("Invalid power value") + raise _RepRapError("Invalid power value") def setSpeed(self, speed): """Set axis move speed (0-255)""" if speed >= 0 and speed <= 0xFF: self.speed = speed else: - raise RepRapError("Invalid speed value") + raise _RepRapError("Invalid speed value") def setStepsPerMM(self, spmm): """Set axis steps per millimeter""" @@ -667,12 +672,17 @@ class cartesianClass: if not waitArrival: print "WARNING : Reseting all axies at the same time is unstable. suggest using waitArrival = True option." #z is done first so we don't break anything we just made - if self.z.homeReset( speed = speed, waitArrival = waitArrival ): - print "Z Reset" - if self.x.homeReset( speed = speed, waitArrival = waitArrival ): - print "X Reset" - if self.y.homeReset( speed = speed, waitArrival = waitArrival ): - print "Y Reset" + if self.z.active: + if self.z.homeReset( speed = speed, waitArrival = waitArrival ): + print "Z Reset" + + if self.x.active: + if self.x.homeReset( speed = speed, waitArrival = waitArrival ): + print "X Reset" + + if self.y.active: + if self.y.homeReset( speed = speed, waitArrival = waitArrival ): + print "Y Reset" # TODO add a way to collect all three notifications (in whatever order) then check they are all there. this will allow symultanious axis movement and use of waitArrival # This requires snap receiver to search packets rather than just returning oldest one. probably need to do this anyway @@ -756,21 +766,36 @@ class cartesianClass: def stop(self): """Stop all motors (but retain current)""" - self.x.forward(0) - self.y.forward(0) - self.z.forward(0) + if self.x.active: + self.x.forward(0) + + if self.y.active: + self.y.forward(0) + + if self.z.active: + self.z.forward(0) def free(self): """Free all motors (no current on coils)""" - self.x.free() - self.y.free() - self.z.free() + if self.x.active: + self.x.free() + + if self.y.active: + self.y.free() + + if self.z.active: + self.z.free() def setPower(self, power): """Set stepper power (0-100)""" - self.x.setPower(power) - self.y.setPower(power) - self.z.setPower(power) + if self.x.active: + self.x.setPower(power) + + if self.y.active: + self.y.setPower(power) + + if self.z.active: + self.z.setPower(power) #def lockout(): #keep sending power down commands to all board every second @@ -778,9 +803,14 @@ class cartesianClass: def setSpeed(self, speed): """Set axies move speed (0-255)""" self.speed = speed - self.x.setSpeed(speed) - self.y.setSpeed(speed) - self.z.setSpeed(speed) + if self.x.active: + self.x.setSpeed(speed) + + if self.y.active: + self.y.setSpeed(speed) + + if self.z.active: + self.z.setSpeed(speed) def setStepsPerMM(self, spmm): """Set axies steps per millimeter""" diff --git a/Software/Replath/pyRepRap/reprap/shapeplotter.py b/Software/Replath/pyRepRap/reprap/shapeplotter.py index 3ea282d..341cf31 100644 --- a/Software/Replath/pyRepRap/reprap/shapeplotter.py +++ b/Software/Replath/pyRepRap/reprap/shapeplotter.py @@ -167,10 +167,10 @@ def circleStroke(x1, y1, x2, y2, radius, resolution, fillDensity = False ): # reversing these point lets locus be drawn in one continual motion poly.addPoint( toolpath.Point(x2 - rsintheta, y2 + rcostheta) ) poly.addPoint( toolpath.Point(x1 - rsintheta, y1 + rcostheta) ) - poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution, fillDensity = False) ) + poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution) ) poly.addPoint( toolpath.Point(x1 + rsintheta, y1 - rcostheta) ) poly.addPoint( toolpath.Point(x2 + rsintheta, y2 - rcostheta) ) - poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution, fillDensity = False) ) + poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution) ) return poly def fill(polygon, fillDensity): diff --git a/Software/Replath/pyRepRap/reprap/snap.py b/Software/Replath/pyRepRap/reprap/snap.py index 2143548..466e6c0 100644 --- a/Software/Replath/pyRepRap/reprap/snap.py +++ b/Software/Replath/pyRepRap/reprap/snap.py @@ -23,6 +23,7 @@ along with pyRepRap. If not, see . import serial, exceptions, threading, time +from __init__ import _RepRapError SYNC_BYTE = 0x54 @@ -44,7 +45,7 @@ def openSerial( port = 0, rate = 19200, tout = 60 ): try: serialPort = serial.Serial( port, rate, timeout = tout ) except: - raise RepRapError("You do not have permissions to use the serial port, try running as root") + raise _RepRapError("You do not have permissions to use the serial port, try running as root") def closeSerial(): diff --git a/Software/Replath/pyRepRap/reprap/toolpath.py b/Software/Replath/pyRepRap/reprap/toolpath.py new file mode 100644 index 0000000..7ab1028 --- /dev/null +++ b/Software/Replath/pyRepRap/reprap/toolpath.py @@ -0,0 +1,182 @@ +""" +This module contains the classed used for internal storage of toolpath instructions. +The module can also import/export Intermediate Toolpath Language (ITL) files +which are pyRepRap's native file format. +""" + +# Python module properties +__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)" +__license__ = "GPL 3.0" +__licence__ = """ +pyRepRap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pyRepRap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pyRepRap. If not, see . +""" + +import xml.dom.minidom +from xml.dom.minidom import Node + + +# Point within a polygon +class Point: + def __init__(self, x = None, y = None, z = None): + self.x, self.y, self.z = x, y, z + +# Polygon within a layer +class Polygon: + def __init__(self, index = None, points = None, closed = False, clone = None, offsetX = 0, offsetY = 0, scale = 1, tool = None, material = None): + if points != None: + self.points = points + else: + self.points = [] + self.index = index + self.closed = closed + self.clone = clone + self.offsetX = offsetX + self.offsetY = offsetY + self.scale = scale + self.pointsPlotted = 0 + self.tool = tool + self.material = material + self.pointsPlotted = 0 + + def addPoint(self, point): + self.points.append(point) + + def addPoints(self, points): + self.points += points + + def addPolygon(self, poly): + self.points += poly.points + +# Layer within a toolpath +class Layer: + def __init__(self, index = None, polygons = None, workingHeight = None, idleHeight = None): + self.index = index + if polygons != None: + self.polygons = polygons + else: + self.polygons = [] + self.workingHeight = workingHeight + self.idleHeight = idleHeight + +# Toolpath object - describes full parameters for machine build +class Object: + def __init__(self, layers = None, scale = 1): + if layers != None: + self.layers = layers + else: + self.currentLayer = Layer() + self.layers = [ self.currentLayer ] + self.offsetX = 0 + self.offsetY = 0 + self.scale = 1 + self.version = 0.3 + self.units = "mm" + self.debug = False + + # Read toolpath object from XML based Intermediate Toolpath Language file + def readITL(self, filename): + doc = xml.dom.minidom.parse(filename) + self.layers = [] + for smilNode in doc.getElementsByTagName("ITL"): + self.version = smilNode.getAttribute("version") + self.layerCount = int(smilNode.getAttribute("layers")) + self.units = smilNode.getAttribute("units") + offset = smilNode.getAttribute("offset") + offsetParts = offset.split(',') + self.offsetX, self.offsetY = float(offsetParts[0]), float(offsetParts[1]) + self.scale = float(smilNode.getAttribute("scale")) + for layerNode in smilNode.getElementsByTagName("LAYER"): + if layerNode.getAttribute("index") == "None": + index = None + else: + index = int(layerNode.getAttribute("index")) + if layerNode.getAttribute("workingHeight") == "None": + workingHeight = None + else: + workingHeight = float(layerNode.getAttribute("workingHeight")) + if layerNode.getAttribute("idleHeight") == "None": + idleHeight = None + else: + idleHeight = float(layerNode.getAttribute("idleHeight")) + currentLayer = Layer(index, workingHeight = workingHeight, idleHeight = idleHeight) + if self.debug: print "Layer index", index + for polygonNode in layerNode.getElementsByTagName("POLYGON"): + if polygonNode.getAttribute("index") == "None": + index = None + else: + index = int(polygonNode.getAttribute("index")) + if polygonNode.getAttribute("clone") == "None": + clone = None + else: + clone = int(polygonNode.getAttribute("clone")) + if polygonNode.getAttribute("closed") == "True": + closed = True + else: + closed = False + offset = polygonNode.getAttribute("offset") + offsetParts = offset.split(',') + offsetX, offsetY = float(offsetParts[0]), float(offsetParts[1]) + scale = float(polygonNode.getAttribute("scale")) + if polygonNode.getAttribute("tool") == "None": + tool = None + else: + tool = polygonNode.getAttribute("tool") + if polygonNode.getAttribute("material") == "None": + material = None + else: + material = polygonNode.getAttribute("material") + if self.debug: print "Polygon index", index + polygon = Polygon(index, closed = closed, clone = clone, offsetX = offsetX, offsetY = offsetY, scale = scale, tool = tool, material = material) + for d in polygonNode.childNodes: + if d.nodeType == Node.TEXT_NODE: + lines = d.data.splitlines() + for l in lines: + parts = l.split('\t') + for i in range( parts.count('') ): + parts.remove('') + if len(parts) > 0: + if self.debug: print parts, parts[0][0], parts[1][0] + if parts[0][0] == "X" and parts[1][0] == "Y": + polygon.addPoint( Point( float(parts[0][ 1: ]), float(parts[1][ 1: ]) ) ) + if len(polygon.points): + currentLayer.polygons.append(polygon) + self.layers.append(currentLayer) + + # Write toolpath object to XML based Intermediate Toolpath Language file + def writeITL(self, filename): + itl = '\n' + for layer in self.layers: + # Index starts at one as zero is used in clone to mean not clone + itl += '\t\n' + for polygon in layer.polygons: + #itl += '\t\t\n' + itl += '\t\t\n' + for pointIndex, point in enumerate(polygon.points): + itl += '\t\t\t' + if point.x != None: + itl += 'X' + str(point.x) + '\t' + if point.y != None: + itl += 'Y' + str(point.y) + '\t' + if point.z != None: + itl += 'Z' + str(point.z) + '\t' + if itl[-1] == '\t': + itl = itl[ :-1] + '\n' + itl += '\t\t\n' + #itl += '\t\t\n' + itl += '\t\n' + itl += '\n' + f = open(filename, 'w') + f.write(itl) + f.close() + diff --git a/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/__init__.py b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/__init__.py new file mode 100644 index 0000000..c0b8dab --- /dev/null +++ b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python + + diff --git a/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/baseplotters.py b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/baseplotters.py new file mode 100644 index 0000000..2137367 --- /dev/null +++ b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/baseplotters.py @@ -0,0 +1,138 @@ +""" +Base classes for import, export and toolhead plugins +""" + +# Python module properties +__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)" +__license__ = "GPL 3.0" +__licence__ = """ +pyRepRap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pyRepRap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pyRepRap. If not, see . +""" + +import threading, reprap + +class ImportPlotter(threading.Thread): + """Base class for import plotter plugins""" + def __init__( self, fileName, toolpath, + feedbackHandler = False, + arcResolution = False, + fillDensity = 4, + debug = False ): + """Create plotter plugin with filename, toolpath (reprap.toolpath.Object object), feedback handler (feedback handler object), fill density (lines / mm) and debug""" + + threading.Thread.__init__(self) + + self.fileName = fileName + self.toolpath = toolpath + self.feedbackHandler = feedbackHandler + self.arcResolution = arcResolution + self.fillDensity = fillDensity + self.debug = debug + + self.loadPreferences() + + def terminate(self): + """Tell thread to terminate ASAP (result of GUI 'Stop' button)""" + self.alive = False + + def run(self): + """Run is executed when thread is started (in new thread) + This should be defined in derived plugin class""" + raise NotImplementedError('Import plotter plugin must define a .run() method!') + + def getFileLimitsXY(self): + """Return bounding limits of file (used for zeroing position) + This should be defined in derived plugin class""" + raise NotImplementedError('Import plotter plugin must define a .getFileLimitsXY() method!') + + def loadPreferences(self): + """Load preferences from file + This should be defined in derived plugin class""" + raise NotImplementedError('Import plotter plugin must define a .loadPreferences() method!') + + +class ExportPlotter(threading.Thread): + """Base class for export plotter plugins""" + def __init__( self, toolpath, toolhead, + feedbackHandler = False, + outputFilename = False): + """Create output plotter plugin with toolpath (reprap.toolpath.Object object), toolhead (toolhead plugin object), feedback handler (feedback handler object) and output file name""" + + threading.Thread.__init__(self) + + self.toolpath = toolpath + self.feedbackHandler = feedbackHandler + self.toolhead = toolhead + self.toolhead.output = self + self.outputFilename = outputFilename + + self.loadPreferences() + + def terminate(self): + """Tell thread to terminate ASAP (result of GUI 'Stop' button)""" + self.alive = False + if dir(self).count("feedbackHandler"): + self.feedbackHandler.setStatus("Aborting plot...") + + def run(self): + """Run is executed when thread is started (in new thread) + This should be defined in derived plugin class""" + raise NotImplementedError('Export plotter plugin must define a .run() method!') + + def cartesianMove(self, x, y, z, units = reprap.UNITS_MM): + """Perform cartesian movement + This should be defined in derived plugin class""" + raise NotImplementedError('Export plotter plugin must define a .cartesianMove() method!') + + def loadPreferences(self): + """Load preferences from file + This should be defined in derived plugin class""" + raise NotImplementedError('Export plotter plugin must define a .loadPreferences() method!') + + +class Tool: + """Base class for tool plugins""" + def __init__(self): + """Create tool object""" + self.loadPreferences() + self.toolInUse = False + + def prepare(self): + """Switch on tool / prepare for use (e.g. switch on cutter) + This should be defined in derived plugin class""" + raise NotImplementedError('Toolhead plugin must define a .prepare() method!') + + def idle(self): + """Switch off tool (e.g. switch off cutter) + This should be defined in derived plugin class""" + raise NotImplementedError('Toolhead plugin must define a .idle() method!') + + def ready(self): + """Tool use about to start, make sure it is ready (e.g. dip paintbrush) + This should be defined in derived plugin class""" + raise NotImplementedError('Toolhead plugin must define a .ready() method!') + + def start(self): + """Start tool use (e.g. lower cutter) + This should be defined in derived plugin class""" + raise NotImplementedError('Toolhead plugin must define a .start() method!') + + def stop(self): + """End tool use (e.g. raise cutter) + This should be defined in derived plugin class""" + raise NotImplementedError('Toolhead plugin must define a .stop() method!') + + + + diff --git a/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/controlpanels.py b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/controlpanels.py new file mode 100644 index 0000000..08709a7 --- /dev/null +++ b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/controlpanels.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# generated by wxGlade 0.6.3 on Mon Jul 21 19:56:38 2008 + +import wx, sys, os, reprap + +# begin wxGlade: extracode +# end wxGlade + + +if sys.platform=="win32": + # Windows (taking path of this script) + iconPath = os.path.join( os.getcwd(), "graphics" ) +else: + # Linux + iconPath = "/usr/share/reprap/icons/" + +appIcon = os.path.join(iconPath, "reprap.png") + + +class AxiesPanel(wx.Panel): + def __init__(self, *args, **kwds): + # begin wxGlade: AxiesPanel.__init__ + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.sizer_axies_staticbox = wx.StaticBox(self, -1, "Axies") + self.label_1 = wx.StaticText(self, -1, "X:") + self.slider_x = wx.Slider(self, -1, 0, 0, 10) + self.gauge_x = wx.Gauge(self, -1, 10) + self.button_home_x = wx.Button(self, wx.ID_HOME, "") + self.checkbox_torque_x = wx.CheckBox(self, -1, "Torque") + self.label_1_copy = wx.StaticText(self, -1, "Y:") + self.slider_y = wx.Slider(self, -1, 0, 0, 10) + self.gauge_y = wx.Gauge(self, -1, 10) + self.button_home_y = wx.Button(self, wx.ID_HOME, "") + self.checkbox_torque_y = wx.CheckBox(self, -1, "Torque") + self.label_1_copy_1 = wx.StaticText(self, -1, "Z:") + self.slider_z = wx.Slider(self, -1, 0, 0, 10) + self.gauge_z = wx.Gauge(self, -1, 10) + self.button_home_z = wx.Button(self, wx.ID_HOME, "") + self.checkbox_torque_z = wx.CheckBox(self, -1, "Torque") + + self.__set_properties() + self.__do_layout() + # end wxGlade + + def __set_properties(self): + # begin wxGlade: AxiesPanel.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: AxiesPanel.__do_layout + sizer_9 = wx.BoxSizer(wx.VERTICAL) + sizer_axies = wx.StaticBoxSizer(self.sizer_axies_staticbox, wx.VERTICAL) + sizer_10 = wx.BoxSizer(wx.VERTICAL) + sizer_3_copy_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4_copy_1 = wx.BoxSizer(wx.VERTICAL) + sizer_5_copy_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_4_copy = wx.BoxSizer(wx.VERTICAL) + sizer_5_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.VERTICAL) + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3.Add(self.label_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(self.slider_x, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0) + sizer_4.Add(self.gauge_x, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0) + sizer_5.Add(self.button_home_x, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0) + sizer_5.Add(self.checkbox_torque_x, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0) + sizer_4.Add(sizer_5, 1, wx.EXPAND, 0) + sizer_3.Add(sizer_4, 1, wx.EXPAND, 0) + sizer_10.Add(sizer_3, 0, wx.ALL|wx.EXPAND, 5) + sizer_3_copy.Add(self.label_1_copy, 0, wx.ADJUST_MINSIZE, 0) + sizer_3_copy.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_4_copy.Add(self.slider_y, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0) + sizer_4_copy.Add(self.gauge_y, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0) + sizer_5_copy.Add(self.button_home_y, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0) + sizer_5_copy.Add(self.checkbox_torque_y, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0) + sizer_4_copy.Add(sizer_5_copy, 1, wx.EXPAND, 0) + sizer_3_copy.Add(sizer_4_copy, 1, wx.EXPAND, 0) + sizer_10.Add(sizer_3_copy, 0, wx.ALL|wx.EXPAND, 5) + sizer_3_copy_1.Add(self.label_1_copy_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_3_copy_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_4_copy_1.Add(self.slider_z, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0) + sizer_4_copy_1.Add(self.gauge_z, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0) + sizer_5_copy_1.Add(self.button_home_z, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0) + sizer_5_copy_1.Add(self.checkbox_torque_z, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0) + sizer_4_copy_1.Add(sizer_5_copy_1, 1, wx.EXPAND, 0) + sizer_3_copy_1.Add(sizer_4_copy_1, 1, wx.EXPAND, 0) + sizer_10.Add(sizer_3_copy_1, 0, wx.ALL|wx.EXPAND, 5) + sizer_axies.Add(sizer_10, 1, wx.ALL|wx.EXPAND, 10) + sizer_9.Add(sizer_axies, 1, wx.ALL|wx.EXPAND, 10) + self.SetSizer(sizer_9) + sizer_9.Fit(self) + # end wxGlade + +# end of class AxiesPanel + + +class MovePanel(wx.Panel): + def __init__(self, *args, **kwds): + # begin wxGlade: MovePanel.__init__ + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.sizer_buttonMove_staticbox = wx.StaticBox(self, -1, "X-Y Move") + self.button_up = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-up.png')))) + self.button_left = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-previous.png')))) + self.button_right = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-next.png')))) + self.button_down = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-down.png')))) + self.label_2 = wx.StaticText(self, -1, "Speed :") + self.slider_speed = wx.Slider(self, -1, 0, 0, 255, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS) + self.label_2_copy = wx.StaticText(self, -1, "Steps :") + self.slider_steps = wx.Slider(self, -1, 0, 0, 1000, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.onClickUp, self.button_up) + self.Bind(wx.EVT_BUTTON, self.onClickLeft, self.button_left) + self.Bind(wx.EVT_BUTTON, self.onClickRight, self.button_right) + self.Bind(wx.EVT_BUTTON, self.onClickDown, self.button_down) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: MovePanel.__set_properties + self.button_up.SetSize(self.button_up.GetBestSize()) + self.button_left.SetSize(self.button_left.GetBestSize()) + self.button_right.SetSize(self.button_right.GetBestSize()) + self.button_down.SetSize(self.button_down.GetBestSize()) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: MovePanel.__do_layout + sizer_8 = wx.BoxSizer(wx.VERTICAL) + sizer_buttonMove = wx.StaticBoxSizer(self.sizer_buttonMove_staticbox, wx.VERTICAL) + sizer_8_copy = wx.BoxSizer(wx.VERTICAL) + grid_sizer_2 = wx.FlexGridSizer(2, 2, 10, 10) + grid_sizer_1 = wx.GridSizer(4, 3, 0, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_up, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_left, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_right, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_down, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_8_copy.Add(grid_sizer_1, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 30) + grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.slider_speed, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.label_2_copy, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.slider_steps, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.AddGrowableCol(1) + sizer_8_copy.Add(grid_sizer_2, 0, wx.EXPAND, 0) + sizer_buttonMove.Add(sizer_8_copy, 1, wx.ALL|wx.EXPAND, 10) + sizer_8.Add(sizer_buttonMove, 1, wx.ALL|wx.EXPAND, 10) + self.SetSizer(sizer_8) + sizer_8.Fit(self) + # end wxGlade + + + def onClickUp(self, event): # wxGlade: MovePanel. + x, y, z = reprap.cartesian.getPos() + reprap.cartesian.seek( ( None, y + int( self.slider_steps.GetValue() ), None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) ) + + def onClickLeft(self, event): # wxGlade: MovePanel. + x, y, z = reprap.cartesian.getPos() + reprap.cartesian.seek( ( x - int( self.slider_steps.GetValue() ), None, None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) ) + + def onClickRight(self, event): # wxGlade: MovePanel. + x, y, z = reprap.cartesian.getPos() + reprap.cartesian.seek( ( x + int( self.slider_steps.GetValue() ), None, None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) ) + + def onClickDown(self, event): # wxGlade: MovePanel. + x, y, z = reprap.cartesian.getPos() + reprap.cartesian.seek( ( None, y - int( self.slider_steps.GetValue() ), None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) ) + +# end of class MovePanel + + +class MainControlFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MainControlFrame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.panel_main = wx.Panel(self, -1) + + # Tool Bar + self.frame_main_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_TEXT|wx.TB_NOICONS) + self.SetToolBar(self.frame_main_toolbar) + self.frame_main_toolbar.AddLabelTool(100, "Home Reset", wx.NullBitmap, wx.NullBitmap, wx.ITEM_NORMAL, "", "") + self.frame_main_toolbar.AddLabelTool(101, "Torque", wx.NullBitmap, wx.NullBitmap, wx.ITEM_CHECK, "", "") + # Tool Bar end + self.panel_axies = AxiesPanel(self.panel_main, -1) + self.panel_move = MovePanel(self.panel_main, -1) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_TOOL, self.onClickHomeResetAll, id=100) + self.Bind(wx.EVT_TOOL, self.onTorqueAllToggle, id=101) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: MainControlFrame.__set_properties + self.SetTitle("RepRap Control") + self.frame_main_toolbar.Realize() + # end wxGlade + + def __do_layout(self): + # begin wxGlade: MainControlFrame.__do_layout + sizer_main = wx.BoxSizer(wx.VERTICAL) + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(self.panel_axies, 1, wx.EXPAND, 0) + sizer_1.Add(self.panel_move, 1, wx.EXPAND, 0) + self.panel_main.SetSizer(sizer_1) + sizer_main.Add(self.panel_main, 1, wx.EXPAND, 0) + self.SetSizer(sizer_main) + sizer_main.Fit(self) + self.Layout() + # end wxGlade + + + def onTorqueAllToggle(self, event): # wxGlade: MainControlFrame. + print "Event handler `onTorqueAllToggle' not implemented!" + event.Skip() + + def onClickHomeResetAll(self, event): # wxGlade: MainControlFrame. + reprap.cartesian.homeReset(waitArrival = True) + reprap.cartesian.free() + +# end of class MainControlFrame + + + diff --git a/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/plugins.py b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/plugins.py new file mode 100644 index 0000000..c256a70 --- /dev/null +++ b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/plugins.py @@ -0,0 +1,80 @@ +""" +RepRap plugins system. All plugins are accessed though this module. +""" + +# Python module properties +__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)" +__license__ = "GPL 3.0" +__licence__ = """ +pyRepRap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pyRepRap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pyRepRap. If not, see . +""" + +import os, sys + +# All modules used by plugins must be imported here to ensure inclusion in py2exe build +import replath.preferences, replath.baseplotters, wx.wizard + +PLUGIN_IMPORT = 1 +PLUGIN_OUTPUT = 2 +PLUGIN_TOOLHEAD = 3 +#print "OSP='" + sys.platform + "'" + +if sys.platform == "win32": + # Windows + print "winp" + pluginsPath = os.path.join( os.getcwd(), "plugins" ) +else: + # Linux + pluginsPath = "/usr/local/share/replath/plugins" + +print "Plugins loading from path'" + pluginsPath + "'" + +pluginsFolders = {PLUGIN_IMPORT:"import", PLUGIN_OUTPUT:"output", PLUGIN_TOOLHEAD:"toolhead"} + +def loadPlugins(pluginsFolder, suffix): + oldDir = os.getcwd() + os.chdir(pluginsFolder) + sys.path.append(pluginsFolder) + plugins = [] + files = os.listdir(pluginsFolder) + for p in files: + if p[ -len(suffix): ] == suffix: + newPlugin = __import__( p[ :-3 ] ) + plugins.append(newPlugin) + print "Loading plugin '" + newPlugin.Title + "' from file '" + p + "'" + os.chdir(oldDir) + sys.path.remove(pluginsFolder) + return plugins + +""" +def getPluginsList(pluginType): + plugins = loadPlugins( os.path.join( pluginsPath, pluginsFolders[pluginType] ), "_" + pluginsFolders[pluginType] + ".py") + pluginList = [] + for p in plugins: + pluginList.append(p.Title) + return pluginList +""" + +def getPlugin(pluginType, index): + plugins = loadPlugins( os.path.join( pluginsPath, pluginsFolders[pluginType] ), "_" + pluginsFolders[pluginType] + ".py") + return plugins[index] + +def getPlugins(pluginType): + return loadPlugins( os.path.join( pluginsPath, pluginsFolders[pluginType] ), "_" + pluginsFolders[pluginType] + ".py") + +def listTitles(plugins): + pluginList = [] + for p in plugins: + pluginList.append(p.Title) + return pluginList diff --git a/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/preferences.py b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/preferences.py new file mode 100644 index 0000000..b479637 --- /dev/null +++ b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/preferences.py @@ -0,0 +1,81 @@ +""" +RepRap preferences system. All preferences are accessed though this module. +""" + +# Python module properties +__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)" +__license__ = "GPL 3.0" +__licence__ = """ +pyRepRap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pyRepRap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pyRepRap. If not, see . +""" + +import sys, os + +def getHomeDir(): + if sys.platform=="win32": + return os.path.join( os.environ.get("USERPROFILE"), "Application Data" ) + else: + return os.environ.get("HOME") + + +class PreferenceHandler: + # prefOwner is object from which '.pref_*' attributes will be written to / read from + def __init__(self, prefOwner, fileName): + if prefOwner: + self.owner = prefOwner + else: + self.owner = self + self.fileName = os.path.join( getHomeDir(), ".pyRepRap", fileName ) + + # Save preferences to file + def save(self): + fileText = "" + for a in dir(self.owner): + if a[ :5 ] == "pref_": + #print "Preference", a, "=", getattr(self.owner, a) + attr = getattr(self.owner, a) # Get attribute (object) + fileText += a + '\t' + str( attr ) + '\t' + str( type(attr) )[ 7:-2 ] + '\n' # Output line format: [Pref name] [Pref Value] [Pref Type] + + f = open(self.fileName, 'w') + f.write(fileText) + f.close() + + # Load preferences from file + def load(self): + if not os.path.exists(self.fileName): + print "Preference file '" + self.fileName + "' does not exist, creating" + # If preferences directory does not exist then create it + dirPath = os.path.join( getHomeDir(), ".pyRepRap" ) + if not os.path.exists(dirPath): + os.mkdir(dirPath) + self.save() + + f = open(self.fileName, 'r') + lines = f.read().split('\n') + for r in lines: + if len(r) > 0 and not r[ :1 ] == "#": # Check line is not blank or commented out + pref, val, dType = tuple( r.split('\t') ) + if dType == "int": + val = int(val) + elif dType == "float": + val = float(val) + elif dType == "long": + val = long(val) + elif dType == "bool": + if val == "True": + val = True + else: + val = False + setattr(self.owner, pref, val) + diff --git a/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/wxpygame.py b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/wxpygame.py new file mode 100644 index 0000000..2a8c662 --- /dev/null +++ b/Software/Replath/replath/build/lib.linux-x86_64-2.7/replath/wxpygame.py @@ -0,0 +1,138 @@ +""" +This module provides a pyGame surface as a wxPython object. +I.e. it lets you use pyGame within a wx frame. + +Code derived / inspired from a vague combination of : + +BufferedCanvas -- Double-buffered, flicker-free canvas widget +Copyright (C) 2005, 2006 Daniel Keep +(GNU Lesser General Public License) + +and + +wxPython wiki : http://wiki.wxpython.org/IntegratingPyGame (Assumed GNU compatible) + +and some work of my own. + + +Example : + +import wxpygame +class DrawCanvas(wxpygame.wxSDLPanel): + def __init__( self, parent, ID=-1 ): + wxpygame.wxSDLPanel.__init__( self, parent,ID ) + + def draw(self): + surface = self.getSurface() + if not surface is None: + pygame.draw.circle( surface, (250, 0, 0), (100, 100), 50 ) + pygame.display.flip() + +""" + +# Python module properties +__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)" +__license__ = "GPL 3.0" +__credits__ = "Daniel Keep for his wx BufferedCanvas that showed me how to make a pyGame wx canvas" +__licence__ = """ +pyRepRap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pyRepRap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pyRepRap. If not, see . +""" + +import wx, pygame, os, sys + +class wxSDLPanel(wx.Panel): + buffer = None + backbuffer = None + def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.NO_FULL_REPAINT_ON_RESIZE): + wx.Panel.__init__(self,parent,ID,pos,size,style) + self.initialized = False + self.resized = False + self._surface = None + self.needsDrawing = True + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_MOTION, self.MouseMove) + self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown) + self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp) + self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) + self.Bind(wx.EVT_IDLE, self.OnIdle) + + def OnIdle(self, ev): + if not self.initialized or self.resized: + if not self.initialized: + # get the handle + hwnd = self.GetHandle() + + os.environ['SDL_WINDOWID'] = str(hwnd) + if sys.platform == 'win32': + os.environ['SDL_VIDEODRIVER'] = 'windib' + + pygame.init() + + + self.initialized = True + else: + self.resized = False + x,y = self.GetSizeTuple() + self._surface = pygame.display.set_mode((x,y)) + + if self.needsDrawing: + self.draw() + + """for event in pygame.event.get(): + if (event.type == pygame.QUIT): + pygame.quit() + sys.exit() + elif (event.type == pygame.MOUSEMOTION): + self.MouseMove() + elif (event.type == pygame.MOUSEBUTTONDOWN): + print "md pygame" + self.OnMouseDown() + elif (event.type == pygame.MOUSEBUTTONUP): + self.OnMouseUp() + """ + + def OnPaint(self, ev): + self.needsDrawing = True + + def OnSize(self, ev): + self.resized = True + + def draw(self): + raise NotImplementedError('please define a .draw() method!') + + def getSurface(self): + return self._surface + + def update(self): + self.Refresh() + print "r" + + #def getSize(self): + # return self.w, self.h + + def MouseMove(self, event): + raise NotImplementedError('please define a .MouseMove() method!') + def OnMouseDown(self, event): + raise NotImplementedError('please define a .OnMouseDown() method!') + def OnMouseUp(self, event): + raise NotImplementedError('please define a .OnMouseUp() method!') + def OnMouseWheel(self, event): + raise NotImplementedError('please define a .OnMouseWheel() method!') + + +#pygame.display.quit() + + + + diff --git a/Software/Replath/replath/build/scripts-2.7/replath b/Software/Replath/replath/build/scripts-2.7/replath new file mode 100755 index 0000000..15c00ab --- /dev/null +++ b/Software/Replath/replath/build/scripts-2.7/replath @@ -0,0 +1,867 @@ +#!/usr/bin/python + +__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)" +__credits__ = "" +__license__ = "GPL 3.0" +__version__ = "0.8" +__licence__ = """ +pyRepRap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pyRepRap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pyRepRap. If not, see . +""" + +# -*- coding: utf-8 -*- +# generated by wxGlade 0.6.1 on Wed Apr 23 11:49:08 2008 + +import wx, pygame, reprap, time, sys, os, threading +import replath.wxpygame as wxpygame +import reprap.shapeplotter, replath.plugins, reprap.toolpath +import replath + +appTitle = "RepRap Plot" + + +plotterPlugins = replath.plugins.getPlugins(replath.plugins.PLUGIN_IMPORT) +outputPlugins = replath.plugins.getPlugins(replath.plugins.PLUGIN_OUTPUT) +toolheadPlugins = replath.plugins.getPlugins(replath.plugins.PLUGIN_TOOLHEAD) +plotterList = replath.plugins.listTitles(plotterPlugins) +outputList = replath.plugins.listTitles(outputPlugins) +toolheadList = replath.plugins.listTitles(toolheadPlugins) + +if sys.platform=="win32": + # Windows (taking path of this script) + iconPath = os.path.join( os.getcwd(), "graphics" ) +else: + # Linux + iconPath = "/usr/local/share/replath/icons/" + +appIcon = os.path.join(iconPath, "reprap.png") + + + +# Feedback action definitions +EVT_FBM_ID = wx.NewId() +FB_STATUS = 1 +FB_COMPLETE = 2 +FB_ABORTED = 3 +FB_MESSAGE = 4 + +# Feedback message event object. Always used by feedbackmessagehandler (external plotters do not use it) +class FeedbackMessageEvent(wx.PyEvent): + """Simple event to carry arbitrary result data.""" + def __init__(self, action, data): + """Init Result Event.""" + wx.PyEvent.__init__(self) + self.SetEventType(EVT_FBM_ID) + self.action = action + self.data = data + +# Passed to plotters so they can give feedback info to the gui (including when they are finished) +class FeedbackMessageHandler: + def __init__(self, parent): + self.parent = parent + parent.Connect(-1, -1, EVT_FBM_ID, self.onEvent) + + def onEvent(self, event): + if event.action == FB_STATUS: + self.parent.setStatusBar(event.data) + elif event.action == FB_COMPLETE: + self.parent.plotComplete() + elif event.action == FB_ABORTED: + self.parent.plotAborted() + elif event.action == FB_MESSAGE: + dlg = wx.MessageDialog(self.parent, str(event.data) + '\n', caption = appTitle, style = wx.OK) + #dlg = wx.MessageDialog(self.parent, 'moo\n', caption = 'moo', style = wx.OK) + dlg.ShowModal() + + def plotComplete(self): + wx.PostEvent( self.parent, FeedbackMessageEvent(FB_COMPLETE, None) ) + + def setStatus(self, text): + wx.PostEvent( self.parent, FeedbackMessageEvent(FB_STATUS, text) ) + + def setProgressPopup(self, text, progress = 0): + #if text: + # #show window + # self.progressDialog.progress.SetValue(int(progress)) + #else: + # #hide window + pass + + def updateProgressPopup(self, progress): + #self.progressDialog.progress.SetValue(int(progress)) + pass + + def showMessagePopup(self, text): + wx.PostEvent( self.parent, FeedbackMessageEvent(FB_MESSAGE, text) ) + + def aborted(self): + wx.PostEvent( self.parent, FeedbackMessageEvent(FB_ABORTED, None) ) + +# content of this block not found: did you rename this class? +pass + +# Dialog class for preferences +class PreferencesDialog(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: PreferencesDialog.__init__ + kwds["style"] = wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.notebook_main = wx.Notebook(self, -1, style=wx.NB_LEFT) + self.panel_toolheads = wx.Panel(self.notebook_main, -1) + self.panel_outputs = wx.Panel(self.notebook_main, -1) + self.panel_inputs = wx.Panel(self.notebook_main, -1) + self.panel_general = wx.Panel(self.notebook_main, -1) + self.sizer_7_staticbox = wx.StaticBox(self, -1, "") + self.sizer_9_staticbox = wx.StaticBox(self.panel_general, -1, "") + self.label_8 = wx.StaticText(self.panel_general, -1, "Plot offset (mm) : ") + self.label_9 = wx.StaticText(self.panel_general, -1, "X : ") + self.text_offsetX = wx.TextCtrl(self.panel_general, -1, "") + self.label_10 = wx.StaticText(self.panel_general, -1, "Y :") + self.text_offsetY = wx.TextCtrl(self.panel_general, -1, "") + self.label_11 = wx.StaticText(self.panel_general, -1, "Fill density (lines / mm) :") + self.text_fillDensity = wx.TextCtrl(self.panel_general, -1, "") + self.label_16 = wx.StaticText(self.panel_general, -1, "Circle resolution (lines / mm in c) :") + self.text_circleResolution = wx.TextCtrl(self.panel_general, -1, "") + self.label_1 = wx.StaticText(self.panel_general, -1, "Delay between lines (seconds) :") + self.text_lineDelay = wx.TextCtrl(self.panel_general, -1, "") + self.label_2 = wx.StaticText(self.panel_general, -1, "Zoom step (factor) :") + self.text_zoomStep = wx.TextCtrl(self.panel_general, -1, "") + self.label_3 = wx.StaticText(self.panel_general, -1, "Grid division (mm) :") + self.text_gridDivision = wx.TextCtrl(self.panel_general, -1, "") + self.checkbox_debug = wx.CheckBox(self.panel_general, -1, "Debug") + self.notebook_inputs = wx.Notebook(self.panel_inputs, -1, style=wx.NB_LEFT) + self.notebook_outputs = wx.Notebook(self.panel_outputs, -1, style=wx.NB_LEFT) + self.notebook_toolheads = wx.Notebook(self.panel_toolheads, -1, style=wx.NB_LEFT) + self.button_Ok = wx.Button(self, wx.ID_OK, "") + self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.hanBtnOk, self.button_Ok) + self.Bind(wx.EVT_BUTTON, self.hanBtnCancel, self.button_Cancel) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: PreferencesDialog.__set_properties + self.SetTitle("RepRap Gerber Plotter - Preferences") + _icon = wx.EmptyIcon() + _icon.CopyFromBitmap(wx.Bitmap(appIcon)) + self.SetIcon(_icon) + # end wxGlade + + def __do_layout(self): + print "panel load" + # Dynamically load panels from plugins + self.preferencePanels = [] + for plugin in outputPlugins: + if dir(plugin).count('PreferencesPanel'): + newPanel = plugin.PreferencesPanel(self.notebook_outputs) + self.preferencePanels.append( newPanel ) + self.notebook_outputs.AddPage(newPanel, plugin.Title) + for plugin in toolheadPlugins: + if dir(plugin).count('PreferencesPanel'): + newPanel = plugin.PreferencesPanel(self.notebook_toolheads) + self.preferencePanels.append( newPanel ) + self.notebook_toolheads.AddPage(newPanel, plugin.Title) + for plugin in plotterPlugins: + if dir(plugin).count('PreferencesPanel'): + newPanel = plugin.PreferencesPanel(self.notebook_inputs) + self.preferencePanels.append( newPanel ) + self.notebook_inputs.AddPage(newPanel, plugin.Title) + + # begin wxGlade: PreferencesDialog.__do_layout + sizer_7 = wx.StaticBoxSizer(self.sizer_7_staticbox, wx.VERTICAL) + sizer_5 = wx.BoxSizer(wx.VERTICAL) + sizer_7_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2 = wx.BoxSizer(wx.VERTICAL) + sizer_9 = wx.StaticBoxSizer(self.sizer_9_staticbox, wx.VERTICAL) + grid_sizer_2 = wx.FlexGridSizer(7, 3, 4, 0) + grid_sizer_1 = wx.FlexGridSizer(4, 11, 4, 0) + grid_sizer_1.Add(self.label_8, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.label_9, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.text_offsetX, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.label_10, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.text_offsetY, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.AddGrowableCol(4) + grid_sizer_1.AddGrowableCol(8) + sizer_9.Add(grid_sizer_1, 0, wx.ALL|wx.EXPAND, 10) + grid_sizer_2.Add(self.label_11, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.text_fillDensity, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.label_16, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.text_circleResolution, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.text_lineDelay, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.text_zoomStep, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.text_gridDivision, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.checkbox_debug, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.AddGrowableCol(2) + sizer_9.Add(grid_sizer_2, 1, wx.ALL|wx.EXPAND, 10) + sizer_2.Add(sizer_9, 1, wx.ALL|wx.EXPAND, 10) + self.panel_general.SetSizer(sizer_2) + sizer_1.Add(self.notebook_inputs, 1, wx.ALL|wx.EXPAND, 10) + self.panel_inputs.SetSizer(sizer_1) + sizer_3.Add(self.notebook_outputs, 1, wx.ALL|wx.EXPAND, 10) + self.panel_outputs.SetSizer(sizer_3) + sizer_4.Add(self.notebook_toolheads, 1, wx.ALL|wx.EXPAND, 10) + self.panel_toolheads.SetSizer(sizer_4) + self.notebook_main.AddPage(self.panel_general, "General") + self.notebook_main.AddPage(self.panel_inputs, "Plotter Plugins") + self.notebook_main.AddPage(self.panel_outputs, "Output Plugins") + self.notebook_main.AddPage(self.panel_toolheads, "Toolhead Plugins") + sizer_5.Add(self.notebook_main, 1, wx.EXPAND, 0) + sizer_5.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_7_copy.Add(self.button_Ok, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_7_copy.Add(self.button_Cancel, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_7_copy, 0, wx.EXPAND, 0) + sizer_7.Add(sizer_5, 1, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 16) + self.SetSizer(sizer_7) + sizer_7.Fit(self) + self.Layout() + self.Centre() + # end wxGlade + + + + def setPrefHandler(self, pref): + self.preferences = pref + + # Set values of frame control + def setPrefValues(self): + self.text_offsetX.SetValue( str(self.preferences.pref_plotOffsetX) ) + self.text_offsetY.SetValue( str(self.preferences.pref_plotOffsetY) ) + self.text_fillDensity.SetValue( str(self.preferences.pref_fillDensity) ) + self.text_lineDelay.SetValue( str(self.preferences.pref_lineDelay) ) + self.checkbox_debug.SetValue( self.preferences.pref_debug ) + self.text_circleResolution.SetValue( str(self.preferences.pref_circleResolution) ) + self.text_gridDivision.SetValue( str(self.preferences.pref_gridDivision) ) + self.text_zoomStep.SetValue( str(self.preferences.pref_zoomStep) ) + + def getPreferences(self): + return self.preferences + + # User clicked OK + def hanBtnOk(self, event): # wxGlade: PreferencesDialog. + self.preferences.pref_plotOffsetX = float( self.text_offsetX.GetValue() ) + self.preferences.pref_plotOffsetY = float( self.text_offsetY.GetValue() ) + self.preferences.pref_fillDensity = int( self.text_fillDensity.GetValue() ) + self.preferences.pref_lineDelay = float( self.text_lineDelay.GetValue() ) + self.preferences.pref_debug = self.checkbox_debug.GetValue() + self.preferences.pref_circleResolution = float( self.text_circleResolution.GetValue() ) + self.preferences.pref_gridDivision = float( self.text_gridDivision.GetValue() ) + self.preferences.pref_zoomStep = float( self.text_zoomStep.GetValue() ) + + for p in self.preferencePanels: + p.savePrefValues() + self.EndModal(wx.OK) + + # User clicked Cancel + def hanBtnCancel(self, event): # wxGlade: PreferencesDialog. + self.preferences = False + self.EndModal(wx.CANCEL) +# end of class PreferencesDialog + +""" +# A set of lines for drawing on the screen TODO - put draw back in +class lineSet: + def __init__(self, parent, colour): + self.parent = parent + self.colour = colour + self.clear() + def setColour(colour): + self.colour = colour + self.tableChanged = True + def addLine(self, line): + self.lines.append(line) + #self.parent.draw() #not ideal + #pygame.display.flip() + self.tableChanged = True + def getLines(self): + return self.lines + def clear(self): + self.lines = [] + self.tableChanged = True + def hasChanged(self): + if self.tableChanged: + self.tableChanged = False + return True + else: + return False +""" + +# Class for pygame canvas +class DrawCanvas(wxpygame.wxSDLPanel): + def __init__( self, parent, ID=-1 ): + wxpygame.wxSDLPanel.__init__(self, parent, ID) + self.previewScale = 5.0 + self.offsetX, self.offsetY = 0, 0 + + self.black = 0, 0, 0 + self.white = 255, 255, 255 + self.grey = 160, 160, 160 + self.greyGreen = 170, 195, 170 + self.darkGrey = 140, 140, 140 + + self.backroundColour = self.white + self.baseColour = 166, 211, 166 + self.gridColour = self.greyGreen + self.previewColour = self.darkGrey + self.plotColour = self.black + + pygame.font.init() + self.font = pygame.font.Font(None, 17) + self.drawSurface = pygame.Surface( ( 0, 0 ) ) + self.drawn = False + + self.drawRect = 0, 0, 10, 10 + + def setParent(self, parent): + self.parent = parent + self.fullRedraw() + + def drawText( self, surface, x, y, text, font ): + text = font.render( text, True, (255, 255, 255), (159, 182, 205) ) + textRect = text.get_rect() + textRect.centerx = x + textRect.centery = y + surface.blit(text, textRect) + + # Draw plot to widget + def draw( self ): + surface = self.getSurface() + w, h = self.GetSizeTuple() + if not surface is None: + surface.fill( self.backroundColour ) + if self.drawn: + surface.blit( self.drawSurface, (self.offsetX, -self.offsetY) )#limit region to visible - is this needed? + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + pygame.display.flip() + + def fullRedraw(self): + if self.parent.currentToolpath: + fileOffsetX, fileOffsetY = self.parent.currentToolpath.offsetX, self.parent.currentToolpath.offsetY + # Find limits + #if len(self.polygons) > 0: + minX, minY, maxX, maxY = 1000000, 1000000, -1000000, -1000000 + if len(self.parent.currentToolpath.layers): + for layer in self.parent.currentToolpath.layers: + for poly in layer.polygons: + for p in poly.points: + minX = min(minX, p.x + fileOffsetX) + minY = min(minY, p.y + fileOffsetY) + maxX = max(maxX, p.x + fileOffsetX) + maxY = max(maxY, p.y + fileOffsetY) + else: + minX, minY, maxX, maxY = 0, 0, 0, 0 + border = int(self.parent.preferences.pref_gridDivision * self.previewScale / 2) + w, h = self.GetSizeTuple() + width, height = int(maxX * self.previewScale) + (2 * border), int(maxY * self.previewScale) + (2 *border) + #print "wh", width, height + if width > 0 and height > 0: + self.drawSurface = pygame.Surface( ( width, height ) ) + self.drawRect = 0, 0, width, height + + # Only draw if we have something to show + #if len(self.polygons) > 0: + # Draw background + pygame.draw.rect( self.drawSurface, self.baseColour, self.drawRect, 0) + # Draw grid + for x in frange( 0, maxX, self.parent.preferences.pref_gridDivision ): + pygame.draw.line( self.drawSurface, self.gridColour, ( int( float(x) * self.previewScale ) + border , border ), ( int( float(x) * self.previewScale ) + border , height - border ) ) + for y in frange( 0, maxY, self.parent.preferences.pref_gridDivision ): + pygame.draw.line( self.drawSurface, self.gridColour, ( border, height - border - int( float(y) * self.previewScale ) ), ( width - border, height - border - int( float(y) * self.previewScale ) ) ) + + # Draw axis labels + pygame.draw.line( self.drawSurface, self.black, (border, height - border), (border + 50, height - border) ) + pygame.draw.line( self.drawSurface, self.black, (border, height - border), (border, height - 50 - border ) ) + self.drawText( self.drawSurface, border + 25, height - border , "X", self.font ) + self.drawText( self.drawSurface, border, height - border - 25, "Y", self.font ) + #else: + # # Draw blank white box + # pygame.draw.rect( self.drawSurface, self.white, self.drawRect, 0) + + for layer in self.parent.currentToolpath.layers: + # Draw polygons + for poly in layer.polygons: + #print "plotting poly", poly, len(poly.points) + oldX, oldY = poly.points[0].x, poly.points[0].y + for ip, p in enumerate(poly.points[ 1: ]): + if ip < poly.pointsPlotted: + lineColour = self.black + else: + lineColour = self.previewColour + x1, y1, x2, y2 = self.scaleRect( (oldX + fileOffsetX, oldY + fileOffsetY, p.x + fileOffsetX, p.y + fileOffsetY), self.previewScale ) + pygame.draw.line( self.drawSurface, lineColour, (x1 + border, height - y1 - border), (x2 + border, height - y2 -border) ) + oldX, oldY = p.x, p.y + # Final line if closed + if poly.closed: + x, y = poly.points[0].x, poly.points[0].y + x1, y1, x2, y2 = self.scaleRect( (oldX + fileOffsetX, oldY + fileOffsetY, x + fileOffsetX, y + fileOffsetY), self.previewScale ) + pygame.draw.line( self.drawSurface, self.previewColour, (x1 + border, height - y1 - border), (x2 + border, height - y2 -border) ) + self.drawn = True + self.draw() + + # Simple coordiante manipulation + def scaleRect( self, rect, scale ): + x1, y1, x2, y2 = rect + scaleX = float(scale) + scaleY = float(scale) + return int( float(x1) * scale ), int( float(y1) * scale ), int( float(x2) * scale ), int( float(y2) * scale ) + + def offsetRect( self, rect, x, y ): + x1, y1, x2, y2 = rect + return x1 + x, y1 + y, x2, y2 + + def offsetLine(self, rect, x, y): + x1, y1, x2, y2 = rect + return x1 + x, y1 + y, x2 + x, y2 + y + + def centreView(self, x, y): + widthV, heightV = self.GetSizeTuple() + null, null, widthD, heightD = self.drawRect + self.offsetX = (widthV - widthD + x) / 2 + self.offsetY = (heightV - heightD + y) / -2 + + # Change draw offset to allow dragging of plot + def MouseMove(self, event): + w, h = self.GetSizeTuple() + if event.LeftIsDown(): + x, y = event.GetPosition() + if event.Dragging(): + self.offsetX, self.offsetY = x + self.moveDeltaX, self.moveDeltaY - y + + # Record offsets for use in drag movement + def OnMouseDown(self, event): + w, h = self.GetSizeTuple() + x, y = event.GetPosition() + #print x, y + self.moveDeltaX, self.moveDeltaY = self.offsetX - x, self.offsetY + y + + def OnMouseUp(self, event): + pass + + # When mouse wheel moved, zoom in or out + def OnMouseWheel(self, event): + w, h = self.GetSizeTuple() + centreX, centreY = w / 2, h / 2 + x, y = event.GetPosition() + #deltaX, deltaY = centreX - x, y - centreY + + if event.GetWheelRotation() > 0: + self.previewScale = self.previewScale + self.parent.preferences.pref_zoomStep + elif self.previewScale >= self.parent.preferences.pref_zoomStep: + self.previewScale = self.previewScale - self.parent.preferences.pref_zoomStep + self.fullRedraw() + #null, null, widthD, heightD = self.drawRect + #self.centreView(x - self.offsetX, h - y - self.offsetY) + #self.centreView(100, 100) + + +# Main frame class +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # Create preference handler that stores preferences on itself + self.preferences = replath.preferences.PreferenceHandler( False, "pyRepRap.conf" ) + # default values for preferences + self.preferences.pref_plotOffsetX = 10.0 + self.preferences.pref_plotOffsetY = 10.0 + self.preferences.pref_fillDensity = 5 + self.preferences.pref_lineDelay = 0.0 + self.preferences.pref_debug = False + self.preferences.pref_circleResolution = 3.0 + self.preferences.pref_gridDivision = 5.0 + self.preferences.pref_zoomStep = 1 + + self.preferences.load() + + self.fileName = False + self.currentPlotter = False + self.currentToolpath = False + + # begin wxGlade: MyFrame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.panel_1 = wx.Panel(self, -1) + + # Menu Bar + self.frmMain_menubar = wx.MenuBar() + self.mnuFile = wx.Menu() + self.mnuOpen = wx.MenuItem(self.mnuFile, 0, "&Open\tCtrl+O", "", wx.ITEM_NORMAL) + self.mnuFile.AppendItem(self.mnuOpen) + self.mnuFile.AppendSeparator() + self.mnuPlot = wx.MenuItem(self.mnuFile, 2, "&Plot\tCtrl+P", "", wx.ITEM_NORMAL) + self.mnuFile.AppendItem(self.mnuPlot) + self.mnuFile.AppendSeparator() + self.mnuQuit = wx.MenuItem(self.mnuFile, 1, "&Quit\tCtrl+Q", "", wx.ITEM_NORMAL) + self.mnuFile.AppendItem(self.mnuQuit) + self.frmMain_menubar.Append(self.mnuFile, "&File") + wxglade_tmp_menu = wx.Menu() + wxglade_tmp_menu.Append(10, "Pr&eferences", "", wx.ITEM_NORMAL) + self.frmMain_menubar.Append(wxglade_tmp_menu, "&Edit") + wxglade_tmp_menu = wx.Menu() + self.mnuAbout = wx.MenuItem(wxglade_tmp_menu, 40, "&About", "", wx.ITEM_NORMAL) + wxglade_tmp_menu.AppendItem(self.mnuAbout) + self.frmMain_menubar.Append(wxglade_tmp_menu, "&Help") + self.SetMenuBar(self.frmMain_menubar) + # Menu Bar end + self.frmMain_statusbar = self.CreateStatusBar(1, 0) + + # Tool Bar + self.frmMain_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_TEXT) + self.SetToolBar(self.frmMain_toolbar) + self.frmMain_toolbar.AddLabelTool(100, "Open", (wx.Bitmap( os.path.join(iconPath, 'document-open.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "Open file", "") + self.frmMain_toolbar.AddSeparator() + self.frmMain_toolbar.AddLabelTool(110, "Stop", (wx.Bitmap( os.path.join(iconPath, 'media-playback-stop.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "Stop current plotting action", "") + self.frmMain_toolbar.AddSeparator() + self.frmMain_toolbar.AddLabelTool(120, "Plot", (wx.Bitmap( os.path.join(iconPath, 'media-playback-start.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "Plot to output plugin", "") + self.frmMain_toolbar.AddSeparator() + self.frmMain_toolbar.AddLabelTool(130, "Preferences", (wx.Bitmap( os.path.join(iconPath, 'configure.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "", "") + # Tool Bar end + self.static_line_1 = wx.StaticLine(self.panel_1, -1) + self.label_22 = wx.StaticText(self.panel_1, -1, "Output :") + self.choice_output = wx.Choice(self.panel_1, -1, choices=[]) + self.label_23 = wx.StaticText(self.panel_1, -1, "Toolhead :") + self.choice_toolhead = wx.Choice(self.panel_1, -1, choices=[]) + self.static_line_2 = wx.StaticLine(self.panel_1, -1) + self.pygameCanvas = DrawCanvas(self.panel_1, -1) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_MENU, self.onClickOpen, self.mnuOpen) + self.Bind(wx.EVT_MENU, self.onClickPlot, self.mnuPlot) + self.Bind(wx.EVT_MENU, self.onClickQuit, self.mnuQuit) + self.Bind(wx.EVT_MENU, self.onClickPreferences, id=10) + self.Bind(wx.EVT_MENU, self.onClickAbout, self.mnuAbout) + self.Bind(wx.EVT_TOOL, self.onClickOpen, id=100) + self.Bind(wx.EVT_TOOL, self.onClickStop, id=110) + self.Bind(wx.EVT_TOOL, self.onClickPlot, id=120) + self.Bind(wx.EVT_TOOL, self.onClickPreferences, id=130) + # end wxGlade + + #self.Bind(wx.EVT_CLOSE, self.onCloseWindow) + self.pygameCanvas.setParent(self) + self.setStatusBar("RepRap Plot") + + def __set_properties(self): + # begin wxGlade: MyFrame.__set_properties + self.SetTitle("RepRap Plotter") + _icon = wx.EmptyIcon() + _icon.CopyFromBitmap(wx.Bitmap(appIcon)) + self.SetIcon(_icon) + self.SetSize((869, 579)) + self.frmMain_statusbar.SetStatusWidths([-1]) + # statusbar fields + frmMain_statusbar_fields = ["frmMain_statusbar"] + for i in range(len(frmMain_statusbar_fields)): + self.frmMain_statusbar.SetStatusText(frmMain_statusbar_fields[i], i) + self.frmMain_toolbar.SetToolBitmapSize((32, 32)) + self.frmMain_toolbar.Realize() + # end wxGlade + + # Load plugin names into choice lists + self.choice_output.Append("None") + for p in outputList: + self.choice_output.Append(p) + self.choice_output.SetSelection(0) + + for p in toolheadList: + self.choice_toolhead.Append(p) + self.choice_toolhead.SetSelection(0) + + def __do_layout(self): + # begin wxGlade: MyFrame.__do_layout + sizer_6 = wx.BoxSizer(wx.VERTICAL) + sizer_main = wx.BoxSizer(wx.VERTICAL) + sizer_19 = wx.BoxSizer(wx.HORIZONTAL) + sizer_main.Add(self.static_line_1, 0, wx.ALL|wx.EXPAND, 5) + sizer_19.Add((10, 1), 0, wx.ADJUST_MINSIZE, 0) + sizer_19.Add(self.label_22, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + sizer_19.Add((10, 1), 0, wx.ADJUST_MINSIZE, 0) + sizer_19.Add(self.choice_output, 0, wx.ADJUST_MINSIZE, 0) + sizer_19.Add((20, 1), 0, wx.ADJUST_MINSIZE, 0) + sizer_19.Add(self.label_23, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + sizer_19.Add((10, 1), 0, wx.ADJUST_MINSIZE, 0) + sizer_19.Add(self.choice_toolhead, 0, wx.ADJUST_MINSIZE, 0) + sizer_main.Add(sizer_19, 0, wx.EXPAND, 0) + sizer_main.Add(self.static_line_2, 0, wx.ALL|wx.EXPAND, 5) + sizer_main.Add(self.pygameCanvas, 5, wx.EXPAND, 1) + self.panel_1.SetSizer(sizer_main) + sizer_6.Add(self.panel_1, 1, wx.EXPAND, 0) + self.SetSizer(sizer_6) + self.Layout() + self.Centre() + # end wxGlade + + def plotComplete(self): + self.pygameCanvas.fullRedraw() + self.pygameCanvas.centreView(0, 0) + self.currentPlotter.join() + self.currentPlotter = False + self.setStatusBar("Plot Complete") + #dlg = wx.MessageDialog(self, "Plot Complete\n", caption = appTitle, style = wx.OK) + #dlg.ShowModal() + + def plotAborted(self): + self.pygameCanvas.fullRedraw() + if self.currentPlotter: + self.currentPlotter.join() + self.currentPlotter = False + self.setStatusBar("Plot aborted") + dlg = wx.MessageDialog(self, "Plot aborted\n", caption = appTitle, style = wx.OK) + dlg.ShowModal() + + # Produces strings for file formats in wx file dialog e.g. 'Gerber Files (*.pho)|*.pho' + def dialogFilterString(self, extensions, name): + rText = name + " (" + for e in extensions: + rText += '*' + e + ';' + rText = rText[ :-1 ] + rText += ")|" + for e in extensions: + rText += '*' + e + ';' + # Removed as windows did not like having no end chr + rText = rText[ :-1 ] + return rText + + def importPlot(self, fileName = False, quiet = False): + if fileName: + self.fileName = fileName + else: + self.fileName = False + filters = "" + allFormats = [] + # Produce strings for file formats for wx file dialog + for p in plotterPlugins: + filters += self.dialogFilterString( p.SupportedFileExtensions, p.FileTitle ) + '|' + allFormats += p.SupportedFileExtensions + # Produce all supported formats string, put it at the start of the list + filters = self.dialogFilterString( allFormats, "All Supported Files" ) + '|' + filters + filters = filters[ :-1 ] + #print "ff [" + filters + "]" + dialog = wx.FileDialog ( None, message = 'Open Gerber File', wildcard = filters, style = wx.OPEN ) + if dialog.ShowModal() == wx.ID_OK: + self.fileName = dialog.GetPath() + self.setStatusBar( "Opened File '" + self.fileName + "'" ) + dialog.Destroy() + + if self.fileName or fileName: + self.currentToolpath = reprap.toolpath.Object() + self.currentToolpath.offsetX, self.currentToolpath.offsetY = self.preferences.pref_plotOffsetX, self.preferences.pref_plotOffsetY + self.currentPlotter = False + plugin = False + cancel = False + feedbackHandler = FeedbackMessageHandler(self) + # Find a plugin that claims to handle files with the extension + for p in plotterPlugins: + # TODO - change to look for last dot not first, as it gets confused with network locations + #(fileBaseName, fileExtension)=os.path.splitext(fileName) + extension = self.fileName[ self.fileName.find('.'): ].lower() + if p.SupportedFileExtensions.count( extension ) > 0: + # # Check if the plotter has a preferences dialog and show it if it has one + if dir(p).count('PreferencesDialog') and not quiet: + plotPrefDialog = p.PreferencesDialog(None, -1, "") + app.SetTopWindow(plotPrefDialog) + if plotPrefDialog.ShowModal() == wx.OK: + plugin = p + else: + cancel = True + break + else: + plugin = p + + # If a suitable plugin has been found + if plugin: + # Create plotter + self.currentPlotter = plugin.plotter(self.fileName, self.currentToolpath, + feedbackHandler = feedbackHandler, + arcResolution = self.preferences.pref_circleResolution, + fillDensity = self.preferences.pref_fillDensity, + debug = self.preferences.pref_debug, + ) + if self.currentPlotter: + # Start plotter thread + self.currentPlotter.start() + elif not cancel : + dlg = wx.MessageDialog(self, "File format unsupported\n", caption = appTitle, style = wx.OK) + dlg.ShowModal() + + def exportPlot(self, fileName = False): + #self.setStatusBar( "Plotting File '" + self.fileName + "'" ) + # Use user selected output module + if self.choice_output.GetSelection() > 0: + outputs = [ self.choice_output.GetSelection() - 1 ] + else: + outputs = [] + feedbackHandler = FeedbackMessageHandler(self) + toolhead = toolheadPlugins[ self.choice_toolhead.GetSelection() ].tool() + outputPlotters = [] + for o in outputs: + outputFilename = None + if outputPlugins[o].FileOutput: + saveDialog = wx.FileDialog(self, message='Save file as...', wildcard=outputPlugins[o].Wildcard, style=wx.SAVE | wx.OVERWRITE_PROMPT) #defaultDir=dir, defaultFile='', + if saveDialog.ShowModal() == wx.ID_OK: + outputFilename = saveDialog.GetPath() + else: + outputFilename = None + saveDialog.Destroy() + + self.currentPlotter = outputPlugins[o].output(self.currentToolpath, toolhead, feedbackHandler, outputFilename) + self.currentPlotter.start() + + + def setStatusBar(self, text): + self.frmMain_statusbar.SetStatusText( text, 0 ) + + def onClickOpen(self, event): # wxGlade: MyFrame. + if self.currentPlotter: + dlg = wx.MessageDialog(self, "Current action must be stopped before opening a file.\n", caption = appTitle, style = wx.OK) + dlg.ShowModal() + else: + self.importPlot() + + #def onCloseWindow(self, evt): + # #self.Destroy() + # wx.Exit() + + def onClickQuit(self, event): # wxGlade: MyFrame. + wx.Exit() + + def onClickPreferences(self, event): # wxGlade: MyFrame. + dialogPref = PreferencesDialog(None, -1, "") + app.SetTopWindow(dialogPref) + + dialogPref.setPrefHandler( self.preferences ) + dialogPref.setPrefValues() + dialogPref.ShowModal() + + self.pygameCanvas.fullRedraw() + + dialogPref.Destroy() + self.preferences.save() + + def onClickAbout(self, event): # wxGlade: MyFrame. + description = "RepRap Plotter is a program for plotting Gerber and CAD files on a RepRap machine." + info = wx.AboutDialogInfo() + info.SetIcon(wx.Icon(appIcon, wx.BITMAP_TYPE_PNG)) + info.SetName('About RepRap Plotter') + info.SetVersion(__version__) + info.SetDescription(description) + #info.SetCopyright('') + info.SetLicence(__licence__) + info.AddDeveloper(__author__) + wx.AboutBox(info) + + def onClickStop(self, event): # wxGlade: MyFrame. + # tell plotter thread to quit + if self.currentPlotter: + self.currentPlotter.terminate() + else: + dlg = wx.MessageDialog(self, "Nothing is currently being plotted.\n", caption = appTitle, style = wx.OK) + dlg.ShowModal() + + def onClickPlot(self, event): # wxGlade: MyFrame. + if self.currentPlotter: + dlg = wx.MessageDialog(self, "Current action must be stopped before plotting.\n", caption = appTitle, style = wx.OK) + dlg.ShowModal() + else: + self.exportPlot() + + +# end of class MyFrame + + +# Range function accepting floats (by Dinu Gherman) +def frange(start, end=None, inc=None): + if end == None: + end = start + 0.0 + start = 0.0 + if inc == None: + inc = 1.0 + L = [] + while 1: + next = start + len(L) * inc + if inc > 0 and next >= end: + break + elif inc < 0 and next <= end: + break + L.append(next) + return L + + +# Strip quotations +def stripQuotes(text): + if (text[0] == '"' and text[-1] == '"') or (text[0] == "'" and text[-1] == "'"): + return text[ 1:-1 ] + else: + return text + + +showGui = True +if len(sys.argv) > 1: + if sys.argv.count("--nogui") or sys.argv.count("--g") or sys.argv.count("--help") or sys.argv.count("-h") > 0: + showGui = False + + +if __name__ == "__main__": + if showGui: + app = wx.PySimpleApp(0) + wx.InitAllImageHandlers() + frmMain = MyFrame(None, -1, "") + app.SetTopWindow(frmMain) + frmMain.Show() + # Command line arg plot file temp TODO proper + + if sys.argv.count("--quiet") or sys.argv.count("--q"): + quiet = True + else: + quiet = False + + if len(sys.argv) > 1: + frmMain.importPlot( stripQuotes(sys.argv[-1]), quiet ) + + + app.MainLoop() + else: + print "TODO : Command line only mode" + if sys.argv.count("--help"): + print "Usage: reprapplot [OPTIONS] [FILE]..." + print "Option GNU long option Meaning" + print " -h --help Show this message" + print " -g --nogui Don't show GUI" + print " -q --quiet Don't ask questions" + + + + diff --git a/Software/Replath/replath/fullplot.bmp b/Software/Replath/replath/fullplot.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a6e5564e7f5f6122fa574c1760fafb7dbdcd1a4e GIT binary patch literal 171194 zcmeHP-H|4@4P5)p88`$--~jyYtQ>|TaUu@Kp3~gUayTT2#t#Slh^x{qhXlGC4WLx2 zlk|^&{^#F+{`&Rn@5f(%JO291pT55Sd;I*<*I$p{zrOzU`~8oP-@pCuy58n5-HYHl+fJyr*%xIq`H4-2%>_#+;KUfdZc=~A}Pv}B4uTytp zA;&*SDl{L977o?O44$_ei<7P+WZ#X`qy0eO2je>jM-S{NaKcklCh40o2&Mf2IfDF>; z&Rp67s1Zak&GPOmA-jAMi?rO0Qqb@$R-B1U2Zk*e1~7?U3>%hk2FMhe?FLh&MyssC zowJ~(RKctGR>|&t3d*tBjh>+9y+CEAh#hFQV0bB}dnIvL&KZDeGuRELGMPTKo{WDw z05#|cej>!bVb%y0qBVl4=?sIEWw4b4oAiiTCf`-nZZOs4V(|On5xGyBn3Xb3mhT2r zM=l1l6MkV^b&6Rm$8F(mFcsutaC+b!vs<&6^$u;9>;{uN7h~xDoPZ7c#VncjAKncn zYc2-u`^?upTgI%KXau$!Ouk$U!twb}+jfmvc&{VCZZMg0F?wFVb-#1tn6)=s!`%%g zM=nOw<##VP?;XGVs!ikF;6vwPROSZxggO{Rv#ku71B2awK#ySCk`m3t0jP;4i~&Ie zCJd%ofEdu1%_XhU#8Rh6%SwFue6mx!LFZSm?-o;u8Gd@GePWg}p0CqxN*TlRG*uT7 zE$Ip~InZ3!>&eyKjVq3MFp*w?FsTJ$6_M>Ht;d#&gGTGAUO9j!F%|Fd^99l-6=VRnI&bW@=AQ!nL^jS zp?Wa310731qEYEpJVJ%VRz!kNjE@&BkWr=Zc(AC7Lhy<4A%kI`XjFO? zk5FN;6_MZ*O3+F_izLYC*p=}TK3-1AA~^F% zBvAq}SBiv>mvd1F4m<{V6eJ0wIiRrwBpTBF3`VH1*e4fygYogAQ4P;{9uF4vWI=B* zJ|x;#$$^fD!D3PARXj$9L{~(DPlSydE09s8aG8*}ibC*-uwk*N7#JN(K%!CURXjq4 z#a2XuPmGTjEs#;A@OZGOibC*-@gdQu7z8{2d;@j&J05eH7yXSb|HQ8UNl#4KaR&EiRyC#FB0N@4nRzX_8BBEBo*)|;U47x^xvT)$ou=5 zb-%Ou`qm@=X``csBG+`!Y++08?x@-?iGo&+R!5QFg4f;^@Z2Ltd7)xyqv#7(a~P4x z-!-brT)BdKW{Igk-?8OidL<=-Tt_RjMCPAcNd3DKw;zSQl$e?`#)?F1R8_eMZ9BFC zH2G{ZA-5(nDiDO9imhPzpA_ixt;Bu4%5F+b%~{6I$r)xx{#!Mir3@2_bN7pZKb5c?mSWq%x8KWImN><8u#moOzGv;b`vf z43=LSRYWc%k-+hIqP2N25}34@<|~25e`+FkFNe6@%s(E6>6!qVTJx$=MdU(~2prd^ zQlu+U54;q>Irne`_Z+&P7(T&I&i9`f@^ft?OC`gzEj5ic6jKJ!P@no*I>0;|TES%e z9cD;84GOAonyP~+tgx9T5L}QyXE1>#c)|n-2wqQtDx9e{tgx9T^td2%j^G}S<{s0a zVR|bUs&J;ru)=1V(Bul@3?##4JDctpUP2Wb@(!WG3L7eS4Txh4q$GF4aw;I}Er|nT zh4KUvle=L#R*?0U#8I)L83O6a-LM=h$a+iSkXQlTfF$K^SdJBBy(Muxte93ns&Y3h z#|pCEk~kPvSRWu^xf_;a1zB%N90@C|38=8#4a>1Y-M8e9ffd#Pfw0^S%b5~1z>@xL ztgz)n!j9n6$lMLffr5HqNgMzxZ0(S+GdOp{exRT>*wep<7`AXoSh*O7m-+V%%YlMA zVM+WdR@kZ`VMlP~V*On`$NYq9o>@XzVSXlrEm0@*avwGx)QVL3ilU9r^UgB7+?Lt(iama}8n7)x2!SYgYw6_&eUIXJexu~cS< z6}ComVYwT2Q?tSUOTm2ptlakymb+oqonJT}9kSG?!wOrSld#+k-MrkhotktfdFLx^ zX@0_TH!MfZuTPdLajdX)xeCkOz$c}j;o7P`t?x_NqP&IWZdeW$)UD48wzP7D1-Ul@ zYrp4iw0)7?LJj+{V3}jGEXX<;#gUb}A-1lO2=(lff*W4AT|vHSROD`G+^ch;wtY-+ z?SkhwWSUY)?uOF9TRPOa&j`NN@B9Hdrq`0Yq4)3y0czd{1pid-e}e2Xk(0Y&V&iWR zsDG;mTN*dQg1j1mao=+{xK456pcXD2%yGji1~STu^uSqfH{Nn;XgVZp>ENLih5?XK zhP(&VV!QF8Q?&1pu%&}(A8cPCqim@Uw3T)Pa_R^+H>(GT3R^n9XM*`X+0IO;nAudX4n??1TS$P+0|IP5!R`&!j@Qop2*;?=5F*F_j4b- zg+D@mQ2cVjS6@mn}3AmsBBuI6q~v$I4CsRBa2t>S9#Mt6KxX<@g3kPi#Fn!C}S zpoLo4E+FLXTCV19G=^xc7B&h9d9|FYxf}HyE!V=jfRNuSx|+N3GfGhZj^LlnJdqAS z#*#==A7eH6EfXQ$Gk9v3RwjeI4OM9F2KH}By|ozSgoPR)T1+W>c&4G|zvgbhyD_s# z^gPW}BH*IMSFZwm@06`~qiPT5)4LxhK1WFzGe;G~Qpy{iA>?Vn`|ifDVaTE+{e5hIk z`OSxYF><5bAe$w8H0hj>d)YJ-(YQ zH90+ZLpwsshH2^7$yXXRKRtItJ6y`1Y3UcqSGx2{dhUjHxRhKX zA;g}Zfi(2}S`AScM zq~~sEhfCQ=Eq$7|FT`IshFgaXOkP)(6ZFI5UU$tJ=!2ia&h zj!t(5NqB8IIzk1VG(%xKL+!O2hU;NIG@Utzug!&R3z)kB58s(!J~2Wak2G^(+X8O4 z8%L)f;{;zgjSH;fk>Dh3PuLxIfnri7*A5i~*AZWR0O#?k4=fDJCD4aY#o z<9V8}t%$bXjjPj-VY^*iVe=0+9gmOsdbVQB-MF>89KYMc+aFuU?Mv~F4&-h)nw!u|JCM7v zbo)}gqXW4cj^-xx(hlTqEZx2o@9048hNHO&y|e?l8%wt@#XCBXyWwbVLNDz=?#8Ws zVgIx2u)=Qkebz_r#;<;sllMHo*zu>B^5#WhJ5X=E8|9pF&eH~hBc_a*CTuIBeRrdr zE&h4JaPY;HkrRaNMzP~=lp`fOJ57m9Oqt~*Y){zjcB7mm&DnfhG-AqJb79*8=5Ca8 z1)R+%2H++`&4q0XxYurwLj^w?4h_srCKw9a8EWC(Ajf0Uqsiz@(ki7fsc}V++zsi- z{E=tUa+L!AWRn_K1j*gd4wtg)TKZY}$}(3>&)v`tm$K_x`nmbaV%JK~-Ovt~vfoG{ff7fJ_qqwIoHg(bx*XQdUZlzHh?)=Q*c6vu%GoAxvoQ7V3(ZG}GZm$(s|utas0 zNO7^f#0tOq>}5^3@9st=arkMXb;uGkKwNvwa)zqJ^_Gc4mMWmkopWyQMkR~+sZ`8l z2^c0WJYX#xN#c61L=MX{=1QM)sCVNj2)&W%Mp;6|%St}7LRA5Yd9h?MHJW(a4aglL z7#2Zbg?~bet>VMi*A-Y5!ujlCfe#!mea!p20ooEST-k$g^&o=K+7WCj7Uh-2|Lg{( z1%G3z!GXhNFe~kag{ub?)T`@x4+0OupZMlCzjtFGB%k{ZC|lA8UgqU+;1#V(=ZERJ z8>+Sr{pAFx6l|Q#@m3S_Yd3=1t0}L{^(eE%7oWolJ1g>#XN4*DoRb)RH#jx$W2{A8yxk57^~h0 zsOglj!Y}r1QhO51w3I6UrlhHW;=qeraZS+qcBuG?M1$(1C;~u2dujrS0!`} gS6Cj>0ht3~2W-3>SHWcs*JU2k0V@Zh4cOQJ0WUQFNB{r; literal 0 HcmV?d00001 diff --git a/Software/Replath/replath/replath/plugins.py b/Software/Replath/replath/replath/plugins.py index 9a47806..c256a70 100644 --- a/Software/Replath/replath/replath/plugins.py +++ b/Software/Replath/replath/replath/plugins.py @@ -36,7 +36,7 @@ if sys.platform == "win32": pluginsPath = os.path.join( os.getcwd(), "plugins" ) else: # Linux - pluginsPath = "/usr/share/replath/plugins" + pluginsPath = "/usr/local/share/replath/plugins" print "Plugins loading from path'" + pluginsPath + "'" diff --git a/Software/Replath/replath/scripts/replath b/Software/Replath/replath/scripts/replath index f362f54..fccda29 100644 --- a/Software/Replath/replath/scripts/replath +++ b/Software/Replath/replath/scripts/replath @@ -42,7 +42,7 @@ if sys.platform=="win32": iconPath = os.path.join( os.getcwd(), "graphics" ) else: # Linux - iconPath = "/usr/share/replath/icons/" + iconPath = "/usr/local/share/replath/icons/" appIcon = os.path.join(iconPath, "reprap.png")