Stian Eikeland bio photo

Stian Eikeland

Developer. Does consultancy work from own company. Lives in Bergen, Norway.

Twitter Github Flickr Vimeo Instagram 500px

Coding a rolling Oloid

Did you know there's a whole class rolling objects that's not spherical or cylindrical and still able to roll in a given direction? I didn't!

Some of them have them even have interesting properties like the fact that every point on their surface touch the ground as they're rolling. The Sphericon and the Oloid are two such objects.

As a fun little experiment I wanted to code and print one.

TL;DR, just watch the video - coding a rolling Oloid. Fullscreen it for readability.

The code to construct an oloid is really super simple, you can construct one by creating a convex hull around two perpendicular circles positioned with the centers at radius distance from each other, like this:

(defn olid [radius]
  (let [c (m/cylinder radius 0.1)
        a (m/translate [0 (/ radius -2)] c)
        b (->> c
               (m/rotate [0 (/ Math/PI 2) 0])
               (m/translate [0 (/ radius 2) 0] ))]
    (m/hull a b)))

Print it!

And let it roll!

via Gfycat

If i were to print it again, I would probably use a higher in-fill percentage to make it a bit heavier. You can also buy these made in metal, which probably feels amazing!

Using scad-clj

Some people have asked how I use Clojure and OpenSCAD, how to set up the live reloading, etc, as the documentation is a bit lacking.

(defn render [model]
  (spit "render.scad" (scad-clj.scad/write-scad model)))

I have this simple helper defined that writes a model to a file. Open the file using OpenSCAD. OpenSCAD will watch the file, and every time you call render on something, it will update the display. You can hide all UI elements other than the display in OpenSCAD, put it side by side with the editor, and even set them up to use the same theme - creating the illusion that your editor and OpenSCAD is the same program.

(render (m/union (m/cylinder 10 10)
                 (m/cube 10 20 20)))

I usually leave a call to render at the bottom of the file I'm working on, and evaluate it as needed. That way a quick call to cider-eval-buffer will update the display.

Adereth got some great tips on how to get started over at his blog. Be sure to check out his amazing keyboard!

The y-split function

I got asked about the y-split function used in the video. It's a simple axis split with a hollowed out cube to make it easier to print, no supports required. I didn't want to make the video more complex than necessary, so I simply used it like magic.

It was custom made for this oloid and looked like this. Quick and dirty, and a bit repetitious.

(defn y-split [obj]
  (let [box (m/cube 10 10 10)
        holed-obj (m/difference obj (m/scale [1.005 1.2 1.005] box))
        a (->> (m/cube 100 100 100)
               (m/translate [0 -50 0])
               (m/intersection holed-obj)
               (m/rotate [(/ Math/PI -2) 0 0])
               (m/translate [35 0 0]))
        b (->> (m/cube 100 100 100)
               (m/translate [0 50 0])
               (m/intersection holed-obj)
               (m/rotate [(/ Math/PI 2) 0 0])
               (m/translate [-35 0 0]))]
    (m/union a b (m/translate [0 -20 5] box)))) 

I just guessed at the tolerances needed, and it worked perfectly, no glue needed. It seems like a useful function for 3D-printing with Clojure, so I think I'll make a general one later.