I’m pleased to announce the second release of ImplicitCAD: 0.0.1. (The first release was 0.0.0 because 0 is the true first ordinal.)
The point of this release is somewhat arbitrarily chosen. We were over due for one and no clean break was in sight. Then I woke up with a nasty headache and couldn’t seem to code, so I thought I’d do a release instead.
I’m going to try and martial together my thoughts and discuss changes in this release and what’s coming up. The TL;DR is that ImplicitCAD is going exciting places and if you are willing to tolerate bugs and file bug reports, you should become a beta user for it.
What has changed in this release of ImplicitCAD?
Bounding Box Determination
Previously, ImplicitCAD required users to provide the bounding boxes for their objects. This was tedious and irritating. And clearly something a computer should be handling.
And with this release, ImplicitCAD will have your computer do it for you.
Now you can write:
import Graphics.Implicit out = union [ rectR 0 (-40,-40) (40,40), translate (40,40) (circle 30) ] main = writeSVG 2 "test.svg" out
Where previously the following was needed:
import Graphics.Implicit out = union [ rectR 0 (-40,-40) (40,40), translate (40,40) (circle 30) ] main = writeSVG 2 (-40,-40) (70,70) "test.svg" out
Symbolic Rendering
Normally ImplicitCAD renders using a modified version of the Marching Cubes algorithm. For some objects, though, there are obvious ways to render them. ImplicitCAD now tries to do just that, falling back to cubes if it can’t.
Symbolic rendering is faster and produces nicer meshes at the same resolution of rendering. So when it can be used, it is a massive improvement for the end user. 🙂
OpenSCAD Parsing
Because of its popularity, ImplicitCAD is working to provide backwards compatibility with OpenSCAD. (Also, people have an irrational fear of Haskell.)
To this end, we provide the extopenscad tool, which runs a extended version of OpenSCAD. The extensions allow you to use the features that are new to ImplicitCAD while still enjoying the syntax of OpenSCAD. It does not yet have full backwards compatibility.
I’m really excited about some of the improvements we’ve made to OpenSCAD. A few demonstrations follow:
Proper programmatic capabilities — in OpenSCAD, there were a number of troubling limitations including not being able to reassign variables in loops:
a = 5; for (c = [1, 2, 3]) { echo(c); a = a*c; echo(a); }
1.0 5.0 2.0 10.0 3.0 30.0 Nothing to render
Functional programming!
echo(map(cos, [0, pi/2, pi]));
Rounding (r=?) for just about everything!
linear_extrude (40, r=8) union (r=5) { translate ([-10,-10]) square (30, r=3); translate ([ 10, 10]) square (30, r=3); }
Higher order modules! Notice that twist is a function!
linear_extrude (height = 40, center=true, twist(h) = 35*cos(h*2*pi/60)) { union ( r = 8) { circle (10); translate ([22,0]) circle (10); translate ([0,22]) circle (10); translate ([-22,0]) circle (10); translate ([0,-22]) circle (10); } }
(These examples and more are available on thingiverse!)
Epic Refactoring
A ludicrous amount of code has changed since 0.0.0 (keep in mind that Haskell is a lot more dense than other other languages, so 2.5K lines of code is a much bigger project than some X0K lines of code in C projects I’ve worked on). A lot of that has been me trying to make the code approachable — I think that needs to be a priority, so that other people can extend ImplicitCAD. I got a lot of awesome advice from r/haskell (thanks in particular to Peaker the awesome essay length code review; I’m still working on using the feedback).
What’s Next?
Backwards Compatible OpenSCAD Parsing
There’s still a long ways to go with OpenSCAD parsing. There’s known bugs (like the lack of user defined modules — this is nearly implemented) and unknown bugs (these lurk deep in the code base, waiting to attack unsuspecting users).
This is something you can help with! Report bugs! They bight, I don’t!
More Symbolic Rendering
I think symbolic rendering can be extended to cover the majority of common use cases. I want to see this become a reality!
GCode Generation
Presently the only thing I really support is Hacklab‘s laser cutter. Really, it is compilers all over again and a lot of consideration needs to be given to how to implement GCode generation. People at my GTALUG talk recommended I study GCC’s architecture. This seems like sound reasoning to me.
Metadata
Adding metadata to objects is a clearly necessary step. One of my friends wants to use ImplicitCAD for generating models for some of his projects, but needs to be able to attach metadata about holes (exact radius, is there any threading?, and so on).
Performance Work
ImplicitCAD can’t guarantee Lipschitz Continuity (c=1) any more, so I had to gave up my Marching Cubes variant. This makes me very sad. Thankfully, I’ve hatched a plot to reacquire my beautiful algorithm…
Unit Testing via Algebraic Topology
Here’s an interesting problem: You want to unit test a CAD program. It gives you triangle meshes when you ask it to render objects. Obviously, there isn’t one ‘right’ triangle mesh. As long as it approximates the object, we’re pretty happy. And it is entirely valid for the triangle mesh to change if we update algorithms.
One test we can do is to calculate topological invariants of the triangle mesh and make sure they match the object.
As you may have gathered, I enjoy hitting computer science problems over the head with massively oversized mathematical hammers. Call it a hobby.
Also, it gives me an excuse to write a Topology library for Haskell.
I’m going to start with Euler Characteristic but I’d eventually like to calculate Homology Groups (the algorithms involved look interesting, at a glance at least).
More Refactoring
I want ImplicitCAD to break the stereotypes of unapproachable Haskell code. In fact, I intend for it to be a super approachable project.
You can help! Take a glance at the code and tell me what your experience was like.
Hijacking This Post for Important Transmissions
The third Toronto RepRap User Group Meeting is happening on February the 27th. If you live in Toronto and are reading this post, you should probably come!
You can keep up to date with the progress of ImplicitCAD by following my twitter account.
Tags: 3d printing, CAD, haskell, ImplicitCAD, openscad, reprap
February 6, 2012 at 23:42 |
Hey Chris,
Any particular reason you’re rendering using an intermediate mesh representation from Marching Cubes? Unless I’m missing something, a raytracer would be fairly straightforward to implement as everything is implicit, and that would give you a “true” rendering of your surface. Or do you need the mesh representation for printer output?
February 7, 2012 at 04:05 |
Hey Xavier,
As you guessed, I need to export triangle meshes. In particular, STL files (which are triangle meshes) are pretty much the standard in open source 3D printing. And I’m not presently providing any visualization options myself.
Chris
February 7, 2012 at 16:06 |
It’s interesting, in some ways an implicit representation would make more sense for a 3d printer, after all, for a given nozzle position it would give you a quick expression to check whether that’s inside or outside the volume.
February 8, 2012 at 04:46 |
Exactly! I’m producing the triangle meshes to interact with existing software, but I’m experimenting with producing GCode (kind of assembly for 3D printers) my self directly from the implicit functions. I think there’s a lot of cool potential there 🙂
You also have me strongly considering writing a ray tracer 🙂 Except I’m trying to figure out how to do it with openCL acceleration… The trick is converting my haskell implicit functions into something it will play nice with. And this is why I never have free time.
February 24, 2012 at 02:30 |
Good gcode generation is still an active research area, if you implement your own you are likely to end up lagging behind the dedicated slicer projects. Perhaps a better approach would be to try and improve the hand off between the CAD program and slicer, STL is a ridiculous format to be using for that interface.
March 23, 2012 at 11:28 |
Generating gcode from the implicit functions would be neat yes. Especially with the shelling functions the outer circumflexes can be made easily. Thats where my gcode generator is currently stuck on; too many special cases 😦
What would be very handy is being able to create an object, or load in an stl file (is that even possible now?) and then slice it when implicitCAD into bi-arc segments. This will make smooth outlines possible.
Great idea btw to use Haskell. I’ve used Miranda/Gofer a long time ago but never dared to make the step to Haskell. Maybe i can help out?
March 24, 2012 at 01:16 |
How about you send me an email? Easier to talk that way. 🙂
February 8, 2012 at 18:01 |
Chris,
I am a big fan of 3D-printing.
I would like to support the RepRap community with
bitcoins. If you install a client, and send me your bitcoin
adress or post it on your blog I will donate 1 Bitcoin to your project.
http://en.wikipedia.org/wiki/Bitcoin
chris
February 20, 2012 at 02:08 |
Hey Chris!
Sorry about taking so long to respond. I was leaving your comment in my pending queue so that I couldn’t forget about it… and getting back to you to longer than expected.
Thanks for the offer. ImplicitCAD doesn’t really have any expenses: there’s no supplies except a little bit of plastic used on test prints. Really, the only resources expended is my time. Some of my other projects require other materials (like my 3D printed lenses project), and that is likely what any donation would be spent on.
In any case, I’ve had some technical issues with setting up bitcoin and, sadly, it’s not one of my higher priorities. If you’re still interested in donating 1 bitcoin, please let me know and I’ll work everything out 🙂
February 18, 2012 at 19:28 |
colah, do you have any documentation anywhere? I’d love to really start using ImplicitCAD (REAL PROGRAMMATIC FEATURES!!!) but I would also love some documentation 😉
February 20, 2012 at 02:00 |
The Haskell API has documentation that can be built by running “cabal haddock”.
The extopenscad interface doesn’t really have that. One of the things I’m working on right now is autogenerating it from the source code. In the mean time, there’s some highly accessible source code you can look at. I’m also mostly compatible with openscad, which has great documentation in its User Manual.
There should hopefully be generated documentation with in a few days 🙂
February 21, 2012 at 05:01 |
Christopher,
I’ve been playing with that very source file. I am a bit of a noob with Haskell (didn’t know about it before ImplicitCAD) so digging through it (man it’s dense!) is fun. The doc call, though, is easy. What I’d really like to know about are the variable reassignment features you’ve added, perhaps making something like http://stevetronics-3dp.blogspot.com/2012/02/openscad-ahhhhh.html possible. I’ve been reading through your variable reassignment example too. Playing away. Does the above look possible? I don’t know if it’s just a basic failing of my logic or extopenscad.
February 21, 2012 at 21:13 |
> Does the above look possible?
Sure. The following should point you in the right direction 🙂
This has pointed out to me a desperate need for indexed assignment and some more assignment operator variations. Thanks!
February 22, 2012 at 00:40 |
I just pulled the latest from GitHub, and it appears you’ve outdone me :). The code snippet on my blog was a “polygon creator” and digging through primitives.hs, I see that you’ve added that very feature. I like it. Can I take some small measure of credit for inspiration? 😉
April 18, 2012 at 18:02 |
[…] Chris will talk a bit about 3D printing and types of printers in general, the software ecosystem around 3D printing, his experience making *lenses* with printers, and his project implicitCAD. […]
May 19, 2012 at 16:28 |
Long story short – I recently built a ShapeOko (http://www.shapeoko.com) and have since been trying all sorts of software combinations for driving it, by trial and error (mostly error). I’d like to cut some cutting tool mounts, and like the idea of programmatically generating the design from the tool size and other parameters.
I’ve tried a few different combinations of s/w, and today got started with OpenSCAD, but hit a shortcoming straight away – I want to specify the basic shapes, then have the code position them as required, but a module can’t query the dimensions of a component passed to it, so all the coordinates have to be calculated by the script. Ugh!
What I really want is to be able to define layout combinators – things like, “line up these child components with a gap of 10mm between them”. Or “line up these child components so that hole 1 of child 0 lines up with hole 3 or child 1, and hole 2 of child 0 lines up with hole 2 of child 1.” (The metadata mentioned above will come in handy for this.)
A quick google for ‘openscad’ “higher order” brought me here, and mention of my old friend Haskell jumped out at me.
Enough of my waffle – I just want to say thanks for releasing this, and now I’ll download it and get started.
Rob.
May 19, 2012 at 16:44 |
Awesome!
The functionality you’re asking about already exists in the dev version, BTW. For example:
pack([30,30], sep=5) {
for (n=[0,1,2]) cube(10);
sphere(5);
}
July 13, 2012 at 09:07 |
Very approachable code indeed! I’d just hope that the very foundational geometric stuff like this would remain within reach for everybody and not be plagued by GPL, which renders the whole thing into the does-not-exist category for many ordinary people like me.
Think about it, the global Haskell land is tiny. Do you see much evidence of people getting ripped off by commercial leechers. Is there any indication that this would change any time soon? No. The GPL riffle is shooting our own people here.
August 16, 2012 at 05:11 |
There are definitely strong arguments in favor of a BSD license. I’ve given quite a bit of thought to ImplicitCAD’s licensing, and the correct course of action isn’t trivial to determine, I think. In any case, I’m sorry that ImplicitCAD’s utility to you is reduced by its licensing, and I’ll try to weight the utility of users that are not able to use GPLed software more strongly when I give reconsideration to licensing.
August 3, 2012 at 09:39 |
Hi Chris,
I ‘m trying to get ImplicitCad working on windows… not so easy.
1. Cygwin didn’t install correctly in the default path, it should have no spaces, like c:\cygwin. Solved.
2. cabal install implicit complains about “Abigious module name ‘Prelude'”. Not solved, but possible work around with latest snapshot, but:
3. cabal install plugins fails with error: Lexical error in string/character literal at character ‘P’. This seems to be a known issue for installing ‘plugins’ at windows. A suggested solution is using ‘Hint’ instead.
4. removing ‘plugins’ from libraries list in implicit.cabal to force the installation was unfortunately not sufficient: “… statements.hs:24:8:Could not find System/Plugins/Load
So that’s where I’m stuck now.
I don’t expect a quick solution, but I wanted to inform you about my findings, and any suggestions to get it work are welcome.
I will try to get it running in a vm running debian.
August 16, 2012 at 05:14 |
Hey Bert!
Please email me (chris@colah.ca) and we’ll try to sort out the problems you’re having. A lot of people have been having issues with plugins, and I may just make a version of ImplicitCAD that doesn’t use them…
August 21, 2012 at 20:27 |
Hi Chris,
Cool package! I’ll try it out when I get some time.
I built a similar library awhile back called Mecha [1], which targets POVRay and OpenSCAD. The largest model I created was to demonstrate the kinematics of a new type of piston pump [2].
As you alluded to, programmatic CAD has many advantages over conventional CAD (i.e. higher orderness, parametrics, etc). But I also think CSG combinator languages have a few drawbacks: mainly the tedious nature of describing complex parts and motion kinematics. One area that would be interesting to explore is what kind of high-level CAD languages could be created that are above the basic CSG operations; where part shapes are mostly synthesized from higher level descriptions. I think this is where the real productively gains could be made.
-Tom
[1] http://hackage.haskell.org/package/mecha
[2] http://www.youtube.com/watch?v=Ow_z99MLvlg&feature=plcp
August 21, 2012 at 20:54 |
Hey Tom,
Mecha is also a cool package. I looked at it before writing ImplicitCAD, but I had a lot of really cool ideas for a graphics engine in a higher order langauge. And I thought it was important to have the graphics engine integrated into Haskell.
I definitly agree with you that basic CSG is a tedious way to desing objects. I’ve been working on creating tools that aleviate this in someways: RCSG, higher order extrusions, and in the near future parts that intelligently snap together… But design will still remain tedious.
Higher level descriptions would be awesome and I’ve been thinking about them a lot. I think they likely need to be very domain specific and targeted at the functionality of the object. Much like how programming languages abstract the actual manner in which an algorithm is executed from the algorithm. For example, one might make one for microfludic devices describing functionality, and the layout would be automatically generated (think parsec)… It’s something I’d like to work on at some point.
December 16, 2013 at 02:50 |
I found this tremendously interesting, and especially liked your explanations of how things work.
I’m new with 3D printing, and am frustrated by the other offerings available (e.g. OpenSCAD makes it very hard to generate screw thread shapes, and nobody makes it easy to combine scanned volumes with CAD-designed things (e.g. one might want to put a nice base and nameplate on a scanned bust)).
But I see no activity in the last year, so I’m wondering whether this is a dead end already, or is it just dormant but at a usable level???
December 16, 2013 at 23:16 |
Hey Dave,
People do use ImplicitCAD for things, but there are bugs.
Sadly, I’m too busy with machine learning research these days to work on ImplicitCAD (blog posts to come on my more recent work!). There are some people looking at taking over working on ImplicitCAD, though.
Chris
December 29, 2013 at 19:11 |
Hello,
When I look at your tutorial at implicitcad.org, it looks as if the language is openSCAD compatible. But I would prefer to define my 3D objects in Haskell, as you do in this blog above. Is there a tutorial for that as well? Do you have some collection of examples in haskell for defining 3d objects?
I have recently bought and built a reprap mendel90 3D printer from a kit, and I would like to use implicitCAD for making models to print.
I wonder what is the status of implicitCAD’s g-code generation for 3D-printing?
Right now, the available software seems to be only in python or C++. This is a pity, when there is such a language as Haskell…
BR, David
December 30, 2013 at 17:27 |
Hey there David!
You can absolutely design objects in Haskell. It’s a more powerful interface than extopenscad. Most people are scared off by the word “Haskell” so I don’t advertise it much.
Import “Graphics.Implicit” into ghci and take a look. 🙂 Sorry there isn’t a tutorial.
Sadly, I’ve been very focused on machine learning research for some time and haven’t worked on ImplicitCAD. The gcode generator works for hacklab’s laser cutter, but doesn’t support anyting else. It could be easily modified to support many 2D CNC devices.
Chris
April 3, 2015 at 11:53 |
Hi again!
eventually I am trying implicit again!
I installed it from the git repo and managed to compile some simple openscad files with the extopenscad command.
I tried the Benchmark.hs file, but the Criterion package seems to be out of sync, so I just commented it out. But from that file I got a picture of how to write models in haskell.
I have a core 3.5 GHz i7 with 4 real cores, and 2 hyperthreads in each and 16GB RAM (and a CUDA card :), and I want to exploit the parallelism. When I run “writeSTL (1/8) “benchmark.stl” object2″ in ghci it takes several minutes, maybe half an hour, and my cpu monitor shows that only one cpu is loaded.
Sorry for my ghc ignorance, but I wonder how to enable it to run in parallel. Should I use a special flag when compiling? I dont see any such option documented. Or maybe only certain kinds of models permit parallel rendering? Or maybe I have to be explicit about parallelism, using the parralels package features, when calling the functions? (havent looket that much in the souce yet, things take time…)
About resolution:
It seems that sharp edges typically get kind of “zig zag” because of how the mesh is rendered. This means that I have to choose a very hogh resolution to get a decent look. and this is expensive to render.
Any hints of how to deal with this?
BR,
David
April 8, 2015 at 22:00 |
Ok, I found how to run it (assuming a module Foo.hs) in parallel: Either run ghci +RTS -N8 -RTS Foo.hs, or run it with ./Foo +RTS -N8, after having compiled with ghc -threaded -rtsopts –make Foo.hs, for 8 parallel tasks. I guess many of you who frequently use Haskell think this is too basic, and not worth mentioning, but there are many others wanting to try, so I think mentioning this in the README, for instance, would help. (but in better formulations than I did 🙂
On performance:
The highest precision I could achieve on my computer for writeSTL on object2 in Benchmark.hs was 0.05 in 5 minutes, and then the generated stl file had visible “jacks” in the corners. I also exported object2 with writeSCAD3 and renered it in openscad — it took a second, and the stl has sharp corners. So is is an issue.
It would be nice if you had an example in the other direction, something that takes time with openSCAD but is quick in implicit.
I have to try more object and model something myself. I miss the mirror command–Isaw it was commented out in the parser as unimplemented. I hope someone takes over this (unless you can continue, Chris), because it deserves it!
BR, David
October 24, 2016 at 14:52 |
I’ve just sent the pull request https://github.com/colah/ImplicitCAD/pull/179 that allows to use scale() with negative arguments, i.e. one could write
scale([-1,1,1])
where
mirror([1,0,0])
is needed.