From 97fa69491f010a5e4117a209a56822339b237c41 Mon Sep 17 00:00:00 2001 From: Ahmet Cem TURAN Date: Wed, 5 Sep 2012 15:13:50 +0300 Subject: [PATCH] Added skFrontend and fixed a few settings Fillet automatically defaults to half edge width clip is now closer, --- .idea/workspace.xml | 238 +++++---- alterations/end.gmc | 1 - config.py | 229 +++++++++ skFrontend.py | 474 ++++++++++++++++++ .../skeinforge_plugins/craft_plugins/clip.py | 2 +- .../craft_plugins/fillet.py | 7 +- .../skeinforge_plugins/craft_plugins/inset.py | 10 +- 7 files changed, 849 insertions(+), 112 deletions(-) create mode 100644 config.py create mode 100644 skFrontend.py diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 21bbfd3..07b21b9 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,10 +2,13 @@ - - + + - + + + + @@ -28,91 +31,73 @@ - - + + - + - + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - + + - + - - + + - + - - + + - + - - + + - + @@ -132,13 +117,6 @@ @@ -177,6 +162,7 @@ + @@ -206,7 +192,11 @@ - - + + + - + + @@ -369,20 +375,20 @@ - + - + + - + - + - @@ -439,90 +445,114 @@ - + - + + + - + - + + + - + - + - + - + + + - + - + + + - + - + + + - + - + + + - + - + + + - + - + - + - + + + - + - + + + - + - + + + - + - + - + - + + + - + - + + + - + - + diff --git a/alterations/end.gmc b/alterations/end.gmc index ac4707d..2a3b5f9 100644 --- a/alterations/end.gmc +++ b/alterations/end.gmc @@ -2,7 +2,6 @@ G91 ; Make coordinates relative G92 E0 ; reset Extruder counter G1 E-2 F900 ;Retract extuder 2mm at 900mm/min G1 Z2 F400 ;Move up tw mm (from current position because it is all relative now) -G1 Z2 F5000 ; Move Z another 2mm up G90 ; Use absolute coordinates again G1 X20 Y20 F3000.0 ;go to almost home M84 ;disable steppers so they dont get hot during idling... diff --git a/config.py b/config.py new file mode 100644 index 0000000..d142b4e --- /dev/null +++ b/config.py @@ -0,0 +1,229 @@ +# -*- coding: utf-8 -*- + +# config.py - v1.0 - 2012-08-31 +# config.py is imported by skFrontend.py +# +# German text strings translation thanks to Markus Hitter +import skFrontend +import os +#----------------------------------------------------- +''' two mandatory parameters to be adapted + to your Skeinforge configuration ''' +#----------------------------------------------------- + +# absolute path to Skeinforge's craft.py: +# Linux sample: "/opt/50_reprap_python_beanshell/skeinforge_application/skeinforge_plugins/craft.py" +# OS X sample: "/Applications/50_reprap_python_beanshell/skeinforge_application/skeinforge_plugins/craft.py" +# Windows: better to double backslashes +# Windows sample: "C:\\50_reprap_python_beanshell\\skeinforge_application\\skeinforge_plugins\\craft.py" + +print ("Current working dir : %s\\skeinforge_application\\skeinforge_plugins\\craft.py" % os.getcwdu()) +#skCraftPath = os.path.join(os.getcwd(), '\\skeinforge_application\\skeinforge_plugins\\craft.py') +skCraftPath = ("%s\\skeinforge_application\\skeinforge_plugins\\craft.py" % os.getcwdu()) +#"%s%s" os.getcwd(),%s (\\skeinforge_application\\) +#skCraftPath = "C:\\Users\\Ahmet\\Documents\\GitHub\\SFACT\\skeinforge_application\\skeinforge_plugins" + + +# absolute path to Skeinforge's extrusion profile used by skFrontend (no ending slash): +# Linux sample: "/home/userName/.skeinforge/profiles/extrusion/profileName" +# OS X sample: "/Users/userName/.skeinforge/profiles/extrusion/profileName" +# Windows: better to double backslashes +# Windows sample: "C:\\Users\\userName\\.skeinforge\\profiles\\extrusion\\profileName" +# Windows sample: "C:\\Documents and Settings\\userName\\.skeinforge\\profiles\\extrusion\\profileName" + +#skProfileDirectory = os.path.join(os.getcwd(), '\\sfact_profiles\\profiles\\\extrusion\\Default\\') +skProfileDirectory = ("%s\\sfact_profiles\\profiles\\extrusion\\Default" % os.getcwdu()) + + +#----------------------------------------------------- +''' controls configuration to be adapted to your usage ''' +#----------------------------------------------------- + +# default directory where to find STL files to be skeinforged: +STLFilesDefaultDirectory = "" + +# interface language +# set to "fr" for french, "en" for english, "de" for german +interfaceLanguage = "en" + +# carve plugin: list of layer thicknesses into drop-down menu: +layerHeightList = ("0.2", "0.25", "0.3", "0.4", "0.5") + +# carve plugin: list of edge widths into drop-down menu: +edgeWidthList = ("0.2", "0.25", "0.33", "0.4", "0.45", "0.5", "0.55", "0.6", "0.7",0.8) + +# speed plugin: feed rate min & max values into spinboxes: +# Skeinforge defaults to 2 & 50 +feedRateMinimumValue = 2 +feedRateMaximumValue = 50 + +# speed plugin: flow rate min & max values into spinboxes: +# Skeinforge defaults to 50 & 250 +flowRateMinimumValue = 1.0 +flowRateMaximumValue = 250.0 + +# multiply plugin: numbers of rows and columns into drop-down menus: +multiplyRowList = range (1,6) +multiplyColList = range (1,6) + +# skirt plugin: number of layers into drop-down menu: +skirtLayersList = range (21) + +#----------------------------------------------------- +''' text strings french version ''' +#----------------------------------------------------- + +if interfaceLanguage == "fr": + thicknessListLabel = "Hauteur des couches" + infillFeedRateListLabel = "Vitesse (mm/s)" + flowRateListLabel = "Débit" + InfillSolidityListLabel = "Remplissage (%)" + multiplyRowListLabel = "Nb de lignes" + multiplyColListLabel = "Nb de colonnes" + skirtLayersListLabel = "Entourage (nb couches)" + saveButtonLabel = "Enregistrer les modifications" + chooseFileButtonLabel = "Skeinforger quoi ?" + noFileSelectedText = "Pas de fichier choisi" + runSkeinforgeButtonLabel = "Générer le G-code" + quitButtonLabel = "Quitter" + titleErrorMsgBox = "Erreur" + unASCIIerrorMessage = "Attention, pas de caractère non-ASCII dans le chemin et le nom du fichier !" + unSavedModificationsDialogTitle = "Modifications non enregistrées" + runSkUnSavedModificationsMsg = "Des modifications ne sont pas enregistrées, lancer Skeinforge tout de même ?" + quitAppUnSavedModificationsMsg = "Des modifications ne sont pas enregistrées, quitter skFrontend tout de même ?" + noExtrusionProfileErrorMsg = "Le profil d’extrusion déclaré dans config.py n’existe pas… !" + +#----------------------------------------------------- +''' text strings english version ''' +#----------------------------------------------------- + +if interfaceLanguage == "en": + thicknessListLabel = "Layer Height" + edgeWidthListLabel = "Edge Width" + infillFeedRateListLabel = "Infill Speed (mm/sec)" + perimeterFeedRateListLabel = "Edge Speed (mm/sec)" + InfillSolidityListLabel = "Infill Solidity (%)" + EdgeShellsListLabel = "Number of Shells " + BottomsListLabel = "Number of Tops/bottoms " + multiplyRowListLabel = "Lines Nb" + multiplyColListLabel = "Columns Nb" + skirtLayersListLabel = "Number of Skirt Layers" + skirtRingsListLabel = "Number of Skirt Rings" + saveButtonLabel = "Save Modifications" + chooseFileButtonLabel = "What to Skeinforge?" + noFileSelectedText = "No File Selected" + runSkeinforgeButtonLabel = " >> G-code via Python" + runPyPyButtonLabel = " >> G-code via PyPy" + quitButtonLabel = "Quit" + titleErrorMsgBox = "Error" + unASCIIerrorMessage = "Warning, no non-ASCII symbol into path or file name!" + unSavedModificationsDialogTitle = "Unsaved Modifications" + runSkUnSavedModificationsMsg = "Some modifications aren't saved,\nrun Skeinforge anyway?" + quitAppUnSavedModificationsMsg = "Some modifications aren't saved,\nquit skFrontend anyway?" + noExtrusionProfileErrorMsg = "Extrusion profile set into config.py don't exists… !" + + +#----------------------------------------------------- +''' text strings german version ''' +#----------------------------------------------------- + +if interfaceLanguage == "de": + thicknessListLabel = "Layerdicke" + infillFeedRateListLabel = "Geschwindigkeit" + flowRateListLabel = "Materialfluss" + InfillSolidityListLabel = "Füllgrad (%)" + multiplyRowListLabel = "Zeilen" + multiplyColListLabel = "Spalten" + skirtLayersListLabel = "Vorhang-Schichten" + saveButtonLabel = "Änderungen speichern" + chooseFileButtonLabel = "Bauteil laden" + noFileSelectedText = "Keine Datei" + runSkeinforgeButtonLabel = "G-code generieren" + quitButtonLabel = "Beenden" + titleErrorMsgBox = "Fehler" + unASCIIerrorMessage = "Warnung, nicht-ASCII-Zeichen sind im Pfad nicht erlaubt." + unSavedModificationsDialogTitle = "Ungespeicherte Änderungen" + runSkUnSavedModificationsMsg = "Änderungen wurden noch nicht gespeichert,\nSkeinforge trotzdem starten?" + quitAppUnSavedModificationsMsg = "Änderungen wurden noch nicht gespeichert,\nskFrontend trotzdem beenden?" + noExtrusionProfileErrorMsg = "Das in config.py deklarierte Profil existiert nicht." + +#----------------------------------------------------- +''' skeinforge parameters to be only modified if + Skeinforge changes (names of files, search strings values…) + Currently Skeinforge 50 ''' +#----------------------------------------------------- + +# name of Skeinforge's extrusion profile setup file: +skExtrusionFile = "extrusion.csv" +# string to search to identify profile's name: +skExtrusionProfileSearchString = "Profile Selection:" + +# name of carve plugin configuration file: +skCarveFile = "carve.csv" +# text to be searched into "skCarveFile" to identify layer height: +skCarveSearchString = "Layer Height (mm):" + +# idem for others plugins files: +skSpeedFile = "speed.csv" +skFeedRateSearchString = "Feed Rate (mm/s):" +skFlowRateSearchString = "Flow Rate Setting (float):" + +skFillFile = "fill.csv" +skInfillSoliditySearchString = "Infill Solidity (ratio):" + +skMultiplyFile = "multiply.csv" +skMultiplyRowSearchString = "Number of Rows (integer):" +skMultiplyColSearchString = "Number of Columns (integer):" + +skSkirtFile = "skirt.csv" +skSkirtLayersSearchString = "Layers To (index):" +skSkirtActivateSearchString = "Activate Skirt" + +#----------------------------------------------------- +''' default values below are only used if no valid values + are found into plugins configuration files ''' +#----------------------------------------------------- + +# default layer height for carve plugin: +skDefaultLayerHeight = "0.4" +# default edge Width for carve plugin: +skDefaultEdgeWidth = "0.45" +# default feed & flow rates for speed plugin: +skDefaultFeedRate = "16.0" +skDefaultFlowRate = "16.0" + +# default infill solidity for fill plugin: +skDefaultInfillSolidity = "0.35" + +# default columns & rows numbers for multiply plugin: +skDefaultMultiplyCol = 1 +skDefaultMultiplyRow = 1 + +# default layers number for skirt plugin: +skDefaultSkirtLayers = 1 + +#----------------------------------------------------- +''' files types to be opened ''' +#----------------------------------------------------- + +openableFilesTypes = [("Stereolithography", ".stl"), ("GNU Triangulated Surface", ".gts"), ("Wavefront 3D Object", ".obj"), ("Scalable Vector Graphics", ".svg"), ("Extensible Markup Language", ".xml")] + +#----------------------------------------------------- +''' display configuration ''' +#----------------------------------------------------- + +windowWidth = "380" +windowHeight= "600" +frameLeftMargin = 25 +frameTopMargin = 15 +frameHeight = 50 +frameWidth = 200 +frameTopOffset = 60 +frameRightOffset = 130 +labelMarginLeft = 2 +labelColor = "blue" +fileNameColor = "#EC9808" +menuMarginTop = 20 +menuWidth = 8 + + \ No newline at end of file diff --git a/skFrontend.py b/skFrontend.py new file mode 100644 index 0000000..df0e90c --- /dev/null +++ b/skFrontend.py @@ -0,0 +1,474 @@ +# -*- coding: utf-8 -*- + +# skFrontend.py - v1.0 - 2012-08-31 +# +# A Skeinforge Frontend for 3D Printing +# Copyright 2012 François Delègue +# +# http://reprapide.fr/skfrontend-un-frontal-pour-skeinforge +# http://reprapide.fr/skfrontend-a-skeinforge-frontend +# +# skFrontend.py can't run without config.py into it's directory +# +# This (so little) program is (very) free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details: . + + +import Tkinter as tk, tkFileDialog, tkMessageBox, os, re, sys +import config as c +from fabmetheus_utilities import settings +import os + +class SkFrontend (tk.Tk): + def __init__(self, *args, **kwargs): + tk.Tk.__init__(self, *args, **kwargs) + self.geometry (c.windowWidth + "x" + c.windowHeight) + self.protocol ('WM_DELETE_WINDOW', self.quitApplication) + self.lastFrametopOffset = 111 + # we quit if no valid path to extrusion profile + if not (os.path.exists (c.skProfileDirectory)): + tkMessageBox.showerror (c.titleErrorMsgBox, c.noExtrusionProfileErrorMsg) + self.destroy () + + self.resizable (width=False, height=False) + # finding used profile name + (self.path, self.profileName) = os.path.split (c.skProfileDirectory) + self.title ("skFrontend :: " + self.profileName) + + #----------------------------------------------------- + ''' parenthesis backslash into search expressions ''' + #----------------------------------------------------- + self.skCarveSearchString = self.backslash (c.skCarveSearchString) + self.skFeedRateSearchString = self.backslash (c.skFeedRateSearchString) + self.skFlowRateSearchString = self.backslash (c.skFlowRateSearchString) + self.skInfillSoliditySearchString = self.backslash (c.skInfillSoliditySearchString) + self.skMultiplyRowSearchString = self.backslash (c.skMultiplyRowSearchString) + self.skMultiplyColSearchString = self.backslash (c.skMultiplyColSearchString) + self.skSkirtLayersSearchString = self.backslash (c.skSkirtLayersSearchString) + self.skSkirtActivateSearchString = self.backslash (c.skSkirtActivateSearchString) + self.skExtrusionProfileSearchString = self.backslash (c.skExtrusionProfileSearchString) + + #----------------------------------------------------- + ''' frame containing layer thickness menu ''' + #----------------------------------------------------- +# settings.LabelDisplay().getFromName('- Extrusion Resolution settings -', self ) +# settings.LabelSeparator().getFromRepository(self) + self.frame1=tk.Frame (self) + self.frame1.pack () + self.frame1.place (x=c.frameLeftMargin, y=c.frameTopMargin, height=c.frameHeight, width=c.frameWidth) + self.label=tk.Label (self.frame1, text=c.thicknessListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + self.layerHeight=tk.StringVar (self) + self.layerHeight.set (self.getSkSetting (c.skCarveFile, self.skCarveSearchString, c.skDefaultLayerHeight)) + self.layerHeights=tk.OptionMenu (self.frame1, self.layerHeight, *c.layerHeightList, command=self.refreshOptionMenu) + self.layerHeights.config (width=c.menuWidth) + self.layerHeights.pack () + self.layerHeights.place (y=c.menuMarginTop) + + self.firstLayerHeight = self.layerHeight.get () + self.newLayerHeight = self.layerHeight.get () + #----------------------------------------------------- + ''' frame containing edge width menu ''' + #----------------------------------------------------- + self.frame1=tk.Frame (self) + self.frame1.pack () + self.newFrametopoffset = c.frameTopOffset*0 + self.frame1.place (x=c.frameLeftMargin + c.frameRightOffset, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight, width=c.frameWidth) + print(self.newFrametopoffset) + self.label=tk.Label (self.frame1, text=c.edgeWidthListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + self.edgeWidth=tk.StringVar (self) + self.edgeWidth.set (self.getSkSetting (c.skCarveFile, self.skCarveSearchString, c.skDefaultEdgeWidth)) + self.edgeWidths=tk.OptionMenu (self.frame1, self.edgeWidth, *c.edgeWidthList, command=self.refreshOptionMenu) + self.edgeWidths.config (width=c.menuWidth) + self.edgeWidths.pack () + self.edgeWidths.place (y=c.menuMarginTop) + + self.firstEdgewidth = self.edgeWidth.get () + self.newEdgeWidth = self.edgeWidth.get () + + #----------------------------------------------------- + ''' frame containing feed rate menu ''' + #----------------------------------------------------- + self.frame2=tk.Frame (self) + self.frame2.pack () + oldFrametopoffset = self.newFrametopoffset + self.newFrametopoffset += c.frameTopOffset + self.frame2.place (x=c.frameLeftMargin, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight, width=c.frameWidth) + print(self.newFrametopoffset) + self.label=tk.Label (self.frame2, text=c.infillFeedRateListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + # validatecommand ==> error!… + # self.feedRate=tk.Spinbox (self.frame2, from_=6, to=100, command=self.refreshSpinBox, validate=tk.ALL, validatecommand=self.refreshSpinBox) ==> error!… + # ==> no modificationButtonState into spinboxes when content is modified via keyboard + self.feedRate=tk.Spinbox (self.frame2, from_=c.feedRateMinimumValue, to=c.feedRateMaximumValue, command=self.refreshSpinBox) + self.feedRate.delete (0,"end") + self.feedRate.insert (0, self.getSkSetting (c.skSpeedFile, self.skFeedRateSearchString, c.skDefaultFeedRate)) + self.feedRate.config (width=c.menuWidth) + self.feedRate.pack () + self.feedRate.place (x=c.labelMarginLeft, y=c.menuMarginTop) + + self.firstFeedRate = self.feedRate.get () + self.newFeedRate = self.feedRate.get () + + #----------------------------------------------------- + + ''' frame containing infill solidity menu ''' + #----------------------------------------------------- + self.frame4=tk.Frame (self) + self.frame4.pack () + self.newFrametopoffset += c.frameTopOffset + self.frame4.place (x=c.frameLeftMargin, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight, width=c.frameWidth) + print(self.newFrametopoffset) + self.label=tk.Label (self.frame4, text=c.InfillSolidityListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + self.infillSolidity=tk.Spinbox (self.frame4, from_=4, to=100, increment=1, command=self.refreshSpinBox) + self.infillSolidity.delete (0,"end") + self.infillSolidity.insert (0, self.ratioToPercentage (self.getSkSetting (c.skFillFile, self.skInfillSoliditySearchString, c.skDefaultInfillSolidity))) + self.infillSolidity.config (width=c.menuWidth) + self.infillSolidity.pack () + self.infillSolidity.place (x=c.labelMarginLeft, y=c.menuMarginTop) + + self.firstInfillSolidity = self.infillSolidity.get () + self.newInfillSolidity = self.infillSolidity.get () + + #----------------------------------------------------- + ''' frame containing multiply rows menu ''' + #----------------------------------------------------- + self.frame5=tk.Frame (self) + self.frame5.pack () + self.newFrametopoffset += c.frameTopOffset + self.frame5.place (x=c.frameLeftMargin, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight, width=c.frameWidth) + + self.label=tk.Label (self.frame5, text=c.multiplyRowListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + self.multiplyRow=tk.StringVar (self) + self.multiplyRow.set (self.getSkSetting (c.skMultiplyFile, self.skMultiplyRowSearchString, c.skDefaultMultiplyRow)) + self.menu=tk.OptionMenu (self.frame5, self.multiplyRow, *c.multiplyRowList, command=self.refreshOptionMenu) + self.menu.config (width=c.menuWidth) + self.menu.pack () + self.menu.place (y=c.menuMarginTop) + + self.firstMultiplyRow = self.multiplyRow.get () + self.newMultiplyRow = self.multiplyRow.get () + + #----------------------------------------------------- + ''' frame containing multiply columns menu ''' + #----------------------------------------------------- + self.frame6=tk.Frame (self) + self.frame6.pack () + self.newFrametopoffset += c.frameTopOffset*0 + self.frame6.place (x=c.frameLeftMargin + c.frameRightOffset, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight, width=c.frameWidth) + + self.label=tk.Label (self.frame6, text=c.multiplyColListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + self.multiplyCol = tk.StringVar (self) + self.multiplyCol.set (self.getSkSetting (c.skMultiplyFile, self.skMultiplyColSearchString, c.skDefaultMultiplyCol)) + self.menu = tk.OptionMenu (self.frame6, self.multiplyCol, *c.multiplyColList, command=self.refreshOptionMenu) + self.menu.config (width=c.menuWidth) + self.menu.pack () + self.menu.place (y=c.menuMarginTop) + + self.firstMultiplyCol = self.multiplyCol.get () + self.newMultiplyCol = self.multiplyCol.get () + + #----------------------------------------------------- + ''' frame containing skirt menu ''' + #----------------------------------------------------- + self.frame7=tk.Frame (self) + self.frame7.pack () + self.newFrametopoffset += c.frameTopOffset + self.frame7.place (x=c.frameLeftMargin, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight, width=c.frameWidth) + + self.label=tk.Label (self.frame7, text=c.skirtLayersListLabel, fg=c.labelColor) + self.label.pack () + self.label.place (x=c.labelMarginLeft) + + self.skirtLayers = tk.StringVar (self) + self.skirtLayers.set (self.getSkSetting (c.skSkirtFile, self.skSkirtLayersSearchString, c.skDefaultSkirtLayers)) + self.menu = tk.OptionMenu (self.frame7, self.skirtLayers, *c.skirtLayersList, command=self.refreshOptionMenu) + self.menu.config (width=c.menuWidth) + self.menu.pack () + self.menu.place (y=c.menuMarginTop) + + self.firstSkirtLayers = self.skirtLayers.get () + self.newSkirtLayers = self.skirtLayers.get () + + #----------------------------------------------------- + ''' last frame of the window: buttons + (plenty of hard-coded controls display values… ) ''' + #----------------------------------------------------- + self.frame8=tk.Frame (self) + self.frame8.pack () + self.newFrametopoffset += c.frameTopOffset + 35 # extra separation + self.frame8.place (x=c.frameLeftMargin, y=c.frameTopMargin + self.newFrametopoffset, height=c.frameHeight+200, width=c.frameWidth + 300) + self.lastFrametopOffset = self.newFrametopoffset + self.saveModificationsButton = tk.Button (self.frame8, text=c.saveButtonLabel, command=self.saveChanges, state=tk.DISABLED) + self.modificationButtonState = "DISABLED" + self.saveModificationsButton.pack () + self.saveModificationsButton.place (x=c.labelMarginLeft) + + self.chooseFileButton = tk.Button (self.frame8, text=c.chooseFileButtonLabel, command=self.chooseFileDialog) + self.chooseFileButton.pack () + self.chooseFileButton.place (x=c.labelMarginLeft, y=40) + + self.fileToSkName = tk.StringVar() + self.fileToSk = tk.Label (self.frame8, fg=c.fileNameColor, textvariable=self.fileToSkName) + self.fileToSkName.set (c.noFileSelectedText) + self.fileToSk.pack () + self.fileToSk.place (x=c.labelMarginLeft+155, y=43) + + self.runSkeinforgeButton = tk.Button (self.frame8, text=c.runSkeinforgeButtonLabel, state=tk.DISABLED, command=self.runSkeinforge) + self.runSkeinforgeButton.pack() + self.runSkeinforgeButton.place (x=c.labelMarginLeft, y=80) + + self.quitButton = tk.Button (self.frame8, text=c.quitButtonLabel, command=self.quitApplication) + self.quitButton.pack () + self.quitButton.place (x=c.labelMarginLeft + 260, y=80) + + #----------------------------------------------------- + ''' compiling regexs ''' + #----------------------------------------------------- + self.searchNumberRegex = "\\t([-+]?[0-9]*\\.?,?[0-9]+)" + self.searchTrueFalseRegex = "\\t(True|False)" + self.searchTextStringRegex = "\\t(.+)" + self.layerHeightRE = re.compile (self.skCarveSearchString + self.searchNumberRegex) + self.feedRateRE = re.compile (self.skFeedRateSearchString + self.searchNumberRegex) + self.flowRateRE = re.compile (self.skFlowRateSearchString + self.searchNumberRegex) + self.infillSolidityRE = re.compile (self.skInfillSoliditySearchString + self.searchNumberRegex) + self.multiplyRowRE = re.compile (self.skMultiplyRowSearchString + self.searchNumberRegex) + self.multiplyColRE = re.compile (self.skMultiplyColSearchString + self.searchNumberRegex) + self.skirtLayersRE = re.compile (self.skSkirtLayersSearchString + self.searchNumberRegex) + self.skirtActivateRE = re.compile (self.skSkirtActivateSearchString + self.searchTrueFalseRegex) + self.extrusionProfileRE = re.compile (self.skExtrusionProfileSearchString + self.searchTextStringRegex) + + #----------------------------------------------------- + ''' set Skeinforge's extrusion profile name ''' + #----------------------------------------------------- + self.setSkeinforgeExtrusionProfile () + + + # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + ''' end of application __init__ ''' + # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + + #----------------------------------------------------- + ''' tracking parameters functions ''' + #----------------------------------------------------- + def refreshOptionMenu (self, unusedButNecessary): + self.newLayerHeight = self.layerHeight.get () + self.newEdgeWidth = self.edgeWidth.get () + self.newMultiplyRow = self.multiplyRow.get () + self.newMultiplyCol = self.multiplyCol.get () + self.newSkirtLayers = self.skirtLayers.get () + self.setSaveModificationButtonState () + + def refreshSpinBox (self): + self.newFeedRate = self.feedRate.get () + self.newFlowRate = self.flowRate.get () + self.newInfillSolidity = self.infillSolidity.get () + self.setSaveModificationButtonState () + return True + + def setSaveModificationButtonState (self): + if ( + self.firstLayerHeight != self.newLayerHeight + or self.firstEdgewidth != self.newEdgeWidth + or self.firstFeedRate != self.newFeedRate + or self.firstFlowRate != self.newFlowRate + or self.firstInfillSolidity != self.newInfillSolidity + or self.firstMultiplyRow != self.newMultiplyRow + or self.firstMultiplyCol != self.newMultiplyCol + or self.firstSkirtLayers != self.newSkirtLayers + ): + self.saveModificationsButton.config (state=tk.NORMAL) + self.modificationButtonState = "NORMAL" + else: + self.saveModificationsButton.config (state=tk.DISABLED) + self.modificationButtonState = "DISABLED" + + #----------------------------------------------------- + ''' getting an sk plugin parameter ''' + #----------------------------------------------------- + def getSkSetting (self, fileName, searchString, defaultReturnValue): + try: + returnValue = defaultReturnValue + p = re.compile (searchString) + file = open (os.path.join (c.skProfileDirectory, fileName), "r") + lines = file.readlines () + for line in lines: + if p.match (line): + ligne = line.split ('\t') + returnValue = ligne[1].rstrip('\n') + break + file.close () + return returnValue + except Exception, err: + tkMessageBox.showerror (c.titleErrorMsgBox, "%s " % str(err)) + return returnValue + + #----------------------------------------------------- + ''' pharenthesis backslash for regex search ''' + #----------------------------------------------------- + def backslash (self, str): + str = re.sub (r'\(', '\\(', str) + str = re.sub (r'\)', '\\)', str) + return str + + #----------------------------------------------------- + ''' transforms ratio into percentage (from 0.3 to 30 for ex.)''' + #----------------------------------------------------- + def ratioToPercentage (self, n): + return int (float (n) * 100) + + #----------------------------------------------------- + ''' transforms percentage into ratio(from 30 to 0.3 for ex.) ''' + #----------------------------------------------------- + def percentageToRatio (self, n): + return str (float (n) / 100) + + #----------------------------------------------------- + ''' choose file to be skeinforged dialog ''' + #----------------------------------------------------- + def chooseFileDialog (self): + self.fileToSkeinforge = tkFileDialog.askopenfilename (initialdir=c.STLFilesDefaultDirectory, filetypes=c.openableFilesTypes) + if self.fileToSkeinforge: + self.fileToSkeinforgeName = self.fileToSkeinforge.rsplit ("/", 1) + self.fileToSkName.set ("") + self.fileToSkName.set (self.fileToSkeinforgeName[1]) + self.runSkeinforgeButton.config (state=tk.NORMAL) + + #----------------------------------------------------- + ''' run Skeinforge ''' + #----------------------------------------------------- + def runSkeinforge (self): + try: + if self.modificationButtonState == "NORMAL": + if tkMessageBox.askquestion (title=c.unSavedModificationsDialogTitle, message=c.runSkUnSavedModificationsMsg) == "no": + return + #print "python " + c.skCraftPath + " " + self.fileToSkeinforge + os.system ("python " + c.skCraftPath + " " + self.fileToSkeinforge) + except Exception, err: + # the more usual error: + tkMessageBox.showerror (c.titleErrorMsgBox, c.unASCIIerrorMessage) + # also possible, less explicit but the real error: + # tkMessageBox.showerror (c.titleErrorMsgBox, "%s " % str(err)) + return 1 + + #----------------------------------------------------- + ''' ask or not file save function for profiles files ''' + #----------------------------------------------------- + def saveChanges (self): + # carve.csv file: layer height + if self.firstLayerHeight != self.newLayerHeight: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skCarveFile), self.layerHeightRE, self.newLayerHeight) + self.firstLayerHeight = self.newLayerHeight + + if self.firstEdgeWidth != self.newEdgeWidth: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skCarveFile), self.edgeWidthRE, self.newEdgeWidth) + self.firstEdgewidth = self.newEdgeWidth + # speed.csv file: feed rate + self.newFeedRate = self.feedRate.get () + if self.firstFeedRate != self.newFeedRate: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skSpeedFile), self.feedRateRE, self.newFeedRate) + self.firstFeedRate = self.newFeedRate + + # speed.csv file: flow rate + self.newFlowRate = self.flowRate.get () + if self.firstFlowRate != self.newFlowRate: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skSpeedFile), self.flowRateRE, self.newFlowRate) + self.firstFlowRate = self.newFlowRate + + # fill.csv file: infill solidity + self.newInfillSolidity = self.infillSolidity.get () + if self.firstInfillSolidity != self.newInfillSolidity: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skFillFile), self.infillSolidityRE, self.percentageToRatio (self.newInfillSolidity)) + self.firstInfillSolidity = self.newInfillSolidity + + # multiply.csv file: number of rows + if self.firstMultiplyRow != self.newMultiplyRow: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skMultiplyFile), self.multiplyRowRE, self.newMultiplyRow) + self.firstMultiplyRow = self.newMultiplyRow + + # multiply.csv file: number of columns + if self.firstMultiplyCol != self.newMultiplyCol: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skMultiplyFile), self.multiplyColRE, self.newMultiplyCol) + self.firstMultiplyCol = self.newMultiplyCol + + # skirt.csv file: layers to, then activate skirt or not + if self.firstSkirtLayers != self.newSkirtLayers: + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skSkirtFile), self.skirtLayersRE, self.newSkirtLayers) + self.firstSkirtLayers = self.newSkirtLayers + if self.newSkirtLayers == "0": + boolean = "False" + else: + boolean = "True" + self.saveIntoFile (os.path.join (c.skProfileDirectory, c.skSkirtFile), self.skirtActivateRE, boolean) + + self.saveModificationsButton.config (state=tk.DISABLED) + self.modificationButtonState = "DISABLED" + + #----------------------------------------------------- + ''' save changes into file ''' + #----------------------------------------------------- + def saveIntoFile (self, file, compiledRE, newValue): + try: + with open (file, "r") as source: + lines = source.readlines () + with open (file, "w") as source: + for line in lines: + matchObject = compiledRE.match (line) + if matchObject: + source.write (re.sub (matchObject.group (1), newValue, line)) + else: + source.write (line) + except Exception, err: + tkMessageBox.showerror (c.titleErrorMsgBox, "%s " % str(err)) + return 1 + + #----------------------------------------------------- + ''' quit ''' + #----------------------------------------------------- + def quitApplication (self): + if self.modificationButtonState == "NORMAL": + if tkMessageBox.askquestion (title=c.unSavedModificationsDialogTitle, message=c.quitAppUnSavedModificationsMsg) == "no": + return + print "ciao!" + self.destroy () + + #----------------------------------------------------- + ''' tell Skeinforge to use profile set into config.py + (end of path into skProfileDirectory var) ''' + #----------------------------------------------------- + def setSkeinforgeExtrusionProfile (self): + # finding Skeinforge's profiles types directory -not extrusion profiles directory + (skProfilesTypePath, unused) = os.path.split (self.path) + self.saveIntoFile (os.path.join (skProfilesTypePath, c.skExtrusionFile), self.extrusionProfileRE, self.profileName) + +#----------------------------------------------------- + +if __name__ == "__main__": + app = SkFrontend () + app.mainloop () + + \ No newline at end of file diff --git a/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py b/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py index 565e895..8c33ef1 100644 --- a/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py +++ b/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py @@ -259,7 +259,7 @@ def parseInitialization(self): self.distanceFeedRate.addTagBracketedLine('clipOverEdgeWidth', self.repository.clipOverEdgeWidth.value) self.edgeWidth = float(splitLine[1]) absoluteEdgeWidth = abs(self.edgeWidth) - self.clipLength = self.repository.clipOverEdgeWidth.value* self.edgeWidth * (euclidean.globalQuarterPi/2) + self.clipLength = self.repository.clipOverEdgeWidth.value* self.edgeWidth * (euclidean.globalQuarterPi/4) self.connectingStepLength = 0.5 * absoluteEdgeWidth self.layerPixelWidth = 0.34321 * absoluteEdgeWidth self.maximumConnectionDistance = self.repository.maximumConnectionDistanceOverEdgeWidth.value * absoluteEdgeWidth diff --git a/skeinforge_application/skeinforge_plugins/craft_plugins/fillet.py b/skeinforge_application/skeinforge_plugins/craft_plugins/fillet.py index d5af827..ebf6a17 100644 --- a/skeinforge_application/skeinforge_plugins/craft_plugins/fillet.py +++ b/skeinforge_application/skeinforge_plugins/craft_plugins/fillet.py @@ -208,11 +208,13 @@ def parseInitialization( self, repository ): elif firstWord == '(': edgeWidth = abs(float(splitLine[1])) self.curveSection = 0.7 * edgeWidth - self.filletRadius = edgeWidth * repository.filletRadiusOverEdgeWidth.value + self.filletRadius = edgeWidth/2 self.minimumRadius = 0.1 * edgeWidth self.reversalSlowdownDistance = edgeWidth * repository.reversalSlowdownDistanceOverEdgeWidth.value self.distanceFeedRate.addLine(line) + + def parseLine(self, line): "Parse a gcode line and add it to the bevel gcode." self.shouldAddLine = True @@ -370,7 +372,7 @@ def __init__(self): self.arcSegment = settings.Radio().getFromRadio( filletLatentStringVar, 'Arc Segment', self, False ) self.bevel = settings.Radio().getFromRadio( filletLatentStringVar, 'Bevel', self, True ) self.cornerFeedRateMultiplier = settings.FloatSpin().getFromValue(0.8, 'Corner Feed Rate Multiplier (ratio):', self, 1.2, 1.0) - self.filletRadiusOverEdgeWidth = settings.FloatSpin().getFromValue( 0.25, 'Fillet Radius over Perimeter Width (ratio):', self, 0.65, 0.35 ) +# self.filletRadiusOverEdgeWidth = settings.FloatSpin().getFromValue( 0.25, 'Fillet Radius over Perimeter Width (ratio):', self, 0.65, 0.35 ) self.reversalSlowdownDistanceOverEdgeWidth = settings.FloatSpin().getFromValue( 0.3, 'Reversal Slowdown Distance over Perimeter Width (ratio):', self, 0.7, 0.5 ) self.useIntermediateFeedRateInCorners = settings.BooleanSetting().getFromValue('Use Intermediate Feed Rate in Corners', self, True ) self.executeTitle = 'Fillet' @@ -382,6 +384,7 @@ def execute(self): writeOutput(fileName) + def main(): "Display the fillet dialog." if len(sys.argv) > 1: diff --git a/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py b/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py index 030537b..e1faa6c 100644 --- a/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py +++ b/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py @@ -301,7 +301,7 @@ def __init__(self): self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Inset') self.addCustomCodeForTemperatureReading = settings.BooleanSetting().getFromValue('Add Custom Code for Temperature Reading', self, True) self.infillInDirectionOfBridge = settings.BooleanSetting().getFromValue('Infill in Direction of Bridge', self, True) - self.infillWidthOverThickness = settings.FloatSpin().getFromValue(1.3, 'Infill Width over Thickness (ratio):', self, 1.7, 1.5) +# self.infillWidthOverThickness = settings.FloatSpin().getFromValue(1.3, 'Infill Width over Thickness (ratio):', self, 1.7, 1.5) self.bridgeWidthMultiplier = settings.FloatSpin().getFromValue( 0.7, 'Bridge Width Multiplier (ratio):', self, 2.0, 1.0 ) self.nozzleDiameter = settings.FloatSpin().getFromValue( 0.1, 'Nozzle Diameter(mm):', self, 1.0, 0.50 ) self.loopOrderChoice = settings.MenuButtonDisplay().getFromName('In case of Conflict Solve:', self ) @@ -402,7 +402,7 @@ def addInset(self, loopLayer): alreadyFilledArounds = [] extrudateLoops = intercircle.getInsetLoopsFromLoops(loopLayer.loops, self.halfEdgeWidth) if self.repository.infillInDirectionOfBridge.value: - self.halfBridgeWidth = self.repository.bridgeWidthMultiplier.value * self.halfEdgeWidth #* (self.nozzleXsection / self.extrusionXsection) + self.halfBridgeWidth = self.repository.bridgeWidthMultiplier.value * self.halfEdgeWidth bridgeRotation = getBridgeDirection(self.belowLoops, extrudateLoops, self.halfBridgeWidth ) if bridgeRotation != None: self.distanceFeedRate.addTagBracketedLine('bridgeRotation', bridgeRotation) @@ -436,17 +436,19 @@ def parseInitialization(self): return elif firstWord == '(': self.layerHeight = float(splitLine[1]) - self.infillWidth = self.repository.infillWidthOverThickness.value * self.layerHeight - self.distanceFeedRate.addTagRoundedLine('infillWidth', self.infillWidth) +# self.infillWidth = self.repository.infillWidthOverThickness.value * self.layerHeight #moved dow so it is defined by edgeWidth +# self.distanceFeedRate.addTagRoundedLine('infillWidth', self.infillWidth)#moved dow so it is defined by edgeWidth self.distanceFeedRate.addTagRoundedLine('volumeFraction', self.repository.volumeFraction.value) elif firstWord == '(': self.edgeWidth = float(splitLine[1]) + self.infillWidth = self.edgeWidth self.halfEdgeWidth = 0.5 * self.edgeWidth self.overlapRemovalWidth = self.edgeWidth * self.repository.overlapRemovalWidthOverEdgeWidth.value self.distanceFeedRate.addTagBracketedLine('nozzleDiameter', self.repository.nozzleDiameter.value ) self.nozzleXsection = (self.repository.nozzleDiameter.value/2) ** 2 * math.pi self.extrusionXsection = ((self.edgeWidth + self.layerHeight)/4) ** 2 * math.pi self.distanceFeedRate.addTagBracketedLine('nozzleXsection', self.nozzleXsection) + self.distanceFeedRate.addTagRoundedLine('infillWidth', self.infillWidth) self.distanceFeedRate.addLine(line) def parseLine(self, line):