Arch: stairs can now be based on an object
This commit is contained in:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user