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
This commit is contained in:
Yorik van Havre 2014-01-14 16:16:04 -02:00
parent e14a9e49d9
commit e352e169da
6 changed files with 72 additions and 48 deletions

View File

@ -321,6 +321,9 @@ class Component:
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 @@ class Component:
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 @@ class ViewProviderComponent:
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 @@ class ViewProviderComponent:
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"):

View File

@ -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 @@ class _Floor:
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

View File

@ -85,6 +85,7 @@ class _CommandRoof:
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 @@ class _Roof(ArchComponent.Component):
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 @@ class _Roof(ArchComponent.Component):
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 @@ class _Roof(ArchComponent.Component):
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"

View File

@ -546,7 +546,9 @@ class _Structure(ArchComponent.Component):
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 @@ class _Structure(ArchComponent.Component):
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

View File

@ -507,16 +507,16 @@ class _Wall(ArchComponent.Component):
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)

View File

@ -556,16 +556,17 @@ class Snapper:
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):