Skip to main content
Adding gif
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73

enter image description hereenter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Setting values that generate the desired shape.
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73

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 )

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.

import bpy, bmesh, math
from mathutils import Vector
import numpy as np

numPoints  = 100
yMin       = -0.5 * np.pi 
yMax       = 3.5  * 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
for zw, xw in zip( [1, 0, -1, 0], [0, -1, 0, 1] ):
    y = np.linspace( yMin, yMax, numPoints )
    z = strut( y ) + zw * width
    x = strut( y ) + 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 )

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.

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 )
Replacing loop with list comprehension
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73
import bpy, bmesh, math
from mathutils import Vector
import numpy as np

numPoints  = 100
yMin       = -0.5 * np.pi 
yMax       = 3.5  * 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
for zw, xw in zip( [1, 0, -1, 0], [0, -1, 0, 1] ):
    y = np.linspace( yMin, yMax, numPoints )
    z = strut( y ) + zw * width
    x = strut( y ) + xw * width

    loop = [][ 
    for xi, yi, zi inbm.verts.new( zipVector(( xxi, yyi, zzi ):
) )  
      loop.append( bm.verts.new( Vector((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 )
import bpy, bmesh, math
from mathutils import Vector
import numpy as np

numPoints  = 100
yMin       = -0.5 * np.pi 
yMax       = 3.5  * 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
for zw, xw in zip( [1, 0, -1, 0], [0, -1, 0, 1] ):
    y = np.linspace( yMin, yMax, numPoints )
    z = strut( y ) + zw * width
    x = strut( y ) + xw * width

    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 )
import bpy, bmesh, math
from mathutils import Vector
import numpy as np

numPoints  = 100
yMin       = -0.5 * np.pi 
yMax       = 3.5  * 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
for zw, xw in zip( [1, 0, -1, 0], [0, -1, 0, 1] ):
    y = np.linspace( yMin, yMax, numPoints )
    z = strut( y ) + zw * width
    x = strut( y ) + 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 )
Removing useless list from zip and setting nicer width default value, removing unneded amplitude vars as it is defined in function
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73
Loading
Fixing bug in Z and X formulae
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73
Loading
Improving explanation
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73
Loading
Source Link
TLousky
  • 16.1k
  • 1
  • 42
  • 73
Loading