From 78151a66d805bf9ad130b1a7faa72df78a1fdac0 Mon Sep 17 00:00:00 2001 From: Paul Lee Date: Sat, 14 Jan 2023 17:37:39 +0800 Subject: [PATCH] [ArchStructure] ArchSketch Feature : Select Edges to build shape Forum Discussion : [ArchSketch - Feature Preview] - Slab, Curtain Wall, ArchWall etc. on Same ArchSketch - https://forum.freecadweb.org/viewtopic.php?f=23&t=73018 --- src/Mod/Arch/ArchStructure.py | 56 +++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index c43333dc16..ad98574099 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -707,6 +707,17 @@ class _Structure(ArchComponent.Component): if not "FaceMaker" in pl: obj.addProperty("App::PropertyEnumeration","FaceMaker","Structure",QT_TRANSLATE_NOOP("App::Property","The facemaker type to use to build the profile of this object")) obj.FaceMaker = ["None","Simple","Cheese","Bullseye"] + if not "ArchSketchEdges" in pl: # PropertyStringList + obj.addProperty("App::PropertyStringList","ArchSketchEdges","Structure",QT_TRANSLATE_NOOP("App::Property","Selected edges (or group of edges) of the base ArchSketch, to use in creating the shape of this Arch Structure (instead of using all the Base shape's edges by default). Input are index numbers of edges or groups.")) + else: + # test if the property was added but as IntegerList, then update; + type = obj.getTypeIdOfProperty('ArchSketchEdges') + if type == "App::PropertyIntegerList": + oldIntValue = obj.ArchSketchEdges + newStrValue = [str(x) for x in oldIntValue] + obj.removeProperty("ArchSketchEdges") + obj.addProperty("App::PropertyStringList","ArchSketchEdges","Structure",QT_TRANSLATE_NOOP("App::Property","Selected edges (or group of edges) of the base ArchSketch, to use in creating the shape of this Arch Structure (instead of using all the Base shape's edges by default). Input are index numbers of edges or groups.")) + obj.ArchSketchEdges = newStrValue self.Type = "Structure" def onDocumentRestored(self,obj): @@ -723,10 +734,10 @@ class _Structure(ArchComponent.Component): if self.clone(obj): return - import Part, DraftGeomUtils base = None pl = obj.Placement extdata = self.getExtrusionData(obj) + if extdata: sh = extdata[0] if not isinstance(sh,list): @@ -827,15 +838,34 @@ class _Structure(ArchComponent.Component): else: baseface = obj.Base.Shape.copy() elif obj.Base.Shape.Wires: - if hasattr(obj,"FaceMaker"): - if obj.FaceMaker != "None": - try: - baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker)) - except Exception: - FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n") - return None + # ArchSketch feature : + # Get base shape wires, and faceMaker, for Structure (slab. etc.) from Base Objects if they store and provide by getStructureBaseShapeWires() + # (thickness, normal/extrusion, length, width, baseface maybe for later) of structure (slab etc.) + structureBaseShapeWires = None + baseShapeWires = None #baseSlabWires / baseSlabOpeningWires = None + faceMaker = None + if hasattr(obj.Base, 'Proxy'): + if hasattr(obj.Base.Proxy, 'getStructureBaseShapeWires'): + structureBaseShapeWires = obj.Base.Proxy.getStructureBaseShapeWires(obj.Base, archsketchEdges=obj.ArchSketchEdges) + # provide selected edges, or groups, in obj.ArchSketchEdges for processing in getStructureBaseShapeWires() (getSortedClusters) as override + # returned a {dict} ( or a [list] ) + # get slab wires; use original wires if structureBaseShapeWires() provided none + if structureBaseShapeWires: # would be false (none) if both base ArchSketch and obj do not have the edges stored / inputed by user + # if structureBaseShapeWires is {dict} + baseShapeWires = structureBaseShapeWires.get('slabWires') + faceMaker = structureBaseShapeWires.get('faceMaker') + if not baseShapeWires: + baseShapeWires = obj.Base.Shape.Wires + if faceMaker or (obj.FaceMaker != "None"): + if not faceMaker: + faceMaker = obj.FaceMaker + try: + baseface = Part.makeFace(baseShapeWires,"Part::FaceMaker"+str(faceMaker)) + except Exception: + FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n") + # Not returning even Part.makeFace fails, fall back to 'non-Part.makeFace' method if not baseface: - for w in obj.Base.Shape.Wires: + for w in baseShapeWires: if not w.isClosed(): p0 = w.OrderedVertexes[0].Point p1 = w.OrderedVertexes[-1].Point @@ -844,9 +874,11 @@ class _Structure(ArchComponent.Component): w.add(e) w.fix(0.1,0,1) # fixes self-intersecting wires f = Part.Face(w) + # check if it is 1st face (f) created from w in baseShapeWires; if not, fuse() if baseface: baseface = baseface.fuse(f) else: + # TODO use Part.Shape() rather than shape.copy() ... ? baseface = f.copy() elif length and width and height: if (length > height) and (IfcType != "Slab"): @@ -894,14 +926,14 @@ class _Structure(ArchComponent.Component): if obj.Normal.Length: normal = Vector(obj.Normal).normalize() else: - normal = baseface.Faces[0].normalAt(0, 0) + normal = baseface.Faces[0].normalAt(0, 0) ## TODO to use ArchSketch's 'normal' for consistency base = None placement = None inverse_placement = None if len(baseface.Faces) > 1: base = [] placement = [] - hint = baseface.Faces[0].normalAt(0, 0) + hint = baseface.Faces[0].normalAt(0, 0) ## TODO anything to do ? for f in baseface.Faces: bf, pf = self.rebase(f, hint) base.append(bf) @@ -1128,7 +1160,7 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent): else: ArchComponent.ViewProviderComponent.onChanged(self,vobj,prop) - def setEdit(self, vobj, mode): + def setEdit(self,vobj,mode): if mode != 0: return None