Jupyter-CadQuery
View CadQuery objects in JupyterLab or in a standalone viewer for any IDE
Click on the "launch binder" icon to start Jupyter-CadQuery on binder:
Overview
Release 3 is a complete rewrite of Jupyter-CadQuery: While the selection of pythreejs and JupyterLab's sidecar looked reasonable in 2019, it turned out they had too many limitations. pythreejs is stuck with an outdated version of threejs and the sidecar project did not improve usability to a level I would have liked to have.
Jupyter-CadQuery is now a 3 layer project:
-
three-cad-viewer This is the complete CAD viewer written in Javascript with threejs being the only dependency. There is are a bunch of live examples and an API documentation.
-
cad-view-widget A thin layer on top of cad-viewer-widget that wraps the CAD viewer into an ipywidget. The API documentation can be found here
-
jupyter-cadquery (this repository) The actual CadQuery viewer, collecting and tessellating CadQuery objects, using cad-view-widget to visualize the objects. It was written with the intent to be as compatible with Jupyter-CadQuery 2.x as reasonable.
Note: For changes see the migration section at the end of this page.
Key Features
- CadQuery support
- CadQuery >= 2.1 including master (as of 2021-04)
- CadQuery Assemblies
- CadQuery Sketch class for both
show
andreplay
- Auto display of CadQuery shapes
- STEP files
- A STEP reader to load STEP files into CadQuery Assemblies preserving hierarchy, names and colors
- Viewing options:
- Directly in the JupyterLab output cell
- In a central Jupyterlab sidecar for any JupyterLab cell
- As a standalone viewer for use from any IDE
- Animations (see examples below)
- Support Manual Assemblies with animation of model
- Animated explode mode for CadQuery assemblies
- Debugging
- Step-by-step in an IDE with the standalone viewer (see example below)
- Visually
- by displaying selected CadQuery faces and edges
- by replaying steps of the rendered object in the Notebook (see example below)
- Viewer features
- Toggle visibility of shapes and edges
- Orthographic and perspective view
- Clipping with max 3 clipping planes (of free orientation)
- Transparency mode
- Double click on shapes shows bounding box info
- Click on tree labels shows bounding box info and optionally hides or isolates the sub tree
Release v3.5.2 (03.01.2023)
Changes
- Default python now is 3.10
- Add support for
Compound
s with mixed shape types - Aligned
show_object
withCQ-Editor
(e.g. supportoptions
dict) - Improved build123d support
- Add support for my private
Alg123d
library (a thin facade on top ofbuild123d
to remove all implicit behavior and give control back to the user)
Fixes
- OCCT bug with helix: If height = 2 * pitch,
GCPnts_QuasiUniformDeflection
returns 2 points only. Jupyter CadQuery detects this and usesGCPnts_QuasiUniformAbscissa
instead
Examples
Animation system in JupyterLab
-
Self programmed animation
-
Explode objects animation
Source of STEP file: https://print.grabcad.com/library/quadruped-robot-w-code-1#!
Debugging
-
In VS Code with Standalone Viewer
-
The top half is the CadQuery code being debugged in VS Code
-
The bottom half is the standalone viewer in a browser window
-
The
show
command in the code will tessellate the objects and send them via zmq to the standalone viewer
-
-
By replaying in the notebook
Installation
Using conda
-
For using Jupyter-CadQuery in Jupyterlab
-
If you don't have it already, create a new conda environment with the latest CadQuery (e.g. master)
conda create -n jcq3 -c conda-forge -c cadquery python=3.10 cadquery=master vtk=9.2.2 conda activate jcq3
-
Install Jupyter-CadQuery (note, matplotlib is only used for the examples)
pip install jupyter-cadquery==3.5.2 cadquery-massembly==1.0.0 matplotlib
Windows users should also install
pywin32
again withconda
to ensure it is configured correctlyconda install pywin32
-
Start Jupyter-CadQuery
conda activate jcq3 jupyter lab
-
If you use the dark theme of JuypterLab, add the following code in the first cell of your notebook:
[1]: from jupyter_cadquery import set_defaults, open_viewer set_defaults(theme="dark") open_viewer("CadQuery")
-
-
For running Jupyter-CadQuery as standalone viewer
-
Start the browser based viewer
conda activate jcq3 jcv [-w width] [-h height] # light theme jcv [-w width] [-h height] -d # dark theme
-
Use it from an IDE: In your code import the
show
orshow_object
function from the viewer:import cadquery as cq from jupyter_cadquery.viewer.client import show, show_object obj = cq. ... show(obj) # or show_object(obj)
show
works as in JupyterLab, whileshow_object
views objects incrementally as in CQ-Editor
-
Using a docker image
-
For using Jupyter-CadQuery in Jupyterlab
-
Start Jupyter-Cadquery
WORKDIR=/tmp/jupyter mkdir -p "$WORKDIR" # this has to exist, otherwise an access error will be thrown docker run -it --rm -v $WORKDIR:/home/cq -p 8888:8888 bwalter42/jupyter_cadquery:3.5.2
Jupyter in the container will start in directory
/home/cq
-
To start with examples, you can
- omit the volume mapping and just run
docker run -it --rm -p 8888:8888 bwalter42/jupyter_cadquery:3.5.2
or - copy the example notebooks to your
$WORKDIR
. They will be available for Jupyter-CadQuery in the container.
- omit the volume mapping and just run
-
If you want to change the Dockerfile,
make docker
will create a new docker image
-
-
For running Jupyter-CadQuery as standalone viewer
-
Start the browser based viewer (eventually add cli options, see notes below):
docker run -it --rm -p 8888:8888 --name jcq -p 5555:5555 bwalter42/jupyter_cadquery:3.5.2 -v
-
In your code import the
show
orshow_object
function from the viewer:import cadquery as cq from jupyter_cadquery.viewer.client import show, show_object obj = cq. ... show(obj) # or show_object(obj)
show
works as in JupyterLab, whileshow_object
views objects incrementally as in CQ-Editor -
Execute your code using the Python interpreter located in the container:
docker exec -i jcq bash -c ". /opt/conda/bin/activate cq; python" < my_project.py
-
Notes:
- To simplify port forwarding, the viewer in the docker container also starts with port 8888 (and not with voila's default port 8866)
- Port 5555 (the zmq port) needs to be forwarded. The
show
of the viewer client will send cad objects to this port - Use
-d
for dark mode and-w
,-h
to set dimensions of the CAD viewer
Demo Notebooks
- A run through of all features
- Standard CadQuery examples in Jupyter CadQuery
- An OCP example (the OCC bottle)
- CadQuery Sketch support
- Animated
MAssembly
examples:- Jupyter notebooks
- IDE plus Viewer:
Usage
a) Show objects
**show(cad_objs, **kwargs)
**
Positional arguments args
:
cad_objs
: Comma separated list of cadquery objects;
Keywork arguments kwargs
:
-
Display options
viewer
: Name of the sidecar viewer (default=None)anchor
: How to open sidecar: "right", "split-right", "split-bottom", ... (default="right")cad_width
: Width of CAD view part of the view (default=800)tree_width
: Width of navigation tree part of the view (default=250)height
: Height of the CAD view (default=600)theme
: Theme "light" or "dark" (default="light")pinning
: Allow replacing the CAD View by a canvas screenshot (default=True in cells, else False)
-
Tessellation options
angular_tolerance
: Shapes: Angular deflection in radians for tessellation (default=0.2)deviation
: Shapes: Deviation from linear deflection value (default=0.1)edge_accuracy
: Edges: Precision of edge discretization (default=None, i.e. mesh quality / 100)default_color
: Default face color (default=(232, 176, 36))default_edge_color
: Default edge color (default="#707070")optimal_bb
: Use optimal bounding box (default=False)render_normals
: Render the vertex normals (default=False)render_edges
: Render edges (default=True)render_mates
: Render mates (for MAssemblies, default=False)mate_scale
: Scale of rendered mates (for MAssemblies, default=1)
-
Viewer options
control
: Use trackball controls ('trackball') or orbit controls ('orbit') (default='trackball')up
: Use z-axis ('Z') or y-axis ('Z') as up direction for the camera, legacy behaviour: 'L' (default='Z')axes
: Show axes (default=False)axes0
: Show axes at (0,0,0) (default=False)grid
: Show grid (default=[False, False, False])ticks
: Hint for the number of ticks in both directions (default=10)ortho
: Use orthographic projections (default=True)transparent
: Show objects transparent (default=False)black_edges
: Show edges in black (default=False)position
: Absolute camera position that will be scaled (default=None)quaternion
: Camera rotation as quaternion (x, y, z, w) (default=None)target
: Camera target to look at (default=None)zoom
: Zoom factor of view (default=2.5)reset_camera
: Reset camera position, rotation and zoom to default (default=True)zoom_speed
: Mouse zoom speed (default=1.0)pan_speed
: Mouse pan speed (default=1.0)rotate_speed
: Mouse rotate speed (default=1.0)ambient_intensity
: Intensity of ambient light (default=0.75)direct_intensity
: Intensity of direct lights (default=0.15)show_parent
: Show the parent for edges, faces and vertices objectstools
: Show the viewer tools like the object tree (default=True)timeit
: Show rendering times, levels = False, 0,1,2,3,4,5 (default=False)js_debug
: Enable debug output in browser console (default=False)
-
Not supported any more:
mac_scrollbar
: The default nowbb_factor
: Removeddisplay
: Use 'viewer=""' (for sidecar display) or 'viewer=None' (for cell display)quality
: Use 'deviation'to control smoothness of rendered edges
b) Manage default values
-
set_defaults(**kwargs)
: allows to globally set the defaults value so they do not need to be provided with everyshow
callkwargs:
- see
show
- see
-
get_default(value)
: Get the global default for a singlevalue
-
get_defaults()
: Get all global defaults -
reset_defaults()
: Reset all defaults back to its initial value
c) Replay objects
Note, this is not supported in the standalone viewer for the time being.
-
replay(args)
Argument
args
:cad_obj
: cadquery objectindex
(default=0
): Element in the fluent API stack to showdebug
(default=False
): Trace building the replay stackcad_width
(default=600
): Width of the CAD viewheight
(default=600
): Height of the CAD view
d) Exports:
-
Export as PNG:
Display your object via
cv = show(a1)
and adapt the cad view as wanted (camera location, axis, transparency, ...).
Then call
cv.export_png("example.png")
-
Export as HTML:
Display your object without using a sidecar (set
viewer
toNone
) viacv = show(a1, viewer=None)
and adapt the cad view as wanted (camera location, axis, transparency, ...).
Then call
cv.export_html()
Note: This does not work with viewers in sidecars!
-
Export as STL:
For CadQuery objects use CadQuery export functions. For
PartGroup
s the following code can be used:from jupyter_cadquery.export import exportSTL exportSTL( part_group, "pg.stl", tolerance=quality, angular_tolerance=angular_tolerance )
Smaller
linear_deflection
andangular_deflection
means more details.
Jupyter-CadQuery classes
-
Part
: A CadQuery shape plus some attributes for it:shape
: CadQuery shapename
: Part name in the viewcolor
: Part color in the viewshow_faces
: show the faces of this particular partshow_edges
: show the edges of this particular part
-
Faces
: CadQuery faces plus some attributesfaces
: List of CadQuery faces (shape.faces(selector))
)name
: Part name in the viewcolor
: Part color in the viewshow_faces
: show the faces for these particular facesshow_edges
: show the edges for these particular faces
-
Edges
:edges
: List of CadQuery edges (shape.edges(selector))
)name
: Part name in the viewcolor
: Part color in the view
-
Vertices
:vertices
: List of CadQuery vertices (shape.vertices(selector))
)name
: Part name in the viewcolor
: Part color in the view
-
PartGroup
: Basically a list of parts and some attributes for the view:name
: PartGroup name in the viewobjects
: all parts and assemblies included in the assembly as a list
Migration from 2.x
Deprecations:
- Import structure changed:
from jupyter_cadquery.cadquery import show, ...
will raise a deprecation error: Usefrom jupyter_cadquery import show, ...
instead.from jupyter_cadquery.occ import show, ...
will raise a deprecation error: Usefrom jupyter_cadquery import show, ...
instead.from jupyter_cadquery.animation import Animation
will raise a deprecation error: Usefrom jupyter_cadquery.cad_animation import Animation
instead.
- Sidecar handling changed
set_sidecar(title, init=True)
will raise a deprecation error: Useopen_viewer(title)
instead.close_sidecar()
will raise a deprecation error: Useclose_viewer(title)
instead.close_sidecars()
will raise a deprecation error: Useclose_viewers(title)
instead.
- Change parameters:
- Parameter
grid
is now a tuple(xy-grid, xz-grid, yz-grid)
instead of a boolean. A deprecation warning will be shown and the tuple(grid, False, False)
used to invoke the old behavior.
- Parameter
Changed behavior:
- The replay mode now shows the result's bounding box as top level step by default instead of the result. Use
show_result=True
for the old behavior. - New parameters
viewer
andanchor
of functionshow
set a sidecar (with title ) andanchor
to determine location of the sidecar (right
,split-right
,split-left
,split-top
,split-bottom
). - The parameter
rotation
of functionshow
has been replaced byquaternion
, since the new viewer uses quaternions instead of Euler angles. - The parameter
quality
is ignored. Usedeviation
to control smoothness of rendered edges. - In 7.5 of opencascade something changed with color handling, so some colors might be different.
- The default view does not render the back material, making transparent views brighter. When switching to clipping view, the back material will set to the edge color to give the impression of cut planes. This means that transparent object look darker.
Parameters of function show
and set_defaults
not supported any more:
mac_scrollbar
: This is used as default now.bb_factor
: Not necessary any more.display
: For sidecar display useviewer="<viewer title>"
and for cell display useviewer=None
.
Credits
- Thomas Paviot for python-occ. Ideas are derived/taken from his
jupyter_renderer.py
- Dave Cowden for CadQuery
- Adam Urbańczyk for the OCP version of CadQuery
Known issues
- z-fighting happens some times, especially when using multiple clip planes (cannot be solved in general)
- Using more than one clip plane will lead to cut surfaces not being shown as solid. (very hard to solve in general)