Skip to content

An extension to render cadquery objects in JupyterLab via pythreejs

License

Notifications You must be signed in to change notification settings

RobertMaaskant/jupyter-cadquery

 
 

Repository files navigation

Jupyter-CadQuery

View CadQuery objects in JupyterLab or in a standalone viewer for any IDE

Overview

Click on the "launch binder" icon to start Jupyter-CadQuery on binder:

Binder: Latest development version

Release v3.0.0 (24.02.2022)

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:

  1. 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. This layer could also serve as the viewer for a CadQuery integration into VS Code (anybody willing to give it a try?)

  2. 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

  3. 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.

New features

  • Performance

    • By removing the back and forth communication from pythreejs (Python) to Javascript (threejs), the new version is significantly faster in showing multi object assemblies.
  • CadQuery feature support

    • Supports the latest CadQuery Sketch class.
  • New CAD View Controller

    • Besides the orbit controller (with z-axis being restricted to show up) it now also supports a trackball controller with full freedom of moving the CAD objects. The trackball controller uses the holroyd algorithm (see e.g. here) to have better control of movements and avoid the usual trackball tumbling.
  • A full re-implementation of Sidecar

    • Sidecars will be reused based on name of the sidecar
    • Supports different anchors (right, split-right, split-left, split-top, split-bottom).
    • Sidecars opening with anchor right will adapt the size to the the size of the CAD view
  • WebGL contexts

    • In a browser only a limited number of WebGL context can be shown at the same time (e.g. 16 in Chrome on my Mac). Hence, Jupyter-CadQuery now thoroughly tracks WebGL contexts, i.e. releases WebGL context when sidecar gets closed.
  • Replay mode

    • Supports CadQuery Sketch class.
    • Replay mode now can show bounding box instead of result to compare step with result.
  • New features

    • Jupyter-CadQuery now allows to show all three grids (xy, xz, yz).
    • show_bbox additionally shows the bounding box.
    • CAD viewer icons are scalable svg icons.
    • Clipping supports an intersection mode.
    • The animation controller is now part of the Javascript component.
    • export_html exports the whole view (with tools) as a HTML page
    • export_png export the CAD view (without tools) as a PNG

Fixes

  • more than I can remember (or am willing to read out of git log) ...

Key Features

  • CadQuery support
    • Supports CadQuery >= 2.1 including master (as of 2021-02-14)
  • Viewing options:
    • Directly in the JupyterLab output cell
    • In a central Jupyterlab sidecar for any JupyterLab cell (see example 1 below)
    • As a standalone viewer for use from any IDE (see example 3 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
  • Assemblies
  • Animations
  • Sketches
    • Support Sketch class for both show and replay
  • Auto display of CadQuery shapes
  • Visual debugging by
    • displaying selected CadQuery faces and edges
    • replaying steps of the rendered object (note, this is not supported in the standalone viewer)

Examples

  1. Simple Example in JupyterLab using Sidecar (light theme)

    Sidecar

    To try this yourself, you can use the code here

  2. Animation system in JupyterLab

    Animated Hexapod in Sidecar

  3. Debugging in VS Code with Standalone Viewer

    Sidecar

    Note:

    • 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

Installation

Using conda

  1. 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.8 cadquery=master
      conda activate jcq3
    • Install Jupyter-CadQuery (note, matplotlib is only used for the examples)

      pip install jupyter-cadquery==3.0.0 matplotlib

      Windows users should also install pywin32 again with conda to ensure it is configured correctly

      conda 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")
  2. 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 or show_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, while show_object views objects incrementally as in CQ-Editor

Using a docker image

  1. 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.0.0

      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.0.0 or
      • copy the example notebooks to your $WORKDIR. They will be available for Jupyter-CadQuery in the container.
    • If you want to change the Dockerfile, make docker will create a new docker image

  2. For running Jupyter-CadQuery as standalone viewer

    • Start the browser based viewer:

      docker run -it --rm -p 8888:8888 -p 5555:5555 bwalter42/jupyter_cadquery:3.0.0 -v [-d]
    • In your code import the show or show_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, while show_object views objects incrementally as in CQ-Editor

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

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')
    • 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 objects
    • show_bbox: Show bounding box (default=False)
    • tools: 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 now
    • bb_factor: Removed
    • display: 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 every show call

    kwargs:

    • see show
  • get_default(value): Get the global default for a single value

  • 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 object
    • index (default=0): Element in the fluent API stack to show
    • debug (default=False): Trace building the replay stack
    • cad_width (default=600): Width of the CAD view
    • height (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 to None) via

    cv = 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 PartGroups 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 and angular_deflection means more details.

Jupyter-CadQuery classes

  • Part: A CadQuery shape plus some attributes for it:

    • shape: CadQuery shape
    • name: Part name in the view
    • color: Part color in the view
    • show_faces: show the faces of this particular part
    • show_edges: show the edges of this particular part
  • Faces: CadQuery faces plus some attributes

    • faces: List of CadQuery faces (shape.faces(selector)))
    • name: Part name in the view
    • color: Part color in the view
    • show_faces: show the faces for these particular faces
    • show_edges: show the edges for these particular faces
  • Edges:

    • edges: List of CadQuery edges (shape.edges(selector)))
    • name: Part name in the view
    • color: Part color in the view
  • Vertices:

    • vertices: List of CadQuery vertices (shape.vertices(selector)))
    • name: Part name in the view
    • color: Part color in the view
  • PartGroup: Basically a list of parts and some attributes for the view:

    • name: PartGroup name in the view
    • objects: 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: Use from jupyter_cadquery import show, ... instead.
    • from jupyter_cadquery.occ import show, ... will raise a deprecation error: Use from jupyter_cadquery import show, ... instead.
    • from jupyter_cadquery.animation import Animation will raise a deprecation error: Use from jupyter_cadquery.cad_animation import Animation instead.
  • Sidecar handling changed
    • set_sidecar(title, init=True) will raise a deprecation error: Use open_viewer(title) instead.
    • close_sidecar() will raise a deprecation error: Use close_viewer(title) instead.
    • close_sidecars() will raise a deprecation error: Use close_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.

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 and anchor of function show set a sidecar (with title ) and anchor to determine location of the sidecar (right, split-right, split-left, split-top, split-bottom).
  • The parameter rotation of function show has been replaced by quaternion, since the new viewer uses quaternions instead of Euler angles.
  • The parameter quality is ignored. Use deviation 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 use viewer="<viewer title>" and for cell display use viewer=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)

About

An extension to render cadquery objects in JupyterLab via pythreejs

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 75.5%
  • Jupyter Notebook 22.4%
  • Other 2.1%