Working Example of CadQuery in Jupyter Notebooks

2,091 views
Skip to first unread message

Adam Vermeer

unread,
Jun 11, 2017, 11:53:08 AM6/11/17
to CadQuery
Hello all,

I threw together a working example of a jupyter notebook with CadQuery.

I've seen a few topics here and there mentioning it, but hadn't seen a working example. 

You can see what I've done here (it's a github repo containing the .ipynb file, a static html file, and a gif showing that it does in fact work)

It really isn't anything special, but it works!  I'm not certain how useful anyone else may find this, but if there's enough interest I could go into more detail about the setup process I took.

Additionally, if anyone can see a better way to accomplish the same goal, please let me know and/or feel free to improve on things yourself.

Dave Cowden

unread,
Jun 11, 2017, 12:30:18 PM6/11/17
to Adam Vermeer, CadQuery
wow! I had not heard of jupyter, but that's really cool!

This is very well timed. Our other Adam, Ubranczyk,  has recently made a huge stride toward the next generation version of CadQuery, which is directly based on OCC, rather than FreeCAD. (https://github.com/adam-urbanczyk/cadquery)  His work is really awesome-- its about 20 test cases short of passing all the existing tests.

At that time, we'll have a challenge on our hands-- we will lose the ability to use Jeremy's cadquery freecad GUI ( https://github.com/jmwright/cadquery-freecad-module) .  Cadquery has exploded since a GUI became available. Its simply indispensable when doing CAD, as it turns out.

Your project represents one way we could get a GUI with the new CQ version.  Jeremy had done some prototyping with electron in the past as an alternative.  What are your thoughts on the relative pros and cons of using Jupyter vs using a custom-built app?



--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/3090ee44-9e2b-40c7-befc-aed7c59a12aa%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dave Cowden

unread,
Jun 11, 2017, 12:52:30 PM6/11/17
to Adam Vermeer, CadQuery
As a side note, reading a bit about Jupyter this morning-- its a very interesting project.  There is a lot of work there to isolate the server from 'bad' user scripts. Its a very difficult problem to solve 'correctly'-- I faced the same challenge on www.parametricparts.com ( back when i had editable cadquery scripts and ran them on the server

@Adam Vermeer, my understanding is that you were probably running your own Jupyter server to take your screenshot, because you have the FreeCAD dependency.  Is that correct? Or does Jupyter also provide a way to install packages into its kernel.   Installation of the dependencies just to try out cadquery is a huge barrier to entry.  If we could give people an easy way to run our examples, and see the output object (as you have done in your proof of concept), we could change the CQ build to push samples up to to public Jupyter server. Then, people could try it out before they have to 'invest' in the installation.

What steps would be necessary to run a public Jupyter server that we could use to post scripts and let people try them out?  

jmwright

unread,
Jun 11, 2017, 12:56:47 PM6/11/17
to CadQuery
Adam, thanks for doing this! I'm very interested in hearing more about your process, and I've shared this thread with a couple people over at Mach 30. It coincides with some work we had been doing with CadQuery, Jupyter and IPython at one point. I think the example you've created is very useful.

@Dave can we get this added to the featured projects in the documentation?

Dave Cowden

unread,
Jun 11, 2017, 1:07:21 PM6/11/17
to jmwright, CadQuery
yes, absolutely. We're about to leave on vacation for a week, but i'll definitely add it to my todo list to do when i get back.

Lets keep this discussion going.  Getting consensus on how we will deliver a GUI to the market is critical now that we are closer to having a FreeCAD-less backend to work with.  I had previously considered using docker as the way to package the dependcies in an easy-to-consume way.  

What if we built a docker container that includes OCC, CQ, and Jupyter server. Then, you'd have an executable container that allows running cq scripts on startup.  Im sure we can find somewhere to run that container for free as an open-source project....

On Sun, Jun 11, 2017 at 8:56 AM, jmwright <wrig...@gmail.com> wrote:
Adam, thanks for doing this! I'm very interested in hearing more about your process, and I've shared this thread with a couple people over at Mach 30. It coincides with some work we had been doing with CadQuery, Jupyter and IPython at one point. I think the example you've created is very useful.

@Dave can we get this added to the featured projects in the documentation?
--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

jmwright

unread,
Jun 11, 2017, 1:35:41 PM6/11/17
to CadQuery
@Dave I expect there would be plenty of challenges to using Jupyter for the default CadQuery 2.0 GUI, but if it worked it could be a powerful tool for everybody from Makers to professional scientists.

Dave Cowden

unread,
Jun 11, 2017, 2:14:53 PM6/11/17
to Jeremy Wright, CadQuery
Jeremy, what is your current thinking if the best GUI strategy/platform? I don't know how far you made it down the electron path, or if you have considered other avenues. I defer to your judgement on the GUI platform, you have a lot more experience than I do. No matter what, I think I can package it into a docker container. A solution  that can present a web server is ideal. Though it's possible to run native apps from within a docker container, it is tricky, and doesn't work at all to run a remote community web server.

I would like to Target ability to offer a prebuilt, pure webserver that can be run locally or on a remote server. Jupyter offers that, but I know next to nothing about how good of a GUI it would make. I'm sure there are many solutions that will meet the requirements.

On Jun 11, 2017 9:35 AM, "jmwright" <wrig...@gmail.com> wrote:
@Dave I expect there would be plenty of challenges to using Jupyter for the default CadQuery 2.0 GUI, but if it worked it could be a powerful tool for everybody from Makers to professional scientists.

--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

Adam Vermeer

unread,
Jun 11, 2017, 2:20:42 PM6/11/17
to CadQuery, adam.v...@gmail.com
Jupyter bills itself as (from the jupyter homepage):

an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text

So the perspective is a document first, code second, it would seem. 
This has some clear Pros:
- scientific and math libraries can be used alongside CQ to make very 'intelligent' models and actually get useful files from it (.step, .stl, for example)
- you can use all manner of modules and plugins to make rich documents that help you visualize as you're creating your geometry. You could, for instance, generate a function that creates a 2D sketch that will work for CadQuery and simultaneously be displayable with a .svg plugin or something similar. Instead of just having to visualize in your head where you are in a sketch, you can get visual feedback right away.
- fairly open platform. If a user is running the server themselves, they have complete control over what kernels and libraries they can use to generate data. 

It also hase cons:
- As I have set up for myself, you do need to run this in a server. Setup isn't difficult, but it's not a single line install, and is certainly off putting for anyone completely new to this sort of thing. (Compare to OpenSCAD, which has a .exe install for windows, which makes it very accessible in comparison)
- layout and notebook functionality is not within our control. At best, we can create widgets / modules to work within the system. This may be problematic when you have a long script. The output will necessarsily be immediately below the cell, so you will be scrolling up and down a lot to see your work. An editor on the left and a display window on the right is much nicer to use when making changes rapidly. (again, OpenSCAD comes to mind as a nice interface to compare to)
- Runs in the browser, so there are a few inconvenient UI concerns. For example, I have had minor frustration with how folder renaming works... it's not a deal breaker by any stretch, but it's the collection of little minor annoyances that could start to turn people off. 

I would conclude by saying I think the Jupyter notebook + CQ method is an excellent stop-gap solution. It would also be a wonderful way to use it for people who can immediately see the value of rich documentation like this. I wouldn't recommend we present it as the defacto GUI going forward.

I played around with the electron GUI prototype a while ago and was impressed with that setup. I think it's the better direction to go for a proper solution.

On Sunday, June 11, 2017 at 2:30:18 PM UTC+2, thebluedirt wrote:
wow! I had not heard of jupyter, but that's really cool!

This is very well timed. Our other Adam, Ubranczyk,  has recently made a huge stride toward the next generation version of CadQuery, which is directly based on OCC, rather than FreeCAD. (https://github.com/adam-urbanczyk/cadquery)  His work is really awesome-- its about 20 test cases short of passing all the existing tests.

At that time, we'll have a challenge on our hands-- we will lose the ability to use Jeremy's cadquery freecad GUI ( https://github.com/jmwright/cadquery-freecad-module) .  Cadquery has exploded since a GUI became available. Its simply indispensable when doing CAD, as it turns out.

Your project represents one way we could get a GUI with the new CQ version.  Jeremy had done some prototyping with electron in the past as an alternative.  What are your thoughts on the relative pros and cons of using Jupyter vs using a custom-built app?


On Sun, Jun 11, 2017 at 7:53 AM, Adam Vermeer <adam.v...@gmail.com> wrote:
Hello all,

I threw together a working example of a jupyter notebook with CadQuery.

I've seen a few topics here and there mentioning it, but hadn't seen a working example. 

You can see what I've done here (it's a github repo containing the .ipynb file, a static html file, and a gif showing that it does in fact work)

It really isn't anything special, but it works!  I'm not certain how useful anyone else may find this, but if there's enough interest I could go into more detail about the setup process I took.

Additionally, if anyone can see a better way to accomplish the same goal, please let me know and/or feel free to improve on things yourself.

--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.

Adam Vermeer

unread,
Jun 11, 2017, 2:31:50 PM6/11/17
to CadQuery, adam.v...@gmail.com
I am running my own server.

What I've done is create a DigitalOcean Droplet running Ubuntu. I installed FreeCAD and Cadquery on that, then installed Jupyter. Then you can just use your python libraries directly in your notebooks. A Docker container would certainly be possible and probably the right way to present this option to newcomers.

I did it this way specifically so that I could use CQ on my phone and iPad. (For the record, it's working quite nicely on android, and once I get SSL cert stuff worked out it will work nicely on my iPad too)

Projects that might be of interest if we want to have some kind of 'try before you buy' server:


I intend over the next days and weeks to try JupyterHub for myself, but as of right now I don't know how to use either of those projects. (Truth be told I'm pretty new to all of this stuff, so there's still plenty of learning to do on my end!)

Oh, and there is this Try Jupyter! which would indicate that we could make a similar server, load it up with example notebooks and put that link up for anyone interested... seems promising.

To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.

Dave Cowden

unread,
Jun 11, 2017, 4:18:58 PM6/11/17
to Adam Vermeer, CadQuery
Ok thanks for the thoughts, that's a very complete analysis!  @ Jeremy what are your thoughts? Are there any other platforms besides electron we should consider, or should we assume that the freecad-less can should use an electron GUI?

To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/31bf2d22-7370-4660-9aa1-28b13d3fecc6%40googlegroups.com.

jmwright

unread,
Jun 11, 2017, 7:36:42 PM6/11/17
to CadQuery
I like Adam's synopsis, and his conclusion that Jupyter should only be a stop-gap UI seems solid. I do still think that there's a large group that would always use Jupyter + CQ, but they're probably not the main group of users. I could be wrong though. We've had a lot of interest from the academic sector.

Electron worked pretty well, but the platform seems to always suffer from high CPU utilization issues. My UI was no exception. Adam Urbanzyk and I have experimented with other PythonOCC GUIs, and something wxPython or Qt based is probably the best bet for flexibility, stability and efficiency. The problem is that those UIs will be more work (at least in my opinion) to create, maintain and distribute in a cross-platform way. Also, as you've noted, having a web GUI is a big plus. This was the main reason I focused on Electron for awhile. If modularized correctly, you end up with a desktop GUI that can also be run as a web app. That's a pretty compelling option for a resource-constrained open source community.

Dave Cowden

unread,
Jun 17, 2017, 6:01:02 PM6/17/17
to Adam Vermeer, CadQuery
I have added this example to the list of linked examples on the CQ readme page.
@Adam let me know if you'd like to change anything about the mention 


To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/b89251a8-f65d-4ba5-ab0e-f3c2b742b814%40googlegroups.com.

Adam Vermeer

unread,
Jun 20, 2017, 6:30:29 AM6/20/17
to CadQuery, adam.v...@gmail.com
Oh, that's awesome! Looks great to me. :)


I've been going further with Jupyter the past few days, and have come up with a 'naive assembly' method. It's rough around the edges yet, but it uses a web library called A-frame to display .json files.

You can position and rotate things and nest parts too, so you can build up a sub-assembly structure.

Here's a quick screenshot. The different colored parts are actually separate 'parts' in the assembly. Intended workflow:

1. Create part using CQ
2. preview part using what I've shown previously
3. define assemblies and subassemblies (giving parts, positions, rotations)
4. preview assembly using a-frame


Once I've got a decent proof of concept documented, I will be updating that github repo with this development.

Dave Cowden

unread,
Jun 20, 2017, 10:47:35 AM6/20/17
to Adam Vermeer, CadQuery
Really cool! Let me know if you need me to change the picture I'm using on the calendar page....

To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/32dbd2a5-b5c7-48f4-af29-18c6d15ee368%40googlegroups.com.

jmwright

unread,
Jun 21, 2017, 11:58:48 PM6/21/17
to CadQuery
That's really cool Adam. Do you call it a "naive assembly" because it positions parts relative to each other without constraints?

If you want to (and can) talk about it, what's your purpose for doing this work? What do you plan to use it for? I'm just curious.

Adam Vermeer

unread,
Jun 22, 2017, 10:14:14 AM6/22/17
to CadQuery
@jmwright

Yea, you're right about 'naive assembly.' It doesn't use any intelligent methods to relate components, and is a pretty blunt way to make assemblies. But it works. The NopHead Mendel90 3D printer design uses OpenSCAD in such a manner, and it's a very impressive project. It's where I first ran into this simple method of making assemblies and sub assemblies.

As for my purpose, well... this is all kind of hobby work that I do in my spare time. The head/face assembly thing in the examples I'm making now is just a little figure I have designed for 3D printing. It's nothing special.

At work I use SolidWorks for industrial designs. I like the program a lot, as it is quite powerful. But for personal projects I can't swing the price tag to use SolidWorks or Inventor (at least not for now). Open Source Tools provide a nice alternative with the added benefit of being malleable for individual purposes (assuming you have the time and know-how to do some programming). An upshot is that I can simultaneously learn programming and design, so that's nice.

The A-frame stuff is cool because it's a webGL library that is focused on making Virtual Reality content easy to both create and to access on the web. My interest in that area is just because I have a hunch that 'VR content creation' as a skill set will be of value somehow.

Some projects I hope to eventually tackle with this setup:

- port the OpenSCAD Mendel design to CadQuery. Documenting / providing instructions right in the notebook with the code that creates the files. Doing this will give me a very close understanding of 3D printer design, which I want to learn anyway.

- create a tool that can create structural truss designs based on load requirements, geometric constraints. Such a tool will help me keep my engineering skills from school 'sharp', and could potentially be useful in future jobs (dunno for sure, of course, just trying to think ahead a bit)

- create design 'kits' for various projects I have in mind (eg. furniture designs, some computer case ideas, a stand for my Nintendo Switch, that sort of thing). People could open up the webpage with the notebook, make some changes to fit their needs, and have the design files generate on the fly.

- make 'product configurator' webpages for my own products or for customers of mine (this is currently just a dream... but there might be potential there, who knows)

So, while the motivation for doing this sort of thing is quite personal, I do enjoy sharing these things as they might be useful for other people's work too.

Dave Cowden

unread,
Jun 22, 2017, 10:42:48 AM6/22/17
to Adam Vermeer, CadQuery
Those projects sound awesome.  The truss generator is a canonical use of cadquery-- generating geometry from engineering requirements.

--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

jmwright

unread,
Jun 23, 2017, 2:33:29 AM6/23/17
to CadQuery
@Adam Those are great projects. The truss idea intrigues me since I've done some tinkering with using CadQuery that way. I also experimented with some generative design concepts too, looking at using evolutionary algorithms to evolve designs based on design requirements. Kind of like Autodesk Dreamcatcher. As with so many other things though, I don't have enough time to pursue it right now. If I get back to it, I'll try using Jupyter for that work.

I do think that your projects will be useful for others, and am glad you're open sourcing your efforts.

BTW - Here's a topic where members of the community have shared some of the things they've done with CadQuery if you're interested. https://groups.google.com/forum/m/#!topic/cadquery/mS2ITd37sQA

Adam Urbanczyk

unread,
Jun 26, 2017, 8:03:02 PM6/26/17
to CadQuery
This is seriously cool! I was thinking about similar stuff for the OCC based CQ. Ho does it work? Do you embed whole three.js every time?

jmwright

unread,
Jun 29, 2017, 8:53:10 PM6/29/17
to CadQuery
When I try to run the "Short Example" code, I get the following error.

Widget Javascript not detected. It may not be installed or enabled properly.

I installed pythreejs and enabled it for Jupyter. Am I missing another module?

Adam Vermeer

unread,
Jun 30, 2017, 4:30:24 AM6/30/17
to CadQuery
@Jim:

https://stackoverflow.com/questions/43769068/jupyter-notebook-widget-javascript-not-detected
This answer will (hopefully) fix your issue.

To summarize the potential fix:
1. Run the following command: jupyter nbextension enable --py --sys-prefix widgetsnbextension
2. Restart the iPython kernel

If that's not working, there is a possibility that ipywidgets isn't yet installed.
You can run:

pip install ipywidgets

Hopefully that sorts it out for you.

Sorry you're running into trouble. It's clear that some more documentation for this will be good, so I'll have to get on that!

@Urbanczyk

I'm glad you like this! I want to be clear that the widget in use (pythree-js) is not my own work. I am merely using existing tools together!

I don't have a good enough internet connection at the moment to verify how three.js is loaded with the widget, but I think it's loaded in once via the Jupyter notebook widget mechanism. Then, new renders in your notebook spawn a new webgl context, but don't 're-embed' three js (that would get huge very quickly, I think) --> I don't know this for sure, and can't verify at the moment, so take it with a grain of salt

jmwright

unread,
Jul 3, 2017, 3:12:19 PM7/3/17
to CadQuery
Thanks Adam, it's working for me now. I think this could be a big step forward for CadQuery's use in scientific research and engineering analysis. Someday when I have time to get back to my experiments with generative design, I'll start building solutions based on your example.

Adam Vermeer

unread,
Jul 6, 2017, 3:50:54 AM7/6/17
to CadQuery
Glad it's working, Jim, and I'm happy that you'll use my example to build your work. That's very exciting for me.

Perhaps you'll be interested in an update to that repo I've made. It now also showcases an assembly notebook.


jmwright

unread,
Jul 6, 2017, 8:28:08 PM7/6/17
to CadQuery
I'm trying to run assembly/bucket_src.ipynb and it's trying to import a custom module from _modules.

ImportError: No module named cqjupyter

Did you just add _modules to sys.path to get that to work?

Can you tell me more about that module? It looks like it could be really helpful for anybody trying to use CadQuery in Jupyter. Maybe it warrants its own library?

The makeSlot function in cqtools.py caught my attention too. Maybe that function is something that could be handy in the main CadQuery library?

I don't want you to feel pressured into doing a bunch of work on the last two items. I just though I'd ask. It would be really cool to be able to list Jupyter as another CadQuery GUI (alongside the FreeCAD module).

Again, no pressure, I'm just greedy when it comes to CadQuery :)

Dave Cowden

unread,
Jul 7, 2017, 2:53:31 AM7/7/17
to CadQuery


@Adam, man that latest example of the complete assembly is so awesome!

A couple of insights and questions for you:

(1) I think this code is _way_ easier than it would be in OpenSCAD, do you agree?
(2) your code does a good job of being cq-idiomatic. very easy to follow
(3) I would like to do a better job in dealing with 2-d.  cq seems to work well when you have simple 2d and you are moving to 3d. But it seems to become cumbersome complared to using a GUI when you need to draw a complex 2d sketch.  Its a huge loss in functionality relative to a CAD system ( even FreeCAD) when you lose the ability to have a 2d geometric solver available.  When i use CAD, i tend to use a lot of construction geometry and trims/extends to create constrainted geometry, and it feels like i just give that up in CQ. What are your thoughts on that?  One solution ( that SCAD uses ) is to allow DXF import.  That lessens the pain, but its a very non-parametric solution.
(4) I know there is a lot that can be done with mate-less assemblies, but could you take an idea at how in CQ we might represent mate connectors? 





--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

Adam Vermeer

unread,
Jul 7, 2017, 3:41:57 AM7/7/17
to CadQuery
@Jim

Yes, I did just add _modules to sys.path. The very first cell in that example is where it is done.

import sys
sys.path.append('/home/adam/_modules')
from cqjupyter import *

(similarly, I do a from cqtools import * later on in a different cell)

You will have to change the string in the append function to match your situation. In my case, I am running Jupyter on a server and the default location runs from /home/adam, so any file or folder added to the top level within Jupyter will show up on that file path.

NOTE: If you are trying to run just one cell in the notebook that depends on cqjupyter, it will give an error until you also run the cell containing the import. So, if you have modified the sys.path.append in the 1st cell, you have to re-run that cell.
OTHER NOTE: If you change anything in the scripts within _modules, the changes will not be recognized by the notebook until you restart the python kernel for that notebook. Use the restart button next to the STOP button on the toolbars to do this. You will have to rerun cells again.

As you've seen, I have 2 scripts in that folder: cqjupyter and cqtools.

Logic is:
- cqjupyter contains any function that is helpful or necessary to using cq within a jupyter context
- cqtools contains any functions that I have considered useful for cq in general (at least according to how I use it). It MUST be useful outside of the jupyter context (otherwise it would be added to cqjupyter)

The reason for not (yet) making a library for these is that I don't think either cqtools or cqjupyter will be 'feature stable' enough to make a library until I've used Jupyter in my workflow for a bit. I keep the scripts in the _modules folder so that I can add stuff quickly and improve things as I use them further. 

Seeing that there is some interest in these things, I will have to consider the smartest way to share this stuff. As you say, maybe a library is the best way forward. I'll need to learn some more about properly making a Python library to continue down that path. I want  to learn that, but it'll take me some time. The _modules folder that I have now is, at least, usable now, in the meantime.


Finally, I agree about the makeSlot function. I created it a while ago though, and I know that it's not totally functional. I haven't added the ability to orient the slot yet (it is currently always along X).. which I just didn't consider when I first made it. 
If it's a feature that could be useful, I can re-work the function and test it a bit more. At that point, I guess it would make sense to do a pull request to add it to the CQ lib?

I don't feel pressured at all. I love cadquery and really am glad I can contribute one way or another :)

jmwright

unread,
Jul 7, 2017, 4:06:17 AM7/7/17
to CadQuery
> Yes, I did just add _modules to sys.path. The very first cell in that example is where it is done.

Sorry, I totally missed that. It's working for me now. Very cool stuff!

> The reason for not (yet) making a library for these is that I don't think either cqtools or cqjupyter will be 'feature stable' enough to make a library until I've used Jupyter in my workflow for a bit. I keep the scripts in the _modules folder so that I can add stuff quickly and improve things as I use them further.

Understood. That sounds like a good approach.

> At that point, I guess it would make sense to do a pull request to add it to the CQ lib?

Yes. We're always happy to accept pull requests once you are happy with the function. We do ask that the new functionality come with unit tests, and we've actually got our Travis file set up so that you'll get an error if the test coverage goes down on your PR.

The community is always here if you want to try out ideas or ask questions.

Adam Vermeer

unread,
Jul 7, 2017, 4:25:46 AM7/7/17
to CadQuery
@thebluedirt, I'm glad you like it :)

Let me address you point by point here.

1. I agree here, to a point. One thing to recognize here is that as I have set it up, you can only apply a single position and rotation to any 1 part. In OpenSCAD, you can chain multiple rotations and move operations. In either case you can still get the object where you need it, but I do find it easier to think of move and rotate as sequential ops. so the ability to chain multiple would be nice. Other than that, I vastly prefer CQ syntax to OpenSCAD, and like that you can use python instead of the SCAD language for math, loops, etc.

2. Thanks! I'm glad it's easy to follow. Good to know I'm doing something right there, haha. More feedback related to code style is always welcome, as I'm otherwise in the dark, not having too much experience elsewhere

3. This is on my mind too. As a very early start, I have made a simple function that takes in a points list and outputs an SVG container with a polyline showing that point list.

This is ONLY a display mechanism. I find that when I use cadquery, one of the slowest mental activities is keepin track of where you are in a polyline sketch in your head. This was my first attempt at alleviating that pain. Obviously, this is not a parametric solution either, and it also doesn't even cover the situation where you are using the arc, circle, or rect functions. 

I have a feeling that DXF import will be a good feature to add, or perhaps SVG import? I think the problem is essentially unavoidable in script based CAD. I say this because the idea of sketches is a very geometric approach, which is by nature highly visual and conducive to interactivity (click this point, then that line, add midpoint constraint, etc etc). For anything 2D that I do, I still always find myself opening up Inkscape to work. It's quick and effective. So, I suspect a major portion of the userbase will always want the import option. 

To add parametric constraint functionality, we most likely need some kind of ID system for every object in the model. Then, we can write functions that take in 2 IDs, and a constraint type (or trim or extend) and modifies the sketch accordingly.

4. I don't have any ideas off the top of my head. I suspect as I continue to work with Jupyter and CQ I'll come up with a few ideas that I'll try out. Maybe some of them become useful for this, who knows? My approach will likely be functions that abstract away from the need to specify position and orientation. They would perhaps take 2 face IDs and a constraint, then calculate the appropriate orientations of each component and provide a new position for each component as well. 

That's all I have at this point.

thebluedirt

unread,
Jul 7, 2017, 11:11:09 AM7/7/17
to CadQuery
Hi, Adam:

Reading your discussion with Jeremy about the import statements, I realized I've forgotten to mention CQGI in the discussion.

Last year, we contemplated when Jeremy created the cadquery freecad module (CQFM), it was clear that there will evolve many different graphical contexts in which to run cq scripts. This is fantastic, but it creates one problem-- the scripts become slightly different depending on where/how they are run. This becomes a problem, because people cannot cut and paste code between projects.  At the time, there were three execution contexts:  (1) pure command line, (2) www.parametricparts.com (now turned off), and (3) cqfm.

To solve this problem, we created the Cadquery Gateway Inteface, https://dcowden.github.io/cadquery/cqgi.html

It specifies a common set of conventions execution contexts should follow, so that scripts are portable.  The most noticable conventions are that functions to display an object should be called show(), the idea of a debug() function, and handling imports so that the user script does not need to do so.  Advanced usage also allows the user to specify new values for variables, without manual changes to the scripts ( useful to allow users to modify key values without digging into the script source).

The CQGI also provides some utility classes that make the job easier on the execution side.


Is it possible to make Jupyter cq scripts CQGI compliant? 

Adam Vermeer

unread,
Jul 14, 2017, 7:24:12 AM7/14/17
to CadQuery
Sorry for a slow reply. It has been a busy week for me.

I think it's very important to follow the standardized convention. As such, I'll gladly make any changes needed. 

I am a bit confused about how to correctly proceed. Could you inform if the following actions are good?

  • show() function
    • I can re-define the cqdisplay() function as show(). This is a very easy change to make. Not sure if that's all that is required?
  • handling imports
    • I can configure the Jupyter server to always import certain modules, so that the user doesn't have to worry. modules I would import: 
      • cadquery as cq (or should I import CQGI? I'm unclear on this)
      • my cqjupyter script
      • pythree.js
      • others I may be forgetting at the moment... 
    • Other libs. that they wish to use are the user's own responsibility. I think this is ok as it would be the case in any context. Eg. if they want to use numpy, they are responsible for that import.
  • debug()
    • I'm not sure what you'd want to see with this, but I can of course build one. Is there an example for any other CQ contexts that I could use to learn? Perhaps something illustrating the correct use of CQGI in the command line context?
  • advanced usage
    • I really see the appeal of having the ability to change parameters without having to modify the script directly... I will have to think about how this makes sense in Jupyter context, as part of the appeal of a Jupyter notebook is that the code is inline with everything else. By its design, the scripts are accessible for quick changes.
    • One thing that could work here is the ipywidgets functions. They add things like interactive sliders, text inputs, etc. which can interface with the scripts. Maybe that's a possible approach?
So, in short, I can quite quickly address the first 2 points (show function and handling imports). I don't know if that counts as compliant yet, but it's a good step closer.

Any insight or feedback welcome, of course :)

Dave Cowden

unread,
Jul 14, 2017, 11:56:11 AM7/14/17
to Adam Vermeer, CadQuery
Hi Adam thanks!

From a compliance view, the most important thing is script portability.  In plain English, it means we would want your scripts, and the cadquery examples, to be runnable as-is when pasted into your jupyter notebooks or into Jeremy's cadquery freecad GUI.

Unfortunately, the cadquery examples are not cqgi compliant either, as they stand now.  It didn't make much sense to push standards when until we had more than one GUI.

The best examples of a cqgi formatted script are not great... They are in the unit tests for cqgi, here:


Reading those tests, I see I told you wrong on the show method, in the tests I called it build_object.  

Let me sort out my own confusion on this and get a couple of more solid examples you could follow before you go any further.




--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

jmwright

unread,
Jul 16, 2017, 3:44:41 AM7/16/17
to CadQuery, adam.v...@gmail.com
@Adam As Dave mentioned, there wasn't a lot of motivation to implement the CQGI in the FreeCAD module when we didn't have another GUI to run scripts in. Now that you're working on Jupyter integration, I have a reason to implement CQGI. I'll try to scrape together enough time to work on that next week. That should help clarify a lot of how things should work. If you and I can share scripts between Jupyter and FreeCAD, we'll know we're on the right track.

jmwright

unread,
Jul 17, 2017, 7:46:05 PM7/17/17
to CadQuery, adam.v...@gmail.com
@Dave I'm looking through the CQGI documentation, and it states that the container (execution environment) should import cadquery as cq. There's no good place with the FreeCAD workbench to inject that without altering what the user sees if a stack trace results. The line numbers would be offset. Is there a way that the Python environment that CQGI runs the scripts in could do have this import taken care of?

Dave Cowden

unread,
Jul 17, 2017, 8:31:41 PM7/17/17
to Jeremy Wright, adam.v...@gmail.com, CadQuery
It is possible, I think. We would have to assume that cadquery is available as a package named 'cadquery', which removes ability of the container to support multiple different cq versions.

Let me look a bit closer tonight and I can suggest an implementation.





Dave Cowden

unread,
Jul 17, 2017, 11:13:08 PM7/17/17
to Jeremy Wright, Adam Vermeer, CadQuery
Ok, I had to refresh myself on what i wrote-- its been longer than i thought and i'm evidently older than i thought ;)

The CQGI CQModel object already has the functionality to:
  1. Parse a cq script
  2. determine ( using an ast tree) all of the variables defined, as well as descriptions for them ( if available)
  3. allow the executing actor to re-define the values of these variables, even though they have been hardcoded in the script
  4. inject the cq and cadquery libraries in the executing context
  5. execute the script in a safe execution context, that removes dangerous methods that could hurt the container
  6. gather all of the objects emitted via debug() and build_object(), and present them in a list after the script executes
  7. trap exceptions and present them , along with a boolean that says whether the script ran,
  8. Compute execution time and provide it to the container

The test cases here (https://github.com/dcowden/cadquery/blob/master/tests/TestCQGI.py) are  somewhat helpful, but none of them actually run a cq script, and none of them really help describe how one might do the 'other work' that's the responsibility of the container.  

Here's a better idea.

Pre-requisites:  Container code includes cadquery, freecad, and cqgi.py.
A user script exists that we'd like to execute, which  uses:
    *  build_object ( ) to export a shape
    * simple variable declarations to declare parameters

Assume the user script is available as USER_SCRIPT

Let's also assume than an object i'm calling 'gui' represents the container-- these methods are kind of abstract and illustrate getting/sending data to the outside environment


When it is time to execute the script, the container does code that looks like this:

    user_script = gui.get_user_script()

    #parse the model, so that we can tell what variables
    #the script has, before we execute it.
    model = cqgi.parse(user_script)

    #optionally get parameters the script defines, 
    # and override them with values from the execution env
    # this is done by modifying the ast tree before execution
    parameters = model.metadata.parameters
    parameters['width'] =  gui.get_param_value['width']
    parameters['height'] = gui.get_param_value['height']

    #run the model. By default,
    #both cq and cadquery are already in scope
    #this is run in a safe sandbox--
    # see cqgi.EnvironmentBuilder for how the executing
    #environment is constructed.

    result = model.build()

    if result.success:
      
        #the model ran. Get the objects
        for object_to_display in result.results:
             gui.display_object(object_to_display)
   
        #how debug objects too
        for debug_object in result.debugObjects:
             gui.display_object_debug(debug_object )
  
    else:
        #the script failed to run.  Show the user an error
        gui.show_error_message(result.exception)


The code is run in an environment that is created by EnvironmentBuilder, and looks like this:



            env = EnvironmentBuilder().with_real_builtins().with_cadquery_objects() \
                .add_entry("build_object", collector.build_object) \
                .add_entry("debug", collector.debug) \
                .add_entry("describe_parameter",collector.describe_parameter) \
                .build()

I hope this helps!
   

Adam Vermeer

unread,
Jul 18, 2017, 6:14:54 AM7/18/17
to CadQuery
Jim and Dave,

Thank you both for the replies and explanations.

I think I've got enough to go on now to go further with a Jupyter implementation. It's hard to predict when I can have something ready, but I will be actively working on things in my spare time.

I'll report back with developments :)

Dave Cowden

unread,
Jul 18, 2017, 11:30:24 AM7/18/17
to Adam Vermeer, CadQuery
Awesome, let us know if we can help...

--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

jmwright

unread,
Jul 23, 2017, 4:35:30 AM7/23/17
to CadQuery, adam.v...@gmail.com
@Adam - I've got a start on a CQGI implementation in CQFM (the CadQuery FreeCAD module). https://github.com/jmwright/cadquery-freecad-module/tree/cqgi

The next step is to add an input control that allows users to change script variables on the fly. Then I'll see about adding debug objects.


On Tuesday, July 18, 2017 at 7:30:24 AM UTC-4, thebluedirt wrote:
Awesome, let us know if we can help...

Dave Cowden

unread,
Jul 23, 2017, 4:37:39 PM7/23/17
to Jeremy Wright, adam.v...@gmail.com, CadQuery
Nice work Jeremy! 

Adam Vermeer

unread,
Aug 7, 2017, 7:48:47 PM8/7/17
to CadQuery
@Jeremy  Your CQGI additions really helped me out a lot!

I was able to get things working with the CQGI and have created a github project to house the code.

You can see it here

There is still a lot of cleaning up to do. I wanted to share what I've got so far though!

Here's a screenshot of the interactive inputs that get created based on the parameters:

You can change values in the boxes and click the button to regen the model with your new vals. 
Only validation that occurs currently is that an input can be either INT or FLOAT. Checkbox is obviously a BOOL.

Let me know what you think!

Jeremy Wright

unread,
Aug 7, 2017, 8:14:19 PM8/7/17
to CadQuery
That's awesome! It's so exciting to see this.

Our FreeCAD module (CQFM) doesn't do much validation yet either. Actually, there's a "validate" function in the CQGI code that will throw a not-implemented-yet error if you try to use it. Hopefully we'll get around to implementing that soon-ish.

I've been working on other things for the past two weeks, but I'm hoping to finish CQFM's CQGI implementation soon. I look forward to trying scripts out in both FreeCAD and Jupyter without having to modify them.

As a side note, I saw this tweet on Twitter awhile back. https://twitter.com/WojciechM/status/780093970814734336

We're not the only ones thinking that CadQuery in Jupyter is a good idea.

Nice work!

Dave Cowden

unread,
Aug 7, 2017, 10:20:17 PM8/7/17
to Adam Vermeer, CadQuery
Whoa that's awesome!  GUI inputs for parameters, super nice! 

This is an example of what I have always hopes for cq script!

--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

Jeremy Wright

unread,
Sep 12, 2017, 8:28:26 PM9/12/17
to CadQuery
I cam across try.jupyter.org while I was working through a data analysis project.


If you click on Welcome to Python.ipynb and look at the bottom, they explain the technologies they use to host the notebooks publicly. I thought maybe that information would come in handy at some point.


On Monday, August 7, 2017 at 6:20:17 PM UTC-4, thebluedirt wrote:
Whoa that's awesome!  GUI inputs for parameters, super nice! 

This is an example of what I have always hopes for cq script!

thebluedirt

unread,
Sep 12, 2017, 10:14:36 PM9/12/17
to CadQuery
Ah, yes-- they are using Docker containers. I think that's totally the right way to do it.

Its in my roadmap to package cq and its dependencies into a docker container so that we have a one-command way to run our stack on any platform ( even windows!).

Interestingly, I've even had good luck running GUI applications as containers.  You cannot run FreeCAD in a linux container, and then export the display to Windows, but you _can_ run FreeCAD in a linux container and export the display of the host-- it works well. In fact, a lot of people run chrome in a container, so that they can limit exposure to viruses.

I see docker as the main way we can tame the beast of a a dependency chain we have to deal with, and make it realy easy to try out new versions.

  The cadquery docker container would provide an entry point that allows you to:
    * run CQFM ( if you export your host display)      ( docker run dcowden/cadquery:1.9 cadquery cqfm)
    * run a webservice that will build models for you when you post them   (docker run dcowden/cadquery:1.9 cadquery webservice )
    * execute a CQ model and provide the results  ( docker run dcowden/cadquery:1.9 cadquery build --output step < cat mymodel.py )
    * provide a command line so you can get a python prompt with everything setup and ready to go ( docker run dcowden/cadquery:1.9 cadquery cmd )

ut.

Jeremy Wright

unread,
Oct 4, 2017, 11:10:40 AM10/4/17
to CadQuery
@Adam I recently converted all the examples in the CadQuery library over to being CQGI-compliant. They've been merged into master now. I also went through and fixed the broken examples.


Those should work as-is if you copy the script text into Jupyter Notebook.

thebluedirt

unread,
Oct 4, 2017, 11:24:06 AM10/4/17
to CadQuery
@Adam i'm very interested to see if these new scripts work for you. script portability between command line, cqfm, and Jupyter is super-important.

We're in the process of designing a command line interface too, which will be delivered as a docker container.  Examples will work as-is in that context as well.

Adam Vermeer

unread,
Oct 4, 2017, 1:21:49 PM10/4/17
to CadQuery
Ooh, this is very exciting!

I'll see if I can test these on my VPS today.

I will report back with results.

I'm settling into a new job, so things have kept me away from CQ for a bit. However, I think (very soon) I'll be able to have a look at try.jupyter.org and set up a server running that. Then, we could direct people to a site with working cadquery code! I'd likely use the example scripts in those notebooks directly.

Promising stuff, I think :)

Jeremy Wright

unread,
Oct 4, 2017, 1:30:34 PM10/4/17
to CadQuery
> Then, we could direct people to a site with working cadquery code!

That would be awesome! Looking forward to hearing your results.

Adam Vermeer

unread,
Oct 4, 2017, 7:42:25 PM10/4/17
to CadQuery
Ok, I tried all of the examples on my server and have the following notes. If The Example is not listed, it worked with no issue.

# CQ examples Rough Notes

Ex008
 - error due to integer being re-cast as float by build_object

Ex009
 - line through identic points error. If you take the 1st point out of the list, this will work correctly in the notebook

Ex024 
 - example meant specifically for use within FreeCAD. Will not produce output in Jupyter.

Ex026 
 - error due to integer being re-cast as float by build_object

Ex027 
 - behaves only as expected when displaying either TOP or COVER. Multiple show_object() calls in 1  cell causes interact duplication and only renders 1 part anyway. 
 - This problem could potentially be solved, but requires rework of the plugin.
 - FreeCAD handles multiple show_object calls by creating multiple solids, one for each call.
 - is this desired behaviour? Would it be better to display each show_object() call as an individual piece (getting it's own window)?

Ex028 
 - works, though it appears to produce unintended geometry. NOT exclusive to Jupyter. Is due to fact that polyline() always seems to have point at the workplane's origin

Ex030 
 - works. Very slow. Could be due to minimal server specs. (DigitalOcean's cheapest tier)

Ex031 
 - Issue with FrenetShell. Only works if makeSolid=True. This is due to fact that Jupyter displays tessellated version of solids. If left as wire, there is nothing for tessellation.
 - again, only one show_object() call permitted per cell (with current sol'n, at least)

Ex032
 - float instead of int error again



My observations related to the int/float issue I keep running into:

- if I explicitly use int(var) within the script, this issue does not occur
- looking at the InputParameter.set_value() function, it seems like an assumption about numerical values is made --> that they will always be OK as floats. Am I reading this correctly?
  - if true, any range() or similar functions that expect int values will only work if the user explicitly forces the variable to be cast as an int by using int(var).

Adam Vermeer

unread,
Oct 4, 2017, 7:51:35 PM10/4/17
to CadQuery
As well, 

I see in all examples that the final call is show_object(), and the CQGI documentation specifies this, so that's cool. 

It's just that I thought that it was supposed to be build_object() at one point, or did I just go crazy and make that up in my own head?

Jeremy Wright

unread,
Oct 4, 2017, 7:52:58 PM10/4/17
to CadQuery
Thanks for the feeback Adam. I need to pull the latest version of your Jupyter Notebook setup and work through these. The iditic points error has been plaguing me off and on for awhile. It seems to work sometimes and throw errors other times.

- looking at the InputParameter.set_value() function, it seems like an assumption about numerical values is made --> that they will always be OK as floats. Am I reading this correctly?

The CQGI implementation is fairly new, so this could be an oversight. Maybe @Dave will have an idea?

On a side note, build_object() was changed to show_object() very recently because "show" more accurately describes what it's doing. Sorry about that. I think I forgot to let you know.

Jeremy Wright

unread,
Oct 4, 2017, 7:54:14 PM10/4/17
to CadQuery
We must have hit post close together.

> It's just that I thought that it was supposed to be build_object() at one point, or did I just go crazy and make that up in my own head?

You're not crazy, it was just poor communication on my part.

Adam Vermeer

unread,
Oct 4, 2017, 8:01:25 PM10/4/17
to CadQuery
Ahh, clear enough. It's a simple change on my side :)

Jeremy Wright

unread,
Oct 5, 2017, 9:44:22 PM10/5/17
to CadQuery
Ex009 - iditic points bug should be fixed in the latest commit to master.

Ex024 - Forgot about that one. That may just have to be an intentional exception to the portability of the scripts.

Ex027
> - is this desired behaviour? Would it be better to display each show_object() call as an individual piece (getting it's own window)?

My preference would be to have all objects rendered with show_object() in the same window, but I don't know if that's what Jupyter Notebook users would expect. Would they expect a separate output cell/window for each rendered object?

Ex028 - I need to track down who contributed that example and ask what their original intention was.

Ex030 - Takes about 50 seconds to render on my I5 laptop. Not sure how long it's taking your setup. That example has always been a slow one.

Ex031 - Fixed in the latest commit to master. This example still creates one invalid solid in some versions of FreeCAD though. We have another issue about the sweep operation being buggy which I hope to get to soon that may address this.

I'll need some help from Dave on the float vs int problem. We need to solve that though.

Thanks for trying those out. We'll get the bugs worked out. It's already great to see so many of the examples working properly somewhere other than FreeCAD.

Jeremy Wright

unread,
Oct 11, 2017, 8:12:00 PM10/11/17
to CadQuery
@Adam - When I try to run the example in the notebook that calls show_object(), I keep getting an error that show_object() is not a function. In the FreeCAD module I have it importing cqgi from cadquery automatically. Can you help me understand how CQGI should work in the notebook? I'm trying to get to the point where I can fix the float-int bug in some of the examples.

Adam Vermeer

unread,
Oct 12, 2017, 1:03:04 AM10/12/17
to CadQuery
Hmm...

I did make changes to cqnb today.

That error sounds to me like:

1. You are using a version of my extension that hasn't made the change from build_object() to show_object(). If you are curious, the only changes are in cqjupyter.py
2. Your Cadquery installation might not be up to date. I had this issue when I used pip install cadquery. It did NOT have the most recent code. I had to install from the github link:

pip install git+https://github.com/dcowden/cadquery

If neither of those are an issue, then I'm afraid I don't know specifically what the cause could be.
- did you add the script import line to your startup folder for Jupyter?
- or did you import cqjupyter in a separate cell in the notebook directly?

If you use 'build_object()', does it work, or provide different errors?

Jeremy Wright

unread,
Oct 12, 2017, 1:53:51 PM10/12/17
to CadQuery
I have the latest cadquery installed from git via pip, and I've put the following lines at the top of the cell.

import cadquery as cq

import sys

sys.path.insert(0, '/home/jwright/Downloads/avnb/_modules')

import cqjupyter

I've copied the text of Ex008 below that and I still get the show_object doesn't exist error. I tried with build_object with the same result. When I look into cqjupyter.py I don't see any reference to show_object, cqgi, or build(). I don't see a branch other than master. Do you maybe have uncommitted changes, or am I overlooking something simple? What should I see in cqjupyter.;py in reference to show_object?

Adam Vermeer

unread,
Oct 12, 2017, 2:09:06 PM10/12/17
to CadQuery
2 thoughts:

1. Perhaps you are using AVNB as opposed to CQNB. Correct repo is https://github.com/RustyVermeer/cqnb
I am realizing now that my organization of this is confusing. AVNB was only ever meant to be a repo for me to place interesting .ipynb files...
Once I was developing the extension a little more, I thought it would be better to use cqnb, as it takes my initials (AV) out of the mix and doesn't pollute the extension with .ipynb files

2. As well, the last line of your imports should instead import all like this:
from cqjuypter import *

I have a feeling that this isn't very pythonic, but it was the easiest option to get something up and running. 

Jeremy Wright

unread,
Oct 12, 2017, 2:14:44 PM10/12/17
to CadQuery
> 1. Perhaps you are using AVNB as opposed to CQNB.

Yes, that's the problem. I grabbed the link for AVNB from an older message. I'll switch to CQNB.

Thanks.

Jeremy Wright

unread,
Oct 12, 2017, 8:58:44 PM10/12/17
to CadQuery
@Adam - I had been testing avnb all this time and didn't realize that cqnb was out there. I just tried the lego example and what you've done with that notebook module is totally awesome!

@Dave - If  you haven't yet, you should take a look. https://github.com/RustyVermeer/cqnb

Ok, I'm done being distracted now, onward to fixing the examples...

Dave Cowden

unread,
Oct 12, 2017, 11:17:52 PM10/12/17
to Jeremy Wright, CadQuery
Holy moly! That's so awesome!

The reality of having cq scripts that are easily customized is finally here!

How could we deploy this on a cheap server so we can let people use it without installing anything?

--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

Jeremy Wright

unread,
Oct 12, 2017, 11:24:57 PM10/12/17
to CadQuery
I don't want to speak for Adam, but I think he has looked into something like "Try Jupyter". Not sure where that's at. Allowing people to try CadQuery out in a browser instantly would be huge. I'm planning to update the CQ docs for CQNB here soon-ish.

Adam Vermeer

unread,
Oct 12, 2017, 11:56:55 PM10/12/17
to CadQuery
I'm glad you both like the module so far!
Still room for improvements of course :)

As for a 'Try CQ' server, I plan to do the following in the coming days:

1. run a tmpnb install on my local setup, just so I know how to properly set it up.
2. create a docker image that can be used instead of the default tmpnb image
3. test THAT image on my localhost
4. set it up on the real deal.
  - I have registered trycadquery.com (doesn't point to anything yet)
  - for my own stuff, I use a DigitalOcean VPS. I don't know if there would be a better option, but I like them and am comfortable using them to run a server to host this.

That final step... feedback is welcome if there is any, but I'm perfectly fine going ahead with those steps as is

Jeremy Wright

unread,
Oct 13, 2017, 1:53:38 AM10/13/17
to CadQuery
> - I have registered trycadquery.com (doesn't point to anything yet)

Awesome! Dave would probably have more thoughts on hosting. I'm a Docker newbie, but I'm working on getting up to speed.

I'm hoping to have all the CadQuery examples working with CQNB within a week or two.

Jeremy Wright

unread,
Oct 13, 2017, 10:58:16 AM10/13/17
to CadQuery
When running Ex008 by copying the text of the script into a cell...
# These can be modified rather than hardcoding values for each dimension.
width = 3.0         # The width of the plate
height = 4.0        # The height of the plate
thickness = 0.25    # The thickness of the plate
polygon_sides = 6   # The number of sides that the polygonal holes should have
polygon_dia = 1.0   # The diameter of the circle enclosing the polygon points

result = cq.Workplane("front").box(width, height, thickness) \
                                    .pushPoints([(0, 0.75), (0, -0.75)]) \
                                    .polygon(polygon_sides, polygon_dia) \
                                    .cutThruAll()

# Displays the result of this script
show_object(result)

...using these settings...


...I get this error:

TypeError                                 Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/ipywidgets/widgets/interaction.pyc in update(self, *args)
    215                     value = widget.get_interact_value()
    216                     self.kwargs[widget._kwarg] = value
--> 217                 self.result = self.f(**self.kwargs)
    218                 if self.auto_display and self.result is not None:
    219                     display(self.result)

/home/jwright/Downloads/cqnb/cqjupyter.py in mkui(**kwargs)
    224             final_scale = scale
    225 
--> 226         mkui.base, mkui.new_model = update_build(cq_model, new_vals, color=color, scale=final_scale)
    227 
    228         # Create the Export options + Button

TypeError: 'NoneType' object is not iterable

Any ideas?

Dave Cowden

unread,
Oct 13, 2017, 11:20:35 AM10/13/17
to Jeremy Wright, CadQuery
If we want to run docker images, then its easiest to narrow the field. Two low-cost options right now compatible with docker are digital ocean and scaleway. Of course there is AWS and Azure and all that, but  they are more expensive.

Both google and aws offer free accounts that come with 1 year of free credits, so that could be a free option for the time being too. in aws i would recommend using ECS ( their container service), and in Google i'd recommend running a kubernetes cluster . 


--
cadquery home: https://github.com/dcowden/cadquery
post issues at https://github.com/dcowden/cadquery/issues
run it at home at : https://github.com/jmwright/cadquery-freecad-module
see it in action at http://www.parametricparts.com
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+unsubscribe@googlegroups.com.

Adam Vermeer

unread,
Oct 13, 2017, 11:48:27 AM10/13/17
to CadQuery
result = cq.Workplane("front").box(width, height, thickness) \
                                    .pushPoints([(0, 0.75), (0, -0.75)]) \
                                    .polygon(int(polygon_sides), polygon_dia) \
                                    .cutThruAll()

If you surround polygon_sides with int(), you guarantee that it is an integer value as opposed to a float. The script then works as expected.

This is what I think is happening:

1. show_object() is run with original script code, so polygon_sides is seen correctly as an integer. No error about 'float expected' is given.
2. due to current module design, no 3d display is given until button is pressed. This button press actually triggers an update_build() function, which uses CQGI's ability to re-build the object based on given parameters.
3. This update build assumes that any number is OK being passed back as a float, so it does. At this point, an error does occur, but is not stated. The error I think is because CQGI passed polygon_sides back as 6.0 instead of 6.
4. Since something went wrong, the next function cqdisplay() does not have a correct object. This function takes a CQ object and tessellates it so that it can display with ThreeJS. Obviously, a NoneType doesn't have a function like that. This is where the error occurs.

Why I think this is the case:
(code from cqgi.py line 255)

def set_value(self, new_value): if len(self.valid_values) > 0 and new_value not in self.valid_values: raise InvalidParameterError( "Cannot set value '{0:s}' for parameter '{1:s}': not a valid value. Valid values are {2:s} " .format(str(new_value), self.name, str(self.valid_values))) if self.varType == NumberParameterType: try: f = float(new_value) self.ast_node.n = f except ValueError: raise InvalidParameterError( "Cannot set value '{0:s}' for parameter '{1:s}': parameter must be numeric." .format(str(new_value), self.name)) elif self.varType == StringParameterType: self.ast_node.s = str(new_value) elif self.varType == BooleanParameterType: if new_value: self.ast_node.id = 'True' else: self.ast_node.id = 'False' else: raise ValueError("Unknown Type of var: ", str(self.varType))

This code takes a NumberParameterType and turns it into a float every time. At least, that's my understanding of this. If I am wrong, then I'll have to delve deeper to find out what's happening.

Jeremy Wright

unread,
Oct 13, 2017, 12:18:55 PM10/13/17
to CadQuery
Please try the cqgi branch that I created. https://github.com/dcowden/cadquery/tree/cqgi

It works well for me. If it works for you too I'll create a PR and let Dave take a look to make sure what I did is acceptable.

Adam Vermeer

unread,
Oct 13, 2017, 12:34:07 PM10/13/17
to CadQuery
Worked for me, too. I only tested the Ex008 though, so haven't discovered if any new weirdness arises.

I think it's the right change, though.

Jeremy Wright

unread,
Oct 13, 2017, 1:33:15 PM10/13/17
to CadQuery
Ok, I tested several more examples in both FreeCAD and a Notebook and everything looks good. I created a PR.

Once trycadquery.com is up I'll plan to change the introduction doc to point people there as a "try before you buy" resource, and highlight CQNB as another GUI option with some added advantages.

It will be interesting to see how people use CQNB.  There's been quite a bit of interest in it already.

Jeremy Wright

unread,
Oct 13, 2017, 11:42:31 PM10/13/17
to CadQuery
@Adam, that int-float PR has been merged into master.

Adam Urbanczyk

unread,
Oct 17, 2017, 8:25:14 PM10/17/17
to CadQuery
Hi Adam,

I am playing with OCC/cq/pythreejs and struggling with the following:

import pythreejs as p3js

cone
= shapes.Solid.makeCone(5,1,5)

t
= Tesselator(cone.wrapped)
t
.Compute(compute_edges=True)


from six import StringIO
import json
import pythreejs
import numpy as np
from pythreejs import *

color
='yellow'

vertices
= [t.GetVertex(i) for i in range(t.ObjGetVertexCount())]
faces
= [t.GetTriangleIndex(i) for i in range(t.ObjGetTriangleCount())]
normals
= [t.GetNormal(i) for i in range(t.ObjGetNormalCount())]

geom
= pythreejs.PlainGeometry(vertices=vertices, faces=faces)
mtl
= pythreejs.LambertMaterial(color=color,shading='FlatShading')
obj
= pythreejs.Mesh(geometry=geom, material=mtl)

tet
= p3js.PlainGeometry(vertices=vertices, faces=faces)
box
= p3js.BoxGeometry(height=1, width=1, depth=1)

mat_red
= p3js.LambertMaterial(color='red')

m_tet
= p3js.Mesh(geometry=tet, material=mat_red, position=[-0.5, -0.5, 0.5])
m_box
= p3js.Mesh(geometry=box, material=mat_red, position=[0, 0, 0])

dl
= p3js.DirectionalLight(color='white', position=[0, 1, 5], intensity=1)
al
= p3js.AmbientLight(color='#777777')

s
=  p3js.Scene(children=[obj,al])

cam
= p3js.PerspectiveCamera(position=[2, 3, 2], up=[0, 0, 1], children=[dl])

renderer
= p3js.Renderer(camera=cam, scene=s, controls=[p3js.OrbitControls(controlling=cam)])
renderer

which gives me the following ugly result:



Do you maybe know what am I doing wrong?

Thanks,
Adam


Auto Generated Inline Image 1

Adam Vermeer

unread,
Oct 17, 2017, 10:27:20 PM10/17/17
to CadQuery
It looks like you calculate the normals for all faces but don't use them in your PlainGeometry.

I haven't tried on my side yet, but I suggest the following change:

# old line
geom
= pythreejs.PlainGeometry(vertices=vertices, faces=faces)

# new line. Only change is using faceNormals.
geom
= pythreejs.PlainGeometry(vertices=vertices, faces=faces, faceNormals=normals)



What I think you're seeing is the correct geometry with no shading applied whatsoever.
The flatshading in ThreeJS (in my opinion) looks simple, but works well in the context of 3D design. But for it to work correctly, it needs face normals. Without passing them into the PlainGeometry, ThreeJS cannot correctly adjust the color on each face (darker or ligther depending on angle relative to light source), hence no shading is seen at all.

Please let me know if this works. If not, I can test some things out a bit later tonight.

Also, I have only used flatshading. Any different scene setups I cannot advise on yet, because I simply haven't explored those options. The flat shading has been good enough for my purposes so far.

Adam Urbanczyk

unread,
Oct 18, 2017, 8:03:52 PM10/18/17
to CadQuery
Thanks Adam. I tried but the result is the same. Which version of pythreejs are you using?

In the meantime I managed to get x3dom-based display to work. I will soon push the code

Auto Generated Inline Image 1

Adam Vermeer

unread,
Oct 20, 2017, 12:35:22 AM10/20/17
to CadQuery
Hey Adam, that result looks very nice! 
I like edges when I do 3D modeling, and haven't found an effective way to do it with threejs yet, so the x3dom rendering is looking nice!

As for the pythreejs, I checked if the version was the cause, and I confirmed that it made the difference on my setup. 

pythreejs==0.3.0 --> causes the issue you see, with no shading on the faces
pythreejs==0.3.1 --> the version I have installed, which produces a shaded result.

If you have used conda to install, the newest version on conda forge is 0.3.0, so to get the proper version you will have to use pip as follows:

pip install pythreejs==0.3.1

This should (hopefully) help you out :)
Reply all
Reply to author
Forward
0 new messages