From e352e169da2578a388dcf89f981820eb87c8f3fb Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 14 Jan 2014 16:16:04 -0200 Subject: [PATCH] Arch: Automatic wall height - fixes #980 + Walls can now be capped by roofs, by subtracting a roof from them + Walls and Structs with height = 0 take height from their parent floor + Changing the placement of a floor changes all the placements of its children --- src/Mod/Arch/ArchComponent.py | 30 +++++++++++++++++------------- src/Mod/Arch/ArchFloor.py | 30 ++++++++++++++++++------------ src/Mod/Arch/ArchRoof.py | 22 ++++++++++++++-------- src/Mod/Arch/ArchStructure.py | 9 ++++++++- src/Mod/Arch/ArchWall.py | 8 ++++---- src/Mod/Draft/DraftSnap.py | 21 +++++++++++---------- 6 files changed, 72 insertions(+), 48 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 6dc766e9d60c..d09ce1145627 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -321,6 +321,9 @@ def hideSubobjects(self,obj,prop): if hasattr(obj,prop): for o in getattr(obj,prop): if Draft.getType(o) != "Window": + if (Draft.getType(obj) == "Wall"): + if (Draft.getType(o) == "Roof"): + continue o.ViewObject.hide() def processSubShapes(self,obj,base,pl=None): @@ -387,6 +390,13 @@ def processSubShapes(self,obj,base,pl=None): if pl: f.Placement = f.Placement.multiply(pl) base = base.cut(f) + + elif (Draft.getType(o) == "Roof") or (Draft.isClone(o,"Roof")): + # roofs define their own special subtraction volume + f = o.Proxy.getSubVolume(o) + if f: + if base.Solids and f.Solids: + base = base.cut(f) elif o.isDerivedFrom("Part::Feature"): if o.Shape: @@ -419,18 +429,7 @@ def getDisplayModes(self,vobj): return modes def setDisplayMode(self,mode): - if mode == "Detailed": - if hasattr(self,"Object"): - if hasattr(self.Object,"Fixtures"): - for f in self.Object.Fixtures: - f.ViewObject.show() - return "Flat Lines" - else: - if hasattr(self,"Object"): - if hasattr(self.Object,"Fixtures"): - for f in self.Object.Fixtures: - f.ViewObject.hide() - return mode + return mode def __getstate__(self): return None @@ -446,7 +445,12 @@ def claimChildren(self): c = [] else: c = [self.Object.Base] - c = c + self.Object.Additions + self.Object.Subtractions + c = c + self.Object.Additions + for s in self.Object.Subtractions: + if Draft.getType(self.Object) == "Wall": + if Draft.getType(s) == "Roof": + continue + c.append(s) if hasattr(self.Object,"Fixtures"): c.extend(self.Object.Fixtures) if hasattr(self.Object,"Armatures"): diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index 9179da18bba0..e1f9f2326b1a 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchCommands +import FreeCAD,FreeCADGui,Draft,ArchCommands, DraftVecUtils from PySide import QtCore from DraftTools import translate @@ -92,19 +92,25 @@ def __setstate__(self,state): self.Type = state def execute(self,obj): + # move children with this floor if hasattr(obj,"Placement"): - self.OldPlacement = obj.Placement.copy() + if not hasattr(self,"OldPlacement"): + self.OldPlacement = obj.Placement.copy() + else: + pl = obj.Placement.copy() + if not DraftVecUtils.equals(pl.Base,self.OldPlacement.Base): + print "placement moved" + delta = pl.Base.sub(self.OldPlacement.Base) + for o in obj.Group: + if hasattr(o,"Placement"): + o.Placement.move(delta) + self.OldPlacement = pl + # adjust childrens heights + for o in obj.Group: + if Draft.getType(o) in ["Wall","Structure"]: + if not o.Height: + o.Proxy.execute(o) - def onChanged(self,obj,prop): - self.Object = obj - if prop == "Placement": - if hasattr(self,"OldPlacement"): - delta = obj.Placement.Base.sub(self.OldPlacement.Base) - for o in obj.Group: - if hasattr(o,"Placement"): - o.Placement.move(delta) - self.OldPlacement = FreeCAD.Placement(obj.Placement) - def addObject(self,child): if hasattr(self,"Object"): g = self.Object.Group diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index d71fc6bfc62d..496bf1110753 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -85,6 +85,7 @@ def Activated(self): class _Roof(ArchComponent.Component): "The Roof object" + def __init__(self,obj): ArchComponent.Component.__init__(self,obj) obj.addProperty("App::PropertyAngle","Angle","Base", @@ -94,16 +95,9 @@ def __init__(self,obj): self.Type = "Roof" def execute(self,obj): - self.createGeometry(obj) - - def onChanged(self,obj,prop): - self.hideSubobjects(obj,prop) - if prop in ["Base","Face","Angle","Additions","Subtractions"]: - self.createGeometry(obj) - - def createGeometry(self,obj): import Part, math, DraftGeomUtils pl = obj.Placement + self.baseface = None base = None if obj.Base and obj.Angle: @@ -116,6 +110,7 @@ def createGeometry(self,obj): if w: if w.isClosed(): f = Part.Face(w) + self.baseface = f.copy() norm = f.normalAt(0,0) c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) d = f.BoundBox.DiagonalLength @@ -147,6 +142,17 @@ def createGeometry(self,obj): if not base.isNull(): obj.Shape = base + def getSubVolume(self,obj,extension=10000): + "returns a volume to be subtracted" + if hasattr(self,"baseface"): + if self.baseface: + norm = self.baseface.normalAt(0,0) + norm = DraftVecUtils.scaleTo(norm,extension) + return self.baseface.extrude(norm) + return None + + + class _ViewProviderRoof(ArchComponent.ViewProviderComponent): "A View Provider for the Roof object" diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 38b412f86229..36b6ec5ca285 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -546,7 +546,9 @@ def execute(self,obj): import Part, DraftGeomUtils # getting default values - height = width = length = 1 + length = 1 + width = 1 + height = 1 if hasattr(obj,"Length"): if obj.Length: length = obj.Length @@ -556,6 +558,11 @@ def execute(self,obj): if hasattr(obj,"Height"): if obj.Height: height = obj.Height + else: + for p in obj.InList: + if Draft.getType(p) == "Floor": + if p.Height: + height = p.Height # creating base shape pl = obj.Placement diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index f5bca95fd49f..3cf667ad85c6 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -507,16 +507,16 @@ def getDefaultValues(self,obj): if hasattr(obj,"Width"): if obj.Width: width = obj.Width - height = normal = None + height = 1 if hasattr(obj,"Height"): if obj.Height: height = obj.Height else: for p in obj.InList: if Draft.getType(p) == "Floor": - height = p.Height - if not height: - height = 1 + if p.Height: + height = p.Height + normal = None if hasattr(obj,"Normal"): if obj.Normal == Vector(0,0,0): normal = Vector(0,0,1) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index ca241ccb8a87..3d2301f3e502 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -556,16 +556,17 @@ def snapToPolar(self,point,last): v = DraftVecUtils.rotate(ax[1],math.radians(a),ax[2]) vecs.extend([v,v.negative()]) for v in vecs: - de = Part.Line(last,last.add(v)).toShape() - np = self.getPerpendicular(de,point) - if ((self.radius == 0) and (point.sub(last).getAngle(v) < 0.087)) \ - or ((np.sub(point)).Length < self.radius): - if self.tracker and not self.selectMode: - self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['parallel']) - self.tracker.on() - self.setCursor('ortho') - return np,de + if not DraftVecUtils.isNull(v): + de = Part.Line(last,last.add(v)).toShape() + np = self.getPerpendicular(de,point) + if ((self.radius == 0) and (point.sub(last).getAngle(v) < 0.087)) \ + or ((np.sub(point)).Length < self.radius): + if self.tracker and not self.selectMode: + self.tracker.setCoords(np) + self.tracker.setMarker(self.mk['parallel']) + self.tracker.on() + self.setCursor('ortho') + return np,de return point,None def snapToGrid(self,point):