diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index 8a4decc85d..ca249c5c45 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -32,6 +32,7 @@ TODO put examples here. import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands,math from FreeCAD import Vector from draftutils import params +import ArchSketchObject if FreeCAD.GuiUp: import FreeCADGui @@ -162,11 +163,11 @@ class _Wall(ArchComponent.Component): # To be combined into Width when PropertyLengthList is available if not "OverrideWidth" in lp: - obj.addProperty("App::PropertyFloatList","OverrideWidth","Wall",QT_TRANSLATE_NOOP("App::Property","This overrides Width attribute to set width of each segment of wall. Ignored if Base object provides Widths information, with getWidths() method. (The 1st value override 'Width' attribute for 1st segment of wall; if a value is zero, 1st value of 'OverrideWidth' will be followed)")) # see DraftGeomUtils.offsetwire() - + obj.addProperty("App::PropertyFloatList","OverrideWidth","Wall",QT_TRANSLATE_NOOP("App::Property","This overrides Width attribute to set width of each segment of wall. Ignored if Base object provides Widths information, with getWidths() method (If a value is zero, the value of 'Width' will be followed). [ENHANCEMENT by ArchSketch] GUI 'Edit Wall Segment Width' Tool is provided in external SketchArch Add-on to let users to set the values interactively. 'Toponaming-Tolerant' if ArchSketch is used in Base (and SketchArch Add-on is installed). Warning : Not 'Toponaming-Tolerant' if just Sketch is used.")) # see DraftGeomUtils.offsetwire() if not "OverrideAlign" in lp: - obj.addProperty("App::PropertyStringList","OverrideAlign","Wall",QT_TRANSLATE_NOOP("App::Property","This overrides Align attribute to set Align of each segment of wall. Ignored if Base object provides Aligns information, with getAligns() method. (The 1st value override 'Align' attribute for 1st segment of wall; if a value is not 'Left, Right, Center', 1st value of 'OverrideAlign' will be followed)")) # see DraftGeomUtils.offsetwire() - + obj.addProperty("App::PropertyStringList","OverrideAlign","Wall",QT_TRANSLATE_NOOP("App::Property","This overrides Align attribute to set align of each segment of wall. Ignored if Base object provides Aligns information, with getAligns() method (If a value is not 'Left, Right, Center', the value of 'Align' will be followed). [ENHANCEMENT by ArchSketch] GUI 'Edit Wall Segment Align' Tool is provided in external SketchArch Add-on to let users to set the values interactively. 'Toponaming-Tolerant' if ArchSketch is used in Base (and SketchArch Add-on is installed). Warning : Not 'Toponaming-Tolerant' if just Sketch is used.")) # see DraftGeomUtils.offsetwire() + if not "OverrideOffset" in lp: + obj.addProperty("App::PropertyFloatList","OverrideOffset","Wall",QT_TRANSLATE_NOOP("App::Property","This overrides Offset attribute to set offset of each segment of wall. Ignored if Base object provides Offsets information, with getOffsets() method (If a value is zero, the value of 'Offset' will be followed). [ENHANCED by ArchSketch] GUI 'Edit Wall Segment Offset' Tool is provided in external Add-on ('SketchArch') to let users to select the edges interactively. 'Toponaming-Tolerant' if ArchSketch is used in Base (and SketchArch Add-on is installed). Warning : Not 'Toponaming-Tolerant' if just Sketch is used. Property is ignored if Base ArchSketch provided the selected edges. ")) # see DraftGeomUtils.offsetwire() if not "Height" in lp: obj.addProperty("App::PropertyLength","Height","Wall",QT_TRANSLATE_NOOP("App::Property","The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid")) if not "Area" in lp: @@ -620,6 +621,37 @@ class _Wall(ArchComponent.Component): # set 'default' align - for filling in any item in the list == 0 or None align = obj.Align # or aligns[0] + # Get offset of each edge segment from Base Objects if they store it + # (Adding support in SketchFeaturePython, DWire...) + offsets = [] # [] or None are both False + if obj.Base: + if hasattr(obj.Base, 'Proxy'): + if hasattr(obj.Base.Proxy, 'getOffsets'): + # Return a list of Offset corresponding to indexes of sorted + # edges of Sketch. + offsets = obj.Base.Proxy.getOffsets(obj.Base) + # Get offset of each edge/wall segment from ArchWall.OverrideOffset if + # Base Object does not provide it + if not offsets: + if obj.OverrideOffset: + if obj.Base.isDerivedFrom("Sketcher::SketchObject"): + # If Base Object is ordinary Sketch (or when ArchSketch.getOffsets() not implemented yet):- + # sort the offset list in OverrideOffset to correspond to indexes of sorted edges of Sketch + if hasattr(ArchSketchObject, 'sortSketchOffset'): + offsets = ArchSketchObject.sortSketchOffset(obj.Base, obj.OverrideOffset) + else: + offsets = obj.OverrideOffset + else: + # If Base Object is not Sketch, but e.g. DWire, the width + # list in OverrrideWidth just correspond to sequential + # order of edges + offsets = obj.OverrideOffset + elif obj.Offset: + offsets = [obj.Offset.Value] + + # Set 'default' offset - for filling in any item in the list == 0 or None + offset = obj.Offset.Value # could be 0 + height = obj.Height.Value if not height: height = self.getParentHeight(obj) @@ -695,6 +727,13 @@ class _Wall(ArchComponent.Component): else: base,placement = self.rebase(obj.Base.Shape) + elif hasattr(obj.Base, 'Proxy') and \ + hasattr(obj.Base.Proxy, 'getWallBaseShapeEdgesInfo'): + wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base) + #get wall edges (not wires); use original edges if getWallBaseShapeEdgesInfo() provided none + if wallBaseShapeEdgesInfo: + self.basewires = wallBaseShapeEdgesInfo.get('wallAxis') # 'wallEdges' # widths, aligns, offsets? + # Sort Sketch edges consistently with below procedures # without using Sketch.Shape.Edges - found the latter order # in some corner case != getSortedClusters() @@ -794,6 +833,14 @@ class _Wall(ArchComponent.Component): widths[n] = width except Exception: widths.append(width) + # Fill the offsets List with ArchWall's default + # offset entry and with same number of items as + # number of edges + try: + if not offsets[n]: + offsets[n] = offset + except Exception: + offsets.append(offset) # Get a direction vector orthogonal to both the # normal of the face/sketch and the direction the @@ -809,7 +856,7 @@ class _Wall(ArchComponent.Component): face = None curAligns = aligns[0] - off = obj.Offset.Value + #off = obj.Offset.Value # off is no longer used if curAligns == "Left": @@ -817,7 +864,8 @@ class _Wall(ArchComponent.Component): curWidth = [] for n in range(edgeNum): curWidth.append(abs(layers[i])) - off = off+layeroffset + #off = off+layeroffset # off is no longer used + offsets = [x+layeroffset for x in offsets] dvec.multiply(curWidth[0]) layeroffset += abs(curWidth[0]) else: @@ -841,8 +889,7 @@ class _Wall(ArchComponent.Component): offsetMode=None, alignList=aligns, normal=normal, - basewireOffset=off) - + basewireOffset=offsets) # Get the 'base' wire taking into account of # width and align of each edge w1 = DraftGeomUtils.offsetWire(wire, dvec, @@ -852,8 +899,7 @@ class _Wall(ArchComponent.Component): offsetMode="BasewireMode", alignList=aligns, normal=normal, - basewireOffset=off) - + basewireOffset=offsets) face = DraftGeomUtils.bind(w1, w2, per_segment=True) elif curAligns == "Right": @@ -863,7 +909,8 @@ class _Wall(ArchComponent.Component): curWidth = [] for n in range(edgeNum): curWidth.append(abs(layers[i])) - off = off+layeroffset + #off = off+layeroffset # off is no longer used + offsets = [x+layeroffset for x in offsets] dvec.multiply(curWidth[0]) layeroffset += abs(curWidth[0]) else: @@ -884,8 +931,7 @@ class _Wall(ArchComponent.Component): offsetMode=None, alignList=aligns, normal=normal, - basewireOffset=off) - + basewireOffset=offsets) w1 = DraftGeomUtils.offsetWire(wire, dvec, bind=False, occ=False, @@ -893,8 +939,7 @@ class _Wall(ArchComponent.Component): offsetMode="BasewireMode", alignList=aligns, normal=normal, - basewireOffset=off) - + basewireOffset=offsets) face = DraftGeomUtils.bind(w1, w2, per_segment=True) #elif obj.Align == "Center": @@ -919,7 +964,7 @@ class _Wall(ArchComponent.Component): offsetMode=None, alignList=aligns, normal=normal, - basewireOffset=off) + basewireOffset=offsets) w1 = DraftGeomUtils.offsetWire(wire, dvec, bind=False, occ=False, @@ -927,11 +972,13 @@ class _Wall(ArchComponent.Component): offsetMode="BasewireMode", alignList=aligns, normal=normal, - basewireOffset=off) + basewireOffset=offsets) face = DraftGeomUtils.bind(w1, w2, per_segment=True) del widths[0:edgeNum] del aligns[0:edgeNum] + del offsets[0:edgeNum] + if face: if layers and (layers[i] < 0): diff --git a/src/Mod/Draft/draftgeoutils/offsets.py b/src/Mod/Draft/draftgeoutils/offsets.py index 359fb8c7e4..8ef9fe1e48 100644 --- a/src/Mod/Draft/draftgeoutils/offsets.py +++ b/src/Mod/Draft/draftgeoutils/offsets.py @@ -195,7 +195,9 @@ def offsetWire(wire, dvec, bind=False, occ=False, in the wire with corresponding index. 'basewireOffset' corresponds to 'offset' in ArchWall which offset - the basewire before creating the wall outline + the basewire before creating the wall outline; or + it can be a list, e.g. corresponds to 'overrideOffset' in ArchWall, so + offset can be 'per segment' of wire, or 'per wall segment' in ArchWall OffsetWire() is now aware of width and align per edge Primarily for use with ArchWall based on Sketch object @@ -206,6 +208,7 @@ def offsetWire(wire, dvec, bind=False, occ=False, in this function if widthList and alignList are provided - 'dvec' to be obsolete in future? """ + if isinstance(wire, list) and isinstance(wire[0], Part.Edge): edges = wire.copy() wire = Part.Wire(edges) @@ -317,10 +320,15 @@ def offsetWire(wire, dvec, bind=False, occ=False, firstAlign = 'Left' alignListC.append('Left') + if not isinstance(basewireOffset, list): + basewireOffset = [basewireOffset] + else: + basewireOffset = basewireOffset # for backward compatability + for i in range(len(edges)): # make a copy so it do not reverse the self.baseWires edges # pointed to by _Wall.getExtrusionData()? - curredge = edges[i].copy() + curredge = Part.Shape(edges[i]).Edges[0] # saved memory? # record first edge's Orientation, Dir, Align and set Delta if i == 0: @@ -363,6 +371,12 @@ def offsetWire(wire, dvec, bind=False, occ=False, else: delta = DraftVecUtils.scaleTo(delta, dvec.Length) + # Consider individual offset distance + try: + currOffset = basewireOffset[i] + except: + currOffset = basewireOffset[0] # use first value + # Consider individual edge Align direction # - ArchWall should now always provide alignList if i == 0: @@ -404,8 +418,8 @@ def offsetWire(wire, dvec, bind=False, occ=False, # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) - if basewireOffset: - delta = DraftVecUtils.scaleTo(delta, basewireOffset) + if currOffset: + delta = DraftVecUtils.scaleTo(delta, currOffset) nedge = offset(curredge,delta,trim=True) else: nedge = curredge @@ -418,11 +432,10 @@ def offsetWire(wire, dvec, bind=False, occ=False, # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) - if basewireOffset: + if currOffset: if curAlign in ['Left', 'Right']: delta = DraftVecUtils.scaleTo(delta, - delta.Length + basewireOffset) - #else: # elif curAlign == 'Center': #pass # no need to add basewireOffset + delta.Length + currOffset) nedge = offset(curredge, delta, trim=True) # TODO arc always in counter-clockwise directinon @@ -452,8 +465,8 @@ def offsetWire(wire, dvec, bind=False, occ=False, # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) - if basewireOffset: - delta = DraftVecUtils.scaleTo(delta, basewireOffset) + if currOffset: + delta = DraftVecUtils.scaleTo(delta, currOffset) nedge = offset(curredge, delta, trim=True) else: nedge = curredge @@ -465,11 +478,10 @@ def offsetWire(wire, dvec, bind=False, occ=False, # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) - if basewireOffset: + if currOffset: delta = DraftVecUtils.scaleTo(delta, - delta.Length + basewireOffset) + delta.Length + currOffset) nedge = offset(curredge, delta, trim=True) - elif curAlign == 'Center': nedge = offset(curredge, delta, trim=True) if curOrientation == "Reversed":