Surface-Oriented CAD, Math, & Telescopes

surfcad is a python proof-of-concept CAD library I’ve been writing for what I call “surface-oriented CAD”.

The idea came to me when I realized that some of things I’d been trying to make in openscad, a CSG based CAD program, would have been much easier to do in the software I’d written for making models of mathematical objects (eg. this model of a solution the diffusion equation). In this software, surface were constructed based on mathematical functions. One had to think to make sure that their object was closed, but it was possible to describe things that would have been prohibitively difficult in a CAD program like openscad.

A Cylinder


from surfcad import *

s = cylinderical_surface(lambda t,h: 10, 50)

f=STLFile("test.stl")

f.add(s.surface())
f.add(s.top_loop().close())
f.add(s.bottom_loop().close())

f.end()

a cylinder

To see what is going on, lets break it down a little:


f.add(s.surface())


f.add(s.top_loop().close())

So you see how we break it down.

Transforms


cylinderical_surface(lambda t,h: 3, 5)


scale([6,8,6])*cylinderical_surface(lambda t,h: 3, 5)


twistz(0.1)*(scale([6,8,6])*cylinderical_surface(lambda t,h: 3, 5))

twistz() begins to demonstrate the raw potential of transforms in surfcad. Basically, you can do any continuous transformation you can imagine (well, actually, in some cases the limiting factor will be your ability to describe the function in python, rather than your imagination…).

Coolness and Joinings

We can do much more interesting surfaces than the one describe above. The following is a minimal surface in Minkowski space (to make this more interesting, in string theory, strings are supposed to sweep out surfaces in Minkowski space), suggested to me by my Real Analysis professor, Robert Jerrard. (I don’t really understand why it works, but the general solution looks eerily similar to the solution to the wave equation, and I’ve been told it is not a coincidence).


cylinderical_surface(lambda t,h: (20.*(cos(t+h)-1/5.*cos(-5.*(t-h))), 20.*(sin(t+h)-1/5.*sin(-5.*(t-h))),20*h), 1.25)


Rather than giving it a boring old solid top, lets make it a thin hollow tube.

To do this, we’ll put a shrunk version in the middle, and then join the top loops to each other and the bottom loops to each other.


from surfcad import *

s = cylinderical_surface(lambda t,h: (20.*(cos(t+h)-1/5.*cos(-5.*(t-h))), 20.*(sin(t+h)-1/5.*sin(-5.*(t-h))),20*h), 1.25)
s2 = scale([0.8,0.8,1.])*s

f=STLFile("out.stl")
f.add(s.surface())
f.add(s2.surface())
f.add(join(s.top_loop(), s2.top_loop()))
f.add(join(s.bottom_loop(), s2.bottom_loop()))
f.end()

A slightly modified version of this (scaled to be printable) is on thingiverse.

As another example of what surfcad can do, I’ve posted code to generate the real and imaginary components of the first few nomials on the complex unit circle on thingiverse.

Some Technical Musings

(You can skip this part if you wish)

The fact of the matter is that I don’t have enough time to implement all the things I should. The following are some of these.

Firstly, the present version has resolution as a constant parameter across all objects. Clearly, that shouldn’t be the case. While it being constant does make the implementation of loop.close() and join() simpler, it is possible to do them without.  You just have to be willing to have multiple points on the higher resolution loop correspond to a single one on the simpler one.

Another place things fall apart is in the naivety of my present algorithms for closing and joining loops. For closing, they should at least be radially connected, preferably convex. And joining has a host of issues involving the alignment of the loops.

It’s also worth noticing that, fundamentally, every surface is just a map from one of [0,1]², S₁×[0,1], or S₁² into ℝ³. This allows for a lot of abstraction, at least into theory.

Something else that I keep thinking of  is a haskell implementation. 3D objects could be a monad, allowing for something like


cylinderical_surface :: ( (Real, Real) -> Real ) -> Real -> Object (Loop, Loop)
s = cylinderical_surface(...)
obj = do { (a1, a2)            (b1, b2)            join a1 b1
           close a2
           close b2
         }

Does any of this have practical applications?

Actually, yes. One advantage to this approach is that it makes it easy to describe surfaces that would be difficult to construct in a CSG modeling program.

So I decided to 3D print a Newtonian telescope to demonstrate how useful this could be. You see, a Newtonian telescope internally uses parabolic mirrors instead of lenses. With the sort of precision a makerbot or reprap prints at, the linear interpolation from sanding a surface should be a good enough parabola for a decent mirror.

(Normally a Newtonian telescope would need a lens in the eyepiece, but I think I can deform the secondary mirror to avoid this. Although, I think you could make a lens by printing a water soluble negative and filling it with epoxy.)

The only trick, I thought, would be making the mirror shiny. As it turned out, that was much more difficult than I expected. In fact, I still haven’t come up with a good enough solution. Spray paint isn’t shiny enough and tinfoil crinkles. Alas, my 3D printable vacuum cleaner, designed in openscad, remains the coolest thing I’ve made.

I’ve received all sorts of awesome suggestions around hacklab, from spinning mercury to floor wax. Norman even offered to silver it for me!

None of the ones I’ve tried so far worked, and I want a solution that anyone can do, so that anyone with a 3D printer can easily make a telescope. What do you think, Internets?

Tags: , , ,

12 Responses to “Surface-Oriented CAD, Math, & Telescopes”

  1. Brian Korsedal Says:

    I dig it. I’m working on a FPGA / bezier based motion controller for RepRaps. It might give you a few ideas.

    Don’t expect it to be finished any time soon. I’m working 2.5 jobs. I started it last year when I didn’t have a job. I stopped because I had no money. Now I have money, but no time. 😦

    Anyway, here it is:

    http://objects.reprap.org/wiki/Elegant_multispline_motion_controller

    -Brian

    • christopherolah Says:

      Thanks.

      We’ve actually been talking about doing similar things for the next iteration of the Hacklab reprap/Malthus by switching to open servos which apparently support Bezier curves directly, but using FPGAs is a brilliant touch.

      More relevant to this post, I’ve been toying around with the idea of having surfcad generate gcode, since it has a lot more information available to it than something getting the stl does. And having splines there would be awesome.

  2. don b Says:

    very interesting

  3. Henrik Akerstedt Says:

    One possible way of applying a mirror is by using Tollens’ reagent.

    http://en.wikipedia.org/wiki/Tollens'_reagent

    It uses relatively common chemicals and will (I think) produce a smooth reflecting surface as long as the underlying surface is smooth enough. As an added bonus, the reaction looks really cool!

    • christopherolah Says:

      An interesting possibility. I’m hoping for an option that is more readily accessible (ie. doesn’t require one to do any chemistry, uses readily available supplies), but perhaps that’s asking for too much?

  4. murrayd Says:

    A homespun parabola: A container of liquid being spun horizontally has a parabolic surface, so a spinning container of catalysed thermosetting polymer could have a smooth parabolic surface, if everything’s done right. Dunno about homespun mirroring though.

  5. teamteamusa Says:

    A DIO Newtonian telescope would be baller!

    For mirroring, silver or aluminum leaf might work as long as the surface being leafed is adequately smooth:

    Click to access Silver_Leaf_Instructions.pdf

  6. buback Says:

    for the mirror: drill a hole at the dish, then stretch a piece of Mylar over the top of the mirror like a drum head and secure it with a hose clamp. Then create a vacuum under the Mylar, sucking it into the dish. it might even be an adjustable mirror, but I don’t know if you would get the proper mirror shape unless it touches the surface.

    you’ll also probably need to maintain the vacuum with a vacuum pump, but i don’t know the permeability of the plastics used.

  7. Quentin Harley Says:

    We made a parabolic (ish) mirror (for a green energy project) by taking some foil blanket (space blanket, emergency blanket) and creating a drum. If you remove air from the drum, the effect is the parabolic mirror. This technique is not good enough for telescope mirrors, but you can do something similar by using your smoothed printed mirror base.

    Find some glue that will hold the film foil down without attacking the aluminium inside, apply to the full mirror base, and stick the foil around the sides of the base, making sure it is air tight and hold it down. Extract the air though a small vent in the base in order to stretch the foil blanket onto the glue inside the base. Keep the vacuum as long as the glue needs to set. Contact adhesive may be advantageous.

  8. kubitus Says:

    To get a really smooth surface which can be made reflective, I would suggest to resort to abrasive technologies – the good old grinding!
    Replace the extruder with a Dremel and let it polish the surface with finer and finer grit.
    Then you can chemically deposit a reflective layer.

  9. Greg Smith (@NotThatGreg) Says:

    Hmm, I suspect that getting the right relationship between shape and surface normal is really critical to an optical application – any small inaccuracy in the CNC will degrade this. Spherical lenses are ground using a process that inherently generates spherical shapes, by constraining motion to be about a center point. is there an analog for parabolas? can you grind a convex paraboloid against, say, a planar or cylindrical grinding element, with a fairly simple motion constraint?

Leave a comment