Arch: Walls can now be based on a selected face of a space

This commit is contained in:
Yorik van Havre 2013-09-06 17:49:26 -03:00
parent 6e66083d3a
commit 60a9b28244
2 changed files with 56 additions and 13 deletions

View File

@ -462,7 +462,13 @@ class ViewProviderComponent:
def claimChildren(self):
if hasattr(self,"Object"):
c = [self.Object.Base]+self.Object.Additions+self.Object.Subtractions
if Draft.getType(self.Object) != "Wall":
c = [self.Object.Base]
elif Draft.getType(self.Object.Base) == "Space":
c = []
else:
c = [self.Object.Base]
c = c + self.Object.Additions + self.Object.Subtractions
if hasattr(self.Object,"Fixtures"):
c.extend(self.Object.Fixtures)
if hasattr(self.Object,"Tool"):

View File

@ -21,7 +21,7 @@
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands
import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands,math
from FreeCAD import Vector
from PyQt4 import QtCore
from DraftTools import translate
@ -30,16 +30,18 @@ __title__="FreeCAD Wall"
__author__ = "Yorik van Havre"
__url__ = "http://free-cad.sourceforge.net"
def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",name=str(translate("Arch","Wall"))):
'''makeWall([obj],[length],[width],[height],[align],[name]): creates a wall based on the
def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",face=None,name=str(translate("Arch","Wall"))):
'''makeWall([obj],[length],[width],[height],[align],[face],[name]): creates a wall based on the
given object, which can be a sketch, a draft object, a face or a solid, or no object at
all, then you must provide length, width and height. Align
can be "Center","Left" or "Right"'''
all, then you must provide length, width and height. Align can be "Center","Left" or "Right",
face can be an index number of a face in the base object to base the wall on.'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
_Wall(obj)
_ViewProviderWall(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if face:
obj.Face = face
if length:
obj.Length = length
if width:
@ -48,7 +50,8 @@ def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",name
obj.Height = height
obj.Align = align
if obj.Base:
obj.Base.ViewObject.hide()
if Draft.getType(obj.Base) != "Space":
obj.Base.ViewObject.hide()
obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Wall")
return obj
@ -143,20 +146,34 @@ class _CommandWall:
self.Width = p.GetFloat("WallWidth",200)
self.Height = p.GetFloat("WallHeight",3000)
self.JOIN_WALLS = p.GetBool("joinWallSketches")
sel = FreeCADGui.Selection.getSelection()
sel = FreeCADGui.Selection.getSelectionEx()
done = False
self.existing = []
if sel:
# automatic mode
import Draft
if Draft.getType(sel[0]) != "Wall":
if Draft.getType(sel[0].Object) != "Wall":
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Wall")))
FreeCADGui.doCommand('import Arch')
for obj in sel:
FreeCADGui.doCommand('Arch.makeWall(FreeCAD.ActiveDocument.'+obj.Name+')')
for selobj in sel:
if Draft.getType(selobj.Object) == "Space":
spacedone = False
if selobj.HasSubObjects:
if "Face" in selobj.SubElementNames[0]:
idx = int(selobj.SubElementNames[0][4:])
FreeCADGui.doCommand("Arch.makeWall(FreeCAD.ActiveDocument."+selobj.Object.Name+",face="+str(idx)+")")
spacedone = True
if not spacedone:
FreeCADGui.doCommand('Arch.makeWall(FreeCAD.ActiveDocument.'+selobj.Object.Name+')')
else:
FreeCADGui.doCommand('Arch.makeWall(FreeCAD.ActiveDocument.'+selobj.Object.Name+')')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
done = True
if not done:
# interactive mode
import DraftTrackers
self.points = []
self.tracker = DraftTrackers.boxTracker()
@ -345,6 +362,8 @@ class _Wall(ArchComponent.Component):
str(translate("Arch","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)")))
obj.addProperty("App::PropertyBool","ForceWire","Base",
str(translate("Arch","If True, if this wall is based on a face, it will use its border wire as trace, and disconsider the face.")))
obj.addProperty("App::PropertyInteger","Face","Base",
str(translate("Arch","The face number of the base object used to build this wall")))
obj.Align = ['Left','Right','Center']
obj.ForceWire = False
self.Type = "Wall"
@ -357,7 +376,7 @@ class _Wall(ArchComponent.Component):
def onChanged(self,obj,prop):
self.hideSubobjects(obj,prop)
if prop in ["Base","Height","Width","Align","Additions","Subtractions"]:
if prop in ["Base","Height","Width","Align","Additions","Subtractions","Face"]:
self.createGeometry(obj)
# propagate movements to children windows
if prop == "Placement":
@ -455,7 +474,25 @@ class _Wall(ArchComponent.Component):
if not obj.Base.Shape.isNull():
if obj.Base.Shape.isValid():
base = obj.Base.Shape.copy()
if base.Solids:
face = None
if hasattr(obj,"Face"):
if obj.Face:
if len(base.Faces) >= obj.Face:
face = base.Faces[obj.Face-1]
if face:
# wall is based on a face
normal = face.normalAt(0,0)
if normal.getAngle(Vector(0,0,1)) > math.pi/4:
normal.multiply(width)
base = face.extrude(normal)
if obj.Align == "Center":
base.translate(normal.negative().multiply(0.5))
elif obj.Align == "Right":
base.translate(normal.negative())
else:
normal.multiply(height)
base = face.extrude(normal)
elif base.Solids:
pass
elif (len(base.Faces) == 1) and (not obj.ForceWire):
if height: