chiark / gitweb /
Move SF into its own directory, to seperate SF and Cura. Rename newui to gui.
[cura.git] / Cura / 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 #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.
48 import __init__
49
50 from datetime import date
51 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
52 from fabmetheus_utilities.svg_reader import SVGReader
53 from fabmetheus_utilities.vector3 import Vector3
54 from fabmetheus_utilities import archive
55 from fabmetheus_utilities import euclidean
56 from fabmetheus_utilities import gcodec
57 from fabmetheus_utilities import settings
58 from fabmetheus_utilities import svg_writer
59 from skeinforge_application.skeinforge_utilities import skeinforge_craft
60 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
61 from skeinforge_application.skeinforge_utilities import skeinforge_profile
62 import cStringIO
63 import os
64 import sys
65 import time
66
67
68 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
69 __date__ = '$Date: 2008/02/05 $'
70 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
71
72
73 def getCraftedText(fileName, svgText='', repository=None):
74         "Scale and convert an svg file or svgText."
75         return getCraftedTextFromText(fileName, archive.getTextIfEmpty(fileName, svgText), repository)
76
77 def getCraftedTextFromText(fileName, svgText, repository=None):
78         "Scale and convert an svgText."
79         if gcodec.isProcedureDoneOrFileIsEmpty(svgText, 'scale'):
80                 return svgText
81         if repository == None:
82                 repository = settings.getReadRepository(ScaleRepository())
83         if repository.activateScale.value:
84                 return ScaleSkein().getCraftedGcode(fileName, repository, svgText)
85         return svgText
86
87 def getNewRepository():
88         'Get new repository.'
89         return ScaleRepository()
90
91 def setLoopLayerScale(loopLayer, xyPlaneScale, zAxisScale):
92         "Set the slice element scale."
93         for loop in loopLayer.loops:
94                 for pointIndex in xrange(len(loop)):
95                         loop[pointIndex] *= xyPlaneScale
96         loopLayer.z *= zAxisScale
97
98 def writeOutput(fileName, shouldAnalyze=True):
99         'Scale the carving.'
100         skeinforge_craft.writeSVGTextWithNounMessage(fileName, ScaleRepository(), shouldAnalyze)
101
102
103 class ScaleRepository:
104         "A class to handle the scale settings."
105         def __init__(self):
106                 "Set the default settings, execute title & settings fileName."
107                 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.scale.html', self )
108                 self.fileNameInput = settings.FileNameInput().getFromFileName(fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Scale', self, '')
109                 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Scale')
110                 self.activateScale = settings.BooleanSetting().getFromValue('Activate Scale', self, False)
111                 self.xyPlaneScale = settings.FloatSpin().getFromValue(0.99, 'XY Plane Scale (ratio):', self, 1.03, 1.01)
112                 self.zAxisScale = settings.FloatSpin().getFromValue(0.99, 'Z Axis Scale (ratio):', self, 1.02, 1.0)
113                 self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser')
114                 self.executeTitle = 'Scale'
115
116         def execute(self):
117                 "Scale button has been clicked."
118                 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
119                 for fileName in fileNames:
120                         writeOutput(fileName)
121
122
123 class ScaleSkein:
124         "A class to scale a skein of extrusions."
125         def getCraftedGcode(self, fileName, repository, svgText):
126                 "Parse svgText and store the scale svgText."
127                 svgReader = SVGReader()
128                 svgReader.parseSVG('', svgText)
129                 if svgReader.sliceDictionary == None:
130                         print('Warning, nothing will be done because the sliceDictionary could not be found getCraftedGcode in preface.')
131                         return ''
132                 xyPlaneScale = repository.xyPlaneScale.value
133                 zAxisScale = repository.zAxisScale.value
134                 decimalPlacesCarried = int(svgReader.sliceDictionary['decimalPlacesCarried'])
135                 layerHeight = zAxisScale * float(svgReader.sliceDictionary['layerHeight'])
136                 edgeWidth = float(svgReader.sliceDictionary['edgeWidth'])
137                 loopLayers = svgReader.loopLayers
138                 for loopLayer in loopLayers:
139                         setLoopLayerScale(loopLayer, xyPlaneScale, zAxisScale)
140                 cornerMaximum = Vector3(-912345678.0, -912345678.0, -912345678.0)
141                 cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0)
142                 svg_writer.setSVGCarvingCorners(cornerMaximum, cornerMinimum, layerHeight, loopLayers)
143                 svgWriter = svg_writer.SVGWriter(
144                         True,
145                         cornerMaximum,
146                         cornerMinimum,
147                         decimalPlacesCarried,
148                         layerHeight,
149                         edgeWidth)
150                 commentElement = svg_writer.getCommentElement(svgReader.documentElement)
151                 procedureNameString = svgReader.sliceDictionary['procedureName'] + ',scale'
152                 return svgWriter.getReplacedSVGTemplate(fileName, loopLayers, procedureNameString, commentElement)
153
154
155 def main():
156         "Display the scale dialog."
157         if len(sys.argv) > 1:
158                 writeOutput(' '.join(sys.argv[1 :]))
159         else:
160                 settings.startMainLoopFromConstructor(getNewRepository())
161
162 if __name__ == "__main__":
163         main()