chiark / gitweb /
Add back the ultimaker platform, and made the platform mesh simpler.
[cura.git] / Cura / slice / cura_sf / skeinforge_application / skeinforge_plugins / craft_plugins / scale.py
1 #! /usr/bin/env python
2 """
3 This page is in the table of contents.
4 Scale scales the carving to compensate for shrinkage after the extrusion has cooled.
5
6 The scale manual page is at:
7
8 http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Scale
9
10 It is best to only change the XY Plane Scale, because that does not affect other variables.  If you choose to change the Z Axis Scale, that increases the layer height so you must increase the feed rate in speed by the same amount and maybe some other variables which depend on layer height.
11
12 ==Operation==
13 The default 'Activate Scale' checkbox is off.  When it is on, the functions described below will work, when it is off, nothing will be done.
14
15 ==Settings==
16 ===XY Plane Scale===
17 Default is 1.01.
18
19 Defines the amount the xy plane of the carving will be scaled.  The xy coordinates will be scaled, but the edge width is not changed, so this can be changed without affecting other variables.
20
21 ===Z Axis Scale===
22 Default is one.
23
24 Defines the amount the z axis of the carving will be scaled.  The default is one because changing this changes many variables related to the layer height.  For example, the feedRate should be multiplied by the Z Axis Scale because the layers would be farther apart.
25
26 ===SVG Viewer===
27 Default is webbrowser.
28
29 If the 'SVG Viewer' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened.  If the 'SVG Viewer' is set to a program name, the scalable vector graphics file will be sent to that program to be opened.
30
31 ==Examples==
32 The following examples scale the file Screw Holder Bottom.stl.  The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and scale.py.
33
34 > python scale.py
35 This brings up the scale dialog.
36
37 > python scale.py Screw Holder Bottom.stl
38 The scale tool is parsing the file:
39 Screw Holder Bottom.stl
40 ..
41 The scale tool has created the file:
42 .. Screw Holder Bottom_scale.gcode
43
44 """
45
46 from __future__ import absolute_import
47
48 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
49 from fabmetheus_utilities.svg_reader import SVGReader
50 from fabmetheus_utilities.vector3 import Vector3
51 from fabmetheus_utilities import archive
52 from fabmetheus_utilities import gcodec
53 from fabmetheus_utilities import settings
54 from fabmetheus_utilities import svg_writer
55 from skeinforge_application.skeinforge_utilities import skeinforge_craft
56 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
57 from skeinforge_application.skeinforge_utilities import skeinforge_profile
58 import sys
59
60
61 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
62 __date__ = '$Date: 2008/02/05 $'
63 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
64
65
66 def getCraftedText(fileName, svgText='', repository=None):
67         "Scale and convert an svg file or svgText."
68         return getCraftedTextFromText(fileName, archive.getTextIfEmpty(fileName, svgText), repository)
69
70 def getCraftedTextFromText(fileName, svgText, repository=None):
71         "Scale and convert an svgText."
72         if gcodec.isProcedureDoneOrFileIsEmpty(svgText, 'scale'):
73                 return svgText
74         if repository == None:
75                 repository = settings.getReadRepository(ScaleRepository())
76         if repository.activateScale.value:
77                 return ScaleSkein().getCraftedGcode(fileName, repository, svgText)
78         return svgText
79
80 def getNewRepository():
81         'Get new repository.'
82         return ScaleRepository()
83
84 def setLoopLayerScale(loopLayer, xyPlaneScale, zAxisScale):
85         "Set the slice element scale."
86         for loop in loopLayer.loops:
87                 for pointIndex in xrange(len(loop)):
88                         loop[pointIndex] *= xyPlaneScale
89         loopLayer.z *= zAxisScale
90
91 def writeOutput(fileName, shouldAnalyze=True):
92         'Scale the carving.'
93         skeinforge_craft.writeSVGTextWithNounMessage(fileName, ScaleRepository(), shouldAnalyze)
94
95
96 class ScaleRepository(object):
97         "A class to handle the scale settings."
98         def __init__(self):
99                 "Set the default settings, execute title & settings fileName."
100                 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.scale.html', self )
101                 self.fileNameInput = settings.FileNameInput().getFromFileName(fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Scale', self, '')
102                 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Scale')
103                 self.activateScale = settings.BooleanSetting().getFromValue('Activate Scale', self, False)
104                 self.xyPlaneScale = settings.FloatSpin().getFromValue(0.99, 'XY Plane Scale (ratio):', self, 1.03, 1.01)
105                 self.zAxisScale = settings.FloatSpin().getFromValue(0.99, 'Z Axis Scale (ratio):', self, 1.02, 1.0)
106                 self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser')
107                 self.executeTitle = 'Scale'
108
109         def execute(self):
110                 "Scale button has been clicked."
111                 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
112                 for fileName in fileNames:
113                         writeOutput(fileName)
114
115
116 class ScaleSkein(object):
117         "A class to scale a skein of extrusions."
118         def getCraftedGcode(self, fileName, repository, svgText):
119                 "Parse svgText and store the scale svgText."
120                 svgReader = SVGReader()
121                 svgReader.parseSVG('', svgText)
122                 if svgReader.sliceDictionary == None:
123                         print('Warning, nothing will be done because the sliceDictionary could not be found getCraftedGcode in preface.')
124                         return ''
125                 xyPlaneScale = repository.xyPlaneScale.value
126                 zAxisScale = repository.zAxisScale.value
127                 decimalPlacesCarried = int(svgReader.sliceDictionary['decimalPlacesCarried'])
128                 layerHeight = zAxisScale * float(svgReader.sliceDictionary['layerHeight'])
129                 edgeWidth = float(svgReader.sliceDictionary['edgeWidth'])
130                 loopLayers = svgReader.loopLayers
131                 for loopLayer in loopLayers:
132                         setLoopLayerScale(loopLayer, xyPlaneScale, zAxisScale)
133                 cornerMaximum = Vector3(-912345678.0, -912345678.0, -912345678.0)
134                 cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0)
135                 svg_writer.setSVGCarvingCorners(cornerMaximum, cornerMinimum, layerHeight, loopLayers)
136                 svgWriter = svg_writer.SVGWriter(
137                         True,
138                         cornerMaximum,
139                         cornerMinimum,
140                         decimalPlacesCarried,
141                         layerHeight,
142                         edgeWidth)
143                 commentElement = svg_writer.getCommentElement(svgReader.documentElement)
144                 procedureNameString = svgReader.sliceDictionary['procedureName'] + ',scale'
145                 return svgWriter.getReplacedSVGTemplate(fileName, loopLayers, procedureNameString, commentElement)
146
147
148 def main():
149         "Display the scale dialog."
150         if len(sys.argv) > 1:
151                 writeOutput(' '.join(sys.argv[1 :]))
152         else:
153                 settings.startMainLoopFromConstructor(getNewRepository())
154
155 if __name__ == "__main__":
156         main()