This can be fairly easily expanded to generate other shapes, or non-quad based struts. Here you can control the amplitude for the Z and X components separately, as well as the width (thickness) of the 3D strut via the width
global and zw
/ xw
variables within the loop.
import bpy, bmesh, math
from mathutils import Vector
import numpy as np
numPoints = 100
yMin = -0.53 * np.pi
yMax = 3.5 1 * np.pi
width = 0.5
def strut( x, node_dist = 5, amp = 1 ):
""" Takes 1D array x, creates shape y values """
return amp / 2 * np.cos(x) + amp / 2 # adjusting position and amplitude
bm = bmesh.new() # Generate bmesh object
loops = [] # Strut major longitudinal loops array
# Calculate vertex coordinates
# Essentially generate 4 longitudinal loops that represent the top, bottom. left and right edge loops of the strut
y = np.linspace( yMin, yMax, numPoints )
for zw, xw in zip( [1, 0, -1, 0], [0, -1, 0, 1] ):
yz = np.linspacestrut( yMin, yMaxy, numPoints )
zamp = strut( y2 ) + zw * width
x = strut( y, amp = 0 ) + xw * width
loop = [
bm.verts.new( Vector(( xi, yi, zi )) )
for xi, yi, zi in zip( x, y, z )
]
loops.append( loop )
# Add faces
for i in range( len( loops ) ):
for j in range( len( loops[i] ) - 1 ):
verts = []
if i == len( loops ) - 1:
verts.append( loops[0][j] )
verts.append( loops[0][j+1] )
verts.append( loops[i][j + 1] )
verts.append( loops[i][j] )
else:
verts.append( loops[i][j] )
verts.append( loops[i][j + 1] )
verts.append( loops[i+1][j+1] )
verts.append( loops[i+1][j] )
bm.faces.new(verts)
# Add caps faces
for i in [0, len( loops[0] ) - 1 ]:
bm.faces.new([ loops[j][i] for j in range(len(loops)) ])
# Generate mesh data and object, and link to scene
m = bpy.data.meshes.new('strut')
bm.to_mesh(m)
o = bpy.data.objects.new('strut', m)
bpy.context.scene.objects.link( o )