2 This page is in the table of contents.
3 Cleave is a script to cleave a shape into svg slice layers.
6 ===Add Layer Template to SVG===
9 When selected, the layer template will be added to the svg output, which adds javascript control boxes. So 'Add Layer Template to SVG' should be selected when the svg will be viewed in a browser.
11 When off, no controls will be added, the svg output will only include the fabrication paths. So 'Add Layer Template to SVG' should be deselected when the svg will be used by other software, like Inkscape.
13 ===Extra Decimal Places===
16 Defines the number of extra decimal places export will output compared to the number of decimal places in the layer height. The higher the 'Extra Decimal Places', the more significant figures the output numbers will have.
18 ===Import Coarseness===
21 When a triangle mesh has holes in it, the triangle mesh slicer switches over to a slow algorithm that spans gaps in the mesh. The higher the 'Import Coarseness' setting, the wider the gaps in the mesh it will span. An import coarseness of one means it will span gaps of the edge width.
26 Defines the height of the layer, this is the most important cleave setting.
29 Cleave slices from bottom to top. To get a single layer, set the "Layers From" to zero and the "Layers To" to one. The layer from until layer to range is a python slice.
34 Defines the index of the bottom layer that will be cleaved. If the layer from is the default zero, the carving will start from the lowest layer. If the 'Layers From' index is negative, then the carving will start from the 'Layers From' index below the top layer.
37 Default is a huge number, which will be limited to the highest index layer.
39 Defines the index of the top layer that will be cleaved. If the 'Layers To' index is a huge number like the default, the carving will go to the top of the model. If the 'Layers To' index is negative, then the carving will go to the 'Layers To' index below the top layer.
42 Default is 'Correct Mesh'.
45 When selected, the mesh will be accurately cleaved, and if a hole is found, cleave will switch over to the algorithm that spans gaps.
48 When selected, cleave will use the gap spanning algorithm from the start. The problem with the gap spanning algothm is that it will span gaps, even if there is not actually a gap in the model.
51 Default is two millimeters.
53 Defines the width of the edge.
56 Default is webbrowser.
58 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.
61 The following examples cleave the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and cleave.py.
64 This brings up the cleave dialog.
66 > python cleave.py Screw Holder Bottom.stl
67 The cleave tool is parsing the file:
68 Screw Holder Bottom.stl
70 The cleave tool has created the file:
71 .. Screw Holder Bottom_cleave.svg
75 from __future__ import absolute_import
81 #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.
84 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
85 from fabmetheus_utilities import archive
86 from fabmetheus_utilities import euclidean
87 from fabmetheus_utilities import gcodec
88 from fabmetheus_utilities import settings
89 from fabmetheus_utilities import svg_writer
90 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
91 from skeinforge_application.skeinforge_utilities import skeinforge_profile
98 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
99 __date__ = '$Date: 2008/02/05 $'
100 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
103 def getCraftedText( fileName, gcodeText = '', repository=None):
105 if fileName.endswith('.svg'):
106 gcodeText = archive.getTextIfEmpty(fileName, gcodeText)
107 if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'cleave'):
109 carving = svg_writer.getCarving(fileName)
112 if repository == None:
113 repository = CleaveRepository()
114 settings.getReadRepository(repository)
115 return CleaveSkein().getCarvedSVG( carving, fileName, repository )
117 def getNewRepository():
118 'Get new repository.'
119 return CleaveRepository()
121 def writeOutput(fileName, shouldAnalyze=True):
122 "Cleave a GNU Triangulated Surface file."
123 startTime = time.time()
124 print('File ' + archive.getSummarizedFileName(fileName) + ' is being cleaved.')
125 repository = CleaveRepository()
126 settings.getReadRepository(repository)
127 cleaveGcode = getCraftedText( fileName, '', repository )
128 if cleaveGcode == '':
130 suffixFileName = fileName[ : fileName.rfind('.') ] + '_cleave.svg'
131 suffixDirectoryName = os.path.dirname(suffixFileName)
132 suffixReplacedBaseName = os.path.basename(suffixFileName).replace(' ', '_')
133 suffixFileName = os.path.join( suffixDirectoryName, suffixReplacedBaseName )
134 archive.writeFileText( suffixFileName, cleaveGcode )
135 print('The cleaved file is saved as ' + archive.getSummarizedFileName(suffixFileName) )
136 print('It took %s to cleave the file.' % euclidean.getDurationString( time.time() - startTime ) )
138 settings.openSVGPage( suffixFileName, repository.svgViewer.value )
141 class CleaveRepository:
142 "A class to handle the cleave settings."
144 "Set the default settings, execute title & settings fileName."
145 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.cleave.html', self )
146 self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getTranslatorFileTypeTuples(), 'Open File to be Cleaved', self, '')
147 self.addLayerTemplateToSVG = settings.BooleanSetting().getFromValue('Add Layer Template to SVG', self, True)
148 self.edgeWidth = settings.FloatSpin().getFromValue( 0.4, 'Edge Width (mm):', self, 4.0, 2.0 )
149 self.extraDecimalPlaces = settings.FloatSpin().getFromValue(0.0, 'Extra Decimal Places (float):', self, 3.0, 2.0)
150 self.importCoarseness = settings.FloatSpin().getFromValue( 0.5, 'Import Coarseness (ratio):', self, 2.0, 1.0 )
151 self.layerHeight = settings.FloatSpin().getFromValue( 0.1, 'Layer Height (mm):', self, 1.0, 0.4 )
152 self.layersFrom = settings.IntSpin().getFromValue( 0, 'Layers From (index):', self, 20, 0 )
153 self.layersTo = settings.IntSpin().getSingleIncrementFromValue( 0, 'Layers To (index):', self, 912345678, 912345678 )
154 self.meshTypeLabel = settings.LabelDisplay().getFromName('Mesh Type: ', self, )
155 importLatentStringVar = settings.LatentStringVar()
156 self.correctMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Correct Mesh', self, True )
157 self.unprovenMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Unproven Mesh', self, False )
158 self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser')
159 settings.LabelSeparator().getFromRepository(self)
160 self.executeTitle = 'Cleave'
163 "Cleave button has been clicked."
164 fileNames = skeinforge_polyfile.getFileOrDirectoryTypes(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
165 for fileName in fileNames:
166 writeOutput(fileName)
170 "A class to cleave a carving."
171 def getCarvedSVG( self, carving, fileName, repository ):
172 "Parse gnu triangulated surface text and store the cleaved gcode."
173 edgeWidth = repository.edgeWidth.value
174 layerHeight = repository.layerHeight.value
175 carving.setCarveLayerHeight( layerHeight )
176 importRadius = 0.5 * repository.importCoarseness.value * abs(edgeWidth)
177 carving.setCarveImportRadius(max(importRadius, 0.001 * layerHeight))
178 carving.setCarveIsCorrectMesh( repository.correctMesh.value )
179 loopLayers = carving.getCarveBoundaryLayers()
180 if len( loopLayers ) < 1:
181 print('Warning, there are no slices for the model, this could be because the model is too small for the Layer Height.')
183 layerThickness = carving.getCarveLayerHeight()
184 decimalPlacesCarried = euclidean.getDecimalPlacesCarried(repository.extraDecimalPlaces.value, layerHeight)
185 svgWriter = svg_writer.SVGWriter(
186 repository.addLayerTemplateToSVG.value,
187 carving.getCarveCornerMaximum(),
188 carving.getCarveCornerMinimum(),
189 decimalPlacesCarried,
190 carving.getCarveLayerHeight(),
192 truncatedRotatedBoundaryLayers = svg_writer.getTruncatedRotatedBoundaryLayers(loopLayers, repository)
193 return svgWriter.getReplacedSVGTemplate( fileName, truncatedRotatedBoundaryLayers, 'cleave', carving.getFabmetheusXML())
197 "Display the cleave dialog."
198 if len(sys.argv) > 1:
199 writeOutput(' '.join(sys.argv[1 :]))
201 settings.startMainLoopFromConstructor(getNewRepository())
203 if __name__ == "__main__":