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
77 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
78 from fabmetheus_utilities import archive
79 from fabmetheus_utilities import euclidean
80 from fabmetheus_utilities import gcodec
81 from fabmetheus_utilities import settings
82 from fabmetheus_utilities import svg_writer
83 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
84 from skeinforge_application.skeinforge_utilities import skeinforge_profile
90 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
91 __date__ = '$Date: 2008/02/05 $'
92 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
95 def getCraftedText( fileName, gcodeText = '', repository=None):
97 if fileName.endswith('.svg'):
98 gcodeText = archive.getTextIfEmpty(fileName, gcodeText)
99 if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'cleave'):
101 carving = svg_writer.getCarving(fileName)
104 if repository == None:
105 repository = CleaveRepository()
106 settings.getReadRepository(repository)
107 return CleaveSkein().getCarvedSVG( carving, fileName, repository )
109 def getNewRepository():
110 'Get new repository.'
111 return CleaveRepository()
113 def writeOutput(fileName, shouldAnalyze=True):
114 "Cleave a GNU Triangulated Surface file."
115 startTime = time.time()
116 print('File ' + archive.getSummarizedFileName(fileName) + ' is being cleaved.')
117 repository = CleaveRepository()
118 settings.getReadRepository(repository)
119 cleaveGcode = getCraftedText( fileName, '', repository )
120 if cleaveGcode == '':
122 suffixFileName = fileName[ : fileName.rfind('.') ] + '_cleave.svg'
123 suffixDirectoryName = os.path.dirname(suffixFileName)
124 suffixReplacedBaseName = os.path.basename(suffixFileName).replace(' ', '_')
125 suffixFileName = os.path.join( suffixDirectoryName, suffixReplacedBaseName )
126 archive.writeFileText( suffixFileName, cleaveGcode )
127 print('The cleaved file is saved as ' + archive.getSummarizedFileName(suffixFileName) )
128 print('It took %s to cleave the file.' % euclidean.getDurationString( time.time() - startTime ) )
130 settings.openSVGPage( suffixFileName, repository.svgViewer.value )
133 class CleaveRepository(object):
134 "A class to handle the cleave settings."
136 "Set the default settings, execute title & settings fileName."
137 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.cleave.html', self )
138 self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getTranslatorFileTypeTuples(), 'Open File to be Cleaved', self, '')
139 self.addLayerTemplateToSVG = settings.BooleanSetting().getFromValue('Add Layer Template to SVG', self, True)
140 self.edgeWidth = settings.FloatSpin().getFromValue( 0.4, 'Edge Width (mm):', self, 4.0, 2.0 )
141 self.extraDecimalPlaces = settings.FloatSpin().getFromValue(0.0, 'Extra Decimal Places (float):', self, 3.0, 2.0)
142 self.importCoarseness = settings.FloatSpin().getFromValue( 0.5, 'Import Coarseness (ratio):', self, 2.0, 1.0 )
143 self.layerHeight = settings.FloatSpin().getFromValue( 0.1, 'Layer Height (mm):', self, 1.0, 0.4 )
144 self.layersFrom = settings.IntSpin().getFromValue( 0, 'Layers From (index):', self, 20, 0 )
145 self.layersTo = settings.IntSpin().getSingleIncrementFromValue( 0, 'Layers To (index):', self, 912345678, 912345678 )
146 self.meshTypeLabel = settings.LabelDisplay().getFromName('Mesh Type: ', self, )
147 importLatentStringVar = settings.LatentStringVar()
148 self.correctMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Correct Mesh', self, True )
149 self.unprovenMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Unproven Mesh', self, False )
150 self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser')
151 settings.LabelSeparator().getFromRepository(self)
152 self.executeTitle = 'Cleave'
155 "Cleave button has been clicked."
156 fileNames = skeinforge_polyfile.getFileOrDirectoryTypes(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
157 for fileName in fileNames:
158 writeOutput(fileName)
161 class CleaveSkein(object):
162 "A class to cleave a carving."
163 def getCarvedSVG( self, carving, fileName, repository ):
164 "Parse gnu triangulated surface text and store the cleaved gcode."
165 edgeWidth = repository.edgeWidth.value
166 layerHeight = repository.layerHeight.value
167 carving.setCarveLayerHeight( layerHeight )
168 importRadius = 0.5 * repository.importCoarseness.value * abs(edgeWidth)
169 carving.setCarveImportRadius(max(importRadius, 0.001 * layerHeight))
170 carving.setCarveIsCorrectMesh( repository.correctMesh.value )
171 loopLayers = carving.getCarveBoundaryLayers()
172 if len( loopLayers ) < 1:
173 print('Warning, there are no slices for the model, this could be because the model is too small for the Layer Height.')
175 layerThickness = carving.getCarveLayerHeight()
176 decimalPlacesCarried = euclidean.getDecimalPlacesCarried(repository.extraDecimalPlaces.value, layerHeight)
177 svgWriter = svg_writer.SVGWriter(
178 repository.addLayerTemplateToSVG.value,
179 carving.getCarveCornerMaximum(),
180 carving.getCarveCornerMinimum(),
181 decimalPlacesCarried,
182 carving.getCarveLayerHeight(),
184 truncatedRotatedBoundaryLayers = svg_writer.getTruncatedRotatedBoundaryLayers(loopLayers, repository)
185 return svgWriter.getReplacedSVGTemplate( fileName, truncatedRotatedBoundaryLayers, 'cleave', carving.getFabmetheusXML())
189 "Display the cleave dialog."
190 if len(sys.argv) > 1:
191 writeOutput(' '.join(sys.argv[1 :]))
193 settings.startMainLoopFromConstructor(getNewRepository())
195 if __name__ == "__main__":