Skip to content
Snippets Groups Projects
Commit 080e472e authored by Paul Marshall's avatar Paul Marshall
Browse files

add_mesh_stairs New add-on in development for quick staircase generation. ...

add_mesh_stairs New add-on in development for quick staircase generation.  Currently feature incomplete.
parent 5ab50f1f
No related branches found
No related tags found
No related merge requests found
# Paul "BrikBot" Marshall
# Created: July 24, 2011
# Last Modified: Spetember 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "StairBuilder",
"author": "Nick van Adium",
"version": (1,1),
"blender": (2, 5, 9),
"api": 40249,
"location": "View3D > Add > Stairs",
"description": "Creates a straight-run staircase with railings and stringer",
"warning": "Add-on is very feature incomplete beyond basic functionality.",
"wiki_url": "",
"tracker_url": "",
"category": "Add Mesh"}
if "bpy" in locals():
import imp
imp.reload(stairbuilder)
else:
from add_mesh_stairs import stairbuilder
import bpy
# Register:
def menu_func_stairs(self, context):
self.layout.operator(stairbuilder.stairs.bl_idname, text="StairBuilder", icon = "PLUGIN")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_mesh_add.append(menu_func_stairs)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_mesh_add.remove(menu_func_stairs)
if __name__ == "__main__":
register()
# Stairbuilder - General
#
# General is an object for creating meshes given the verts and faces.
# Stair Type (typ):
# - id1 = Freestanding staircase
# - id2 = Housed-open staircase
# - id3 = Box staircase
# - id4 = Circular staircase
#
# Paul "BrikBot" Marshall
# Created: September 19, 2011
# Last Modified: September 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
import bpy
from bpy_extras import object_utils
from math import atan
from mathutils import Vector
class General:
def __init__(self,rise,run,N):
self.stop=float(N)*Vector([run,0,rise])
self.slope=rise/run
self.angle=atan(self.slope)
#identical quads for all objects except stringer
self.faces=[[0,1,3,2],[0,1,5,4],[0,2,6,4],[4,5,7,6],[2,3,7,6],[1,3,7,5]]
def Make_mesh(self, verts, faces, name):
# Create new mesh
mesh = bpy.data.meshes.new(name)
# Make a mesh from a list of verts/edges/faces.
mesh.from_pydata(verts, [], faces)
# Set mesh to use auto smoothing:
mesh.use_auto_smooth = True
# Update mesh geometry after adding stuff.
mesh.update()
return object_utils.object_data_add(bpy.context, mesh, operator=None)
# Stairbuilder - Post generation
#
# Generates posts for stair generation.
# Stair Type (typ):
# - id1 = Freestanding staircase
# - id2 = Housed-open staircase
# - id3 = Box staircase
# - id4 = Circular staircase
#
# Paul "BrikBot" Marshall
# Created: September 19, 2011
# Last Modified: September 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
from mathutils import Vector
class Posts:
def __init__(self,G,rise,run,d,w,wT,nP,hR,tR, rEnable, lEnable):
self.G = G #General
self.rise = rise #Stair rise
self.run = run #Stair run
self.x1=Vector([0,0,hR-tR]) #rail start
self.x2=G.stop+Vector([0,0,hR-tR]) #rail stop
self.d=d #post depth
self.w=w #post width
self.wT=wT #tread width
self.nP=nP #number of posts
self.sp=Vector([(self.x2[0]-self.x1[0])/float(nP+1),0,0]) #spacing between posts
self.rEnable = rEnable
self.lEnable = lEnable
self.Create()
def Intersect(self,i,d):
'''find intersection point, x, for rail and post'''
x3=self.x1+i*self.sp+Vector([d,d,d])
x4=x3+Vector([0,0,self.x2[-1]])
a=self.x2-self.x1
b=x4-x3
c=x3-self.x1
cr_ab=a.cross(b)
mag_cr_ab=(cr_ab * cr_ab)
return self.x1+a*((c.cross(b).dot(cr_ab))/mag_cr_ab)
def Create(self):
for i in range(0,self.nP+2,1):
coords = []
#intersections with rail
coords.append(self.Intersect(i,0.0))
coords.append(self.Intersect(i,self.d))
#intersections with tread
coords.append(Vector([self.x1[0]+i*self.sp[0],0,
int(coords[0][0]/self.run)*self.rise]))
coords.append(coords[2]+Vector([self.d,0,0]))
#inner face
for j in range(4):
coords.append(coords[j]+Vector([0,self.w,0]))
if self.rEnable:
self.G.Make_mesh(coords, self.G.faces, 'posts')
if self.lEnable:
#make post on other side of steps as well
for j in coords:
j += Vector([0,self.wT-self.w,0])
self.G.Make_mesh(coords, self.G.faces, 'posts')
# Stairbuilder - Retainer generation
#
# Generates retainers for stair generation.
# Stair Type (typ):
# - id1 = Freestanding staircase
# - id2 = Housed-open staircase
# - id3 = Box staircase
# - id4 = Circular staircase
#
# Paul "BrikBot" Marshall
# Created: September 19, 2011
# Last Modified: September 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
from math import tan
from mathutils import Vector
class Rails:
def __init__(self,G,w,t,h,tT,wP,dP,wT, rEnable, lEnable):
self.G = G #General
self.w=w #rail width
self.t=t #rail thickness
self.h=h #rail height
self.start=Vector([0,0,self.h-self.t]) #rail start
self.stop=G.stop+Vector([0,0,self.h-self.t]) #rail stop
self.tT=tT #tread toe
self.wP=wP #post width
self.dP=dP #post depth
self.wT=wT #tread width
self.rEnable = rEnable
self.lEnable = lEnable
self.Create()
def Create(self):
#determine offset to include railing toe
offset=Vector([self.tT,0,self.tT*tan(self.G.angle)])
coords = []
coords.append(self.start-offset)
coords.append(self.stop+offset+Vector([self.dP,0,
self.dP*tan(self.G.angle)]))
coords.append(self.start-offset+Vector([0,self.w,0]))
coords.append(self.stop+offset+Vector([self.dP,self.w,
self.dP*tan(self.G.angle)]))
for j in range(4):
coords.append(coords[j]+Vector([0,0,self.t]))
#centre over posts
for j in coords:
j += Vector([0,0.5*(-self.w+self.wP),0])
if self.rEnable:
self.G.Make_mesh(coords, self.G.faces, 'rails')
if self.lEnable:
#make rail on other side
for j in coords:
j += Vector([0,self.wT-self.wP,0])
self.G.Make_mesh(coords, self.G.faces, 'rails')
# Stairbuilder - Retainer generation
#
# Generates retainers for stair generation.
# Stair Type (typ):
# - id1 = Freestanding staircase
# - id2 = Housed-open staircase
# - id3 = Box staircase
# - id4 = Circular staircase
#
# Paul "BrikBot" Marshall
# Created: September 19, 2011
# Last Modified: September 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
from mathutils import Vector
class Retainers:
def __init__(self,G,w,h,wP,wT,hR,n, rEnable, lEnable):
self.G = G #General
self.w=w #retainer width
self.h=h #retainer height
self.wP=wP #post width
self.wT=wT #tread width
self.nR=n #number of retainers
self.sp=hR/float(n+1) #retainer spacing
self.rEnable = rEnable
self.lEnable = lEnable
self.Create()
def Create(self):
for i in range(self.nR):
coords = []
offset=(i+1)*Vector([0,0,self.sp])
coords.append(offset)
coords.append(self.G.stop + offset)
coords.append(offset + Vector([0,self.w,0]))
coords.append(self.G.stop + offset + Vector([0,self.w,0]))
for j in range(4):
coords.append(coords[j] + Vector([0,0,self.h]))
#centre in posts
for j in coords:
j += Vector([0,0.5*(self.wP-self.w),0])
if self.rEnable:
self.G.Make_mesh(coords, self.G.faces, 'retainers')
if self.lEnable:
#make retainer on other side
for j in coords:
j += Vector([0,self.wT-self.wP,0])
self.G.Make_mesh(coords,self.G.faces, 'retainers')
This diff is collapsed.
# Stairbuilder - Stringer generation
#
# Generates stringer mesh for stair generation.
# Stair Type (typ):
# - id1 = Freestanding staircase
# - id2 = Housed-open staircase
# - id3 = Box staircase
# - id4 = Circular staircase
# Stringer Type (typ_s):
# - sId1 = Classic
# - sId2 = I-Beam
# - sId3 = C-Beam
#
# Paul "BrikBot" Marshall
# Created: September 19, 2011
# Last Modified: September 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
from math import atan, cos, tan
from mathutils import Vector
from mathutils.geometry import (intersect_line_plane,
intersect_line_line)
class Stringer:
def __init__(self,G,typ,typ_s,rise,run,w,h,nT,hT,wT,tT,tO,tw,tf,tp,g,nS = 1,notMulti=True):
self.G = G #General
self.typ = typ # Stair type
self.typ_s = typ_s # Stringer type
self.rise = rise #Stair rise
self.run = run #Stair run
if notMulti:
self.w=w/100 #stringer width
else:
self.w=(wT*(w/100))/nS
self.h = h #stringer height
self.nT=nT #number of treads
self.hT=hT #tread height
self.wT=wT #tread width
self.tT=tT #tread toe
self.tO = tO #Tread overhang
self.tw = self.w * (tw / 100) #stringer web thickness
self.tf = tf #stringer flange thickness
self.tp = 1 - (tp / 100) #stringer flange taper
self.g = g #does stringer intersect the ground?
self.nS=nS #number of stringers
# Default stringer object (classic / sId1):
self.faces1=[[0,1,3,2],[1,5,3],[3,5,4],[6,7,9,8],[7,11,9],[9,11,10],
[0,2,8,6],[0,1,7,6],[1,5,11,7],[2,3,9,8],[3,4,10,9],[4,5,11,10]]
# Box stair type stringer:
self.faces2=[[0,1,7,6],[1,3,9,7],[3,4,10,9],[4,10,11,5],[5,11,8,2],
[2,8,6,0],[0,1,2],[1,2,5,3],[3,4,5],[6,7,8],[7,8,11,9],[9,10,11]]
# I-beam stringer (I-Beam / sId2 / Taper < 100%):
# @todo: faces are not complete nor are they layed out correctly. Check verts also.
self.faces3a=[[0,1,17,16],[1,2,18,17],[2,3,19,18],[3,4,20,19],[4,5,21,20],[5,6,22,21],
[6,7,23,22],[7,8,24,23],[8,9,25,24],[9,10,26,25],[10,11,27,26],
[11,12,28,27],[12,13,29,28],[13,14,30,29],[14,15,31,30],[15,0,16,31],
[0,1,2,15],[2,11,14,15],[11,12,13,14],[2,3,10,11],[3,4,5,6],[3,6,7,10],
[7,8,9,10],[16,17,18,31],[18,27,30,31],[27,28,29,30],[18,19,26,27],
[19,20,21,22],[19,22,23,26],[23,24,25,26]]
# I-beam stringer (I-Beam / sId2 / Taper = 100%):
self.faces3b=[[0,1,9,8],[1,2,10,9],[2,3,11,10],[3,4,12,11],[4,5,13,12],[5,6,14,13],
[6,7,15,14],[7,0,8,15],[0,1,6,7],[1,2,5,6],[2,3,4,5],[8,9,14,15],
[9,10,13,14],[10,11,12,13]]
# I-beam stringer for housed-open stringed:
self.faces3c=[[0,1,2,7],[2,3,6,7],[3,4,5,6],[1,2,23,16],[2,3,22,23],[3,4,21,22],
[16,17,18,23],[18,19,22,23],[19,20,21,22],[17,8,15,18],[18,15,14,19],
[19,14,13,20],[8,9,10,15],[10,11,14,15],[11,12,13,14],[9,10,53,52],
[10,11,54,53],[11,12,55,54],[52,53,61,60],[53,54,62,61],[54,55,63,62],
[60,61,34,33],[61,62,35,34],[62,63,36,35],[32,33,34,39],[34,35,38,39],
[35,36,37,38],[41,32,39,42],[42,39,38,43],[43,38,37,44],[40,41,42,47],
[42,43,46,47],[43,44,45,46],[25,26,47,40],[26,27,46,47],[27,28,45,46],
[24,25,26,31],[26,27,30,31],[27,28,29,30],[24,31,57,56],[31,30,58,57],
[30,29,59,58],[48,49,57,56],[49,50,58,57],[50,51,59,58],[0,7,49,48],
[7,6,50,49],[6,5,51,50],[0,1,16,48],[16,40,56,48],[24,25,40,56],
[16,17,41,40],[8,9,52,17],[17,52,60,41],[32,33,60,41],[12,13,20,55],
[20,44,63,55],[37,44,63,36],[20,21,45,44],[28,29,51,21],[21,51,59,45],
[28,45,59,29],[4,5,51,21]]
# C-beam stringer (C-Beam / sId3):
self.faces4=[[]]
self.Create()
def Create(self):
if self.typ == "id1":
if self.typ_s == "sId1":
offset = (self.wT / (self.nS + 1)) - (self.w / 2)
for i in range(self.nS):
for j in range(self.nT):
coords = []
coords.append(Vector([0, offset, -self.rise]))
coords.append(Vector([self.run, offset, -self.rise]))
coords.append(Vector([0, offset, -self.hT]))
coords.append(Vector([self.run, offset, -self.hT]))
coords.append(Vector([self.run, offset, 0]))
coords.append(Vector([self.run * 2, offset, 0]))
for k in range(6):
coords.append(coords[k]+Vector([0, self.w, 0]))
for k in coords:
k += j*Vector([self.run, 0, self.rise])
self.G.Make_mesh(coords,self.faces1,'stringer')
offset += self.wT / (self.nS + 1)
elif self.typ_s == "sId2":
self.IBeam()
elif self.typ == "id2":
if self.typ_s == "sId1":
coords = []
coords.append(Vector([-self.tT, -self.w, -self.rise]))
coords.append(Vector([self.hT / self.G.slope, -self.w, -self.rise]))
coords.append(Vector([-self.tT, -self.w, 0]))
coords.append(Vector([self.nT * self.run, -self.w,
((self.nT - 1) * self.rise) - self.hT]))
coords.append(Vector([self.nT * self.run, -self.w, self.nT * self.rise]))
coords.append(Vector([(self.nT * self.run) - self.tT, -self.w,
self.nT * self.rise]))
for i in range(6):
coords.append(coords[i] + Vector([0, self.w, 0]))
self.G.Make_mesh(coords, self.faces2, 'stringer')
for i in coords:
i += Vector([0, self.w + self.wT, 0])
self.G.Make_mesh(coords, self.faces2, 'stringer')
elif self.typ_s == "sId2":
self.HousedIBeam()
elif self.typ == "id3":
h = (self.rise - self.hT) - self.rise #height of top section
for i in range(self.nT):
coords = []
coords.append(Vector([i * self.run,0,-self.rise]))
coords.append(Vector([(i + 1) * self.run,0,-self.rise]))
coords.append(Vector([i * self.run,0,h + (i * self.rise)]))
coords.append(Vector([(i + 1) * self.run,0,h + (i * self.rise)]))
for j in range(4):
coords.append(coords[j] + Vector([0,self.wT,0]))
self.G.Make_mesh(coords, self.G.faces, 'stringer')
def IBeam(self):
mid = self.w / 2
web = self.tw / 2
# Bottom of the stringer:
baseZ = -self.rise - self.hT - self.h
# Top of the strigner:
topZ = -self.rise - self.hT
# Vertical taper amount:
taper = self.tf * self.tp
offset = (self.wT / (self.nS + 1)) - mid
# taper < 100%:
if self.tp > 0:
for i in range(self.nS):
coords = []
coords.append(Vector([0, offset, baseZ]))
coords.append(Vector([0, offset, baseZ + taper]))
coords.append(Vector([0, offset + (mid - web), baseZ + self.tf]))
coords.append(Vector([0, offset + (mid - web), topZ - self.tf]))
coords.append(Vector([0, offset, topZ - taper]))
coords.append(Vector([0, offset, topZ]))
coords.append(Vector([0, offset + (mid - web), topZ]))
coords.append(Vector([0, offset + (mid + web), topZ]))
coords.append(Vector([0, offset + self.w, topZ]))
coords.append(Vector([0, offset + self.w, topZ - taper]))
coords.append(Vector([0, offset + (mid + web), topZ - self.tf]))
coords.append(Vector([0, offset + (mid + web), baseZ + self.tf]))
coords.append(Vector([0, offset + self.w, baseZ + taper]))
coords.append(Vector([0, offset + self.w, baseZ]))
coords.append(Vector([0, offset + (mid + web), baseZ]))
coords.append(Vector([0, offset + (mid - web), baseZ]))
for j in range(16):
coords.append(coords[j]+Vector([self.run * self.nT, 0, self.rise * self.nT]))
# If the bottom meets the ground:
# Bottom be flat with the xy plane, but shifted down.
# Either project onto the plane along a vector (hard) or use the built in
# interest found in mathutils.geometry (easy). Using intersect:
if self.g:
for j in range(16):
coords[j] = intersect_line_plane(coords[j], coords[j + 16],
Vector([0, 0, topZ]),
Vector([0, 0, 1]))
self.G.Make_mesh(coords, self.faces3a, 'stringer')
offset += self.wT / (self.nS + 1)
# taper = 100%:
else:
for i in range(self.nS):
coords = []
coords.append(Vector([0, offset, baseZ]))
coords.append(Vector([0, offset + (mid - web), baseZ + self.tf]))
coords.append(Vector([0, offset + (mid - web), topZ - self.tf]))
coords.append(Vector([0, offset, topZ]))
coords.append(Vector([0, offset + self.w, topZ]))
coords.append(Vector([0, offset + (mid + web), topZ - self.tf]))
coords.append(Vector([0, offset + (mid + web), baseZ + self.tf]))
coords.append(Vector([0, offset + self.w, baseZ]))
for j in range(8):
coords.append(coords[j]+Vector([self.run * self.nT, 0, self.rise * self.nT]))
self.G.Make_mesh(coords, self.faces3b, 'stringer')
offset += self.wT / (self.nS + 1)
return {'FINISHED'}
def HousedIBeam(self):
webOrth = Vector([self.rise, 0, -self.run]).normalized()
webHeight = Vector([self.run + self.tT, 0, -self.hT]).project(webOrth).length
vDelta_1 = self.tf * tan(self.G.angle)
vDelta_2 = (self.rise * (self.nT - 1)) - (webHeight + self.tf)
flange_y = (self.w - self.tw) / 2
front = -self.tT - self.tf
outer = -self.tO - self.tw - flange_y
coords = []
if self.tp > 0:
# Upper-Outer flange:
coords.append(Vector([front, outer, -self.rise]))
coords.append(Vector([-self.tT, outer, -self.rise]))
coords.append(Vector([-self.tT, outer, 0]))
coords.append(Vector([(self.run * (self.nT - 1)) - self.tT, outer,
self.rise * (self.nT - 1)]))
coords.append(Vector([self.run * self.nT, outer,
self.rise * (self.nT - 1)]))
coords.append(Vector([self.run * self.nT, outer,
(self.rise * (self.nT - 1)) + self.tf]))
coords.append(Vector([(self.run * (self.nT - 1)) - self.tT, outer,
(self.rise * (self.nT - 1)) + self.tf]))
coords.append(Vector([front, outer, self.tf - vDelta_1]))
# Lower-Outer flange:
coords.append(coords[0] + Vector([self.tf + webHeight, 0, 0]))
coords.append(coords[1] + Vector([self.tf + webHeight, 0, 0]))
coords.append(intersect_line_line(coords[9],
coords[9] - Vector([0, 0, 1]),
Vector([self.run, 0, -self.hT - self.tf]),
Vector([self.run * 2, 0, self.rise - self.hT - self.tf]))[0])
coords.append(Vector([(self.run * self.nT) - ((webHeight - self.hT) / tan(self.G.angle)),
outer, vDelta_2]))
coords.append(coords[4] - Vector([0, 0, self.tf + webHeight]))
coords.append(coords[5] - Vector([0, 0, self.tf + webHeight]))
coords.append(coords[11] + Vector([0, 0, self.tf]))
coords.append(intersect_line_line(coords[8],
coords[8] - Vector([0, 0, 1]),
Vector([self.run, 0, -self.hT]),
Vector([self.run * 2, 0, self.rise - self.hT]))[0])
# Outer web:
coords.append(coords[1] + Vector([0, flange_y, 0]))
coords.append(coords[8] + Vector([0, flange_y, 0]))
coords.append(coords[15] + Vector([0, flange_y, 0]))
coords.append(coords[14] + Vector([0, flange_y, 0]))
coords.append(coords[13] + Vector([0, flange_y, 0]))
coords.append(coords[4] + Vector([0, flange_y, 0]))
coords.append(coords[3] + Vector([0, flange_y, 0]))
coords.append(coords[2] + Vector([0, flange_y, 0]))
# Upper-Inner flange and lower-inner flange:
for i in range(16):
coords.append(coords[i] + Vector([0, self.w, 0]))
# Inner web:
for i in range(8):
coords.append(coords[i + 16] + Vector([0, self.tw, 0]))
# Mid nodes to so faces will be quads:
for i in [0,7,6,5,9,10,11,12]:
coords.append(coords[i] + Vector([0, flange_y, 0]))
for i in range(8):
coords.append(coords[i + 48] + Vector([0, self.tw, 0]))
self.G.Make_mesh(coords, self.faces3c, 'stringer')
for i in coords:
i += Vector([0, (self.tO * 2) + self.wT + self.tf, 0])
self.G.Make_mesh(coords, self.faces3c, 'stringer')
return {'FINISHED'}
def CBeam(self):
return {'FINISHED'}
# Stairbuilder - Tread generation
#
# Generates treads for stair generation.
# Stair Type (typ):
# - id1 = Freestanding staircase
# - id2 = Housed-open staircase
# - id3 = Box staircase
# - id4 = Circular staircase
# Tread Type (typ_t):
# - tId1 = Classic
# - tId2 = Basic Steel
# - tId3 = Bar 1
# - tId4 = Bar 2
# - tId5 = Bar 3
#
# Paul "BrikBot" Marshall
# Created: September 19, 2011
# Last Modified: September 20, 2011
# Homepage (blog): http://post.darkarsenic.com/
# //blog.darkarsenic.com/
#
# Coded in IDLE, tested in Blender 2.59.
# Search for "@todo" to quickly find sections that need work.
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# The Blender Rock Creation tool is for rapid generation of mesh rocks in Blender.
# Copyright (C) 2011 Paul Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
from copy import copy
from math import sqrt
from mathutils import Vector
class Treads:
def __init__(self,G,typ,typ_t,run,w,h,d,r,toe,o,n,tk,sec,sp,sn):
self.G = G #General
self.typ = typ #Stair type
self.typ_t = typ_t #Tread type
self.run = run #Stair run
self.w=w #tread width
self.h=h #tread height
self.d=d #tread run
self.r=r #tread rise
self.t=toe #tread nosing
self.o=o #tread side overhang
self.n=n #number of treads
self.tk=tk #thickness of tread metal
self.sec=sec #metal sections for tread
if sec != 1 and typ_t not in ["tId4", "tId5"]:
self.sp=((d+toe)*(sp/100))/(sec-1) #spacing between sections (% of depth)
elif typ_t in ["tId4", "tId5"]:
self.sp=sp/100 #keep % value
else:
self.sp=0
self.sn=sn #number of cross sections
self.tId2_faces = [[0,1,2,3],[0,3,4,5],[4,5,6,7],[6,7,8,9],[8,9,10,11],
[12,13,14,15],[12,15,16,17],[16,17,18,19],
[18,19,20,21],[20,21,22,23],[0,1,13,12],[1,2,14,13],
[2,3,15,14],[3,4,16,15],[4,7,19,16],[7,8,20,19],
[8,11,23,20],[11,10,22,23],[10,9,21,22],[9,6,18,21],
[6,5,17,18],[5,0,12,17]]
self.out_faces = [[0,2,3,1],[0,2,10,8],[9,11,3,1],[9,11,10,8],
[2,6,7,3],[2,6,14,10],[11,15,7,3],[11,15,14,10],
[0,4,5,1],[0,4,12,8],[9,13,5,1],[9,13,12,8],
[4,6,7,5],[4,6,14,12],[13,15,14,12],[13,15,7,5]]
self.Create()
def Create(self):
# Setup the coordinates:
coords = []
coords2 = []
coords3 = []
cross = 0
cW = 0
depth = 0
offset = 0
height = 0
if self.typ in ["id1", "id2", "id3"]:
if self.typ_t == "tId1":
coords.append(Vector([-self.t,-self.o,0]))
coords.append(Vector([self.d,-self.o,0]))
coords.append(Vector([-self.t,self.w + self.o,0]))
coords.append(Vector([self.d,self.w + self.o,0]))
for i in range(4):
coords.append(coords[i]+Vector([0,0,-self.h]))
elif self.typ_t == "tId2":
depth = (self.d + self.t - (self.sec - 1) * self.sp) / self.sec
inset = depth / 4
tDepth = depth - self.t
coords.append(Vector([-self.t, -self.o, -self.h])) #0
coords.append(Vector([inset - self.t, -self.o, -self.h])) #1
coords.append(Vector([inset - self.t, -self.o, -self.h + self.tk])) #2
coords.append(Vector([self.tk - self.t, -self.o, -self.h + self.tk])) #3
coords.append(Vector([self.tk - self.t, -self.o, -self.tk])) #4
coords.append(Vector([-self.t, -self.o, 0])) #5
coords.append(Vector([tDepth, -self.o, 0])) #6
coords.append(Vector([tDepth - self.tk, -self.o, -self.tk])) #7
coords.append(Vector([tDepth - self.tk, -self.o, self.tk - self.h])) #8
coords.append(Vector([tDepth, -self.o, -self.h])) #9
coords.append(Vector([tDepth - inset, -self.o, -self.h])) #10
coords.append(Vector([tDepth - inset, -self.o, -self.h + self.tk])) #11
for i in range(12):
coords.append(coords[i] + Vector([0, self.w + (2 * self.o), 0]))
elif self.typ_t in ["tId3", "tId4", "tId5"]:
# Frame:
coords.append(Vector([-self.t,-self.o,-self.h]))
coords.append(Vector([self.d,-self.o,-self.h]))
coords.append(Vector([-self.t,-self.o,0]))
coords.append(Vector([self.d,-self.o,0]))
for i in range(4):
if (i % 2) == 0:
coords.append(coords[i] + Vector([self.tk,self.tk,0]))
else:
coords.append(coords[i] + Vector([-self.tk,self.tk,0]))
for i in range(4):
coords.append(coords[i] + Vector([0,self.w + self.o,0]))
for i in range(4):
coords.append(coords[i + 4] + Vector([0,self.w + self.o - (2 * self.tk),0]))
# Tread sections:
if self.typ_t == "tId3":
offset = (self.tk * sqrt(2)) / 2
topset = self.h - offset
self.sp = ((self.d + self.t - (2 * self.tk)) - (offset * (self.sec) + topset)) / (self.sec + 1)
baseX = -self.t + self.sp + self.tk
coords2.append(Vector([baseX, self.tk - self.o, offset - self.h]))
coords2.append(Vector([baseX + offset, self.tk - self.o, -self.h]))
for i in range(2):
coords2.append(coords2[i] + Vector([topset, 0, topset]))
for i in range(4):
coords2.append(coords2[i] + Vector([0, (self.w + self.o) - (2 * self.tk), 0]))
elif self.typ_t in ["tId4", "tId5"]:
offset = ((self.run + self.t) * self.sp) / (self.sec + 1)
topset = (((self.run + self.t) * (1 - self.sp)) - (2 * self.tk)) / self.sec
baseX = -self.t + self.tk + offset
baseY = self.w + self.o - 2 * self.tk
coords2.append(Vector([baseX, -self.o + self.tk, -self.h / 2]))
coords2.append(Vector([baseX + topset, -self.o + self.tk, -self.h / 2]))
coords2.append(Vector([baseX, -self.o + self.tk, 0]))
coords2.append(Vector([baseX + topset, -self.o + self.tk, 0]))
for i in range(4):
coords2.append(coords2[i] + Vector([0, baseY, 0]))
# Tread cross-sections:
if self.typ_t in ["tId3", "tId4"]:
cW = self.tk
cross = (self.w + (2 * self.o) - (self.sn + 2) * self.tk) / (self.sn + 1)
else: # tId5
spacing = self.sp ** (1 / 4)
cross = ((2*self.o + self.w) * spacing) / (self.sn + 1)
cW = (-2*self.tk + (2*self.o + self.w) * (1 - spacing)) / self.sn
self.sp = topset
height = -self.h / 2
baseY = -self.o + self.tk + cross
coords3.append(Vector([-self.t + self.tk, baseY, -self.h]))
coords3.append(Vector([self.d - self.tk, baseY, -self.h]))
coords3.append(Vector([-self.t + self.tk, baseY, height]))
coords3.append(Vector([self.d - self.tk, baseY, height]))
for i in range(4):
coords3.append(coords3[i] + Vector([0, cW, 0]))
# Make the treads:
for i in range(self.n):
if self.typ_t == "tId1":
self.G.Make_mesh(coords,self.G.faces,'treads')
elif self.typ_t == "tId2":
temp = []
for j in coords:
temp.append(copy(j))
for j in range(self.sec):
self.G.Make_mesh(temp, self.tId2_faces, 'treads')
for k in temp:
k += Vector([depth + self.sp, 0, 0])
elif self.typ_t in ["tId3", "tId4", "tId5"]:
self.G.Make_mesh(coords,self.out_faces,'treads')
temp = []
for j in coords2:
temp.append(copy(j))
for j in range(self.sec):
self.G.Make_mesh(temp,self.G.faces,'bars')
for k in temp:
k += Vector([offset + self.sp, 0, 0])
for j in coords2:
j += Vector([self.d, 0, self.r])
temp = []
for j in coords3:
temp.append(copy(j))
for j in range(self.sn):
self.G.Make_mesh(temp,self.G.faces,'crosses')
for k in temp:
k += Vector([0, cW + cross, 0])
for j in coords3:
j += Vector([self.d, 0, self.r])
for j in coords:
j += Vector([self.d,0,self.r])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment