chiark / gitweb /
Merge pull request #724 from Dim3nsioneer/SteamEngine
[cura.git] / Cura / util / validators.py
1 """
2 Setting validators.
3 These are the validators for various profile settings, each validator can be attached to a setting.
4 The validators can be queried to see if the setting is valid.
5 There are 3 possible outcomes:
6         Valid   - No problems found
7         Warning - The value is valid, but not recommended
8         Error   - The value is not a proper number, out of range, or some other way wrong.
9 """
10 from __future__ import division
11 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12
13 import types
14 import math
15
16 SUCCESS = 0
17 WARNING = 1
18 ERROR   = 2
19
20 class validFloat(object):
21         def __init__(self, setting, minValue = None, maxValue = None):
22                 self.setting = setting
23                 self.setting._validators.append(self)
24                 self.minValue = minValue
25                 self.maxValue = maxValue
26         
27         def validate(self):
28                 try:
29                         f = float(eval(self.setting.getValue().replace(',','.'), {}, {}))
30                         if self.minValue is not None and f < self.minValue:
31                                 return ERROR, 'This setting should not be below ' + str(round(self.minValue, 3))
32                         if self.maxValue is not None and f > self.maxValue:
33                                 return ERROR, 'This setting should not be above ' + str(self.maxValue)
34                         return SUCCESS, ''
35                 except (ValueError, SyntaxError, TypeError, NameError):
36                         return ERROR, '"' + str(self.setting.getValue()) + '" is not a valid number or expression'
37
38 class validInt(object):
39         def __init__(self, setting, minValue = None, maxValue = None):
40                 self.setting = setting
41                 self.setting._validators.append(self)
42                 self.minValue = minValue
43                 self.maxValue = maxValue
44         
45         def validate(self):
46                 try:
47                         f = int(eval(self.setting.getValue(), {}, {}))
48                         if self.minValue is not None and f < self.minValue:
49                                 return ERROR, 'This setting should not be below ' + str(self.minValue)
50                         if self.maxValue is not None and f > self.maxValue:
51                                 return ERROR, 'This setting should not be above ' + str(self.maxValue)
52                         return SUCCESS, ''
53                 except (ValueError, SyntaxError, TypeError, NameError):
54                         return ERROR, '"' + str(self.setting.getValue()) + '" is not a valid whole number or expression'
55
56 class warningAbove(object):
57         def __init__(self, setting, minValueForWarning, warningMessage):
58                 self.setting = setting
59                 self.setting._validators.append(self)
60                 self.minValueForWarning = minValueForWarning
61                 self.warningMessage = warningMessage
62         
63         def validate(self):
64                 try:
65                         f = float(eval(self.setting.getValue().replace(',','.'), {}, {}))
66                         if isinstance(self.minValueForWarning, types.FunctionType):
67                                 if f >= self.minValueForWarning():
68                                         return WARNING, self.warningMessage % (self.minValueForWarning())
69                         else:
70                                 if f >= self.minValueForWarning:
71                                         return WARNING, self.warningMessage
72                         return SUCCESS, ''
73                 except (ValueError, SyntaxError, TypeError):
74                         #We already have an error by the int/float validator in this case.
75                         return SUCCESS, ''
76
77 class warningBelow(object):
78         def __init__(self, setting, minValueForWarning, warningMessage):
79                 self.setting = setting
80                 self.setting._validators.append(self)
81                 self.minValueForWarning = minValueForWarning
82                 self.warningMessage = warningMessage
83
84         def validate(self):
85                 try:
86                         f = float(eval(self.setting.getValue().replace(',','.'), {}, {}))
87                         if isinstance(self.minValueForWarning, types.FunctionType):
88                                 if f <= self.minValueForWarning():
89                                         return WARNING, self.warningMessage % (self.minValueForWarning())
90                         else:
91                                 if f <= self.minValueForWarning:
92                                         return WARNING, self.warningMessage
93                         return SUCCESS, ''
94                 except (ValueError, SyntaxError, TypeError):
95                         #We already have an error by the int/float validator in this case.
96                         return SUCCESS, ''
97
98 class wallThicknessValidator(object):
99         def __init__(self, setting):
100                 self.setting = setting
101                 self.setting._validators.append(self)
102         
103         def validate(self):
104                 from Cura.util import profile
105                 try:
106                         wallThickness = profile.getProfileSettingFloat('wall_thickness')
107                         nozzleSize = profile.getProfileSettingFloat('nozzle_size')
108                         if wallThickness < 0.01:
109                                 return SUCCESS, ''
110                         if wallThickness <= nozzleSize * 0.5:
111                                 return ERROR, 'Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable'
112                         if wallThickness <= nozzleSize * 0.85:
113                                 return WARNING, 'Trying to print walls thinner then the 0.8 * nozzle size. Small chance that this will produce usable results'
114                         if wallThickness < nozzleSize:
115                                 return SUCCESS, ''
116                         if nozzleSize <= 0:
117                                 return ERROR, 'Incorrect nozzle size'
118                         
119                         lineCount = int(wallThickness / nozzleSize)
120                         lineWidth = wallThickness / lineCount
121                         lineWidthAlt = wallThickness / (lineCount + 1)
122                         if lineWidth >= nozzleSize * 1.5 and lineWidthAlt <= nozzleSize * 0.85:
123                                 return WARNING, 'Current selected wall thickness results in a line thickness of ' + str(lineWidthAlt) + 'mm which is not recommended with your nozzle of ' + str(nozzleSize) + 'mm'
124                         return SUCCESS, ''
125                 except ValueError:
126                         #We already have an error by the int/float validator in this case.
127                         return SUCCESS, ''
128
129 class printSpeedValidator(object):
130         def __init__(self, setting):
131                 self.setting = setting
132                 self.setting._validators.append(self)
133
134         def validate(self):
135                 from Cura.util import profile
136                 try:
137                         nozzleSize = profile.getProfileSettingFloat('nozzle_size')
138                         layerHeight = profile.getProfileSettingFloat('layer_height')
139                         printSpeed = profile.getProfileSettingFloat('print_speed')
140                         
141                         printVolumePerMM = layerHeight * nozzleSize
142                         printVolumePerSecond = printVolumePerMM * printSpeed
143                         #Using 10mm3 per second with a 0.4mm nozzle (normal max according to Joergen Geerds)
144                         maxPrintVolumePerSecond = 10 / (math.pi*(0.2*0.2)) * (math.pi*(nozzleSize/2*nozzleSize/2))
145                         
146                         if printVolumePerSecond > maxPrintVolumePerSecond:
147                                 return WARNING, 'You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)' % (maxPrintVolumePerSecond, printVolumePerSecond)
148                         
149                         return SUCCESS, ''
150                 except ValueError:
151                         #We already have an error by the int/float validator in this case.
152                         return SUCCESS, ''
153