Loading

MakerBot Print is our newest print-prepration software, which supports native CAD files and STL assemblies,
allows you to interact with all your printers via the Cloud, and many other exciting new features.

Download Now

How to Model a Solomonic Column

Please Login to Comment

I've seen a number of different solutions for helixes around. Has anyone tried modeling a Solomonic column in OpenSCAD (example from Wikipedia attached). I'd like to use this kind of shape in something but I'm still a relative beginner with modeling and not quite sure where to start. Thanks in advance.

Another way to do this is to use a screw thread library that allows a custom thread profile. You could model the profile as a sine wave as follows:

use <quickthread.scad>;

verticalPeriod = 25;
horizontalAmplitude = 5;
slicesPerPeriod = 24;
innerDiameter = 14;
height = 100;

threadProfile = 
  [for(t=[0:slicesPerPeriod])
    let (angle=t/slicesPerPeriod*360,
         z=t/slicesPerPeriod*verticalPeriod)
      [horizontalAmplitude*(1+sin(angle-90))/2,z]];

rawThread(threadProfile, d=innerDiameter, h=height, clip=true);

This would let you model a column from a photo more precisely. Just could load the photo into Inkscape, manually draw a curve that matches a single thread profile (from minimum to minimum), move the curve to the drawing origin, and export it using an Inkscape to OpenSCAD points exporter (like my svg2scad.py).

Yet another thread library for OpenSCAD
by arpruss

Here's what it looks like when I traced the profile in Inkscape:

use <quickthread.scad>;

verticalPeriod = 25;
horizontalAmplitude = 5;
slicesPerPeriod = 24;
height = 100;

center_solomonic_1 = [79.199909333,42.292352021];
size_solomonic_1 = [1.631156250,7.371619750];
stroke_width_solomonic_1 = 0.066145833;
// paths for solomonic_1
points_solomonic_1_1 = [ [-0.815578125,-3.685809875],[-0.748958998,-3.150609391],[-0.572605793,-2.734330050],[-0.031722219,-2.073088138],[0.262295618,-1.735402233],[0.525022465,-1.331190808],[0.721202056,-0.814092195],[0.815578125,-0.137744729],[0.745489380,0.521014405],[0.560709961,1.042796876],[0.299470093,1.470260329],[-0.299470093,2.212860759],[-0.560709961,2.613313024],[-0.745489380,3.090076848],[-0.815578125,3.685809875] ];

points_left = points_solomonic_1_1[0][0];
points_bottom = points_solomonic_1_1[0][1];
points_top = points_solomonic_1_1[len(points_solomonic_1_1)-1][1];
scale = verticalPeriod / (points_top-points_bottom);
innerDiameter = 4.607347540 * scale;
profile = scale * [for (p=points_solomonic_1_1) p-[points_left,points_bottom]];
rawThread(profile, d=innerDiameter, h=height, clip=true);    

Just to add to what other are saying, the function for the radius in cross-section is basically the same in polar coordinates as the function for the profile over one thread period. So for a triangular thread, the function for theta would be const+m*triangle(theta).

In your picture, it looks like the profile is a simple cosine (or sine) wave so the function for the cross-section would be const+m*cos(theta).

I know that r=cos(theta) is a circle (yep, check it out) but I'm not sure what r=c+cos(theta) is. Possibly an ellipse? (It's not. Just graphed it on Desmos).

radius = 30;
height = 300;
numberOfTwists = height / 45;
$fn=100;

linear_extrude(
height = height,
convexity = 10,
twist = 360numberOfTwists,
scale=1) {
offset(r=-radius) offset(delta=+radius) {
scale([0.88,0.96,1]) translate([-0.19
radius,0]) circle(d=radius*1.8);
}
}

plenty of people have commented on linear_extrude. I'll add that you can make almost any thread with linear_extrude. The thread profile modulates the radius of a circle, and you extrude/twist that.

This doesn't work well for tight threads, though, it gets all jagged.

Just because I'm familiar with it, I'd use my tubemesh library: https://www.thingiverse.com/thing:2406760
Then just make a cross-section that is an off-center circle (or some more complicated polar plot if you like):

use <tubemesh.scad>;

offset = 3;
radius = 10;
height = 100;
twists = 4;
precision = 1;

section = [ for(i=[0:5:360]) [offset + radius*cos(i),radius*sin(i)] ];

morphExtrude(section,twist=360*twists,height=height,numSlices=height/precision);

Play with the parameters to make it match the column you want.

Some Solomonic columns have multiple lobes in the cross-section. For these, you might use a polar section like:

section = [ for(i=[0:5:360]) (radius+lobeHeight*abs(cos((i)*lobes/2)))*[cos(i),sin(i)]];
Tube mesh extrusion library for OpenSCAD
by arpruss

I updated my tube mesh library to produce a smoother mesh for twisty things like this. Just add optimize=5 (or more) to the morphExtrude() call. The way this works, is it tries to realign the points in the successive sections by a small amount (up to optimize-1) for better smoothness. Below, the smoother.jpg is produced by the above code with the optimize parameter added, while the rougher.jpg is produced with linear_extrude and twist (which is pretty much the same as the unoptimized tube mesh output).

The rotate_extrude() documents stay specifically that "It can not be used to produce a helix or screw threads." I decided to try using it anyway. I think the profile of those original columns is an ogee curve, but I used one cycle of a cosine function between -180 and 180.
The helix is formed by moving each segment up a little higher on the z-axis, so that won't be a smooth surface. You can make it look smooth by using a higher values for steps, but that is kind of a hack and your models will be needlessly complex.

You could almost form the segments by extruding the profile as a very thing sheet then do the same for the next iteration with some transforms and use hull() between them. Unfortunately, the cross section is not convex so this chained hull() trick will fill in the gaps and ruin the curve. I wrote a library to solve just this sort of problem but it's just a little too long for a post here. If you're interested in seeing it let me know and I'll put it on github or something.

spiral(3);

steps=48;

module profile(rad=1)
{
     rotate_extrude(angle=360/steps) {
        polygon([for (y=[-180:20:180]) [rad+cos(y)/4,y/180]]);
    }
}

module spiral(count=1) {
    for (i=[0:steps*count]) {
        rotate([0,0,i*360/steps]) translate([0,0,2*i/steps]) profile();
    }
}

I would try "rotate_extrude" using some function of 1-cos(t).

looks like a single helix ? maybe the code included with https://www.thingiverse.com/thing:1805732 will help

Double Helix Pencil Holder
by pmoews

That kinda looks like barley-twist, a design that was pretty common in older English furniture.

It looks like linear_extrude() has all the parameters needed to control the twist rate of a 2D shape along the Z axis. All that's then needed is the proper shape, which https://infogalactic.com/info/Solomonic_column suggests is an S-curve. A few minutes' hacking yielded this:

  radius     = 25;
  height     = 100;
  numberOfTwists = 1;
  $fn=90;

  linear_extrude(height = height, convexity = 10, twist = 360*numberOfTwists, scale=1)
  {
    // make a rounded S-curve

    // first, the ends
    translate([3/4*radius,0])
      circle(d=radius/2);
    translate([-3/4*radius,0])
      circle(d=radius/2);

    // then, half of the curve
    translate([radius*3/8,0])
    difference()
    {
      circle(d=5/4*radius);
      circle(d=1/4*radius);
      translate([0,-3/4*radius])
        square(3/2*radius, center=true);
    }

    // finally, mirror the curve on the other side
    translate([-radius*3/8,0])
    difference()
    {
      circle(d=5/4*radius);
      circle(d=1/4*radius);
      translate([0,3/4*radius])
        square(3/2*radius, center=true);
    }
  }

which produced a shape shown in spiral_vase.png. Making the curve a bit "fatter" might bring it closer to the desired shape, so a little more hacking yielded this (both curve shapes are included):

radius     = 25;
height     = 100;
numberOfTwists = 1;
$fn=90;

linear_extrude(height = height, convexity = 10, twist = 360*numberOfTwists, scale=1)
  shape_2();

// make a rounded S-curve
module shape_1()
{
  // first, the ends
  translate([3/4*radius,0])
    circle(d=radius/2);
  translate([-3/4*radius,0])
    circle(d=radius/2);

  // then, half of the curve
  translate([radius*3/8,0])
  difference()
  {
    circle(d=5/4*radius);
    circle(d=1/4*radius);
    translate([0,-3/4*radius])
      square(3/2*radius, center=true);
  }

  // finally, mirror the curve on the other side
  translate([-radius*3/8,0])
  difference()
  {
    circle(d=5/4*radius);
    circle(d=1/4*radius);
    translate([0,3/4*radius])
      square(3/2*radius, center=true);
  }
}

// a fattened curve
module shape_2()
{
  // start with three circles of equal size, touching each other
  circle(d=2/3*radius);
  translate([2/3*radius,0])
    circle(d=2/3*radius);
  translate([-2/3*radius,0])
    circle(d=2/3*radius);

  // join center and right with a half-curve
  translate([1/3*radius,0])
  difference()
  {
    circle(d=4/3*radius);
    translate([0,-2/3*radius])
      square(4/3*radius, center=true);
  }

  // join the center and left with the mirror image of the above
  translate([-1/3*radius,0])
  difference()
  {
    circle(d=4/3*radius);
    translate([0,2/3*radius])
      square(4/3*radius, center=true);
  }
}

It produces the shape shown in barley_twist.png.

I think linear_extrude() with a twist should do the trick. For a single helix, maybe just use an offset circle, something like this:

$fn=96;

solomic_column(25, 2, .75);

module solomic_column(height, radius, pitch)
{
    linear_extrude(height = height, twist = 180*pitch*(height/radius))
        translate([radius/4, 0, 0]) circle(r = radius);
}

It still leaves and interesting pattern on the surface unless you use pretty high values of $fn

This is what I ended up with. To be honest, I didn't really understand how twist worked with linear_extrude. Thanks for giving me a more concrete example than the one in the docs.

radius     = 25;
height     = 300;
numberOfTwists = height / 125;
$fn=90;

linear_extrude(
    height = height, 
    convexity = 10, 
    twist = 360*numberOfTwists, 
    scale=1) {
        offset(r=-radius) offset(delta=+radius) {
            union() {
                translate([0.5*radius,0])
                circle(d=radius*5/4);
                translate([-0.5*radius,0])
                circle(d=radius*5/4);
                circle(d=6/4*radius);
            }
        }
    }

This doesn't exactly match the reference image, but it's close enough for how I want to use this.

Thanks! That's a great start.