Skip to content

Instantly share code, notes, and snippets.

@jstults jstults/octet.py
Created Dec 21, 2012

Embed
What would you like to do?
functions for generating mged (BRLCAD) commands to make octet truss primitives
#
# http://www.variousconsequences.com/2012/12/octet-truss-for-topology-optimization.html
#
import scipy as sp
class rcc_shape():
def __init__(self, name, origin, height, radius):
self.name = name
self.origin = origin
self.height = height
self.radius = radius
def mged_string(self):
return("in %s rcc %g %g %g %g %g %g %g\n" % (self.name, self.origin[0], self.origin[1], self.origin[2], self.height[0], self.height[1], self.height[2], self.radius))
#class mged_commands():
# def __init__(self, fname):
# self.fname = fname
# self.fout = open(fname,"w")
# self.part_count = 0
class octet_prim():
"""
generate an octet truss primative (one cell) with specified element radius
"""
def __init__(self, name, origin, length, radius):
self.name = name
self.origin = origin
self.length = length # length of members
self.radius = radius # radius of members
self.unit = sp.sqrt(length**2 + length**2) # unit cube side length
self.x1 = sp.array([0.0, 0.0, 0.0])
self.x2 = sp.array([self.length, 0.0, 0.0])
self.x3 = sp.array([0.0, self.length, 0.0])
self.x4 = sp.array([self.length, self.length, 0.0])
self.x5 = sp.array([self.length/2.0, self.length/2.0, self.length*sp.sin(sp.pi/4.0)])
self.x6 = sp.array([self.length/2.0, self.length/2.0, -self.length*sp.sin(sp.pi/4.0)])
self.shape_list = []
self.shape_list.append( rcc_shape("%s-rcc1.s"%self.name, self.x1, self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc2.s"%self.name, self.x1, self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc3.s"%self.name, self.x2, self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc4.s"%self.name, self.x3, self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc5.s"%self.name, self.x1, self.x5, radius) )
self.shape_list.append( rcc_shape("%s-rcc6.s"%self.name, self.x2, self.x5-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc7.s"%self.name, self.x3, self.x5-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc8.s"%self.name, self.x4, self.x5-self.x4, radius) )
self.shape_list.append( rcc_shape("%s-rcc9.s"%self.name, self.x1, self.x6, radius) )
self.shape_list.append( rcc_shape("%s-rcc10.s"%self.name, self.x2, self.x6-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc11.s"%self.name, self.x3, self.x6-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc12.s"%self.name, self.x4, self.x6-self.x4, radius) )
self.shape_list.append( rcc_shape("%s-rcc13.s"%self.name, self.x5, self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc14.s"%self.name, self.x5, -self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc15.s"%self.name, self.x5, self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc16.s"%self.name, self.x5, -self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc17.s"%self.name, self.x6, self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc18.s"%self.name, self.x6, -self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc19.s"%self.name, self.x6, self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc20.s"%self.name, self.x6, -self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc21.s"%self.name, self.x1, self.x5-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc22.s"%self.name, self.x2, self.x5-self.x3-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc23.s"%self.name, self.x1, self.x6-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc24.s"%self.name, self.x2, self.x6-self.x3-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc25.s"%self.name, self.x1, self.x5-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc26.s"%self.name, self.x1, self.x6-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc27.s"%self.name, self.x3, self.x5-self.x2-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc28.s"%self.name, self.x3, self.x6-self.x2-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc29.s"%self.name, self.x3, self.x5, radius) )
self.shape_list.append( rcc_shape("%s-rcc30.s"%self.name, self.x3, self.x6, radius) )
self.shape_list.append( rcc_shape("%s-rcc31.s"%self.name, self.x4, self.x5-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc32.s"%self.name, self.x4, self.x6-self.x2, radius) )
self.shape_list.append( rcc_shape("%s-rcc33.s"%self.name, self.x4, self.x5-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc34.s"%self.name, self.x4, self.x6-self.x3, radius) )
self.shape_list.append( rcc_shape("%s-rcc35.s"%self.name, self.x2, self.x5, radius) )
self.shape_list.append( rcc_shape("%s-rcc36.s"%self.name, self.x2, self.x6, radius) )
def mged_string(self):
# insert all the right circular cylinders
mged_string = ""
for s in self.shape_list:
mged_string = mged_string + s.mged_string()
# union the cylinders
mged_string = mged_string + "r %s"%self.name
for s in self.shape_list:
mged_string = mged_string + " u " + s.name
mged_string = mged_string + "\n"
# rotate and translate to put a corner on the origin
mged_string = mged_string + "B %s\n"%self.name
mged_string = mged_string + "oed / %s/%s-rcc1.s\n"%(self.name,self.name)
mged_string = mged_string + "rot 0 0 45\n"
mged_string = mged_string + "translate %g %g %g\n" % (0,self.length*sp.sin(sp.pi/4.0),self.length*sp.sin(sp.pi/4.0))
mged_string = mged_string + "accept\n"
# offset to self.origin
mged_string = mged_string + "oed / %s/%s-rcc1.s\n"%(self.name,self.name)
mged_string = mged_string + "translate %g %g %g\n" % (self.origin[0], self.origin[1], self.origin[2])
mged_string = mged_string + "accept\n"
return(mged_string)
if __name__ == "__main__":
# make a BRL-CAD database with an octet truss made of rcc
# primitives, union the rcc's into a region, convert the region
# into an stl
import os
# Path to the mged executables:
MGED_PATH = "~/brlcad/.build/bin/"
# octet truss parameters, member radius and length
radius = 0.4
length = 8.0
# command file:
mged_commands = "octet_prim_%s_%s.mged" % (radius, length)
brlcad_dbase = "octet_prim_%s_%s.g" % (radius, length)
stl_file = "octet_prim_%s_%s.stl" % (radius, length)
rname = "region1.r"
fout = open(mged_commands, "w")
x1 = sp.array([0.0, 0.0, 0.0])
x2 = sp.array([length, 0.0, 0.0])
x3 = sp.array([0.0, length, 0.0])
x4 = sp.array([length, length, 0.0])
x5 = sp.array([length/2.0, length/2.0, length*sp.sin(sp.pi/4.0)])
x6 = sp.array([length/2.0, length/2.0, -length*sp.sin(sp.pi/4.0)])
offset = sp.array([length*sp.sin(sp.pi/4.0),0.0,length*sp.sin(sp.pi/4.0)])
angle = sp.pi / 4.0
rotation = sp.array([[sp.cos(angle), -sp.sin(angle), 0],[sp.sin(angle), sp.cos(angle), 0],[0, 0, 1.0]])
shape_list = []
shape_list.append( rcc_shape("rcc1.s", x1, x2, radius) )
shape_list.append( rcc_shape("rcc2.s", x1, x3, radius) )
shape_list.append( rcc_shape("rcc3.s", x2, x3, radius) )
shape_list.append( rcc_shape("rcc4.s", x3, x2, radius) )
shape_list.append( rcc_shape("rcc5.s", x1, x5, radius) )
shape_list.append( rcc_shape("rcc6.s", x2, x5-x2, radius) )
shape_list.append( rcc_shape("rcc7.s", x3, x5-x3, radius) )
shape_list.append( rcc_shape("rcc8.s", x4, x5-x4, radius) )
shape_list.append( rcc_shape("rcc9.s", x1, x6, radius) )
shape_list.append( rcc_shape("rcc10.s", x2, x6-x2, radius) )
shape_list.append( rcc_shape("rcc11.s", x3, x6-x3, radius) )
shape_list.append( rcc_shape("rcc12.s", x4, x6-x4, radius) )
shape_list.append( rcc_shape("rcc13.s", x5, x2, radius) )
shape_list.append( rcc_shape("rcc14.s", x5, -x2, radius) )
shape_list.append( rcc_shape("rcc15.s", x5, x3, radius) )
shape_list.append( rcc_shape("rcc16.s", x5, -x3, radius) )
shape_list.append( rcc_shape("rcc17.s", x6, x2, radius) )
shape_list.append( rcc_shape("rcc18.s", x6, -x2, radius) )
shape_list.append( rcc_shape("rcc19.s", x6, x3, radius) )
shape_list.append( rcc_shape("rcc20.s", x6, -x3, radius) )
shape_list.append( rcc_shape("rcc21.s", x1, x5-x3, radius) )
shape_list.append( rcc_shape("rcc22.s", x2, x5-x3-x2, radius) )
shape_list.append( rcc_shape("rcc23.s", x1, x6-x3, radius) )
shape_list.append( rcc_shape("rcc24.s", x2, x6-x3-x2, radius) )
shape_list.append( rcc_shape("rcc25.s", x1, x5-x2, radius) )
shape_list.append( rcc_shape("rcc26.s", x1, x6-x2, radius) )
shape_list.append( rcc_shape("rcc27.s", x3, x5-x2-x3, radius) )
shape_list.append( rcc_shape("rcc28.s", x3, x6-x2-x3, radius) )
shape_list.append( rcc_shape("rcc29.s", x3, x5, radius) )
shape_list.append( rcc_shape("rcc30.s", x3, x6, radius) )
shape_list.append( rcc_shape("rcc31.s", x4, x5-x2, radius) )
shape_list.append( rcc_shape("rcc32.s", x4, x6-x2, radius) )
shape_list.append( rcc_shape("rcc33.s", x4, x5-x3, radius) )
shape_list.append( rcc_shape("rcc34.s", x4, x6-x3, radius) )
shape_list.append( rcc_shape("rcc35.s", x2, x5, radius) )
shape_list.append( rcc_shape("rcc36.s", x2, x6, radius) )
# commands to make all the parts:
for s in shape_list:
fout.write(s.mged_string())
# command to make a region out of all the parts in the shape list:
mgedr = "r region1.r"
for s in shape_list:
mgedr = mgedr + " u " + s.name # union parts to region
fout.write(mgedr + "\n")
fout.write("B region1.r\n")
fout.write("oed / region1.r/rcc1.s\n")
fout.write("rot 0 0 45\n")
fout.write("translate %g %g %g\n" % (0,length*sp.sin(sp.pi/4.0),length*sp.sin(sp.pi/4.0)))
fout.write("accept\n")
fout.close()
# run the commands in mged
retval = os.system("cat %s | %smged -c %s" % (mged_commands, MGED_PATH, brlcad_dbase) )
# export the region to an stl file
atol = 0.001 # absolute tolerance
D = 0.000001 # calculation accuracy
retval = os.system("%sg-stl -a %f -D %f -o %s %s %s" % (MGED_PATH, atol, D, stl_file, brlcad_dbase, rname))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.