chiark / gitweb /
Add uppercase STL and HEX to file dialog filters for linux/MacOS
[cura.git] / Cura / cura_sf / skeinforge_application / skeinforge_plugins / craft_plugins / bottom.py
1 #! /usr/bin/env python
2 """
3 This page is in the table of contents.
4 Bottom sets the bottom of the carving to the defined altitude.
5
6 The bottom manual page is at:
7 http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Bottom
8
9 ==Operation==
10 The default 'Activate Bottom' checkbox is on.  When it is on, the functions described below will work, when it is off, the functions will not be called.
11
12 ==Settings==
13 ===Additional Height over Layer Thickness===
14 Default is half.
15
16 The layers will start at the altitude plus the 'Additional Height over Layer Thickness' times the layer height.  The default value of half means that the bottom layer is at the height of the bottom slice, because each slice is made through the middle of each layer.  Raft expects the layers to start at an additional half layer height.  You should only change 'Additional Height over Layer Thickness' if you are manipulating the skeinforge output with your own program which does not use the raft tool.
17
18 ===Altitude===
19 Default is zero.
20
21 Defines the altitude of the bottom of the model.  The bottom slice has a z of the altitude plus the 'Additional Height over Layer Thickness' times the layer height.
22
23 ===SVG Viewer===
24 Default is webbrowser.
25
26 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.
27
28 ==Examples==
29 The following examples bottom the file Screw Holder Bottom.stl.  The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and bottom.py.
30
31 > python bottom.py
32 This brings up the bottom dialog.
33
34 > python bottom.py Screw Holder Bottom.stl
35 The bottom tool is parsing the file:
36 Screw Holder Bottom.stl
37 ..
38 The bottom tool has created the file:
39 .. Screw Holder Bottom_bottom.gcode
40
41 """
42
43 from __future__ import absolute_import
44 #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.
45 import __init__
46
47 from datetime import date
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 euclidean
53 from fabmetheus_utilities import gcodec
54 from fabmetheus_utilities import settings
55 from fabmetheus_utilities import svg_writer
56 from skeinforge_application.skeinforge_utilities import skeinforge_craft
57 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
58 from skeinforge_application.skeinforge_utilities import skeinforge_profile
59 import cStringIO
60 import os
61 import sys
62 import time
63
64
65 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
66 __date__ = '$Date: 2008/02/05 $'
67 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
68
69
70 def getCraftedText(fileName, svgText='', repository=None):
71         "Bottom and convert an svg file or svgText."
72         return getCraftedTextFromText(fileName, archive.getTextIfEmpty(fileName, svgText), repository)
73
74 def getCraftedTextFromText(fileName, svgText, repository=None):
75         "Bottom and convert an svgText."
76         if gcodec.isProcedureDoneOrFileIsEmpty(svgText, 'bottom'):
77                 return svgText
78         if repository == None:
79                 repository = settings.getReadRepository(BottomRepository())
80         if not repository.activateBottom.value:
81                 return svgText
82         return BottomSkein().getCraftedGcode(fileName, repository, svgText)
83
84 def getNewRepository():
85         'Get new repository.'
86         return BottomRepository()
87
88 def writeOutput(fileName, shouldAnalyze=True):
89         'Bottom the carving.'
90         skeinforge_craft.writeSVGTextWithNounMessage(fileName, BottomRepository(), shouldAnalyze)
91
92
93 class BottomRepository:
94         "A class to handle the bottom settings."
95         def __init__(self):
96                 "Set the default settings, execute title & settings fileName."
97                 skeinforge_profile.addListsToCraftTypeRepository(
98                         'skeinforge_application.skeinforge_plugins.craft_plugins.bottom.html', self)
99                 self.fileNameInput = settings.FileNameInput().getFromFileName(
100                         fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Bottom', self, '')
101                 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Bottom')
102                 self.activateBottom = settings.BooleanSetting().getFromValue('Activate Bottom', self, True)
103                 self.additionalHeightOverLayerThickness = settings.FloatSpin().getFromValue(
104                         0.0, 'Additional Height over Layer Thickness (ratio):', self, 1.0, 0.5)
105                 self.altitude = settings.FloatSpin().getFromValue(-1.0, 'Altitude (mm):', self, 1.0, 0.0)
106                 self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser')
107                 self.executeTitle = 'Bottom'
108
109         def execute(self):
110                 "Bottom 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 BottomSkein:
117         "A class to bottom a skein of extrusions."
118         def getCraftedGcode(self, fileName, repository, svgText):
119                 "Parse svgText and store the bottom 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                 decimalPlacesCarried = int(svgReader.sliceDictionary['decimalPlacesCarried'])
126                 edgeWidth = float(svgReader.sliceDictionary['edgeWidth'])
127                 layerHeight = float(svgReader.sliceDictionary['layerHeight'])
128                 loopLayers = svgReader.loopLayers
129                 zMinimum = 987654321.0
130                 for loopLayer in loopLayers:
131                         zMinimum = min(loopLayer.z, zMinimum)
132                 deltaZ = repository.altitude.value + repository.additionalHeightOverLayerThickness.value * layerHeight - zMinimum
133                 for loopLayer in loopLayers:
134                         loopLayer.z += deltaZ
135                 cornerMaximum = Vector3(-912345678.0, -912345678.0, -912345678.0)
136                 cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0)
137                 svg_writer.setSVGCarvingCorners(cornerMaximum, cornerMinimum, layerHeight, loopLayers)
138                 svgWriter = svg_writer.SVGWriter(
139                         True,
140                         cornerMaximum,
141                         cornerMinimum,
142                         decimalPlacesCarried,
143                         layerHeight,
144                         edgeWidth)
145                 commentElement = svg_writer.getCommentElement(svgReader.documentElement)
146                 procedureNameString = svgReader.sliceDictionary['procedureName'] + ',bottom'
147                 return svgWriter.getReplacedSVGTemplate(fileName, loopLayers, procedureNameString, commentElement)
148
149
150 def main():
151         "Display the bottom dialog."
152         if len(sys.argv) > 1:
153                 writeOutput(' '.join(sys.argv[1 :]))
154         else:
155                 settings.startMainLoopFromConstructor(getNewRepository())
156
157 if __name__ == "__main__":
158         main()