Tests compiling Replath

pull/9/head
Carlos Garcia Saura 2013-09-26 01:42:44 +02:00
parent d389a67ab2
commit bfd0b378a5
24 changed files with 2025 additions and 101 deletions

View File

@ -1,3 +1,8 @@
Dependencies
--
sudo apt-get install potrace
(among others)
Author
--
pyRepRap and Replath by Stefan Blanke (<http://reprap.org/wiki/Builders/pyRepRap> and <http://reprap.org/wiki/Builders/Replath>)

View File

@ -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"""

View File

@ -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):

View File

@ -23,7 +23,6 @@ along with pyRepRap. If not, see <http://www.gnu.org/licenses/>.
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():

View File

@ -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()

View File

@ -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()

View File

@ -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"""

View File

@ -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):

View File

@ -23,6 +23,7 @@ along with pyRepRap. If not, see <http://www.gnu.org/licenses/>.
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():

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
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 = '<ITL version = "0.2" layers="' + str( len(self.layers) ) + '" units="mm" offset="' + str(self.offsetX) + ',' + str(self.offsetY) + '" scale="' + str(self.scale) + '">\n'
for layer in self.layers:
# Index starts at one as zero is used in clone to mean not clone
itl += '\t<LAYER index="' + str(layer.index) + '" workingHeight="' + str(layer.workingHeight) + '" idleHeight="' + str(layer.idleHeight) + '">\n'
for polygon in layer.polygons:
#itl += '\t\t<TOOL name="' + toolName + '" index="0">\n'
itl += '\t\t<POLYGON index="' + str(polygon.index) + '" clone="' + str(polygon.clone) + '" closed="' + str(polygon.closed) + '" offset="' + str(polygon.offsetX) + ',' + str(polygon.offsetY) + '" scale="' + str(polygon.scale) + '" tool="' + str(polygon.tool) + '" material="' + str(polygon.material) + '">\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</POLYGON>\n'
#itl += '\t\t</TOOL>\n'
itl += '\t</LAYER>\n'
itl += '</ITL>\n'
f = open(filename, 'w')
f.write(itl)
f.close()

View File

@ -0,0 +1,3 @@
#!/usr/bin/env python

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
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!')

View File

@ -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.<event_handler>
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.<event_handler>
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.<event_handler>
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.<event_handler>
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.<event_handler>
print "Event handler `onTorqueAllToggle' not implemented!"
event.Skip()
def onClickHomeResetAll(self, event): # wxGlade: MainControlFrame.<event_handler>
reprap.cartesian.homeReset(waitArrival = True)
reprap.cartesian.free()
# end of class MainControlFrame

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
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

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
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)

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
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()

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
# -*- 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.<event_handler>
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.<event_handler>
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.<event_handler>
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.<event_handler>
wx.Exit()
def onClickPreferences(self, event): # wxGlade: MyFrame.<event_handler>
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.<event_handler>
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.<event_handler>
# 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.<event_handler>
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"

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

View File

@ -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 + "'"

View File

@ -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")