'Correct_Mesh': DEFSET,
'Unproven_Mesh': DEFSET,
'SVG_Viewer': DEFSET,
+ 'FlipX': storedSetting("flip_x"),
+ 'FlipY': storedSetting("flip_y"),
+ 'FlipZ': storedSetting("flip_z"),
+ 'Scale': storedSetting("model_scale"),
+ 'Rotate': storedSetting("model_rotate_base"),
},'scale': {
'Activate_Scale': "False",
'XY_Plane_Scale_ratio': DEFSET,
validators.validFloat(c, 0.0)
configBase.TitleRow(left, "Sequence")
c = configBase.SettingRow(left, "Print order sequence", 'sequence', ['Loops > Perimeter > Infill', 'Loops > Infill > Perimeter', 'Infill > Loops > Perimeter', 'Infill > Perimeter > Loops', 'Perimeter > Infill > Loops', 'Perimeter > Loops > Infill'], 'Sequence of printing. The perimeter is the outer print edge, the loops are the insides of the walls, and the infill is the insides.');
- c = configBase.SettingRow(left, "Force first layer sequence", 'force_first_layer_sequence', ['True', 'False'], 'This setting forces the order of the first layer to be \'Perimeter > Loops > Infill\'')
+ c = configBase.SettingRow(left, "Force first layer sequence", 'force_first_layer_sequence', True, 'This setting forces the order of the first layer to be \'Perimeter > Loops > Infill\'')
configBase.TitleRow(left, "Infill")
c = configBase.SettingRow(left, "Infill pattern", 'infill_type', ['Line', 'Grid Circular', 'Grid Hexagonal', 'Grid Rectangular'], 'Pattern of the none-solid infill. Line is default, but grids can provide a strong print.')
- c = configBase.SettingRow(left, "Solid infill top", 'solid_top', ['True', 'False'], 'Create a solid top surface, if set to false the top is filled with the fill percentage. Useful for cups/vases.')
+ c = configBase.SettingRow(left, "Solid infill top", 'solid_top', True, 'Create a solid top surface, if set to false the top is filled with the fill percentage. Useful for cups/vases.')
configBase.TitleRow(left, "Joris")
- c = configBase.SettingRow(left, "Joris the outer edge", 'joris', ['False', 'True'], '[Joris] is a code name for smoothing out the Z move of the outer edge. This will create a steady Z increase over the whole print. It is intended to be used with a single walled wall thickness to make cups/vases.')
+ c = configBase.SettingRow(left, "Joris the outer edge", 'joris', False, '[Joris] is a code name for smoothing out the Z move of the outer edge. This will create a steady Z increase over the whole print. It is intended to be used with a single walled wall thickness to make cups/vases.')
main.Fit()
self.Fit()
self.type = type
self.label = wx.StaticText(panel, -1, label)
+ getSettingFunc = settings.getPreference
if self.type == 'profile':
- if isinstance(defaultValue, types.StringTypes):
- self.ctrl = wx.TextCtrl(panel, -1, settings.getProfileSetting(configName, defaultValue))
- else:
- self.ctrl = wx.ComboBox(panel, -1, settings.getProfileSetting(configName, defaultValue[0]), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
+ getSettingFunc = settings.getProfileSetting
+ if isinstance(defaultValue, types.StringTypes):
+ self.ctrl = wx.TextCtrl(panel, -1, getSettingFunc(configName, defaultValue))
+ self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
+ elif isinstance(defaultValue, types.BooleanType):
+ self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
+ self.ctrl.SetValue(getSettingFunc(configName, defaultValue) == "True")
+ self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
else:
- if isinstance(defaultValue, types.StringTypes):
- self.ctrl = wx.TextCtrl(panel, -1, settings.getPreference(configName, defaultValue))
- else:
- self.ctrl = wx.ComboBox(panel, -1, settings.getPreference(configName, defaultValue[0]), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
+ self.ctrl = wx.ComboBox(panel, -1, getSettingFunc(configName, defaultValue[0]), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
+ self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
#self.helpButton = wx.Button(panel, -1, "?", style=wx.BU_EXACTFIT)
#self.helpButton.SetToolTip(wx.ToolTip(help))
- self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingTextChange)
self.ctrl.Bind(wx.EVT_ENTER_WINDOW, lambda e: panel.main.OnPopupDisplay(self))
self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, panel.main.OnPopupHide)
#sizer.Add(helpButton, (x,y+2))
sizer.SetRows(x+1)
- def OnSettingTextChange(self, e):
+ def OnSettingChange(self, e):
if self.type == 'profile':
settings.putProfileSetting(self.configName, self.GetValue())
else:
self.panel.main.UpdatePopup(self)
def GetValue(self):
- return self.ctrl.GetValue()
+ return str(self.ctrl.GetValue())
def SetValue(self, value):
- self.ctrl.SetValue(value)
+ if isinstance(self.ctrl, wx.CheckBox):
+ self.ctrl.SetValue(str(value) == "True")
+ else:
+ self.ctrl.SetValue(value)
#Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value.
class settingNotify():
self.func(f)
return validators.SUCCESS, ''
except ValueError:
+ self.func()
return validators.SUCCESS, ''
+
\r
wx.MessageBox('Please move the printer head to the center of the machine\nalso move the platform so it is not at the highest or lowest position,\nand make sure the machine is powered on.', 'Machine check', wx.OK | wx.ICON_INFORMATION)\r
wx.CallAfter(self.AddProgressText, "Checking endstops")\r
- if self.DoCommCommandWithTimeout('M119') != "ok x_min:l x_max:l y_min:l y_max:l z_min:l z_max:l"\r
+ if self.DoCommCommandWithTimeout('M119') != "ok x_min:l x_max:l y_min:l y_max:l z_min:l z_max:l":\r
wx.CallAfter(self.AddProgressText, "Error: There is a problem in your endstops!")\r
wx.CallAfter(self.AddProgressText, "Error: One of them seems to be pressed while it shouldn't")\r
return\r
nb.AddPage(alterationPanel.alterationPanel(nb), "Start/End-GCode")
+ (left, right) = self.CreateConfigTab(nb, '3D Model')
+ configBase.TitleRow(left, "Scale")
+ c = configBase.SettingRow(left, "Scale", 'model_scale', '1.0', '')
+ validators.validFloat(c, 0.01)
+ configBase.settingNotify(c, self.preview3d.updateModelTransform)
+ configBase.TitleRow(left, "Flip")
+ c = configBase.SettingRow(left, "Flip X", 'flip_x', False, '')
+ configBase.settingNotify(c, self.preview3d.updateModelTransform)
+ c = configBase.SettingRow(left, "Flip Y", 'flip_y', False, '')
+ configBase.settingNotify(c, self.preview3d.updateModelTransform)
+ c = configBase.SettingRow(left, "Flip Z", 'flip_z', False, '')
+ configBase.settingNotify(c, self.preview3d.updateModelTransform)
+ configBase.TitleRow(right, "Rotate")
+ c = configBase.SettingRow(right, "Rotate (deg)", 'model_rotate_base', '0', '')
+ validators.validFloat(c)
+ configBase.settingNotify(c, self.preview3d.updateModelTransform)
+
# load and slice buttons.
loadButton = wx.Button(self, -1, 'Load STL')
sliceButton = wx.Button(self, -1, 'Slice to GCode')
\r
def DoModelLoad(self):\r
self.modelDirty = False\r
- self.triangleMesh = fabmetheus_interpret.getCarving(self.modelFilename)\r
+ triangleMesh = fabmetheus_interpret.getCarving(self.modelFilename)\r
+ triangleMesh.origonalVertexes = list(triangleMesh.vertexes)\r
+ for i in xrange(0, len(triangleMesh.origonalVertexes)):\r
+ triangleMesh.origonalVertexes[i] = triangleMesh.origonalVertexes[i].copy()\r
+ self.triangleMesh = triangleMesh\r
self.gcode = None\r
- self.moveModel()\r
+ self.updateModelTransform()\r
wx.CallAfter(self.updateToolbar)\r
wx.CallAfter(self.glCanvas.Refresh)\r
\r
self.glCanvas.renderTransparent = False\r
self.glCanvas.Refresh()\r
\r
+ def updateModelTransform(self, f=0):\r
+ if self.triangleMesh == None:\r
+ return\r
+ for face in self.triangleMesh.faces:\r
+ face.normal = None\r
+ scale = 1.0\r
+ rotate = 0.0\r
+ try:\r
+ scale = float(settings.getProfileSetting('model_scale', '1.0'))\r
+ rotate = float(settings.getProfileSetting('model_rotate_base', '0.0')) / 180 * math.pi\r
+ except:\r
+ pass\r
+ scaleX = scale\r
+ scaleY = scale\r
+ scaleZ = scale\r
+ if settings.getProfileSetting('flip_x') == 'True':\r
+ scaleX = -scaleX\r
+ if settings.getProfileSetting('flip_y') == 'True':\r
+ scaleY = -scaleY\r
+ if settings.getProfileSetting('flip_z') == 'True':\r
+ scaleZ = -scaleZ\r
+ mat00 = math.cos(rotate) * scaleX\r
+ mat01 =-math.sin(rotate) * scaleY\r
+ mat10 = math.sin(rotate) * scaleX\r
+ mat11 = math.cos(rotate) * scaleY\r
+ \r
+ for i in xrange(0, len(self.triangleMesh.origonalVertexes)):\r
+ self.triangleMesh.vertexes[i].x = self.triangleMesh.origonalVertexes[i].x * mat00 + self.triangleMesh.origonalVertexes[i].y * mat01\r
+ self.triangleMesh.vertexes[i].y = self.triangleMesh.origonalVertexes[i].x * mat10 + self.triangleMesh.origonalVertexes[i].y * mat11\r
+ self.triangleMesh.vertexes[i].z = self.triangleMesh.origonalVertexes[i].z * scaleZ\r
+ self.moveModel()\r
+ \r
def moveModel(self):\r
if self.triangleMesh == None:\r
return\r
v.y += self.machineCenter.y\r
self.triangleMesh.getMinimumZ()\r
self.modelDirty = True\r
+ self.glCanvas.Refresh()\r
\r
class PreviewGLCanvas(glcanvas.GLCanvas):\r
def __init__(self, parent):\r
v1 = self.parent.triangleMesh.vertexes[face.vertexIndexes[0]]\r
v2 = self.parent.triangleMesh.vertexes[face.vertexIndexes[1]]\r
v3 = self.parent.triangleMesh.vertexes[face.vertexIndexes[2]]\r
- if not hasattr(face, 'normal'):\r
+ if face.normal == None:\r
face.normal = (v2 - v1).cross(v3 - v1)\r
face.normal.normalize()\r
glNormal3f(face.normal.x, face.normal.y, face.normal.z)\r
glVertex3f(v1.x, v1.y, v1.z)\r
glVertex3f(v2.x, v2.y, v2.z)\r
glVertex3f(v3.x, v3.y, v3.z)\r
+ glNormal3f(-face.normal.x, -face.normal.y, -face.normal.z)\r
+ glVertex3f(v1.x, v1.y, v1.z)\r
+ glVertex3f(v3.x, v3.y, v3.z)\r
+ glVertex3f(v2.x, v2.y, v2.z)\r
glEnd()\r
glEndList()\r
if self.renderTransparent:\r
glEnable(GL_LIGHTING)\r
glEnable(GL_LIGHT0)\r
glEnable(GL_DEPTH_TEST)\r
+ glEnable(GL_CULL_FACE)\r
glDisable(GL_BLEND)\r
\r
glClearColor(0.0, 0.0, 0.0, 1.0)\r
from fabmetheus_utilities import svg_writer
from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
from skeinforge_application.skeinforge_utilities import skeinforge_profile
+from fabmetheus_utilities.vector3 import Vector3
import math
import os
import sys
import time
+import math
__author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
settings.LabelSeparator().getFromRepository(self)
self.executeTitle = 'Carve'
+ self.flipX = settings.BooleanSetting().getFromValue('FlipX', self, False)
+ self.flipY = settings.BooleanSetting().getFromValue('FlipY', self, False)
+ self.flipZ = settings.BooleanSetting().getFromValue('FlipZ', self, False)
+ self.scale = settings.FloatSpin().getFromValue( 0.1, 'Scale', self, 10.0, 1.0 )
+ self.rotate = settings.FloatSpin().getFromValue( -180.0, 'Rotate', self, 180.0, 0.0 )
+
+
def execute(self):
"Carve button has been clicked."
fileNames = skeinforge_polyfile.getFileOrDirectoryTypes(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
"A class to carve a carving."
def getCarvedSVG(self, carving, fileName, repository):
"Parse gnu triangulated surface text and store the carved gcode."
+
+ scale = repository.scale.value
+ rotate = repository.rotate.value / 180 * math.pi
+ scaleX = scale
+ scaleY = scale
+ scaleZ = scale
+ if repository.flipX.value == 'True':
+ scaleX = -scaleX
+ if repository.flipY.value == 'True':
+ scaleY = -scaleY
+ if repository.flipZ.value == 'True':
+ scaleZ = -scaleZ
+ mat00 = math.cos(rotate) * scaleX
+ mat01 =-math.sin(rotate) * scaleY
+ mat10 = math.sin(rotate) * scaleX
+ mat11 = math.cos(rotate) * scaleY
+
+ for i in xrange(0, len(carving.vertexes)):
+ carving.vertexes[i] = Vector3(
+ carving.vertexes[i].x * mat00 + carving.vertexes[i].y * mat01,
+ carving.vertexes[i].x * mat10 + carving.vertexes[i].y * mat11,
+ carving.vertexes[i].z * scaleZ)
+
layerHeight = repository.layerHeight.value
edgeWidth = repository.edgeWidth.value
carving.setCarveLayerHeight(layerHeight)