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. [![enter image description here][1]][1] Here's the code: import bpy, bmesh, math from mathutils import Vector import numpy as np zAmplitude = 1 xAmplitude = 1 numPoints = 100 yMin = -0.5 * np.pi yMax = 3.5 * np.pi width = 2 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 for a, zw, xw in zip( np.linspace( -np.pi / 4, np.pi / 4, 4 ), [ 1, 0, -1, 0 ], [ 0, -1, 0, 1] ): y = np.linspace( yMin, yMax, numPoints ) z = strut( y ) + zw * zAmplitude x = strut( y ) + xw * xAmplitude loop = [] for xi, yi, zi in zip( x, y, z ): loop.append( bm.verts.new( Vector(( xi, yi, zi )) ) ) 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 ) [1]: https://i.sstatic.net/GZS1n.jpg