CSG Molecular Model


In this example I converted the A-magnet model to a set of NURBS spheres then performed boolean union on them. The one interesting part of this is that you can't perform union on disjoint spheres, so I had to create a little routine to find out which is touching which then order the operations.


the modeling language code looks like
 

<<
atom0 :  makegeom(sphere( pt( 2.252000, -5.410000, -0.470000 ), 1.600000 ))$;
atom1 :  makegeom(sphere( pt( -1.645000, -0.802000, -0.140000 ), 1.400000 ))$;
atom2 :  makegeom(sphere( pt( -0.417000, -1.347000, -0.150000 ), 1.600000 ))$;
atom3 :  makegeom(sphere( pt( -0.191000, -2.733000, -0.280000 ), 1.600000 ))$;
atom4 :  makegeom(sphere( pt( -1.049000, -3.808000, -0.430000 ), 1.400000 ))$;
atom5 :  makegeom(sphere( pt( -0.253000, -4.833000, -0.500000 ), 1.600000 ))$;
atom6 :  makegeom(sphere( pt( 1.073000, -4.504000, -0.420000 ), 1.400000 ))$;
atom7 :  makegeom(sphere( pt( 1.112000, -3.139000, -0.280000 ), 1.600000 ))$;
atom8 :  makegeom(sphere( pt( 2.210000, -2.370000, -0.160000 ), 1.400000 ))$;
atom9 :  makegeom(sphere( pt( 1.868000, -1.105000, -0.040000 ), 1.600000 ))$;
atom10 :  makegeom(sphere( pt( -2.476000, -1.404000, -0.230000 ), 1.100000 ))$;
atom11 :  makegeom(sphere( pt( -0.608000, -5.858000, -0.612000 ), 1.100000 ))$;
atom12 :  makegeom(sphere( pt( 2.698000, -0.407000, 0.067000 ), 1.100000 ))$;
atom13 :  makegeom(sphere( pt( 0.658000, -0.554000, -0.030000 ), 1.400000 ))$;
atom14 :  makegeom(sphere( pt( -1.755000, 0.217000, -0.042000 ), 1.100000 ))$;

combine0 : atom0;
combine1:combineshells( combine0, atom5,"+", TRUE, 0.005)$;
combine2:combineshells( combine1, atom6,"+", TRUE, 0.005)$;
combine3:combineshells( combine2, atom7,"+", TRUE, 0.005)$;
combine4:combineshells( combine3, atom8,"+", TRUE, 0.005)$;
combine5:combineshells( combine4, atom9,"+", TRUE, 0.005)$;
combine6:combineshells( combine5, atom11,"+", TRUE, 0.005)$;
combine7:combineshells( combine6, atom12,"+", TRUE, 0.005)$;
combine8:combineshells( combine7, atom13,"+", TRUE, 0.005)$;
combine9:combineshells( combine8, atom1,"+", TRUE, 0.005)$;
combine10:combineshells( combine9, atom2,"+", TRUE, 0.005)$;
combine11:combineshells( combine10, atom3,"+", TRUE, 0.005)$;
combine12:combineshells( combine11, atom4,"+", TRUE, 0.005)$;
combine13:combineshells( combine12, atom10,"+", TRUE, 0.005)$;
combine14:combineshells( combine13, atom14,"+", TRUE, 0.005)$;
>>

note the order the atoms are used in the combine section is not the same as they were read in - luckily the script does all the work.
 

Magnets

We want to add magnets to represent hydrogen bonds. Here is a preliminary picture of the magnet holes represented by cylinders. The depth goes all the way to the center of the sphere for now.

Here I have added a magnet radius and depth as well as a wall thickness for the magnet "holder".

The converter from the pdb file adds material above the atom to position the face of the magnet correctly. When all is said and done, it is still a solid model. I'll be asking Sam Drake about modifications for manufacture, but I think it is essentially done.

The final script generated modeling language commands look like:

<<
magnetradius : 0.1;
magnetholderradius : magnetradius * 1.2;
magnetheight : 0.2;
atom0 :  makegeom(sphere( pt( 2.252000, -5.410000, -0.470000 ), 1.600000 ))$;
atom1 :  makegeom(sphere( pt( -1.645000, -0.802000, -0.140000 ), 1.400000 ))$;
atom2 :  makegeom(sphere( pt( -0.417000, -1.347000, -0.150000 ), 1.600000 ))$;
atom3 :  makegeom(sphere( pt( -0.191000, -2.733000, -0.280000 ), 1.600000 ))$;
atom4 :  makegeom(sphere( pt( -1.049000, -3.808000, -0.430000 ), 1.400000 ))$;
atom5 :  makegeom(sphere( pt( -0.253000, -4.833000, -0.500000 ), 1.600000 ))$;
atom6 :  makegeom(sphere( pt( 1.073000, -4.504000, -0.420000 ), 1.400000 ))$;
atom7 :  makegeom(sphere( pt( 1.112000, -3.139000, -0.280000 ), 1.600000 ))$;
atom8 :  makegeom(sphere( pt( 2.210000, -2.370000, -0.160000 ), 1.400000 ))$;
atom9 :  makegeom(sphere( pt( 1.868000, -1.105000, -0.040000 ), 1.600000 ))$;
atom10 :  makegeom(sphere( pt( -2.476000, -1.404000, -0.230000 ), 1.100000 ))$;
atom11 :  makegeom(sphere( pt( -0.608000, -5.858000, -0.612000 ), 1.100000 ))$;
atom12 :  makegeom(sphere( pt( 2.698000, -0.407000, 0.067000 ), 1.100000 ))$;
atom13 :  makegeom(sphere( pt( 0.658000, -0.554000, -0.030000 ), 1.400000 ))$;
magnetpt0 : pt( 0.418000, 0.949000, 0.091000 );
magnetvec0 : vecfrom2pts( magnetpt0, pt(0.658000, -0.554000, -0.030000));
magnetholder0 : makegeom(rightcircylinder( magnetpt0, magnetvec0, magnetholderradius ));
magnetholevec0 : vecscale( magnetvec0, magnetheight / veclength( magnetvec0 ) );
magnethole0 : makegeom(rightcircylinder( magnetpt0, magnetholevec0, magnetradius ));
holder0 : combineshells( magnetholder0 ,magnethole0, "-", TRUE, 0.005 );
atom14 :  makegeom(sphere( pt( -1.755000, 0.217000, -0.042000 ), 1.100000 ))$;
magnetpt1 : pt( -1.939000, 1.340000, 0.160000 );
magnetvec1 : vecfrom2pts( magnetpt1, pt(-1.755000, 0.217000, -0.042000));
magnetholder1 : makegeom(rightcircylinder( magnetpt1, magnetvec1, magnetholderradius ));
magnetholevec1 : vecscale( magnetvec1, magnetheight / veclength( magnetvec1 ) );
magnethole1 : makegeom(rightcircylinder( magnetpt1, magnetholevec1, magnetradius ));
holder1 : combineshells( magnetholder1 ,magnethole1, "-", TRUE, 0.005 );
>>
combine0 : atom0;
combine1:combineshells( combine0, atom5,"+", TRUE, 0.005)$;
combine2:combineshells( combine1, atom6,"+", TRUE, 0.005)$;
combine3:combineshells( combine2, atom7,"+", TRUE, 0.005)$;
combine4:combineshells( combine3, atom8,"+", TRUE, 0.005)$;
combine5:combineshells( combine4, atom9,"+", TRUE, 0.005)$;
combine6:combineshells( combine5, atom11,"+", TRUE, 0.005)$;
combine7:combineshells( combine6, atom12,"+", TRUE, 0.005)$;
combine8:combineshells( combine7, atom13,"+", TRUE, 0.005)$;
combine9:combineshells( combine8, atom1,"+", TRUE, 0.005)$;
combine10:combineshells( combine9, atom2,"+", TRUE, 0.005)$;
combine11:combineshells( combine10, atom3,"+", TRUE, 0.005)$;
combine12:combineshells( combine11, atom4,"+", TRUE, 0.005)$;
combine13:combineshells( combine12, atom10,"+", TRUE, 0.005)$;
combine14:combineshells( combine13, atom14,"+", TRUE, 0.005)$;
combine15:combineshells( combine14, magnetholder0,"+", TRUE, 0.005)$;
combine16:combineshells( combine15, magnethole0,"-", TRUE, 0.005)$;
combine17:combineshells( combine16, magnetholder1,"+", TRUE, 0.005)$;
combine18:combineshells( combine17, magnethole1,"-", TRUE, 0.005)$;
 
 

Fabrication

Once the model has been created, an alpha_1 program called shl_mash converts it into triangles from the trimmed NURBS representation. This triangle model is then converted into an stl file with a1tostl.

The quickslice program reads the stl file and creates the layer and support layer commands for the Stratasys machine. The machine takes around 11-13 hours per molecule to complete, and then the support layers must be removed by hand. Here are some pictures of the results.

The A base

The holes to hold the magnets in the A base. One hole goes into the model to provide a path between the hollow center and the outside. This is needed for the boolean operation as well as removal of support structure from the inside, if desired.

The A base with magnets sloppily inserted. They would need to be glued in eventually.

The T base

The A and T paired up.


The U base

The A and U paired up. They join more tightly than shown.