Allow math expressions in fields.

master
daid 2012-04-10 16:45:53 +02:00
parent 7fb30600a2
commit a79a7c066d
5 changed files with 82 additions and 71 deletions

View File

@ -4,6 +4,7 @@ Settings is a collection of utilities to display, read & write the settings and
"""
from __future__ import absolute_import
from __future__ import division
#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
import __init__
@ -18,11 +19,15 @@ def DEFSET(setting):
def storedSetting(name):
return lambda setting: profile.getProfileSetting(name)
def storedSettingFloat(name):
return lambda setting: profile.getProfileSettingFloat(name)
def storedSettingInt(name):
return lambda setting: int(profile.getProfileSettingFloat(name))
def storedPreference(name):
return lambda setting: profile.getPreference(name)
def ifSettingAboveZero(name):
return lambda setting: float(profile.getProfileSetting(name)) > 0
return lambda setting: profile.getProfileSettingFloat(name) > 0
def ifSettingIs(name, value):
return lambda setting: profile.getProfileSetting(name) == value
@ -33,7 +38,7 @@ def raftLayerCount(setting):
return '0'
def storedPercentSetting(name):
return lambda setting: float(profile.getProfileSetting(name)) / 100
return lambda setting: profile.getProfileSettingFloat(name) / 100
def calculateEdgeWidth(setting):
return profile.calculateEdgeWidth()
@ -43,7 +48,7 @@ def calculateShells(setting):
def calculateShellsBase(setting):
edgeWidth = profile.calculateEdgeWidth()
extraWall = float(profile.getProfileSetting('extra_base_wall_thickness'))
extraWall = profile.getProfileSettingFloat('extra_base_wall_thickness')
return profile.calculateLineCount() - 1 + int(extraWall / edgeWidth + 0.0001)
@ -51,13 +56,13 @@ def calculateSolidLayerCount(setting):
return profile.calculateSolidLayerCount()
def firstLayerSpeedRatio(setting):
bottomSpeed = float(profile.getProfileSetting('bottom_layer_speed'))
speed = float(profile.getProfileSetting('print_speed'))
bottomSpeed = profile.getProfileSettingFloat('bottom_layer_speed')
speed = profile.getProfileSettingFloat('print_speed')
return bottomSpeed/speed
def calcSupportDistanceRatio(setting):
edgeWidth = calculateEdgeWidth(setting)
distance = float(profile.getProfileSetting('support_distance'))
distance = profile.getProfileSettingFloat('support_distance')
return distance / edgeWidth
def calculateMultiplyDistance(setting):
@ -65,22 +70,22 @@ def calculateMultiplyDistance(setting):
return 10.0 / edgeWidth
def calcBottomLayerFlowRateRatio(setting):
bottomThickness = float(profile.getProfileSetting('bottom_thickness'))
layerThickness = float(profile.getProfileSetting('layer_height'))
bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
layerThickness = profile.getProfileSettingFloat('layer_height')
if bottomThickness < layerThickness:
return 1.0
return bottomThickness / layerThickness
def calcExtraBottomThickness(setting):
bottomThickness = float(profile.getProfileSetting('bottom_thickness'))
layerThickness = float(profile.getProfileSetting('layer_height'))
bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
layerThickness = profile.getProfileSettingFloat('layer_height')
if bottomThickness < layerThickness:
return 0.0
return bottomThickness - layerThickness
def calcLayerSkip(setting):
bottomThickness = float(profile.getProfileSetting('bottom_thickness'))
layerThickness = float(profile.getProfileSetting('layer_height'))
bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
layerThickness = profile.getProfileSettingFloat('layer_height')
if bottomThickness < layerThickness:
return 0
return int(math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1)
@ -92,7 +97,7 @@ def getProfileInformation():
'Edge_Width_mm': calculateEdgeWidth,
'Extra_Decimal_Places_float': DEFSET,
'Import_Coarseness_ratio': DEFSET,
'Layer_Height_mm': storedSetting("layer_height"),
'Layer_Height_mm': storedSettingFloat("layer_height"),
'Layers_From_index': calcLayerSkip,
'Layers_To_index': DEFSET,
'Correct_Mesh': DEFSET,
@ -103,8 +108,8 @@ def getProfileInformation():
'FlipZ': storedSetting("flip_z"),
'SwapXZ': storedSetting("swap_xz"),
'SwapYZ': storedSetting("swap_yz"),
'Scale': storedSetting("model_scale"),
'Rotate': storedSetting("model_rotate_base"),
'Scale': storedSettingFloat("model_scale"),
'Rotate': storedSettingFloat("model_rotate_base"),
},'scale': {
'Activate_Scale': "False",
'XY_Plane_Scale_ratio': DEFSET,
@ -128,7 +133,7 @@ def getProfileInformation():
},'inset': {
'Add_Custom_Code_for_Temperature_Reading': "False",
'Infill_in_Direction_of_Bridge': "True",
'Infill_Width': storedSetting("nozzle_size"),
'Infill_Width': storedSettingFloat("nozzle_size"),
'Loop_Order_Choice': DEFSET,
'Overlap_Removal_Width_over_Perimeter_Width_ratio': DEFSET,
'Turn_Extruder_Heater_Off_at_Shut_Down': DEFSET,
@ -156,7 +161,7 @@ def getProfileInformation():
'Line': ifSettingIs('infill_type', 'Line'),
'Infill_Perimeter_Overlap_ratio': storedPercentSetting('fill_overlap'),
'Infill_Solidity_ratio': storedPercentSetting('fill_density'),
'Infill_Width': storedSetting("nozzle_size"),
'Infill_Width': storedSettingFloat("nozzle_size"),
'Sharpest_Angle_degrees': DEFSET,
'Solid_Surface_Thickness_layers': calculateSolidLayerCount,
'Start_From_Choice': DEFSET,
@ -164,8 +169,8 @@ def getProfileInformation():
'Thread_Sequence_Choice': storedSetting('sequence'),
},'multiply': {
'Activate_Multiply': "True",
'Center_X_mm': storedSetting("machine_center_x"),
'Center_Y_mm': storedSetting("machine_center_y"),
'Center_X_mm': storedSettingFloat("machine_center_x"),
'Center_Y_mm': storedSettingFloat("machine_center_y"),
'Number_of_Columns_integer': storedSetting('model_multiply_x'),
'Number_of_Rows_integer': storedSetting('model_multiply_y'),
'Reverse_Sequence_every_Odd_Layer': DEFSET,
@ -177,8 +182,8 @@ def getProfileInformation():
'Bridge_Flow_Rate_Multiplier_ratio': storedPercentSetting('bridge_material_amount'),
'Duty_Cyle_at_Beginning_portion': DEFSET,
'Duty_Cyle_at_Ending_portion': DEFSET,
'Feed_Rate_mm/s': storedSetting("print_speed"),
'Flow_Rate_Setting_float': storedSetting("print_speed"),
'Feed_Rate_mm/s': storedSettingFloat("print_speed"),
'Flow_Rate_Setting_float': storedSettingFloat("print_speed"),
'Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio,
'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio,
'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': firstLayerSpeedRatio,
@ -189,19 +194,19 @@ def getProfileInformation():
'Maximum_Z_Feed_Rate_mm/s': DEFSET,
'Perimeter_Feed_Rate_Multiplier_ratio': DEFSET,
'Perimeter_Flow_Rate_Multiplier_ratio': DEFSET,
'Travel_Feed_Rate_mm/s': storedSetting("travel_speed"),
'Travel_Feed_Rate_mm/s': storedSettingFloat("travel_speed"),
'Bottom_layer_flow_rate_ratio': calcBottomLayerFlowRateRatio,
},'temperature': {
'Activate_Temperature': DEFSET,#ifSettingAboveZero('print_temperature'),
'Cooling_Rate_Celcius/second': DEFSET,
'Heating_Rate_Celcius/second': DEFSET,
'Base_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Interface_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Object_First_Layer_Infill_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Object_First_Layer_Perimeter_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Object_Next_Layers_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Support_Layers_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Supported_Layers_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"),
'Base_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
'Interface_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
'Object_First_Layer_Infill_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
'Object_First_Layer_Perimeter_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
'Object_Next_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
'Support_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
'Supported_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
},'raft': {
'Activate_Raft': "True",
'Add_Raft,_Elevate_Nozzle,_Orbit': DEFSET,
@ -223,7 +228,7 @@ def getProfileInformation():
'Name_of_Support_Start_File': DEFSET,
'Operating_Nozzle_Lift_over_Layer_Thickness_ratio': DEFSET,
'Raft_Additional_Margin_over_Length_%': DEFSET,
'Raft_Margin_mm': storedSetting('raft_margin'),
'Raft_Margin_mm': storedSettingFloat('raft_margin'),
'Support_Cross_Hatch': 'False',
'Support_Flow_Rate_over_Operating_Flow_Rate_ratio': storedPercentSetting('support_rate'),
'Support_Gap_over_Perimeter_Extrusion_Width_ratio': calcSupportDistanceRatio,
@ -284,16 +289,16 @@ def getProfileInformation():
'Bridge_Cool_Celcius': DEFSET,
'Cool_Type': DEFSET,
'Maximum_Cool_Celcius': DEFSET,
'Minimum_Layer_Time_seconds': storedSetting("cool_min_layer_time"),
'Minimum_Layer_Time_seconds': storedSettingFloat("cool_min_layer_time"),
'Minimum_Orbital_Radius_millimeters': DEFSET,
'Name_of_Cool_End_File': DEFSET,
'Name_of_Cool_Start_File': DEFSET,
'Orbital_Outset_millimeters': DEFSET,
'Turn_Fan_On_at_Beginning': storedSetting("fan_enabled"),
'Turn_Fan_Off_at_Ending': "False",
'Minimum_feed_rate_mm/s': storedSetting("cool_min_feedrate"),
'Fan_on_at_layer': storedSetting('fan_layer'),
'Fan_speed_%': storedSetting('fan_speed'),
'Minimum_feed_rate_mm/s': storedSettingFloat("cool_min_feedrate"),
'Fan_on_at_layer': storedSettingInt('fan_layer'),
'Fan_speed_%': storedSettingInt('fan_speed'),
},'hop': {
'Activate_Hop': "False",
'Hop_Over_Layer_Thickness_ratio': DEFSET,
@ -362,14 +367,14 @@ def getProfileInformation():
'Activate_Dimension': "True",
'Absolute_Extrusion_Distance': "True",
'Relative_Extrusion_Distance': "False",
'Extruder_Retraction_Speed_mm/s': storedSetting('retraction_speed'),
'Filament_Diameter_mm': storedSetting("filament_diameter"),
'Filament_Packing_Density_ratio': storedSetting("filament_density"),
'Extruder_Retraction_Speed_mm/s': storedSettingFloat('retraction_speed'),
'Filament_Diameter_mm': storedSettingFloat("filament_diameter"),
'Filament_Packing_Density_ratio': storedSettingFloat("filament_density"),
'Maximum_E_Value_before_Reset_float': DEFSET,
'Minimum_Travel_for_Retraction_millimeters': storedSetting("retraction_min_travel"),
'Minimum_Travel_for_Retraction_millimeters': storedSettingFloat("retraction_min_travel"),
'Retract_Within_Island': DEFSET,
'Retraction_Distance_millimeters': storedSetting('retraction_amount'),
'Restart_Extra_Distance_millimeters': storedSetting('retraction_extra'),
'Retraction_Distance_millimeters': storedSettingFloat('retraction_amount'),
'Restart_Extra_Distance_millimeters': storedSettingFloat('retraction_extra'),
},'alteration': {
'Activate_Alteration': "True",
'Name_of_End_File': "end.gcode",

View File

@ -95,10 +95,10 @@ class mainWindow(configBase.configWindowBase):
configBase.TitleRow(left, "Accuracy")
c = configBase.SettingRow(left, "Layer height (mm)", 'layer_height', '0.2', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.')
validators.validFloat(c, 0.0)
validators.validFloat(c, 0.0001)
validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 80.0 / 100.0), "Thicker layers then %.2fmm (80%% nozzle size) usually give bad results and are not recommended.")
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.validFloat(c, 0.0001)
validators.wallThicknessValidator(c)
configBase.TitleRow(left, "Fill")

View File

@ -1,3 +1,5 @@
from __future__ import division
import sys
import math
import threading
@ -163,11 +165,7 @@ class previewPanel(wx.Panel):
self.updateModelTransform()
def OnScale(self, e):
try:
scale = float(self.scale.GetValue())
except:
scale = 1.0
profile.putProfileSetting('model_scale', str(scale))
profile.putProfileSetting('model_scale', self.scale.GetValue())
self.updateModelTransform()
def OnRotate(self, e):
@ -292,8 +290,8 @@ class previewPanel(wx.Panel):
scale = 1.0
rotate = 0.0
try:
scale = float(profile.getProfileSetting('model_scale'))
rotate = float(profile.getProfileSetting('model_rotate_base')) / 180 * math.pi
scale = profile.getProfileSettingFloat('model_scale')
rotate = profile.getProfileSettingFloat('model_rotate_base') / 180.0 * math.pi
except:
pass
scaleX = scale

View File

@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import division
import __init__
import types
@ -19,14 +20,14 @@ class validFloat():
def validate(self):
try:
f = float(self.setting.GetValue())
f = float(eval(self.setting.GetValue(), {}, {}))
if self.minValue != None and f < self.minValue:
return ERROR, 'This setting should not be below ' + str(self.minValue)
if self.maxValue != None and f > self.maxValue:
return ERROR, 'This setting should not be above ' + str(self.maxValue)
return SUCCESS, ''
except ValueError:
return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid number'
except (ValueError, SyntaxError):
return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid number or expression'
class validInt():
def __init__(self, setting, minValue = None, maxValue = None):
@ -37,14 +38,14 @@ class validInt():
def validate(self):
try:
f = int(self.setting.GetValue())
f = int(eval(self.setting.GetValue(), {}, {}))
if self.minValue != None and f < self.minValue:
return ERROR, 'This setting should not be below ' + str(self.minValue)
if self.maxValue != None and f > self.maxValue:
return ERROR, 'This setting should not be above ' + str(self.maxValue)
return SUCCESS, ''
except ValueError:
return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid whole number'
except (ValueError, SyntaxError):
return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid whole number or expression'
class warningAbove():
def __init__(self, setting, minValueForWarning, warningMessage):
@ -55,7 +56,7 @@ class warningAbove():
def validate(self):
try:
f = float(self.setting.GetValue())
f = float(eval(self.setting.GetValue(), {}, {}))
if isinstance(self.minValueForWarning, types.FunctionType):
if f >= self.minValueForWarning():
return WARNING, self.warningMessage % (self.minValueForWarning())
@ -63,7 +64,7 @@ class warningAbove():
if f >= self.minValueForWarning:
return WARNING, self.warningMessage
return SUCCESS, ''
except ValueError:
except (ValueError, SyntaxError):
#We already have an error by the int/float validator in this case.
return SUCCESS, ''
@ -74,8 +75,8 @@ class wallThicknessValidator():
def validate(self):
try:
wallThickness = float(self.setting.GetValue())
nozzleSize = float(profile.getProfileSetting('nozzle_size'))
wallThickness = profile.getProfileSettingFloat('wall_thickness')
nozzleSize = profile.getProfileSettingFloat('nozzle_size')
if wallThickness <= nozzleSize * 0.5:
return ERROR, 'Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable'
if wallThickness <= nozzleSize * 0.85:
@ -100,9 +101,9 @@ class printSpeedValidator():
def validate(self):
try:
nozzleSize = float(profile.getProfileSetting('nozzle_size'))
layerHeight = float(profile.getProfileSetting('layer_height'))
printSpeed = float(profile.getProfileSetting('print_speed'))
nozzleSize = profile.getProfileSettingFloat('nozzle_size')
layerHeight = profile.getProfileSettingFloat('layer_height')
printSpeed = profile.getProfileSettingFloat('print_speed')
printVolumePerMM = layerHeight * nozzleSize
printVolumePerSecond = printVolumePerMM * printSpeed

View File

@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import division
#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
import __init__
@ -126,10 +127,16 @@ def getProfileSetting(name):
if not globalProfileParser.has_section('profile'):
globalProfileParser.add_section('profile')
globalProfileParser.set('profile', name, str(default))
print name + " not found in profile, so using default: " + str(default)
#print name + " not found in profile, so using default: " + str(default)
return default
return globalProfileParser.get('profile', name)
def getProfileSettingFloat(name):
try:
return float(eval(getProfileSetting(name), {}, {}))
except (ValueError, SyntaxError):
return 0.0
def putProfileSetting(name, value):
#Check if we have a configuration file loaded, else load the default.
if not globals().has_key('globalProfileParser'):
@ -160,7 +167,7 @@ def getPreference(name):
if not globalPreferenceParser.has_section('preference'):
globalPreferenceParser.add_section('preference')
globalPreferenceParser.set('preference', name, str(default))
print name + " not found in preferences, so using default: " + str(default)
#print name + " not found in preferences, so using default: " + str(default)
return default
return unicode(globalPreferenceParser.get('preference', name), "utf-8")
@ -179,8 +186,8 @@ def putPreference(name, value):
## Utility functions to calculate common profile values
#########################################################
def calculateEdgeWidth():
wallThickness = float(getProfileSetting('wall_thickness'))
nozzleSize = float(getProfileSetting('nozzle_size'))
wallThickness = getProfileSettingFloat('wall_thickness')
nozzleSize = getProfileSettingFloat('nozzle_size')
if wallThickness < nozzleSize:
return wallThickness
@ -193,8 +200,8 @@ def calculateEdgeWidth():
return lineWidth
def calculateLineCount():
wallThickness = float(getProfileSetting('wall_thickness'))
nozzleSize = float(getProfileSetting('nozzle_size'))
wallThickness = getProfileSettingFloat('wall_thickness')
nozzleSize = getProfileSettingFloat('nozzle_size')
if wallThickness < nozzleSize:
return 1
@ -207,8 +214,8 @@ def calculateLineCount():
return lineCount
def calculateSolidLayerCount():
layerHeight = float(getProfileSetting('layer_height'))
solidThickness = float(getProfileSetting('solid_layer_thickness'))
layerHeight = getProfileSettingFloat('layer_height')
solidThickness = getProfileSettingFloat('solid_layer_thickness')
return int(math.ceil(solidThickness / layerHeight - 0.0001))
#########################################################
@ -230,7 +237,7 @@ def getAlterationFileContents(filename, allowMagicPrefix = True):
eSteps = float(getPreference('steps_per_e'))
if eSteps > 0:
prefix += 'M92 E'+str(eSteps)+'\n'
temp = float(getProfileSetting('print_temperature'))
temp = getProfileSettingFloat('print_temperature')
if temp > 0:
prefix += 'M109 S'+str(temp)+'\n'
elif filename == 'replace.csv':