Arch: stairs can now be based on an object

This commit is contained in:
Yorik van Havre
2013-08-30 20:04:27 -03:00
parent db52897ff2
commit c1a0e62d61

View File

@@ -26,10 +26,20 @@ from FreeCAD import Vector
from DraftTools import translate from DraftTools import translate
from PyQt4 import QtCore from PyQt4 import QtCore
def makeStairs(base=None,length=None,width=None,height=None):
def makeStairs(base=None,length=4.5,width=1,height=3,steps=17):
"""makeStairs([base,length,width,height,steps]): creates a Stairs
objects with given attributes."""
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Stairs") obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Stairs")
_Stairs(obj) _Stairs(obj)
_ViewProviderStairs(obj.ViewObject) _ViewProviderStairs(obj.ViewObject)
if base:
obj.Base = base
obj.Length = length
obj.Width = width
obj.Height = height
obj.NumberOfSteps = steps
class _CommandStairs: class _CommandStairs:
"the Arch Stairs command definition" "the Arch Stairs command definition"
@@ -40,12 +50,17 @@ class _CommandStairs:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Space","Creates a stairs objects")} 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Space","Creates a stairs objects")}
def Activated(self): def Activated(self):
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Space"))) FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Stairs")))
FreeCADGui.doCommand("import Arch") FreeCADGui.doCommand("import Arch")
FreeCADGui.doCommand("Arch.makeStairs()") if len(FreeCADGui.Selection.getSelection()) == 1:
n = FreeCADGui.Selection.getSelection()[0].Name
FreeCADGui.doCommand("Arch.makeStairs(base=FreeCAD.ActiveDocument."+n+")")
else:
FreeCADGui.doCommand("Arch.makeStairs()")
FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute() FreeCAD.ActiveDocument.recompute()
class _Stairs(ArchComponent.Component): class _Stairs(ArchComponent.Component):
"A stairs object" "A stairs object"
def __init__(self,obj): def __init__(self,obj):
@@ -100,13 +115,16 @@ class _Stairs(ArchComponent.Component):
if prop in ["Base"]: if prop in ["Base"]:
self.getShape(obj) self.getShape(obj)
elif prop in ["NumberOfSteps","Length","Height"]: elif prop in ["NumberOfSteps","Length","Height"]:
self.setStepData(obj) if obj.NumberOfSteps > 1:
l = obj.Length
def setStepData(self,obj): h = obj.Height
"sets step depth and height values" if obj.Base:
if obj.NumberOfSteps > 1: if obj.Base.isDerivedFrom("Part::Feature"):
obj.TreadDepth = float(obj.Length)/(obj.NumberOfSteps-1) l = obj.Base.Shape.Length
obj.RiserHeight = float(obj.Height)/obj.NumberOfSteps if obj.Base.Shape.BoundBox.ZLength:
h = obj.Base.Shape.BoundBox.ZLength
obj.TreadDepth = float(l)/(obj.NumberOfSteps-1)
obj.RiserHeight = float(h)/obj.NumberOfSteps
def makeStairsTread(self,basepoint,depthvec,widthvec,nosing=0,thickness=0): def makeStairsTread(self,basepoint,depthvec,widthvec,nosing=0,thickness=0):
"returns the shape of a single tread" "returns the shape of a single tread"
@@ -133,6 +151,8 @@ class _Stairs(ArchComponent.Component):
if thickness: if thickness:
if mode == "Massive": if mode == "Massive":
points = [basepoint] points = [basepoint]
#adding thread points
for i in range(nsteps-1): for i in range(nsteps-1):
last = points[-1] last = points[-1]
if i == 0: if i == 0:
@@ -142,22 +162,29 @@ class _Stairs(ArchComponent.Component):
points.extend([p1,p2]) points.extend([p1,p2])
resHeight1 = thickness*((math.sqrt(heightvec.Length**2 + depthvec.Length**2))/depthvec.Length) resHeight1 = thickness*((math.sqrt(heightvec.Length**2 + depthvec.Length**2))/depthvec.Length)
#print "lheight = ",heightvec.Length," ldepth = ",depthvec.Length," resheight1 = ",resHeight1 #print "lheight = ",heightvec.Length," ldepth = ",depthvec.Length," resheight1 = ",resHeight1
# adding closing points
last = points[-1] last = points[-1]
p1 = last.add(Vector(0,0,-resHeight1+abs(sthickness))) p1 = last.add(Vector(0,0,-resHeight1+abs(sthickness)))
resHeight2 = ((nsteps-1)*heightvec.Length)-resHeight1 resHeight2 = ((nsteps-1)*heightvec.Length)-resHeight1
resLength = (depthvec.Length/heightvec.Length)*resHeight2 resLength = (depthvec.Length/heightvec.Length)*resHeight2
p2 = p1.add(Vector(-resLength,0,-resHeight2)) hvec = DraftVecUtils.scaleTo(depthvec,-resLength)
p2 = p1.add(Vector(hvec.x,hvec.y,-resHeight2))
# making shape
points.extend([p1,p2,basepoint]) points.extend([p1,p2,basepoint])
struct = Part.Face(Part.makePolygon(points)) pol = Part.makePolygon(points)
#print points
struct = Part.Face(pol)
struct = struct.extrude(widthvec) struct = struct.extrude(widthvec)
return struct return struct
def align(self,basepoint,align,width): def align(self,basepoint,align,width,widthvec):
"moves a given basepoint according to the alignment" "moves a given basepoint according to the alignment"
if align == "Center": if align == "Center":
basepoint = basepoint.add(Vector(0,width/2,0)) basepoint = basepoint.add(DraftVecUtils.scaleTo(widthvec,-width/2))
elif align == "Right": elif align == "Right":
basepoint = basepoint.add(Vector(0,width,0)) basepoint = basepoint.add(DraftVecUtils.scaleTo(widthvec,-width))
return basepoint return basepoint
def getShape(self,obj): def getShape(self,obj):
@@ -165,15 +192,52 @@ class _Stairs(ArchComponent.Component):
steps = [] steps = []
structure = [] structure = []
pl = obj.Placement pl = obj.Placement
lstep = lheight = depthvec = widthvec = None
heightvec = basepoint = None
# base tests
if not obj.Width: if not obj.Width:
return return
if not obj.Height: if not obj.Height:
return if not obj.Base:
return
if obj.NumberOfSteps < 2: if obj.NumberOfSteps < 2:
return return
if obj.Base: if obj.Base:
pass
import Part,DraftGeomUtils
# we have a baseline, check it is valid
if not obj.Base.isDerivedFrom("Part::Feature"):
return
if not obj.Base.Shape.Edges:
return
if obj.Base.Shape.Faces:
return
if (len(obj.Base.Shape.Edges) == 1):
edge = obj.Base.Shape.Edges[0]
if isinstance(edge.Curve,Part.Line):
# case 1: only one straight edge
print "stair case 1"
v = DraftGeomUtils.vec(edge)
if round(v.z,Draft.precision()) != 0:
height = v.z
v = Vector(v.x,v.y,0)
else:
height = obj.Height
lstep = float(v.Length)/(obj.NumberOfSteps-1)
lheight = float(height)/obj.NumberOfSteps
depthvec = DraftVecUtils.scaleTo(v,lstep)
widthvec = DraftVecUtils.scaleTo(depthvec.cross(Vector(0,0,1)),obj.Width)
heightvec = Vector(0,0,lheight)
basepoint = edge.Vertexes[0].Point
else: else:
# no baseline, we calculate a simple, straight stair
if not obj.Length: if not obj.Length:
return return
@@ -183,18 +247,22 @@ class _Stairs(ArchComponent.Component):
depthvec = Vector(lstep,0,0) depthvec = Vector(lstep,0,0)
widthvec = Vector(0,-obj.Width,0) widthvec = Vector(0,-obj.Width,0)
heightvec = Vector(0,0,lheight) heightvec = Vector(0,0,lheight)
basepoint = Vector(0,0,0)
if depthvec and widthvec and heightvec and basepoint:
# making structure # making structure
basepoint = self.align(Vector(0,0,0),obj.Align,obj.Width) sbasepoint = self.align(basepoint,obj.Align,obj.Width,widthvec)
s = self.makeStairsStructure(obj.Structure,obj.NumberOfSteps,basepoint,depthvec, s = self.makeStairsStructure(obj.Structure,obj.NumberOfSteps,sbasepoint,depthvec,
widthvec,heightvec,obj.StructureThickness,obj.TreadThickness) widthvec,heightvec,obj.StructureThickness,obj.TreadThickness)
if s: if s:
structure.append(s) structure.append(s)
# making steps # making steps
for i in range(obj.NumberOfSteps-1): for i in range(obj.NumberOfSteps-1):
basepoint = self.align(Vector(i*lstep,0,(i+1)*lheight),obj.Align,obj.Width) tpoint = (Vector(depthvec).multiply(i)).add(Vector(heightvec).multiply(i+1))
s = self.makeStairsTread(basepoint,depthvec,widthvec,obj.Nosing,obj.TreadThickness) tbasepoint = self.align(basepoint.add(tpoint),obj.Align,obj.Width,widthvec)
s = self.makeStairsTread(tbasepoint,depthvec,widthvec,obj.Nosing,obj.TreadThickness)
if s: if s:
steps.append(s) steps.append(s)