├── .gitignore ├── DefeaturingCMD.py ├── DefeaturingFeature.py ├── DefeaturingTools-a.py ├── DefeaturingTools.py ├── DefeaturingTools.ui ├── FuzzyTools.py ├── Init.py ├── InitGui.py ├── README.md ├── Resources ├── FreeCAD-addon-manager-available.svg ├── Made-with-Python_.svg ├── icons │ ├── Defeaturing-icon.svg │ ├── DefeaturingParametric.svg │ ├── Freecad.svg │ ├── FuzzyCommon.svg │ ├── FuzzyCut.svg │ ├── FuzzyUnion.svg │ ├── Path-SelectLoop.svg │ ├── RefineShapeFeature.svg │ ├── centering-w.svg │ ├── defeaturingTools.svg │ └── error.svg └── made-with-python.svg ├── dft_locator.py └── package.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files, back, bat 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | *.bak 17 | *.bat 18 | 19 | # Windows shortcuts 20 | *.lnk 21 | 22 | # Python executable 23 | *.pyc 24 | 25 | # ========================= 26 | # Operating System Files 27 | # ========================= 28 | 29 | # OSX 30 | # ========================= 31 | 32 | .DS_Store 33 | .AppleDouble 34 | .LSOverride 35 | 36 | # Thumbnails 37 | ._* 38 | 39 | # Files that might appear in the root of a volume 40 | .DocumentRevisions-V100 41 | .fseventsd 42 | .Spotlight-V100 43 | .TemporaryItems 44 | .Trashes 45 | .VolumeIcon.icns 46 | 47 | # Directories potentially created on remote AFP share 48 | .AppleDB 49 | .AppleDesktop 50 | Network Trash Folder 51 | Temporary Items 52 | .apdisk 53 | -------------------------------------------------------------------------------- /DefeaturingCMD.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #**************************************************************************** 3 | #* * 4 | #* Kicad STEPUP (TM) (3D kicad board and models to STEP) for FreeCAD * 5 | #* 3D exporter for FreeCAD * 6 | #* Kicad STEPUP TOOLS (TM) (3D kicad board and models to STEP) for FreeCAD * 7 | #* Copyright (c) 2015 * 8 | #* Maurice easyw@katamail.com * 9 | #* * 10 | #* Kicad STEPUP (TM) is a TradeMark and cannot be freely usable * 11 | #* * 12 | 13 | import FreeCAD, FreeCADGui, Part, os 14 | import os, sys, tempfile 15 | import FreeCAD, FreeCADGui 16 | from PySide import QtGui, QtCore 17 | import dft_locator 18 | 19 | 20 | try: 21 | from PathScripts.PathUtils import horizontalEdgeLoop 22 | from PathScripts.PathUtils import horizontalFaceLoop 23 | from PathScripts.PathUtils import loopdetect 24 | except: 25 | FreeCAD.Console.PrintError('Path WB not found\n') 26 | 27 | reload_Gui=False#True 28 | 29 | def reload_lib(lib): 30 | if (sys.version_info > (3, 0)): 31 | import importlib 32 | importlib.reload(lib) 33 | else: 34 | reload (lib) 35 | 36 | DefeaturingWBpath = os.path.dirname(dft_locator.__file__) 37 | DefeaturingWB_icons_path = os.path.join( DefeaturingWBpath, 'Resources', 'icons') 38 | 39 | class DefeatShapeFeature: 40 | def IsActive(self): 41 | #print ('isactive') 42 | if hasattr(Part, "OCC_VERSION"): 43 | OCCMV = Part.OCC_VERSION.split('.')[0] 44 | OCCmV = Part.OCC_VERSION.split('.')[1] 45 | if (int(OCCMV)>= 7) and (int(OCCmV)>= 3): 46 | sel = FreeCADGui.Selection.getSelectionEx() 47 | for sub in sel: 48 | if 'Face' in str(sub.SubElementNames): 49 | return True 50 | else: 51 | return False 52 | 53 | def Activated(self): 54 | #def execute(): 55 | import Part, DefeaturingFeature 56 | #print ('activated') 57 | selection=FreeCADGui.Selection.getSelectionEx() 58 | rh_faces = [];rh_faces_names=[] 59 | selEx=FreeCADGui.Selection.getSelectionEx() 60 | if len (selEx) > 0: 61 | FreeCAD.ActiveDocument.openTransaction('dft') 62 | for selFace in selEx: 63 | for i,f in enumerate(selFace.SubObjects): 64 | if 'Face' in selFace.SubElementNames[i]: 65 | rh_faces.append(f) 66 | rh_faces_names.append(selFace.ObjectName+'.'+selFace.SubElementNames[i]) 67 | print(selFace.ObjectName+'.'+selFace.SubElementNames[i]) 68 | #print (len(rh_faces)) 69 | for selobj in selection: 70 | newobj=selobj.Document.addObject("Part::FeaturePython",'defeat') 71 | DefeaturingFeature.DefeatShape(rh_faces_names,newobj,selobj.Object) 72 | DefeaturingFeature.ViewProviderTree(newobj.ViewObject) 73 | newobj.Label='defeat_%s' % selobj.Object.Label 74 | selobj.Object.ViewObject.hide() 75 | FreeCAD.ActiveDocument.commitTransaction() 76 | FreeCAD.ActiveDocument.recompute() 77 | def GetResources(self): 78 | return {'Pixmap' : os.path.join(DefeaturingWB_icons_path,'DefeaturingParametric.svg'), 'MenuText': \ 79 | QtCore.QT_TRANSLATE_NOOP('DefeatShapeFeature',\ 80 | 'Defeat Shape Feature'), 'ToolTip': \ 81 | QtCore.QT_TRANSLATE_NOOP('DefeatShapeFeature',\ 82 | 'Create Defeat Shape Parametric Feature')} 83 | FreeCADGui.addCommand('DefeatShapeFeature',DefeatShapeFeature()) 84 | ## 85 | 86 | class DefeaturingTools: 87 | "defeaturing tools object" 88 | 89 | def GetResources(self): 90 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'defeaturingTools.svg') , # the name of a svg file available in the resources 91 | 'MenuText': "Defeaturing Tools" , 92 | 'ToolTip' : "Defeaturing workbench"} 93 | 94 | def IsActive(self): 95 | import os, sys 96 | return True 97 | 98 | def Activated(self): 99 | # do something here... 100 | import DefeaturingTools 101 | reload_lib(DefeaturingTools) 102 | FreeCAD.Console.PrintWarning( 'Defeaturing Tools active :)\n' ) 103 | #import kicadStepUptools 104 | 105 | FreeCADGui.addCommand('DefeaturingTools',DefeaturingTools()) 106 | ## 107 | class DF_SelectLoop: 108 | "the Path command to complete loop selection definition" 109 | def __init__(self): 110 | self.obj = None 111 | self.sub = [] 112 | self.active = False 113 | 114 | def GetResources(self): 115 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'Path-SelectLoop.svg') , 116 | 'MenuText': "Defeaturing_SelectLoop", 117 | 'ToolTip': "Defeaturing SelectLoop"} 118 | 119 | def IsActive(self): 120 | #if bool(FreeCADGui.Selection.getSelection()) is False: 121 | # return False 122 | if 0: #try: 123 | sel = FreeCADGui.Selection.getSelectionEx()[0] 124 | if sel.Object == self.obj and sel.SubElementNames == self.sub: 125 | return self.active 126 | self.obj = sel.Object 127 | self.sub = sel.SubElementNames 128 | if sel.SubObjects: 129 | self.active = self.formsPartOfALoop(sel.Object, sel.SubObjects[0], sel.SubElementNames) 130 | else: 131 | self.active = False 132 | return self.active 133 | return True 134 | #except Exception as exc: 135 | # PathLog.error(exc) 136 | # traceback.print_exc(exc) 137 | # return False 138 | 139 | def Activated(self): 140 | sel = FreeCADGui.Selection.getSelectionEx()[0] 141 | obj = sel.Object 142 | edge1 = sel.SubObjects[0] 143 | if 'Face' in sel.SubElementNames[0]: 144 | loop = horizontalFaceLoop(sel.Object, sel.SubObjects[0], sel.SubElementNames) 145 | if loop: 146 | FreeCADGui.Selection.clearSelection() 147 | FreeCADGui.Selection.addSelection(sel.Object, loop) 148 | loopwire = [] 149 | elif len(sel.SubObjects) == 1: 150 | loopwire = horizontalEdgeLoop(obj, edge1) 151 | else: 152 | edge2 = sel.SubObjects[1] 153 | loopwire = loopdetect(obj, edge1, edge2) 154 | 155 | if loopwire: 156 | FreeCADGui.Selection.clearSelection() 157 | elist = obj.Shape.Edges 158 | for e in elist: 159 | for i in loopwire.Edges: 160 | if e.hashCode() == i.hashCode(): 161 | FreeCADGui.Selection.addSelection(obj, "Edge"+str(elist.index(e)+1)) 162 | 163 | def formsPartOfALoop(self, obj, sub, names): 164 | if names[0][0:4] != 'Edge': 165 | if names[0][0:4] == 'Face' and horizontalFaceLoop(obj, sub, names): 166 | return True 167 | return False 168 | if len(names) == 1 and horizontalEdgeLoop(obj, sub): 169 | return True 170 | if len(names) == 1 or names[1][0:4] != 'Edge': 171 | return False 172 | return True 173 | 174 | if FreeCAD.GuiUp: 175 | FreeCADGui.addCommand('DF_SelectLoop', DF_SelectLoop()) 176 | ## 177 | class refineFeatureTool: 178 | "refine Feature Parametric" 179 | 180 | def GetResources(self): 181 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'RefineShapeFeature.svg') , # the name of a svg file available in the resources 182 | 'MenuText': "refine Feature" , 183 | 'ToolTip' : "refine Feature Parametric"} 184 | 185 | def IsActive(self): 186 | if len(FreeCADGui.Selection.getSelection()) > 0: 187 | return True 188 | 189 | def Activated(self): 190 | import OpenSCADFeatures 191 | doc=FreeCAD.ActiveDocument 192 | docG = FreeCADGui.ActiveDocument 193 | sel=FreeCADGui.Selection.getSelectionEx() 194 | if len (sel) > 0: 195 | for selobj in sel: 196 | if hasattr(selobj.Object,"Shape"): 197 | newobj=selobj.Document.addObject("Part::FeaturePython",'refined') 198 | OpenSCADFeatures.RefineShape(newobj,selobj.Object) 199 | OpenSCADFeatures.ViewProviderTree(newobj.ViewObject) 200 | ## to do: see if it is possible to conserve colors in refining 201 | ao = FreeCAD.ActiveDocument.ActiveObject 202 | docG.ActiveObject.ShapeColor=docG.getObject(selobj.Object.Name).ShapeColor 203 | docG.ActiveObject.LineColor=docG.getObject(selobj.Object.Name).LineColor 204 | docG.ActiveObject.PointColor=docG.getObject(selobj.Object.Name).PointColor 205 | docG.ActiveObject.DiffuseColor=docG.getObject(selobj.Object.Name).DiffuseColor 206 | docG.ActiveObject.Transparency=docG.getObject(selobj.Object.Name).Transparency 207 | #newobj.Label='r_%s' % selobj.Object.Label 208 | newobj.Label=selobj.Object.Label 209 | selobj.Object.ViewObject.hide() 210 | doc.recompute() 211 | FreeCADGui.addCommand('refineFeatureTool',refineFeatureTool()) 212 | ## 213 | 214 | class FuzzyCut: 215 | "Fuzzy boolean Cut" 216 | 217 | def GetResources(self): 218 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'FuzzyCut.svg') , # the name of a svg file available in the resources 219 | 'MenuText': "Fuzzy boolean Cut" , 220 | 'ToolTip' : "Fuzzy boolean Cut"} 221 | 222 | def IsActive(self): 223 | doc = FreeCAD.ActiveDocument 224 | if hasattr(Part, "OCC_VERSION"): 225 | OCCMV = Part.OCC_VERSION.split('.')[0] 226 | OCCmV = Part.OCC_VERSION.split('.')[1] 227 | if (int(OCCMV)>= 7) and (int(OCCmV)>= 1): 228 | #return True 229 | if len(FreeCADGui.Selection.getSelection()) == 2: 230 | return True 231 | else: 232 | return False 233 | 234 | def Activated(self): 235 | # do something here... 236 | import FuzzyTools 237 | reload_lib(FuzzyTools) 238 | FuzzyTools.fuzzyCut() 239 | # FreeCAD.Console.PrintWarning( 'Fuzzy Boolean Tools active :)\n' ) 240 | 241 | FreeCADGui.addCommand('FuzzyCut',FuzzyCut()) 242 | ## 243 | 244 | class FuzzyUnion: 245 | "Fuzzy boolean Union" 246 | 247 | def GetResources(self): 248 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'FuzzyUnion.svg') , # the name of a svg file available in the resources 249 | 'MenuText': "Fuzzy boolean Union" , 250 | 'ToolTip' : "Fuzzy boolean Union"} 251 | 252 | def IsActive(self): 253 | doc = FreeCAD.ActiveDocument 254 | if hasattr(Part, "OCC_VERSION"): 255 | OCCMV = Part.OCC_VERSION.split('.')[0] 256 | OCCmV = Part.OCC_VERSION.split('.')[1] 257 | if (int(OCCMV)>= 7) and (int(OCCmV)>= 1): 258 | #return True 259 | if len(FreeCADGui.Selection.getSelection()) > 1: 260 | return True 261 | else: 262 | return False 263 | 264 | def Activated(self): 265 | # do something here... 266 | import FuzzyTools 267 | reload_lib(FuzzyTools) 268 | FuzzyTools.fuzzyUnion() 269 | # FreeCAD.Console.PrintWarning( 'Fuzzy Boolean Tools active :)\n' ) 270 | 271 | FreeCADGui.addCommand('FuzzyUnion',FuzzyUnion()) 272 | ## 273 | class FuzzyCommon: 274 | "Fuzzy boolean Common" 275 | 276 | def GetResources(self): 277 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'FuzzyCommon.svg') , # the name of a svg file available in the resources 278 | 'MenuText': "Fuzzy boolean Common" , 279 | 'ToolTip' : "Fuzzy boolean Common"} 280 | 281 | def IsActive(self): 282 | doc = FreeCAD.ActiveDocument 283 | if hasattr(Part, "OCC_VERSION"): 284 | OCCMV = Part.OCC_VERSION.split('.')[0] 285 | OCCmV = Part.OCC_VERSION.split('.')[1] 286 | if (int(OCCMV)>= 7) and (int(OCCmV)>= 1): 287 | #return True 288 | if len(FreeCADGui.Selection.getSelection()) > 1: 289 | return True 290 | else: 291 | return False 292 | 293 | def Activated(self): 294 | # do something here... 295 | import FuzzyTools 296 | reload_lib(FuzzyTools) 297 | FuzzyTools.fuzzyCommon() 298 | # FreeCAD.Console.PrintWarning( 'Fuzzy Boolean Tools active :)\n' ) 299 | 300 | FreeCADGui.addCommand('FuzzyCommon',FuzzyCommon()) 301 | ## 302 | class ResetPosition: 303 | "Defeaturing reset position tool" 304 | 305 | def GetResources(self): 306 | return {'Pixmap' : os.path.join( DefeaturingWB_icons_path , 'centering-w.svg') , # the name of a svg file available in the resources 307 | 'MenuText': "Centering Widgets" , 308 | 'ToolTip' : "Centering Widgets\nManipulator workbench"} 309 | 310 | def IsActive(self): 311 | import os, sys 312 | return True #False #True 313 | 314 | def Activated(self): 315 | # do something here... 316 | #import kicadStepUptools 317 | #reload_lib( kicadStepUptools ) 318 | import DefeaturingTools 319 | reload_lib(DefeaturingTools) 320 | DefeaturingTools.RHDockWidget.setFloating(True) 321 | DefeaturingTools.RH_centerOnScreen(DefeaturingTools.RHDockWidget) 322 | 323 | FreeCADGui.addCommand('ResetPosition',ResetPosition()) 324 | ## 325 | -------------------------------------------------------------------------------- /DefeaturingFeature.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #*************************************************************************** 3 | #* * 4 | #* Copyright (c) 2017 * 5 | #* Maurice easyw@katamail.com * 6 | #* * 7 | # * 8 | # Defeaturing WB * 9 | # * 10 | # (C) Maurice easyw-fc 2018 * 11 | # This program is free software; you can redistribute it and/or modify * 12 | # it under the terms of the GNU Library General Public License (LGPL) * 13 | # as published by the Free Software Foundation; either version 2 of * 14 | # the License, or (at your option) any later version. * 15 | # for detail see the LICENCE text file. * 16 | #**************************************************************************** 17 | 18 | import dft_locator, os 19 | DefeaturingWBpath = os.path.dirname(dft_locator.__file__) 20 | DefeaturingWB_icons_path = os.path.join( DefeaturingWBpath, 'Resources', 'icons') 21 | global defeat_icon, use_cm 22 | defeat_icon=os.path.join(DefeaturingWB_icons_path,'DefeaturingParametric.svg') 23 | use_cm = True 24 | 25 | ''' 26 | This Script includes python Features to represent Defeaturing Operations 27 | ''' 28 | class ViewProviderTree: 29 | "A generic View Provider for Elements with Children" 30 | 31 | def __init__(self, obj): 32 | obj.Proxy = self 33 | self.Object = obj.Object 34 | 35 | def attach(self, obj): 36 | self.Object = obj.Object 37 | return 38 | 39 | def getIcon(self): 40 | #import osc_locator, os 41 | global defeat_icon 42 | if isinstance(self.Object.Proxy,DefeatShape): 43 | #print (defeat_icon) 44 | # try: 45 | # if self.upd: return (defeat_icon) 46 | # except: pass 47 | return(defeat_icon) 48 | 49 | def updateData(self, fp, prop): 50 | #print (fp.Label) 51 | #if fp.Label.find('_ERR') != -1: 52 | # fp.touch() 53 | # #import FreeCAD 54 | # #doc = FreeCAD.ActiveDocument 55 | # #doc.getObject(fp.Name).touch() 56 | # print('touched') 57 | #self.getIcon() 58 | #try: self.upd 59 | #except: self.upd=True 60 | #self.upd=not self.upd 61 | #print('update') 62 | return 63 | 64 | def getDisplayModes(self,obj): 65 | modes=[] 66 | return modes 67 | 68 | def setDisplayMode(self,mode): 69 | return mode 70 | 71 | def onChanged(self, vp, prop): 72 | #self.getIcon() 73 | #print (prop) 74 | #self.getIcon() 75 | #print('change') 76 | return 77 | 78 | def __getstate__(self): 79 | # return {'ObjectName' : self.Object.Name} 80 | return None 81 | 82 | def __setstate__(self,state): 83 | if state is not None: 84 | import FreeCAD 85 | doc = FreeCAD.ActiveDocument #crap 86 | self.Object = doc.getObject(state['ObjectName']) 87 | 88 | # dumps and loads replace __getstate__ and __setstate__ post v. 0.21.2 89 | def dumps(self): 90 | return None 91 | 92 | def loads(self, state): 93 | if state is not None: 94 | import FreeCAD 95 | doc = FreeCAD.ActiveDocument #crap 96 | self.Object = doc.getObject(state['ObjectName']) 97 | 98 | def claimChildren(self): 99 | objs = [] 100 | if hasattr(self.Object.Proxy,"Base"): 101 | objs.append(self.Object.Proxy.Base) 102 | if hasattr(self.Object,"Base"): 103 | objs.append(self.Object.Base) 104 | if hasattr(self.Object,"Objects"): 105 | objs.extend(self.Object.Objects) 106 | if hasattr(self.Object,"Components"): 107 | objs.extend(self.Object.Components) 108 | if hasattr(self.Object,"Children"): 109 | objs.extend(self.Object.Children) 110 | return objs 111 | 112 | 113 | ## 114 | class DefeatShape: 115 | '''return a refined shape''' 116 | def __init__(self, fc, obj, child=None): 117 | 118 | global use_cm 119 | import FreeCAD 120 | doc = FreeCAD.ActiveDocument 121 | obj.addProperty("App::PropertyLink","Base","Base", 122 | "The base object that must be defeatured") 123 | obj.Proxy = self 124 | obj.Base = child 125 | obj.addProperty("App::PropertyStringList","Faces","dFaces", 126 | "List of Faces to be defeatured") 127 | obj.Faces = fc 128 | if use_cm: 129 | obj.addProperty("App::PropertyStringList","CM","dFaces", 130 | "Center of Mass") 131 | #print(fc) 132 | cm = [] 133 | for f in fc: 134 | oname = obj.Base.Name #f.split('.')[0] 135 | o = doc.getObject(oname) 136 | fnbr = int(f.split('.')[1].strip('Face'))-1 137 | mf = o.Shape.Faces[fnbr] 138 | cm.append('x='+"{0:.3f}".format(mf.CenterOfMass.x)+' y='+"{0:.3f}".format(mf.CenterOfMass.y)+' z='+"{0:.3f}".format(mf.CenterOfMass.z)) 139 | obj.CM = cm 140 | obj.addProperty("App::PropertyBool","useFaceNbr","dFaces", 141 | "use Face Number") 142 | 143 | def onChanged(self, fp, prop): 144 | "Do something when a property has changed" 145 | import FreeCAD 146 | doc = FreeCAD.ActiveDocument 147 | d_faces=[] 148 | #print (prop,' changed') 149 | if (prop == 'useFaceNbr' or prop == 'Shape') and len (fp.Base.Shape.Faces) > 0: 150 | #print (fp.useFaceNbr) 151 | if fp.useFaceNbr: #not use_cm: 152 | cm_list=[] 153 | for fn in fp.Faces: 154 | oname = fp.Base.Name #fp.Faces[0].split('.')[0] 155 | fnbr = int(fn.split('.')[1].strip('Face'))-1 156 | o = doc.getObject(oname) 157 | for i, f in enumerate (o.Shape.Faces): 158 | if i == fnbr: 159 | #print (i) 160 | d_faces.append(f) 161 | c='x='+"{0:.3f}".format(f.CenterOfMass.x)+' y='+"{0:.3f}".format(f.CenterOfMass.y)+' z='+"{0:.3f}".format(f.CenterOfMass.z) 162 | cm_list.append(c) 163 | #print (c) 164 | #print(fp.CM) 165 | #print (f.CenterOfMass) 166 | #print (f.hashCode()) 167 | fp.CM = cm_list 168 | else: 169 | #print(fp.Base.Shape.Faces) 170 | if len (fp.Base.Shape.Faces) > 0: 171 | #if fp.Base.Shape.isValid(): 172 | fc = [] 173 | #fc.append(fp.Faces[0]) 174 | for i, c in enumerate(fp.CM): 175 | for j, f in enumerate (fp.Base.Shape.Faces): 176 | if c ==('x='+"{0:.3f}".format(f.CenterOfMass.x)+' y='+"{0:.3f}".format(f.CenterOfMass.y)+' z='+"{0:.3f}".format(f.CenterOfMass.z)): 177 | d_faces.append(f) 178 | #print (f.CenterOfMass) 179 | fc.append(str(fp.Base.Name)+'.'+'Face'+str(j+1)) 180 | fp.Faces = fc 181 | else: 182 | print('loading first time') 183 | #doc.recompute() 184 | pass 185 | 186 | def execute(self, fp): 187 | global defeat_icon, use_cm 188 | import OpenSCADUtils, FreeCAD, FreeCADGui, Part, os 189 | doc = FreeCAD.ActiveDocument 190 | docG = FreeCADGui.ActiveDocument 191 | #print(fp.Base.Shape.Faces) 192 | #if 0: # 193 | if len (fp.Faces) > 0: 194 | if fp.Base and fp.Base.Shape.isValid(): 195 | #print (fp.Faces) 196 | # rh_faces_names -> (selFace.ObjectName+'.'+selFace.SubElementNames[i]) 197 | d_faces=[] 198 | if fp.useFaceNbr: #not use_cm: 199 | cm_list=[] 200 | for fn in fp.Faces: 201 | oname = fp.Base.Name #fp.Faces[0].split('.')[0] 202 | fnbr = int(fn.split('.')[1].strip('Face'))-1 203 | o = doc.getObject(oname) 204 | for i, f in enumerate (o.Shape.Faces): 205 | if i == fnbr: 206 | #print (i) 207 | d_faces.append(f) 208 | c='x='+"{0:.3f}".format(f.CenterOfMass.x)+' y='+"{0:.3f}".format(f.CenterOfMass.y)+' z='+"{0:.3f}".format(f.CenterOfMass.z) 209 | cm_list.append(c) 210 | #print (c) 211 | #print(fp.CM) 212 | #print (f.CenterOfMass) 213 | #print (f.hashCode()) 214 | fp.CM = cm_list 215 | else: 216 | oname = fp.Base.Name #fp.Faces[0].split('.')[0] 217 | o = doc.getObject(oname) 218 | fc = [] 219 | #fc.append(fp.Faces[0]) 220 | for i, c in enumerate(fp.CM): 221 | for j, f in enumerate (fp.Base.Shape.Faces): 222 | if c ==('x='+"{0:.3f}".format(f.CenterOfMass.x)+' y='+"{0:.3f}".format(f.CenterOfMass.y)+' z='+"{0:.3f}".format(f.CenterOfMass.z)): 223 | d_faces.append(f) 224 | #print (f.CenterOfMass) 225 | fc.append(str(o.Name)+'.'+'Face'+str(j+1)) 226 | #fp.Faces = fc 227 | check_faces = True 228 | if not fp.useFaceNbr: #use_cm: 229 | if len (d_faces) != len (fp.CM): 230 | check_faces = False 231 | elif len (d_faces) == 0: 232 | check_faces = False 233 | if check_faces: 234 | sh = fp.Base.Shape.defeaturing(d_faces) 235 | if fp.Base.Shape.isPartner(sh): 236 | #fp.touch() 237 | FreeCAD.Console.PrintError('Defeaturing failed 1\n') 238 | #defeat_icon=os.path.join(DefeaturingWB_icons_path,'error.svg') 239 | defeat_icon=os.path.join(DefeaturingWB_icons_path,'DefeaturingParametric.svg') 240 | docG.getObject(fp.Name).ShapeColor = (1.00,0.00,0.00) 241 | raise NameError('Defeaturing FAILED!') 242 | #try: 243 | # raise NameError('Defeaturing FAILED!') 244 | #except NameError: 245 | # print ('Defeaturing FAILED!') 246 | # raise 247 | #raise Exception('Defeaturing FAILED!') 248 | else: 249 | fp.Shape=OpenSCADUtils.applyPlacement(sh) 250 | if fp.Label.find('_ERR') != -1: 251 | fp.Label=fp.Label[:fp.Label.rfind('_ERR')] 252 | defeat_icon=os.path.join(DefeaturingWB_icons_path,'DefeaturingParametric.svg') 253 | docG.getObject(fp.Name).ShapeColor = docG.getObject(fp.Base.Name).ShapeColor 254 | docG.getObject(fp.Name).LineColor = docG.getObject(fp.Base.Name).LineColor 255 | docG.getObject(fp.Name).PointColor = docG.getObject(fp.Base.Name).PointColor 256 | docG.getObject(fp.Name).DiffuseColor= docG.getObject(fp.Base.Name).DiffuseColor 257 | docG.getObject(fp.Name).Transparency= docG.getObject(fp.Base.Name).Transparency 258 | else: 259 | #defeat_icon=os.path.join(DefeaturingWB_icons_path,'error.svg') 260 | defeat_icon=os.path.join(DefeaturingWB_icons_path,'DefeaturingParametric.svg') 261 | #fp.touch() 262 | FreeCAD.Console.PrintError('Defeaturing failed 2\n') 263 | sh = fp.Base.Shape 264 | fp.Shape=OpenSCADUtils.applyPlacement(sh) 265 | if fp.Label.find('_ERR') == -1: 266 | fp.Label='%s_ERR' % fp.Label 267 | docG.getObject(fp.Name).ShapeColor = (1.00,0.00,0.00) 268 | raise Exception('Defeaturing FAILED!') 269 | #doc.recompute() 270 | else: 271 | print('first executing') 272 | ## 273 | 274 | ## class UnionFuzzyShape: 275 | ## '''return a fuzzy unioned shape''' 276 | ## def __init__(self, compNames, obj, child=None): 277 | ## #obj.addProperty("App::PropertyLink","Base","Base", 278 | ## # "The base object that must be fuzzy unioned") 279 | ## obj.addProperty("App::PropertyStringList","Components","Components", 280 | ## "List of Objects to be fuzzy unioned") 281 | ## obj.Proxy = self 282 | ## obj.Base = child 283 | ## obj.Components = compNames 284 | ## 285 | ## def onChanged(self, fp, prop): 286 | ## "Do something when a property has changed" 287 | ## pass 288 | ## 289 | ## def execute(self, fp): 290 | ## if len (fp.Components) > 1: 291 | ## makeOp=True 292 | ## for name in fp.Components: 293 | ## if not doc.getObject(name).Shape.isValid(): 294 | ## makeOp=False 295 | ## if makeOp: 296 | ## import OpenSCADUtils, FuzzyTools 297 | ## #sh=fp.Base.Shape.removeSplitter() 298 | ## ### do my ops 299 | ## result_shape = FuzzyTools.fuzzyUnion() 300 | ## fp.Shape=OpenSCADUtils.applyPlacement(result_shape) 301 | ## 302 | -------------------------------------------------------------------------------- /DefeaturingTools-a.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'C:\Users\userC\Documents\GitHub\Defeaturing_WB\DefeaturingTools.ui' 4 | # 5 | # Created: Wed Jul 18 12:50:18 2018 6 | # by: pyside-uic 0.2.15 running on PySide 1.2.2 7 | # 8 | # WARNING! All changes made in this file will be lost! 9 | 10 | from PySide import QtCore, QtGui 11 | 12 | class Ui_DockWidget(object): 13 | def setupUi(self, DockWidget): 14 | DockWidget.setObjectName("DockWidget") 15 | DockWidget.resize(260, 534) 16 | icon = QtGui.QIcon() 17 | icon.addPixmap(QtGui.QPixmap("icons-new/Center-Align.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 18 | DockWidget.setWindowIcon(icon) 19 | DockWidget.setToolTip("Defeaturing tools") 20 | DockWidget.setLayoutDirection(QtCore.Qt.LeftToRight) 21 | DockWidget.setFeatures(QtGui.QDockWidget.AllDockWidgetFeatures) 22 | DockWidget.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea|QtCore.Qt.RightDockWidgetArea) 23 | DockWidget.setWindowTitle("Defeaturing Tools") 24 | self.dockWidgetContents = QtGui.QWidget() 25 | self.dockWidgetContents.setObjectName("dockWidgetContents") 26 | self.PB_RHoles = QtGui.QPushButton(self.dockWidgetContents) 27 | self.PB_RHoles.setGeometry(QtCore.QRect(12, 288, 32, 32)) 28 | self.PB_RHoles.setToolTip("remove Hole from Face") 29 | self.PB_RHoles.setText("") 30 | self.PB_RHoles.setObjectName("PB_RHoles") 31 | self.PB_Edges = QtGui.QPushButton(self.dockWidgetContents) 32 | self.PB_Edges.setGeometry(QtCore.QRect(220, 36, 32, 32)) 33 | self.PB_Edges.setToolTip("add selected Edges to List") 34 | self.PB_Edges.setText("") 35 | self.PB_Edges.setObjectName("PB_Edges") 36 | self.TE_Faces = QtGui.QPlainTextEdit(self.dockWidgetContents) 37 | self.TE_Faces.setGeometry(QtCore.QRect(24, 164, 190, 71)) 38 | self.TE_Faces.setToolTip("List of Face(s)") 39 | self.TE_Faces.setObjectName("TE_Faces") 40 | self.checkBox_keep_original = QtGui.QCheckBox(self.dockWidgetContents) 41 | self.checkBox_keep_original.setGeometry(QtCore.QRect(124, 252, 110, 33)) 42 | self.checkBox_keep_original.setToolTip("keep the original object") 43 | self.checkBox_keep_original.setText("keep Object") 44 | self.checkBox_keep_original.setChecked(True) 45 | self.checkBox_keep_original.setObjectName("checkBox_keep_original") 46 | self.InfoLabel = QtGui.QLabel(self.dockWidgetContents) 47 | self.InfoLabel.setGeometry(QtCore.QRect(24, 0, 196, 36)) 48 | self.InfoLabel.setText("Select Edge(s)\n" 49 | "Ctrl+Click") 50 | self.InfoLabel.setObjectName("InfoLabel") 51 | self.TE_Edges = QtGui.QPlainTextEdit(self.dockWidgetContents) 52 | self.TE_Edges.setEnabled(True) 53 | self.TE_Edges.setGeometry(QtCore.QRect(24, 36, 190, 66)) 54 | self.TE_Edges.setToolTip("List of Edge(s)") 55 | self.TE_Edges.setPlainText("") 56 | self.TE_Edges.setObjectName("TE_Edges") 57 | self.PB_Faces = QtGui.QPushButton(self.dockWidgetContents) 58 | self.PB_Faces.setGeometry(QtCore.QRect(220, 164, 32, 32)) 59 | self.PB_Faces.setToolTip("add selected Faces to List") 60 | self.PB_Faces.setText("") 61 | self.PB_Faces.setObjectName("PB_Faces") 62 | self.PB_Edges_Clear = QtGui.QPushButton(self.dockWidgetContents) 63 | self.PB_Edges_Clear.setGeometry(QtCore.QRect(220, 71, 32, 32)) 64 | self.PB_Edges_Clear.setToolTip("clear List") 65 | self.PB_Edges_Clear.setText("") 66 | self.PB_Edges_Clear.setObjectName("PB_Edges_Clear") 67 | self.PB_Faces_Clear = QtGui.QPushButton(self.dockWidgetContents) 68 | self.PB_Faces_Clear.setGeometry(QtCore.QRect(220, 200, 32, 32)) 69 | self.PB_Faces_Clear.setToolTip("clear List") 70 | self.PB_Faces_Clear.setText("") 71 | self.PB_Faces_Clear.setObjectName("PB_Faces_Clear") 72 | self.Edge_Nbr = QtGui.QLabel(self.dockWidgetContents) 73 | self.Edge_Nbr.setGeometry(QtCore.QRect(48, 104, 53, 16)) 74 | self.Edge_Nbr.setText("0") 75 | self.Edge_Nbr.setObjectName("Edge_Nbr") 76 | self.Face_Nbr = QtGui.QLabel(self.dockWidgetContents) 77 | self.Face_Nbr.setGeometry(QtCore.QRect(48, 236, 53, 16)) 78 | self.Face_Nbr.setText("0") 79 | self.Face_Nbr.setObjectName("Face_Nbr") 80 | self.label = QtGui.QLabel(self.dockWidgetContents) 81 | self.label.setGeometry(QtCore.QRect(24, 124, 177, 45)) 82 | self.label.setText("Select Face(s)\n" 83 | "Ctrl+Click") 84 | self.label.setObjectName("label") 85 | self.checkBox_Refine = QtGui.QCheckBox(self.dockWidgetContents) 86 | self.checkBox_Refine.setGeometry(QtCore.QRect(12, 260, 89, 20)) 87 | self.checkBox_Refine.setToolTip("refine the resulting solid\n" 88 | "after the operation ") 89 | self.checkBox_Refine.setText("refine") 90 | self.checkBox_Refine.setChecked(False) 91 | self.checkBox_Refine.setObjectName("checkBox_Refine") 92 | self.checkBox_keep_faces = QtGui.QCheckBox(self.dockWidgetContents) 93 | self.checkBox_keep_faces.setGeometry(QtCore.QRect(128, 140, 100, 20)) 94 | self.checkBox_keep_faces.setToolTip("keep construction faces") 95 | self.checkBox_keep_faces.setText("keep faces") 96 | self.checkBox_keep_faces.setObjectName("checkBox_keep_faces") 97 | self.PB_RFaces = QtGui.QPushButton(self.dockWidgetContents) 98 | self.PB_RFaces.setGeometry(QtCore.QRect(68, 288, 32, 32)) 99 | self.PB_RFaces.setToolTip("remove \'in List\' Faces") 100 | self.PB_RFaces.setText("") 101 | self.PB_RFaces.setObjectName("PB_RFaces") 102 | self.PB_AFaces = QtGui.QPushButton(self.dockWidgetContents) 103 | self.PB_AFaces.setGeometry(QtCore.QRect(124, 288, 32, 32)) 104 | self.PB_AFaces.setToolTip("add Faces from \'in List\' Edges") 105 | self.PB_AFaces.setText("") 106 | self.PB_AFaces.setObjectName("PB_AFaces") 107 | self.PB_makeShell = QtGui.QPushButton(self.dockWidgetContents) 108 | self.PB_makeShell.setGeometry(QtCore.QRect(12, 360, 32, 32)) 109 | self.PB_makeShell.setToolTip("make Solid from in list Faces") 110 | self.PB_makeShell.setText("") 111 | self.PB_makeShell.setObjectName("PB_makeShell") 112 | self.PB_makeShell_2 = QtGui.QPushButton(self.dockWidgetContents) 113 | self.PB_makeShell_2.setGeometry(QtCore.QRect(68, 360, 32, 32)) 114 | self.PB_makeShell_2.setToolTip("make Solid from the Faces\n" 115 | "of the selected Objects") 116 | self.PB_makeShell_2.setText("") 117 | self.PB_makeShell_2.setObjectName("PB_makeShell_2") 118 | self.PB_check_TypeId = QtGui.QPushButton(self.dockWidgetContents) 119 | self.PB_check_TypeId.setGeometry(QtCore.QRect(124, 468, 32, 32)) 120 | font = QtGui.QFont() 121 | font.setWeight(50) 122 | font.setItalic(False) 123 | font.setUnderline(False) 124 | font.setBold(False) 125 | self.PB_check_TypeId.setFont(font) 126 | self.PB_check_TypeId.setToolTip("show/hide TypeId of the Shape") 127 | self.PB_check_TypeId.setText("") 128 | self.PB_check_TypeId.setObjectName("PB_check_TypeId") 129 | self.Obj_Nbr = QtGui.QLabel(self.dockWidgetContents) 130 | self.Obj_Nbr.setGeometry(QtCore.QRect(164, 104, 53, 16)) 131 | self.Obj_Nbr.setText("0") 132 | self.Obj_Nbr.setObjectName("Obj_Nbr") 133 | self.Obj_Nbr_2 = QtGui.QLabel(self.dockWidgetContents) 134 | self.Obj_Nbr_2.setGeometry(QtCore.QRect(164, 236, 53, 16)) 135 | self.Obj_Nbr_2.setText("0") 136 | self.Obj_Nbr_2.setObjectName("Obj_Nbr_2") 137 | self.PB_AEdges = QtGui.QPushButton(self.dockWidgetContents) 138 | self.PB_AEdges.setGeometry(QtCore.QRect(220, 288, 32, 32)) 139 | self.PB_AEdges.setToolTip("create a copy of the \'in List\' Edges") 140 | self.PB_AEdges.setText("") 141 | self.PB_AEdges.setObjectName("PB_AEdges") 142 | self.PB_showEdgeList = QtGui.QPushButton(self.dockWidgetContents) 143 | self.PB_showEdgeList.setGeometry(QtCore.QRect(12, 396, 32, 32)) 144 | self.PB_showEdgeList.setToolTip("show \'in List\' Edge(s)") 145 | self.PB_showEdgeList.setText("") 146 | self.PB_showEdgeList.setObjectName("PB_showEdgeList") 147 | self.PB_showFaceList = QtGui.QPushButton(self.dockWidgetContents) 148 | self.PB_showFaceList.setGeometry(QtCore.QRect(68, 396, 32, 32)) 149 | self.PB_showFaceList.setToolTip("show \'in List\' Face(s)") 150 | self.PB_showFaceList.setText("") 151 | self.PB_showFaceList.setObjectName("PB_showFaceList") 152 | self.PB_Refine = QtGui.QPushButton(self.dockWidgetContents) 153 | self.PB_Refine.setGeometry(QtCore.QRect(124, 396, 32, 32)) 154 | self.PB_Refine.setToolTip("refine") 155 | self.PB_Refine.setText("") 156 | self.PB_Refine.setObjectName("PB_Refine") 157 | self.PB_RefineParametric = QtGui.QPushButton(self.dockWidgetContents) 158 | self.PB_RefineParametric.setGeometry(QtCore.QRect(220, 396, 32, 32)) 159 | self.PB_RefineParametric.setToolTip("parametric Refine") 160 | self.PB_RefineParametric.setText("") 161 | self.PB_RefineParametric.setObjectName("PB_RefineParametric") 162 | self.PB_CFaces = QtGui.QPushButton(self.dockWidgetContents) 163 | self.PB_CFaces.setGeometry(QtCore.QRect(12, 324, 32, 32)) 164 | self.PB_CFaces.setToolTip("copy Faces from \'in List\' Edges") 165 | self.PB_CFaces.setText("") 166 | self.PB_CFaces.setObjectName("PB_CFaces") 167 | self.PB_TFace = QtGui.QPushButton(self.dockWidgetContents) 168 | self.PB_TFace.setGeometry(QtCore.QRect(68, 324, 32, 32)) 169 | self.PB_TFace.setToolTip("copy Faces from \'in List\' Edges") 170 | self.PB_TFace.setText("") 171 | self.PB_TFace.setObjectName("PB_TFace") 172 | self.offset_input = QtGui.QLineEdit(self.dockWidgetContents) 173 | self.offset_input.setGeometry(QtCore.QRect(128, 328, 73, 22)) 174 | self.offset_input.setToolTip("Face offset to apply") 175 | self.offset_input.setText("0.0") 176 | self.offset_input.setObjectName("offset_input") 177 | self.PB_TEdge = QtGui.QPushButton(self.dockWidgetContents) 178 | self.PB_TEdge.setGeometry(QtCore.QRect(220, 324, 32, 32)) 179 | self.PB_TEdge.setToolTip("copy Faces from \'in List\' Edges") 180 | self.PB_TEdge.setText("") 181 | self.PB_TEdge.setObjectName("PB_TEdge") 182 | self.PB_close = QtGui.QPushButton(self.dockWidgetContents) 183 | self.PB_close.setGeometry(QtCore.QRect(-1, -1, 20, 20)) 184 | self.PB_close.setToolTip("add selected Edges to List") 185 | self.PB_close.setText("") 186 | self.PB_close.setObjectName("PB_close") 187 | self.Version = QtGui.QLabel(self.dockWidgetContents) 188 | self.Version.setGeometry(QtCore.QRect(200, 0, 53, 16)) 189 | self.Version.setText("0") 190 | self.Version.setObjectName("Version") 191 | self.PB_left = QtGui.QPushButton(self.dockWidgetContents) 192 | self.PB_left.setGeometry(QtCore.QRect(-1, 17, 20, 20)) 193 | self.PB_left.setToolTip("dock left") 194 | self.PB_left.setText("") 195 | self.PB_left.setObjectName("PB_left") 196 | self.PB_right = QtGui.QPushButton(self.dockWidgetContents) 197 | self.PB_right.setGeometry(QtCore.QRect(-1, 34, 20, 20)) 198 | self.PB_right.setToolTip("dock right") 199 | self.PB_right.setText("") 200 | self.PB_right.setObjectName("PB_right") 201 | self.PB_makeEdge = QtGui.QPushButton(self.dockWidgetContents) 202 | self.PB_makeEdge.setGeometry(QtCore.QRect(12, 468, 32, 32)) 203 | self.PB_makeEdge.setToolTip("make Edge from selected Vertexes") 204 | self.PB_makeEdge.setText("") 205 | self.PB_makeEdge.setObjectName("PB_makeEdge") 206 | self.PB_expSTEP = QtGui.QPushButton(self.dockWidgetContents) 207 | self.PB_expSTEP.setGeometry(QtCore.QRect(124, 360, 32, 32)) 208 | self.PB_expSTEP.setToolTip("make Solid from the Faces\n" 209 | "of the selected Objects") 210 | self.PB_expSTEP.setText("") 211 | self.PB_expSTEP.setObjectName("PB_expSTEP") 212 | self.PB_PartDefeaturing = QtGui.QPushButton(self.dockWidgetContents) 213 | self.PB_PartDefeaturing.setEnabled(False) 214 | self.PB_PartDefeaturing.setGeometry(QtCore.QRect(172, 288, 32, 32)) 215 | self.PB_PartDefeaturing.setToolTip("show \'in List\' Edge(s)") 216 | self.PB_PartDefeaturing.setText("") 217 | self.PB_PartDefeaturing.setObjectName("PB_PartDefeaturing") 218 | self.PB_CleaningFaces = QtGui.QPushButton(self.dockWidgetContents) 219 | self.PB_CleaningFaces.setGeometry(QtCore.QRect(220, 360, 32, 32)) 220 | self.PB_CleaningFaces.setToolTip("clean Face(s) removing\n" 221 | "holes and merging Outwire") 222 | self.PB_CleaningFaces.setText("") 223 | self.PB_CleaningFaces.setObjectName("PB_CleaningFaces") 224 | self.PB_checkS = QtGui.QPushButton(self.dockWidgetContents) 225 | self.PB_checkS.setGeometry(QtCore.QRect(12, 432, 32, 32)) 226 | self.PB_checkS.setToolTip("show \'in List\' Edge(s)") 227 | self.PB_checkS.setText("") 228 | self.PB_checkS.setObjectName("PB_checkS") 229 | self.tolerance_value = QtGui.QLineEdit(self.dockWidgetContents) 230 | self.tolerance_value.setGeometry(QtCore.QRect(128, 436, 73, 22)) 231 | self.tolerance_value.setToolTip("Face offset to apply") 232 | self.tolerance_value.setText("0.0") 233 | self.tolerance_value.setObjectName("tolerance_value") 234 | self.PB_setTol = QtGui.QPushButton(self.dockWidgetContents) 235 | self.PB_setTol.setGeometry(QtCore.QRect(220, 432, 32, 32)) 236 | self.PB_setTol.setToolTip("copy Faces from \'in List\' Edges") 237 | self.PB_setTol.setText("") 238 | self.PB_setTol.setObjectName("PB_setTol") 239 | self.PB_getTol = QtGui.QPushButton(self.dockWidgetContents) 240 | self.PB_getTol.setGeometry(QtCore.QRect(68, 432, 32, 32)) 241 | self.PB_getTol.setToolTip("copy Faces from \'in List\' Edges") 242 | self.PB_getTol.setText("") 243 | self.PB_getTol.setObjectName("PB_getTol") 244 | self.PB_sewS = QtGui.QPushButton(self.dockWidgetContents) 245 | self.PB_sewS.setGeometry(QtCore.QRect(220, 468, 32, 32)) 246 | self.PB_sewS.setToolTip("copy Faces from \'in List\' Edges") 247 | self.PB_sewS.setText("") 248 | self.PB_sewS.setObjectName("PB_sewS") 249 | self.PB_RHhelp = QtGui.QPushButton(self.dockWidgetContents) 250 | self.PB_RHhelp.setGeometry(QtCore.QRect(172, 468, 32, 32)) 251 | self.PB_RHhelp.setToolTip("Help") 252 | self.PB_RHhelp.setText("") 253 | self.PB_RHhelp.setObjectName("PB_RHhelp") 254 | DockWidget.setWidget(self.dockWidgetContents) 255 | 256 | self.retranslateUi(DockWidget) 257 | QtCore.QMetaObject.connectSlotsByName(DockWidget) 258 | 259 | def retranslateUi(self, DockWidget): 260 | pass 261 | 262 | 263 | if __name__ == "__main__": 264 | import sys 265 | app = QtGui.QApplication(sys.argv) 266 | DockWidget = QtGui.QDockWidget() 267 | ui = Ui_DockWidget() 268 | ui.setupUi(DockWidget) 269 | DockWidget.show() 270 | sys.exit(app.exec_()) 271 | 272 | -------------------------------------------------------------------------------- /DefeaturingTools.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DockWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 260 10 | 534 11 | 12 | 13 | 14 | 15 | icons-new/Center-Align.pngicons-new/Center-Align.png 16 | 17 | 18 | Defeaturing tools 19 | 20 | 21 | Qt::LeftToRight 22 | 23 | 24 | QDockWidget::AllDockWidgetFeatures 25 | 26 | 27 | Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea 28 | 29 | 30 | Defeaturing Tools 31 | 32 | 33 | 34 | 35 | 36 | 12 37 | 288 38 | 32 39 | 32 40 | 41 | 42 | 43 | remove Hole from Face 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 220 53 | 36 54 | 32 55 | 32 56 | 57 | 58 | 59 | add selected Edges to List 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 24 69 | 164 70 | 190 71 | 71 72 | 73 | 74 | 75 | List of Face(s) 76 | 77 | 78 | 79 | 80 | 81 | 124 82 | 252 83 | 110 84 | 33 85 | 86 | 87 | 88 | keep the original object 89 | 90 | 91 | keep Object 92 | 93 | 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 24 101 | 0 102 | 196 103 | 36 104 | 105 | 106 | 107 | Select Edge(s) 108 | Ctrl+Click 109 | 110 | 111 | 112 | 113 | true 114 | 115 | 116 | 117 | 24 118 | 36 119 | 190 120 | 66 121 | 122 | 123 | 124 | List of Edge(s) 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 220 134 | 164 135 | 32 136 | 32 137 | 138 | 139 | 140 | add selected Faces to List 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 220 150 | 71 151 | 32 152 | 32 153 | 154 | 155 | 156 | clear List 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 220 166 | 200 167 | 32 168 | 32 169 | 170 | 171 | 172 | clear List 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 48 182 | 104 183 | 53 184 | 16 185 | 186 | 187 | 188 | 0 189 | 190 | 191 | 192 | 193 | 194 | 48 195 | 236 196 | 53 197 | 16 198 | 199 | 200 | 201 | 0 202 | 203 | 204 | 205 | 206 | 207 | 24 208 | 124 209 | 177 210 | 45 211 | 212 | 213 | 214 | Select Face(s) 215 | Ctrl+Click 216 | 217 | 218 | 219 | 220 | 221 | 12 222 | 260 223 | 89 224 | 20 225 | 226 | 227 | 228 | refine the resulting solid 229 | after the operation 230 | 231 | 232 | refine 233 | 234 | 235 | false 236 | 237 | 238 | 239 | 240 | 241 | 128 242 | 140 243 | 100 244 | 20 245 | 246 | 247 | 248 | keep construction faces 249 | 250 | 251 | keep faces 252 | 253 | 254 | 255 | 256 | 257 | 68 258 | 288 259 | 32 260 | 32 261 | 262 | 263 | 264 | remove 'in List' Faces 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 124 274 | 288 275 | 32 276 | 32 277 | 278 | 279 | 280 | add Faces from 'in List' Edges 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 12 290 | 360 291 | 32 292 | 32 293 | 294 | 295 | 296 | make Solid from in list Faces 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 68 306 | 360 307 | 32 308 | 32 309 | 310 | 311 | 312 | make Solid from the Faces 313 | of the selected Objects 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 124 323 | 468 324 | 32 325 | 32 326 | 327 | 328 | 329 | 330 | 50 331 | false 332 | false 333 | false 334 | 335 | 336 | 337 | show/hide TypeId of the Shape 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 164 347 | 104 348 | 53 349 | 16 350 | 351 | 352 | 353 | 0 354 | 355 | 356 | 357 | 358 | 359 | 164 360 | 236 361 | 53 362 | 16 363 | 364 | 365 | 366 | 0 367 | 368 | 369 | 370 | 371 | 372 | 220 373 | 288 374 | 32 375 | 32 376 | 377 | 378 | 379 | create a copy of the 'in List' Edges 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 12 389 | 396 390 | 32 391 | 32 392 | 393 | 394 | 395 | show 'in List' Edge(s) 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 68 405 | 396 406 | 32 407 | 32 408 | 409 | 410 | 411 | show 'in List' Face(s) 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 124 421 | 396 422 | 32 423 | 32 424 | 425 | 426 | 427 | refine 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 220 437 | 396 438 | 32 439 | 32 440 | 441 | 442 | 443 | parametric Refine 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 12 453 | 324 454 | 32 455 | 32 456 | 457 | 458 | 459 | copy Faces from 'in List' Edges 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 68 469 | 324 470 | 32 471 | 32 472 | 473 | 474 | 475 | copy Faces from 'in List' Edges 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 128 485 | 328 486 | 73 487 | 22 488 | 489 | 490 | 491 | Face offset to apply 492 | 493 | 494 | 0.0 495 | 496 | 497 | 498 | 499 | 500 | 220 501 | 324 502 | 32 503 | 32 504 | 505 | 506 | 507 | copy Faces from 'in List' Edges 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | -1 517 | -1 518 | 20 519 | 20 520 | 521 | 522 | 523 | add selected Edges to List 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 200 533 | 0 534 | 53 535 | 16 536 | 537 | 538 | 539 | 0 540 | 541 | 542 | 543 | 544 | 545 | -1 546 | 17 547 | 20 548 | 20 549 | 550 | 551 | 552 | dock left 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | -1 562 | 34 563 | 20 564 | 20 565 | 566 | 567 | 568 | dock right 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 12 578 | 468 579 | 32 580 | 32 581 | 582 | 583 | 584 | make Edge from selected Vertexes 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 124 594 | 360 595 | 32 596 | 32 597 | 598 | 599 | 600 | make Solid from the Faces 601 | of the selected Objects 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | false 610 | 611 | 612 | 613 | 172 614 | 288 615 | 32 616 | 32 617 | 618 | 619 | 620 | show 'in List' Edge(s) 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 220 630 | 360 631 | 32 632 | 32 633 | 634 | 635 | 636 | clean Face(s) removing 637 | holes and merging Outwire 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 12 647 | 432 648 | 32 649 | 32 650 | 651 | 652 | 653 | show 'in List' Edge(s) 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 128 663 | 436 664 | 73 665 | 22 666 | 667 | 668 | 669 | Face offset to apply 670 | 671 | 672 | 0.0 673 | 674 | 675 | 676 | 677 | 678 | 220 679 | 432 680 | 32 681 | 32 682 | 683 | 684 | 685 | copy Faces from 'in List' Edges 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 68 695 | 432 696 | 32 697 | 32 698 | 699 | 700 | 701 | copy Faces from 'in List' Edges 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 220 711 | 468 712 | 32 713 | 32 714 | 715 | 716 | 717 | copy Faces from 'in List' Edges 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 172 727 | 468 728 | 32 729 | 32 730 | 731 | 732 | 733 | Help 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 172 743 | 360 744 | 32 745 | 32 746 | 747 | 748 | 749 | connect 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 172 759 | 396 760 | 32 761 | 32 762 | 763 | 764 | 765 | simple copy 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 68 775 | 468 776 | 32 777 | 32 778 | 779 | 780 | 781 | reset Placement 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 4 794 | 795 | 796 | 4 797 | 798 | 799 | true 800 | 801 | 802 | true 803 | 804 | 805 | true 806 | 807 | 808 | 809 | -------------------------------------------------------------------------------- /FuzzyTools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | #**************************************************************************** 4 | #* * 5 | #* Copyright (c) 2017 * 6 | #* Maurice easyw@katamail.com * 7 | #* * 8 | # * 9 | # Repair Defeaturing Macro * 10 | # * 11 | # (C) Maurice easyw-fc 2018 * 12 | # This program is free software; you can redistribute it and/or modify * 13 | # it under the terms of the GNU Library General Public License (LGPL) * 14 | # as published by the Free Software Foundation; either version 2 of * 15 | # the License, or (at your option) any later version. * 16 | # for detail see the LICENCE text file. * 17 | #**************************************************************************** 18 | 19 | 20 | import FreeCAD, FreeCADGui, Draft, Part 21 | import re, os, sys 22 | from PySide import QtCore, QtGui 23 | 24 | __version__ = "v1.0.2" 25 | 26 | def f_say(msg): 27 | FreeCAD.Console.PrintMessage(msg) 28 | FreeCAD.Console.PrintMessage('\n') 29 | 30 | def f_sayw(msg): 31 | FreeCAD.Console.PrintWarning(msg) 32 | FreeCAD.Console.PrintWarning('\n') 33 | 34 | def f_sayerr(msg): 35 | FreeCAD.Console.PrintError(msg) 36 | FreeCAD.Console.PrintWarning('\n') 37 | 38 | ## 39 | def fuzzyCut(): 40 | import Part 41 | global fuzzyTolerance 42 | from PySide import QtCore, QtGui 43 | 44 | fuzzyTolerance = 0.01 45 | reply = QtGui.QInputDialog.getText(None, "Tolerance","Fuzzy Tolerance",QtGui.QLineEdit.Normal,str(fuzzyTolerance)) 46 | if reply[1]: 47 | # user clicked OK 48 | replyText = reply[0] 49 | fuzzyTolerance = float (replyText) 50 | else: 51 | # user clicked Cancel 52 | replyText = reply[0] # which will be "" if they clicked Cancel 53 | doc = FreeCAD.ActiveDocument 54 | docG = FreeCADGui.ActiveDocument 55 | sel = FreeCADGui.Selection.getSelection() 56 | if len(sel)==2: 57 | if 0: 58 | doc.addObject("Part::Cut","Cut") 59 | added = doc.ActiveObject 60 | added.Base = sel[0] 61 | added.Tool = sel[1] 62 | else: 63 | shapeBase = sel[0].Shape 64 | shapeTool = sel[1].Shape 65 | result_shape = shapeBase.cut(shapeTool, fuzzyTolerance) 66 | Part.show(result_shape) 67 | added = doc.ActiveObject 68 | docG.getObject(sel[0].Name).Visibility=False 69 | docG.getObject(sel[1].Name).Visibility=False 70 | docG.getObject(added.Name).ShapeColor=docG.getObject(sel[0].Name).ShapeColor 71 | docG.getObject(added.Name).Transparency=docG.getObject(sel[0].Name).Transparency 72 | docG.getObject(added.Name).DisplayMode=docG.getObject(sel[0].Name).DisplayMode 73 | added.Label = 'CutFuzzy' 74 | doc.recompute() 75 | ## 76 | def fuzzyUnion(): 77 | import Part 78 | global fuzzyTolerance 79 | 80 | fuzzyTolerance = 0.01 81 | reply = QtGui.QInputDialog.getText(None, "Tolerance","Fuzzy Tolerance",QtGui.QLineEdit.Normal,str(fuzzyTolerance)) 82 | if reply[1]: 83 | # user clicked OK 84 | replyText = reply[0] 85 | fuzzyTolerance = float (replyText) 86 | else: 87 | # user clicked Cancel 88 | replyText = reply[0] # which will be "" if they clicked Cancel 89 | doc = FreeCAD.ActiveDocument 90 | docG = FreeCADGui.ActiveDocument 91 | sel = FreeCADGui.Selection.getSelection() 92 | shapes = [] 93 | for s in sel[1:]: 94 | shapes.append(s.Shape) 95 | c = sel[0].Shape.multiFuse(shapes, fuzzyTolerance) 96 | Part.show(c) 97 | added = doc.ActiveObject 98 | for s in sel: 99 | docG.getObject(s.Name).Visibility=False 100 | docG.getObject(added.Name).ShapeColor=docG.getObject(sel[0].Name).ShapeColor 101 | docG.getObject(added.Name).Transparency=docG.getObject(sel[0].Name).Transparency 102 | docG.getObject(added.Name).DisplayMode=docG.getObject(sel[0].Name).DisplayMode 103 | added.Label = 'UnionFuzzy' 104 | doc.recompute() 105 | ## 106 | def fuzzyCommon(): 107 | import Part 108 | global fuzzyTolerance 109 | 110 | fuzzyTolerance = 0.01 111 | reply = QtGui.QInputDialog.getText(None, "Tolerance","Fuzzy Tolerance",QtGui.QLineEdit.Normal,str(fuzzyTolerance)) 112 | if reply[1]: 113 | # user clicked OK 114 | replyText = reply[0] 115 | fuzzyTolerance = float (replyText) 116 | else: 117 | # user clicked Cancel 118 | replyText = reply[0] # which will be "" if they clicked Cancel 119 | doc = FreeCAD.ActiveDocument 120 | docG = FreeCADGui.ActiveDocument 121 | sel = FreeCADGui.Selection.getSelection() 122 | shapes = [] 123 | for s in sel[1:]: 124 | shapes.append(s.Shape) 125 | c = sel[0].Shape.common(shapes, fuzzyTolerance) 126 | Part.show(c) 127 | added = doc.ActiveObject 128 | for s in sel: 129 | docG.getObject(s.Name).Visibility=False 130 | docG.getObject(added.Name).ShapeColor=docG.getObject(sel[0].Name).ShapeColor 131 | docG.getObject(added.Name).Transparency=docG.getObject(sel[0].Name).Transparency 132 | docG.getObject(added.Name).DisplayMode=docG.getObject(sel[0].Name).DisplayMode 133 | added.Label = 'CommonFuzzy' 134 | doc.recompute() 135 | ## -------------------------------------------------------------------------------- /Init.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #**************************************************************************** 3 | #* * 4 | #* Defeaturing WB for FreeCAD * 5 | #* Copyright (c) 2018 * 6 | #* Maurice easyw@katamail.com * 7 | #* * 8 | #* Defeaturing WB * 9 | #* * 10 | 11 | -------------------------------------------------------------------------------- /InitGui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #*************************************************************************** 3 | #* * 4 | #* Copyright (c) 2017 * 5 | #* Maurice easyw@katamail.com * 6 | #* * 7 | # * 8 | # Defeaturing WB * 9 | # * 10 | # (C) Maurice easyw-fc 2018 * 11 | # This program is free software; you can redistribute it and/or modify * 12 | # it under the terms of the GNU Library General Public License (LGPL) * 13 | # as published by the Free Software Foundation; either version 2 of * 14 | # the License, or (at your option) any later version. * 15 | # for detail see the LICENCE text file. * 16 | #**************************************************************************** 17 | 18 | DWB_wb_version='v 1.2.9' 19 | global myurlDWB 20 | myurlDWB='https://github.com/easyw/Defeaturing_WB' 21 | global mycommitsDWB 22 | mycommitsDWB=80 #v 1.2.9 23 | 24 | 25 | import FreeCAD, FreeCADGui, Part, os, sys 26 | import re, time 27 | 28 | if (sys.version_info > (3, 0)): #py3 29 | import urllib 30 | from urllib import request, error #URLError, HTTPError 31 | else: #py2 32 | import urllib2 33 | from urllib2 import Request, urlopen, URLError, HTTPError 34 | 35 | import dft_locator 36 | from DefeaturingCMD import * 37 | 38 | DefeaturingWBpath = os.path.dirname(dft_locator.__file__) 39 | DefeaturingWB_icons_path = os.path.join( DefeaturingWBpath, 'Resources', 'icons') 40 | 41 | global main_DWB_Icon 42 | main_DWB_Icon = os.path.join( DefeaturingWB_icons_path , 'Defeaturing-icon.svg') 43 | 44 | 45 | #try: 46 | # from FreeCADGui import Workbench 47 | #except ImportError as e: 48 | # FreeCAD.Console.PrintWarning("error") 49 | 50 | class DefeaturingWB ( Workbench ): 51 | global main_DWB_Icon, DWB_wb_version 52 | 53 | "Defeaturing WB object" 54 | Icon = main_DWB_Icon 55 | #Icon = ":Resources/icons/kicad-StepUp-tools-WB.svg" 56 | MenuText = "Defeaturing" 57 | ToolTip = "Defeaturing workbench" 58 | 59 | def GetClassName(self): 60 | return "Gui::PythonWorkbench" 61 | 62 | def Initialize(self): 63 | 64 | self.appendToolbar("Defeaturing Tools", ["DefeaturingTools","DF_SelectLoop","refineFeatureTool","DefeatShapeFeature","ResetPosition"]) 65 | 66 | #self.appendMenu("ksu Tools", ["ksuTools","ksuToolsEdit"]) 67 | self.appendMenu("Defeaturing Tools", ["refineFeatureTool","DefeaturingTools","DF_SelectLoop","ResetPosition"]) 68 | 69 | self.appendToolbar("Fuzzy Tools", ["FuzzyCut","FuzzyUnion","FuzzyCommon"]) 70 | self.appendMenu("Fuzzy Tools", ["FuzzyCut","FuzzyUnion","FuzzyCommon"]) 71 | 72 | Log ("Loading Defeaturing Module... done\n") 73 | 74 | def Activated(self): 75 | # do something here if needed... 76 | Msg ("Defeaturing WB Activated("+DWB_wb_version+")\n") 77 | from PySide import QtGui 78 | import time 79 | 80 | 81 | def Deactivated(self): 82 | # do something here if needed... 83 | Msg ("Defeaturing WB Deactivated()\n") 84 | 85 | ### 86 | 87 | FreeCADGui.addWorkbench(DefeaturingWB) 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## FreeCAD Defeaturing Workbench 2 | 3 | 4 | [![made-with-python](Resources/made-with-python.svg)](https://www.python.org/) 5 | 6 | [![FreeCAD Addokn manager status](Resources/FreeCAD-addon-manager-available.svg)](https://www.freecad.org) 7 | 8 | Intended for editing STEP models, removing/adding of selected features from the model 9 | 10 | ## Features 11 | 12 | * Features a set of tools to edit a Shape or a STEP model, removing hole(s), face(s), simplifying the model, changing the tolerance, applying Fuzzy Boolean operations etc... 13 | * Tools to create more solid shape(s), from edge(s), face(s) or shell(s). 14 | * Possiblity using direct modeling of the model, when the history of operations is unavailable. (This is the case for 3D STEP models). 15 | * Useful in situations to quickly remove proprietary details of the model before sharing it. See [Defeaturing](https://wiki.freecadweb.org/Defeaturing) 16 | * More details at [wiki.freecadweb.org/Defeaturing_Workbench](https://wiki.freecadweb.org/Defeaturing_Workbench) 17 | 18 | 19 | ## Prerequisites 20 | 21 | * FreeCAD v0.15 r4671 22 | * FreeCAD v0.16 >= r6712 23 | * FreeCAD v0.17 >= r13522 24 | * FreeCAD v0.18+ 25 | * Recommended: OCCT v7.3.0 or greater 26 | 27 | ## Installation 28 | 29 | Install via the FreeCAD [Addon Manager](https://wiki.freecadweb.org/Std_AddonMgr) 30 | 31 | 32 | ## Screenshots 33 | 34 | ![image](https://user-images.githubusercontent.com/4140247/112375777-117ad380-8cba-11eb-933d-88fa29aa2010.png) 35 | 36 | 37 | #### Release notes: 38 | 39 | * v1.1: Improve README + typo fixes 40 | * v1.0.1: Initial version 41 | 42 | ## Developers 43 | 44 | * Defeaturing tools: Maurice [@easyw](https://github.com/easyw/Defeaturing_WB) 45 | -------------------------------------------------------------------------------- /Resources/FreeCAD-addon-manager-available.svg: -------------------------------------------------------------------------------- 1 | FreeCAD addon manager: availableFreeCAD addon manageravailable -------------------------------------------------------------------------------- /Resources/Made-with-Python_.svg: -------------------------------------------------------------------------------- 1 | Made with: PythonMade withPython -------------------------------------------------------------------------------- /Resources/icons/Defeaturing-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 25 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 46 | 50 | 54 | 55 | 57 | 61 | 65 | 66 | 68 | 72 | 76 | 77 | 88 | 95 | 106 | 117 | 126 | 137 | 139 | 143 | 147 | 148 | 159 | 161 | 165 | 169 | 170 | 181 | 183 | 187 | 191 | 192 | 201 | 203 | 207 | 211 | 212 | 213 | 235 | 246 | 247 | 249 | 250 | 252 | image/svg+xml 253 | 255 | 256 | 257 | 258 | [Yorik van Havre] 259 | 260 | 261 | Arch_Pipe_Tree 262 | 2016-08-24 263 | http://www.freecadweb.org/wiki/index.php?title=Artwork 264 | 265 | 266 | FreeCAD 267 | 268 | 269 | FreeCAD/src/Mod/Arch/Resources/icons/Arch_Pipe_Tree.svg 270 | 271 | 272 | FreeCAD LGPL2+ 273 | 274 | 275 | https://www.gnu.org/copyleft/lesser.html 276 | 277 | 278 | [agryson] Alexander Gryson 279 | 280 | 281 | 282 | 283 | 284 | 288 | 291 | 297 | 303 | 310 | 318 | 326 | 330 | 337 | 344 | 345 | 346 | 347 | 348 | -------------------------------------------------------------------------------- /Resources/icons/DefeaturingParametric.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 25 | 29 | 33 | 34 | 36 | 40 | 44 | 45 | 47 | 51 | 55 | 56 | 58 | 62 | 66 | 67 | 74 | 85 | 96 | 98 | 102 | 106 | 107 | 118 | 128 | 137 | 147 | 158 | 168 | 171 | 175 | 179 | 180 | 190 | 193 | 197 | 201 | 202 | 213 | 216 | 220 | 224 | 225 | 236 | 246 | 249 | 253 | 257 | 258 | 268 | 271 | 275 | 279 | 280 | 290 | 293 | 297 | 301 | 302 | 312 | 315 | 319 | 323 | 324 | 335 | 345 | 347 | 351 | 355 | 356 | 359 | 363 | 367 | 368 | 369 | 388 | 399 | 400 | 402 | 403 | 405 | image/svg+xml 406 | 408 | 409 | 410 | 411 | [Stefan Tröger] 412 | 413 | 414 | PartDesign_Thickness 415 | 2015-05-21 416 | http://www.freecadweb.org/wiki/index.php?title=Artwork 417 | 418 | 419 | FreeCAD 420 | 421 | 422 | FreeCAD/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Thickness.svg 423 | 424 | 425 | FreeCAD LGPL2+ 426 | 427 | 428 | https://www.gnu.org/copyleft/lesser.html 429 | 430 | 431 | [agryson] Alexander Gryson 432 | 433 | 434 | 435 | 436 | 437 | 441 | 444 | 450 | 456 | 462 | 468 | 474 | 480 | 486 | 492 | 498 | 504 | 512 | 515 | 517 | 526 | 527 | 536 | 537 | 538 | 539 | 540 | -------------------------------------------------------------------------------- /Resources/icons/Freecad.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | image/svg+xml 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Resources/icons/FuzzyCommon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 26 | 30 | 34 | 35 | 37 | 41 | 45 | 46 | 53 | 64 | 66 | 70 | 74 | 75 | 77 | 81 | 85 | 86 | 97 | 99 | 103 | 107 | 108 | 119 | 130 | 132 | 136 | 140 | 141 | 152 | 155 | 159 | 163 | 164 | 165 | 184 | 195 | 196 | 198 | 199 | 201 | image/svg+xml 202 | 204 | 205 | 206 | 207 | [wmayer] 208 | 209 | 210 | Part_Common 211 | 2011-10-10 212 | http://www.freecadweb.org/wiki/index.php?title=Artwork 213 | 214 | 215 | FreeCAD 216 | 217 | 218 | FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Common.svg 219 | 220 | 221 | FreeCAD LGPL2+ 222 | 223 | 224 | https://www.gnu.org/copyleft/lesser.html 225 | 226 | 227 | [agryson] Alexander Gryson 228 | 229 | 230 | 231 | 232 | 233 | 237 | 240 | 247 | 254 | 260 | 266 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /Resources/icons/FuzzyCut.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 26 | 30 | 34 | 35 | 37 | 41 | 45 | 46 | 53 | 64 | 66 | 70 | 74 | 75 | 86 | 88 | 92 | 96 | 97 | 100 | 104 | 108 | 109 | 110 | 129 | 140 | 141 | 143 | 144 | 146 | image/svg+xml 147 | 149 | 150 | 151 | 152 | [wmayer] 153 | 154 | 155 | Part_Cut 156 | 2011-10-10 157 | http://www.freecadweb.org/wiki/index.php?title=Artwork 158 | 159 | 160 | FreeCAD 161 | 162 | 163 | FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Cut.svg 164 | 165 | 166 | FreeCAD LGPL2+ 167 | 168 | 169 | https://www.gnu.org/copyleft/lesser.html 170 | 171 | 172 | [agryson] Alexander Gryson 173 | 174 | 175 | 176 | 177 | 178 | 182 | 185 | 192 | 199 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /Resources/icons/FuzzyUnion.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 27 | 31 | 35 | 36 | 38 | 42 | 46 | 47 | 49 | 53 | 57 | 58 | 65 | 76 | 78 | 82 | 86 | 87 | 98 | 100 | 104 | 108 | 109 | 120 | 131 | 133 | 137 | 141 | 142 | 145 | 149 | 153 | 154 | 155 | 174 | 185 | 186 | 188 | 189 | 191 | image/svg+xml 192 | 194 | 195 | 196 | 197 | [wmayer] 198 | 199 | 200 | Part_Fuse 201 | 2011-10-10 202 | http://www.freecadweb.org/wiki/index.php?title=Artwork 203 | 204 | 205 | FreeCAD 206 | 207 | 208 | FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_ 209 | 210 | 211 | FreeCAD LGPL2+ 212 | 213 | 214 | https://www.gnu.org/copyleft/lesser.html 215 | 216 | 217 | [agryson] Alexander Gryson 218 | 219 | 220 | 221 | 222 | 223 | 227 | 232 | 238 | 243 | 244 | 245 | -------------------------------------------------------------------------------- /Resources/icons/Path-SelectLoop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | image/svg+xml 110 | 111 | 112 | Path-SelectLoop 113 | 2016-10-19 114 | http://www.freecadweb.org/wiki/index.php?title=Artwork 115 | 116 | 117 | FreeCAD 118 | 119 | 120 | FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-SelectLoop.svg 121 | 122 | 123 | FreeCAD LGPL2+ 124 | 125 | 126 | https://www.gnu.org/copyleft/lesser.html 127 | 128 | 129 | [agryson] Alexander Gryson 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /Resources/icons/RefineShapeFeature.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | image/svg+xml 88 | 89 | 90 | 91 | 92 | [Sebastian Hoogen] 93 | 94 | 95 | OpenSCAD_RefineShapeFeature 96 | 2012-05-03 97 | http://www.freecadweb.org/wiki/index.php?title=Artwork 98 | 99 | 100 | FreeCAD 101 | 102 | 103 | FreeCAD/src/Mod/OpenSCAD/Resources/icons/OpenSCAD_RefineShape 104 | 105 | 106 | FreeCAD LGPL2+ 107 | 108 | 109 | https://www.gnu.org/copyleft/lesser.html 110 | 111 | 112 | [agryson] Alexander Gryson 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /Resources/icons/centering-w.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 43 | 46 | 50 | 54 | 55 | 65 | 68 | 72 | 76 | 77 | 78 | 97 | 99 | 100 | 102 | image/svg+xml 103 | 105 | 106 | 107 | 108 | 109 | 114 | 117 | 123 | 129 | 130 | 133 | 140 | 147 | 154 | 161 | 167 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /Resources/icons/defeaturingTools.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 27 | 31 | 35 | 36 | 38 | 42 | 46 | 47 | 54 | 64 | 67 | 71 | 75 | 76 | 86 | 97 | 100 | 104 | 108 | 109 | 110 | 131 | 142 | 143 | 145 | 146 | 148 | image/svg+xml 149 | 151 | 152 | 153 | 154 | [wmayer] 155 | 156 | 157 | Part_Box 158 | 2011-10-10 159 | http://www.freecadweb.org/wiki/index.php?title=Artwork 160 | 161 | 162 | FreeCAD 163 | 164 | 165 | FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Box.svg 166 | 167 | 168 | FreeCAD LGPL2+ 169 | 170 | 171 | https://www.gnu.org/copyleft/lesser.html 172 | 173 | 174 | [agryson] Alexander Gryson 175 | 176 | 177 | 178 | 179 | 180 | 184 | 190 | 195 | 201 | 207 | 213 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /Resources/icons/error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | image/svg+xml 18 | 19 | 20 | Path-Stop 21 | 2015-07-04 22 | http://www.freecadweb.org/wiki/index.php?title=Artwork 23 | 24 | 25 | FreeCAD 26 | 27 | 28 | FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-Stop.svg 29 | 30 | 31 | FreeCAD LGPL2+ 32 | 33 | 34 | https://www.gnu.org/copyleft/lesser.html 35 | 36 | 37 | [agryson] Alexander Gryson 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Resources/made-with-python.svg: -------------------------------------------------------------------------------- 1 | made with: pythonmade withpython -------------------------------------------------------------------------------- /dft_locator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #**************************************************************************** 3 | #* * 4 | #* Kicad STEPUP (TM) (3D kicad board and models to STEP) for FreeCAD * 5 | #* 3D exporter for FreeCAD * 6 | #* Kicad STEPUP TOOLS (TM) (3D kicad board and models to STEP) for FreeCAD * 7 | #* Copyright (c) 2015 * 8 | #* Maurice easyw@katamail.com * 9 | #* * 10 | #* Kicad STEPUP (TM) is a TradeMark and cannot be freely usable * 11 | #* * 12 | 13 | 14 | import os, sys 15 | 16 | def module_path(): 17 | #return os.path.dirname(unicode(__file__, encoding)) 18 | return os.path.dirname(__file__) 19 | 20 | def abs_module_path(): 21 | #return os.path.dirname(unicode(__file__, encoding)) 22 | #return os.path.dirname(__file__) 23 | return os.path.realpath(__file__) 24 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | Defeaturing Workbench 4 | A set of tools to edit a Shape or a STEP model. 5 | 1.2.9 6 | Maui 7 | AGPLv3.0 8 | https://github.com/easyw/Defeaturing_WB 9 | Resources/icons/Defeaturing-icon.svg 10 | 11 | 12 | 13 | DefeaturingWB 14 | ./ 15 | 0.18.0 16 | defeaturing 17 | fuzzy 18 | step 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------