diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index ff65f9698b..12598f5a25 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -61,6 +61,7 @@ SET(Draft_utilities SET(Draft_functions draftfunctions/__init__.py draftfunctions/cut.py + draftfunctions/downgrade.py draftfunctions/draftify.py draftfunctions/fuse.py draftfunctions/heal.py diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 7f793e869e..673e03eadd 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -181,6 +181,8 @@ from draftutils.gui_utils import load_texture from draftfunctions.cut import cut +from draftfunctions.downgrade import downgrade + from draftfunctions.draftify import draftify from draftfunctions.fuse import fuse @@ -786,227 +788,6 @@ def makeDrawingView(obj,page,lwmod=None,tmod=None,otherProjection=None): -def downgrade(objects,delete=False,force=None): - """downgrade(objects,delete=False,force=None): Downgrades the given object(s) (can be - an object or a list of objects). If delete is True, old objects are deleted. - The force attribute can be used to - force a certain way of downgrading. It can be: explode, shapify, subtr, - splitFaces, cut2, getWire, splitWires, splitCompounds. - Returns a dictionary containing two lists, a list of new objects and a list - of objects to be deleted""" - - import Part, DraftGeomUtils - - if not isinstance(objects,list): - objects = [objects] - - global deleteList, addList - deleteList = [] - addList = [] - - # actions definitions - - def explode(obj): - """explodes a Draft block""" - pl = obj.Placement - newobj = [] - for o in obj.Components: - o.ViewObject.Visibility = True - o.Placement = o.Placement.multiply(pl) - if newobj: - deleteList(obj) - return newobj - return None - - def cut2(objects): - """cuts first object from the last one""" - newobj = cut(objects[0],objects[1]) - if newobj: - addList.append(newobj) - return newobj - return None - - def splitCompounds(objects): - """split solids contained in compound objects into new objects""" - result = False - for o in objects: - if o.Shape.Solids: - for s in o.Shape.Solids: - newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Solid") - newobj.Shape = s - addList.append(newobj) - result = True - deleteList.append(o) - return result - - def splitFaces(objects): - """split faces contained in objects into new objects""" - result = False - params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") - preserveFaceColor = params.GetBool("preserveFaceColor") # True - preserveFaceNames = params.GetBool("preserveFaceNames") # True - for o in objects: - voDColors = o.ViewObject.DiffuseColor if (preserveFaceColor and hasattr(o,'ViewObject')) else None - oLabel = o.Label if hasattr(o,'Label') else "" - if o.Shape.Faces: - for ind, f in enumerate(o.Shape.Faces): - newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Face") - newobj.Shape = f - if preserveFaceNames: - newobj.Label = "{} {}".format(oLabel, newobj.Label) - if preserveFaceColor: - """ At this point, some single-color objects might have - just a single entry in voDColors for all their faces; handle that""" - tcolor = voDColors[ind] if ind 1): - result = splitCompounds(objects) - #print(result) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found 1 multi-solids compound: exploding it")+"\n") - - # special case, we have one parametric object: we "de-parametrize" it - elif (len(objects) == 1) and hasattr(objects[0],'Shape') and hasattr(objects[0], 'Base'): - result = shapify(objects[0]) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found 1 parametric object: breaking its dependencies")+"\n") - addList.append(result) - #deleteList.append(objects[0]) - - # we have only 2 objects: cut 2nd from 1st - elif len(objects) == 2: - result = cut2(objects) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found 2 objects: subtracting them")+"\n") - - elif (len(faces) > 1): - - # one object with several faces: split it - if len(objects) == 1: - result = splitFaces(objects) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found several faces: splitting them")+"\n") - - # several objects: remove all the faces from the first one - else: - result = subtr(objects) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found several objects: subtracting them from the first one")+"\n") - - # only one face: we extract its wires - elif (len(faces) > 0): - result = getWire(objects[0]) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found 1 face: extracting its wires")+"\n") - - # no faces: split wire into single edges - elif not onlyedges: - result = splitWires(objects) - if result: - FreeCAD.Console.PrintMessage(translate("draft", "Found only wires: extracting their edges")+"\n") - - # no result has been obtained - if not result: - FreeCAD.Console.PrintMessage(translate("draft", "No more downgrade possible")+"\n") - - if delete: - names = [] - for o in deleteList: - names.append(o.Name) - deleteList = [] - for n in names: - FreeCAD.ActiveDocument.removeObject(n) - select(addList) - return [addList,deleteList] - - def getParameterFromV0(edge, offset): """return parameter at distance offset from edge.Vertexes[0] sb method in Part.TopoShapeEdge???""" diff --git a/src/Mod/Draft/draftfunctions/downgrade.py b/src/Mod/Draft/draftfunctions/downgrade.py new file mode 100644 index 0000000000..2b8bffefe4 --- /dev/null +++ b/src/Mod/Draft/draftfunctions/downgrade.py @@ -0,0 +1,274 @@ +# *************************************************************************** +# * Copyright (c) 2009, 2010 Yorik van Havre * +# * Copyright (c) 2009, 2010 Ken Cline * +# * Copyright (c) 2020 FreeCAD Developers * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * 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 Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** +"""This module provides the code for Draft offset function. +""" +## @package offset +# \ingroup DRAFT +# \brief This module provides the code for Draft offset function. + +import FreeCAD as App + +import draftutils.gui_utils as gui_utils +import draftutils.utils as utils + +from draftutils.translate import _tr + +from draftutils.utils import shapify +from draftfunctions.cut import cut + + +def downgrade(objects, delete=False, force=None): + """downgrade(objects,delete=False,force=None) + + Downgrade the given object(s) (can be an object or a list of objects). + + Parameters + ---------- + objects : + + delete : bool + If delete is True, old objects are deleted. + + force : string + The force attribute can be used to force a certain way of downgrading. + It can be: explode, shapify, subtr, splitFaces, cut2, getWire, + splitWires, splitCompounds. + + Return + ---------- + Returns a dictionary containing two lists, a list of new objects and a + list of objects to be deleted + """ + + import Part + import DraftGeomUtils + + if not isinstance(objects,list): + objects = [objects] + + global deleteList, addList + deleteList = [] + addList = [] + + # actions definitions + + def explode(obj): + """explodes a Draft block""" + pl = obj.Placement + newobj = [] + for o in obj.Components: + o.ViewObject.Visibility = True + o.Placement = o.Placement.multiply(pl) + if newobj: + deleteList(obj) + return newobj + return None + + def cut2(objects): + """cuts first object from the last one""" + newobj = cut(objects[0],objects[1]) + if newobj: + addList.append(newobj) + return newobj + return None + + def splitCompounds(objects): + """split solids contained in compound objects into new objects""" + result = False + for o in objects: + if o.Shape.Solids: + for s in o.Shape.Solids: + newobj = App.ActiveDocument.addObject("Part::Feature","Solid") + newobj.Shape = s + addList.append(newobj) + result = True + deleteList.append(o) + return result + + def splitFaces(objects): + """split faces contained in objects into new objects""" + result = False + params = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + preserveFaceColor = params.GetBool("preserveFaceColor") # True + preserveFaceNames = params.GetBool("preserveFaceNames") # True + for o in objects: + voDColors = o.ViewObject.DiffuseColor if (preserveFaceColor and hasattr(o,'ViewObject')) else None + oLabel = o.Label if hasattr(o,'Label') else "" + if o.Shape.Faces: + for ind, f in enumerate(o.Shape.Faces): + newobj = App.ActiveDocument.addObject("Part::Feature","Face") + newobj.Shape = f + if preserveFaceNames: + newobj.Label = "{} {}".format(oLabel, newobj.Label) + if preserveFaceColor: + """ At this point, some single-color objects might have + just a single entry in voDColors for all their faces; handle that""" + tcolor = voDColors[ind] if ind 1): + result = splitCompounds(objects) + #print(result) + if result: + App.Console.PrintMessage(_tr("Found 1 multi-solids compound: exploding it")+"\n") + + # special case, we have one parametric object: we "de-parametrize" it + elif (len(objects) == 1) and hasattr(objects[0],'Shape') and hasattr(objects[0], 'Base'): + result = shapify(objects[0]) + if result: + App.Console.PrintMessage(_tr("Found 1 parametric object: breaking its dependencies")+"\n") + addList.append(result) + #deleteList.append(objects[0]) + + # we have only 2 objects: cut 2nd from 1st + elif len(objects) == 2: + result = cut2(objects) + if result: + App.Console.PrintMessage(_tr("Found 2 objects: subtracting them")+"\n") + + elif (len(faces) > 1): + + # one object with several faces: split it + if len(objects) == 1: + result = splitFaces(objects) + if result: + App.Console.PrintMessage(_tr("Found several faces: splitting them")+"\n") + + # several objects: remove all the faces from the first one + else: + result = subtr(objects) + if result: + App.Console.PrintMessage(_tr("Found several objects: subtracting them from the first one")+"\n") + + # only one face: we extract its wires + elif (len(faces) > 0): + result = getWire(objects[0]) + if result: + App.Console.PrintMessage(_tr("Found 1 face: extracting its wires")+"\n") + + # no faces: split wire into single edges + elif not onlyedges: + result = splitWires(objects) + if result: + App.Console.PrintMessage(_tr("Found only wires: extracting their edges")+"\n") + + # no result has been obtained + if not result: + App.Console.PrintMessage(_tr("No more downgrade possible")+"\n") + + if delete: + names = [] + for o in deleteList: + names.append(o.Name) + deleteList = [] + for n in names: + App.ActiveDocument.removeObject(n) + gui_utils.select(addList) + return [addList,deleteList] +