posOffset = Vector3()
currentE = 0
pathList = []
- currentPath = {'type': 'move', 'list': [pos.copy()]}
scale = 1.0
posAbs = True
+ feedRate = 3600
pathType = 'CUSTOM';
+ layerNr = 0; #Note layer 0 will be the start code.
+ startCodeDone = False
+ currentPath = {'type': 'move', 'pathType': pathType, 'list': [pos.copy()], 'layerNr': layerNr}
for line in f:
if line.startswith(';TYPE:'):
pathType = line[6:].strip()
+ if pathType != "CUSTOM":
+ startCodeDone = True
G = self.getCodeInt(line, 'G')
if G is not None:
if G == 0 or G == 1: #Move
y = self.getCodeFloat(line, 'Y')
z = self.getCodeFloat(line, 'Z')
e = self.getCodeFloat(line, 'E')
+ f = self.getCodeFloat(line, 'F')
if x is not None:
if posAbs:
pos.x = x * scale
else:
pos.y += y * scale
if z is not None:
+ oldZ = pos.z
if posAbs:
pos.z = z * scale
else:
pos.z += z * scale
+ if oldZ != pos.z and startCodeDone:
+ layerNr += 1
+ if f is not None:
+ feedRate = f
newPoint = pos.copy()
moveType = 'move'
if e is not None:
if e < currentE:
moveType = 'retract'
currentE = e
- if currentPath['type'] != moveType:
+ if currentPath['type'] != moveType or currentPath['pathType'] != pathType:
pathList.append(currentPath)
- currentPath = {'type': moveType, 'pathType': pathType, 'list': [currentPath['list'][-1]]}
+ currentPath = {'type': moveType, 'pathType': pathType, 'list': [currentPath['list'][-1]], 'layerNr': layerNr}
currentPath['list'].append(newPoint)
elif G == 20: #Units are inches
scale = 25.4
pass
else:
print "Unknown M code:" + str(M)
+ self.layerCount = layerNr
self.pathList = pathList
def getCodeInt(self, str, id):
c = configBase.SettingRow(left, "Wall thickness (mm)", 'wall_thickness', '0.8', 'Thickness of the walls.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines.')
validators.validFloat(c, 0.0)
validators.wallThicknessValidator(c)
+ configBase.settingNotify(c, self.preview3d.updateWallLineWidth)
configBase.TitleRow(left, "Fill")
c = configBase.SettingRow(left, "Bottom/Top thickness (mm)", 'solid_layer_thickness', '0.6', 'This controls the thickness of the bottom and top layers, the amount of solid layers put down is calculated by the layer thickness and this value.\nHaving this value a multiply of the layer thickness makes sense. And keep it near your wall thickness to make an evenly strong part.')
configBase.TitleRow(left, "Machine nozzle")
c = configBase.SettingRow(left, "Nozzle size (mm)", 'nozzle_size', '0.4', 'The nozzle size is very important, this is used to calculate the line width of the infill, and used to calculate the amount of outside wall lines and thickness for the wall thickness you entered in the print settings.')
validators.validFloat(c, 0.1, 1.0)
+ configBase.settingNotify(c, self.preview3d.updateWallLineWidth)
+ configBase.settingNotify(c, self.preview3d.updateInfillLineWidth)
configBase.TitleRow(left, "Retraction")
c = configBase.SettingRow(left, "Minimal travel (mm)", 'retraction_min_travel', '5.0', 'Minimal amount of travel needed for a retraction to happen at all. To make sure you do not get a lot of retractions in a small area')
\r
from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret\r
from fabmetheus_utilities.vector3 import Vector3\r
+from fabmetheus_utilities import settings\r
from newui import gcodeInterpreter\r
\r
class previewPanel(wx.Panel):\r
self.glCanvas = PreviewGLCanvas(self)\r
self.init = 0\r
self.triangleMesh = None\r
- self.pathList = None\r
+ self.gcode = None\r
self.machineSize = Vector3(210, 210, 200)\r
self.machineCenter = Vector3(0, 0, 0)\r
\r
tb = wx.ToolBar( self, -1 )\r
self.ToolBar = tb\r
tb.SetToolBitmapSize( ( 21, 21 ) )\r
- transparentButton = wx.Button(tb, -1, "T", size=(21,21))\r
- tb.AddControl(transparentButton)\r
- self.Bind(wx.EVT_BUTTON, self.OnConfigClick, transparentButton)\r
\r
button = wx.Button(tb, -1, "3D", size=(21*2,21))\r
tb.AddControl(button)\r
button = wx.Button(tb, -1, "Top", size=(21*2,21))\r
tb.AddControl(button)\r
self.Bind(wx.EVT_BUTTON, self.OnTopClick, button)\r
+\r
+ self.transparentButton = wx.Button(tb, -1, "T", size=(21,21))\r
+ tb.AddControl(self.transparentButton)\r
+ self.Bind(wx.EVT_BUTTON, self.OnConfigClick, self.transparentButton)\r
\r
self.layerSpin = wx.SpinCtrl(tb, -1, '', size=(21*4,21), style=wx.SP_ARROW_KEYS)\r
tb.AddControl(self.layerSpin)\r
+ self.Bind(wx.EVT_SPINCTRL, self.OnLayerNrChange, self.layerSpin)\r
+ self.transparentButton.Show(False)\r
self.layerSpin.Show(False)\r
\r
tb.Realize()\r
\r
def OnTopClick(self, e):\r
self.glCanvas.view3D = False\r
- self.glCanvas.zoom = 150\r
+ self.glCanvas.zoom = 100\r
self.glCanvas.offsetX = 0\r
self.glCanvas.offsetY = 0\r
self.glCanvas.Refresh()\r
\r
+ def OnLayerNrChange(self, e):\r
+ self.modelDirty = True\r
+ self.glCanvas.Refresh()\r
+\r
def updateCenterX(self, x):\r
self.machineCenter.x = x\r
self.moveModel()\r
self.moveModel()\r
self.glCanvas.Refresh()\r
\r
+ def updateWallLineWidth(self, setting):\r
+ self.glCanvas.lineWidth = settings.calculateEdgeWidth(setting)\r
+ \r
+ def updateInfillLineWidth(self, setting):\r
+ self.glCanvas.infillLineWidth = settings.getSetting('nozzle_size')\r
+ \r
def loadModelFile(self, filename):\r
self.modelFilename = filename\r
#Do the STL file loading in a background thread so we don't block the UI.\r
def DoModelLoad(self):\r
self.modelDirty = False\r
self.triangleMesh = fabmetheus_interpret.getCarving(self.modelFilename)\r
- self.pathList = None\r
+ self.gcode = None\r
self.moveModel()\r
+ wx.CallAfter(self.updateToolbar)\r
wx.CallAfter(self.glCanvas.Refresh)\r
\r
def DoGCodeLoad(self):\r
gcode = gcodeInterpreter.gcode(self.gcodeFilename)\r
self.modelDirty = False\r
- self.pathList = gcode.pathList\r
+ self.gcode = gcode\r
self.triangleMesh = None\r
self.modelDirty = True\r
+ wx.CallAfter(self.updateToolbar)\r
wx.CallAfter(self.glCanvas.Refresh)\r
\r
+ def updateToolbar(self):\r
+ self.transparentButton.Show(self.triangleMesh != None)\r
+ self.layerSpin.Show(self.gcode != None)\r
+ if self.gcode != None:\r
+ self.layerSpin.SetRange(1, self.gcode.layerCount)\r
+ \r
def OnConfigClick(self, e):\r
self.glCanvas.renderTransparent = not self.glCanvas.renderTransparent\r
self.glCanvas.Refresh()\r
self.zoom = 150\r
self.offsetX = 0\r
self.offsetY = 0\r
+ self.lineWidth = 0.4\r
+ self.fillLineWidth = 0.4\r
self.view3D = True\r
self.renderTransparent = False\r
self.modelDisplayList = None\r
glVertex3f(0, machineSize.y, machineSize.z)\r
glEnd()\r
\r
- if self.parent.pathList != None:\r
+ if self.parent.gcode != None:\r
if self.modelDisplayList == None:\r
self.modelDisplayList = glGenLists(1);\r
if self.parent.modelDirty:\r
self.parent.modelDirty = False\r
glNewList(self.modelDisplayList, GL_COMPILE)\r
- for path in self.parent.pathList:\r
+ for path in self.parent.gcode.pathList:\r
+ c = 1.0\r
+ if path['layerNr'] != self.parent.layerSpin.GetValue():\r
+ if path['layerNr'] < self.parent.layerSpin.GetValue():\r
+ c = 0.5 - (self.parent.layerSpin.GetValue() - path['layerNr']) * 0.1\r
+ if c < -0.5:\r
+ continue\r
+ if c < 0.1:\r
+ c = 0.1\r
+ else:\r
+ break\r
if path['type'] == 'move':\r
- glColor3f(0,0,1)\r
+ glColor3f(0,0,c)\r
if path['type'] == 'extrude':\r
if path['pathType'] == 'FILL':\r
- glColor3f(0.5,0.5,0)\r
+ glColor3f(c/2,c/2,0)\r
elif path['pathType'] == 'WALL-INNER':\r
- glColor3f(0,1,0)\r
+ glColor3f(0,c,0)\r
else:\r
- glColor3f(1,0,0)\r
+ glColor3f(c,0,0)\r
if path['type'] == 'retract':\r
- glColor3f(0,1,1)\r
- glBegin(GL_LINE_STRIP)\r
- for v in path['list']:\r
- glVertex3f(v.x, v.y, v.z)\r
- glEnd()\r
+ glColor3f(0,c,c)\r
+ if path['type'] == 'extrude':\r
+ if path['pathType'] == 'FILL':\r
+ lineWidth = self.fillLineWidth / 2\r
+ else:\r
+ lineWidth = self.lineWidth / 2\r
+ for i in xrange(0, len(path['list'])-1):\r
+ v0 = path['list'][i]\r
+ v1 = path['list'][i+1]\r
+ normal = (v0 - v1).cross(Vector3(0,0,1))\r
+ normal.normalize()\r
+ v2 = v0 + normal * lineWidth\r
+ v3 = v1 + normal * lineWidth\r
+ v0 = v0 - normal * lineWidth\r
+ v1 = v1 - normal * lineWidth\r
+\r
+ glBegin(GL_QUADS)\r
+ glVertex3f(v0.x, v0.y, v0.z - 0.001)\r
+ glVertex3f(v1.x, v1.y, v1.z - 0.001)\r
+ glVertex3f(v3.x, v3.y, v3.z - 0.001)\r
+ glVertex3f(v2.x, v2.y, v2.z - 0.001)\r
+ glEnd()\r
+ for v in path['list']:\r
+ glBegin(GL_TRIANGLE_FAN)\r
+ glVertex3f(v.x, v.y, v.z - 0.001)\r
+ for i in xrange(0, 16+1):\r
+ glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.001)\r
+ glEnd()\r
+ else:\r
+ glBegin(GL_LINE_STRIP)\r
+ for v in path['list']:\r
+ glVertex3f(v.x, v.y, v.z)\r
+ glEnd()\r
glEndList()\r
glCallList(self.modelDisplayList)\r
\r