Got it to work with Bmesh (not necessary but easier to work with IMHO). Had to add several chunks of code that will generate 4 waves as the main longitudinal edge loops, and add faces to the mesh.
This can be fairly easily expanded to generate other shapes, or non-quad based struts. Here you can control the width (thickness) of the 3D strut via the width
global and zw
/ xw
variables within the loop.
I also changed the strut function a tiny bit. Instead of normalizing between -4 to +4 X pi, I just use the Y values provided. In this example I'm providing the minimum and maximum Y values as multiples of pi directly, so I removed the normalization to open up the possibility to create a wave in whichever length and number of peaks you want.
Here's the code:
import bpy, bmesh, math
from mathutils import Vector
import numpy as np
numPoints = 100
yMin = -3 * np.pi
yMax = 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] ):
z = strut( y, amp = 2 ) + 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 )