Skip to content

Instantly share code, notes, and snippets.

@jmwright
Last active January 31, 2024 13:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmwright/5f3f399faeeac1664ecaba0a01dc076f to your computer and use it in GitHub Desktop.
Save jmwright/5f3f399faeeac1664ecaba0a01dc076f to your computer and use it in GitHub Desktop.
CadQuery Tips and Tricks

1. Conda Installation

If you use conda you might try creating a new environment and install using conda directly:

  conda create -n cadquery-master
  conda install -c cadquery -c conda-forge cadquery=master

Or if you want both cq-editor and cadquery:

  conda create -n cqgui-master
  conda install -c cadquery -c conda-forge cq-editor=master

2. Conda Update

This will allow you to update a Conda environment.

conda remove cq-editor
conda clean --all --force-pkgs-dirs
conda install --force-reinstall -c conda-forge -c cadquery cq-editor=master

3. Reusing wires from a face.

result = ( cq.Workplane("XY") .box(2.0, 2.0, 0.5) .faces(">Y").wires().toPending().offset2D(-.1) .transformed(rotate=(-90,0,0)).extrude(.5) )

4. Standalone 3D viewer

import sys
from OCP.BRepPrimAPI import BRepPrimAPI_MakeBox
from cq_editor.widgets import viewer as cqv
import cadquery as cq


app = cqv.QApplication(sys.argv)
viewer = cqv.OCCViewer()

dlg = cqv.QDialog()
dlg.setFixedHeight(400)
dlg.setFixedWidth(600)

cqv.layout(dlg,(viewer,),dlg)
dlg.show()

#box = BRepPrimAPI_MakeBox(20,20,30)
box = cq.Workplane("XY").box(20,20,30).val().wrapped
box_ais = cqv.AIS_ColoredShape(box)

viewer.display(box_ais)
sys.exit(app.exec_())

This helper can also be used in conjunction with this.

5. Use of lambdas

.each(lambda p: p.scale(25.4))

6. Show all wires in CQ-editor

res = cq.Workplane().rect(1,1).rect(3,3).consolidateWires()

7. Monkey-patch show_object into code

Put this at the top of your script and show_object() will have no effect when running outside of CQ-editor:


if 'show_object' not in globals():
    def show_object(*args, **kwargs):
        pass

If you want to use show_object inside non-main modules you can do this (it's a bit of a hack though)

# (main module)
import my_other_module

my_other_module.show_object = show_object

8. Set Alpha and Highlight Face in Color in CQ-editor

res = (
       cq.Workplane()
       .ellipse(10,5)
       .workplane(10)
       .ellipse(8,10)
       .loft()
)

res2 = res.faces('>Z')

show_object(res,'res',options=dict(alpha=0.9))
show_object(res2,'res2',options=dict(alpha=0.1,color=(1.,0,0)))

Link

9. Select Arbitrary Axes

stand.faces('>Z').edges('|(1,1,0) or |(1,-1,0)')

Link

10. Finding Everything That Is Installed By Anaconda

conda create --dry-run --json -n dummy <package>

Link

11. Using Multiplication for Locations

L =  Ltrans*Lrot1 * Lrto2

Link

12. Torus Generation

import cadquery as cq

path = cq.Workplane().slot2D(20,5)
sweep = cq.Workplane("YZ", origin = (0,2.5)).slot2D(3,2,90).sweep(path)
revolve = cq.Workplane("XZ").move(10,-10).slot2D(2.5,2).wire().revolve(360,(0,0),(0,1))

Source: Discord

13. Fix CQ-editor On Manjaro

sudo mcopy /lib/libstdc++.so.6 ~/.conda/envs/cqgui/lib

Source: Google Groups

14. Adding an Offset Between Two Parts in an Assembly with a Dummy Vertex

a = cq.Workplane("XY").rect(xLen=1, yLen=2).extrude(5)
b = cq.Workplane("XY").rect(xLen=2, yLen=1).extrude(10)

assembly = (
    cq.Assembly(a, name="a", color=cq.Color("red"))
    .add(b, name="b", color=cq.Color("green"))
)
assembly.constrain(
    "a",
    cq.Vertex.makeVertex(3, 0, 0),
    "b",
    b.vertices("<X and <Y and <Z").val(),
    "Point",
)
assembly.constrain("a@faces@>X", "b@faces@<X", "Axis")
assembly.solve()

show_object(assembly)

15. Using describe_parameter()

height = 60.0
describe_parameter(height, '30.0 140.0')

width = 80.0
describe_parameter(width, '20.0 100.0')

Source: GitHub

16. Importing an STL With the cqMore Extension

Sample code is here

Source: Google Groups

17. Use the Sketch feature to create a cut with filleted edges inside a box.

import cadquery as cq

s1 = (
    cq.Sketch()
    .rect(30, 40)
    .rect(10, 10, mode="s", tag="rectcut")
    .vertices(">X", tag="rectcut")
    .fillet(1)
    .vertices("<X", tag="rectcut")
    .fillet(2)
)

r = cq.Workplane().placeSketch(s1).extrude(10)

Source: Discord

17. How to Fix "Developer Cannot Be Verified" on MacOS

If there is an error similar to this:

Error loading Python lib '/Users/me/Downloads/CQ-editor-MacOS/CQ-editor/libpython3.8.dylib': dlopen: dlopen(/Users/me/Downloads/CQ-editor-MacOS/CQ-editor/libpython3.8.dylib, 10): no suitable image found. Did find:
/Users/me/Downloads/CQ-editor-MacOS/CQ-editor/libpython3.8.dylib: code signature in (/Users/me/Downloads/CQ-editor-MacOS/CQ-editor/libpython3.8.dylib) not valid for use in process using Library Validation: library load disallowed by system policy

Try this form:

xattr -r -d com.apple.quarantine path/to/CQ-editor-MacOS

Source GitHub

18. Get the Global Rather than Local Coordinates (xmin, ymax, etc) of a BoundingBox

# Font that is offset and not symmetrical in all axes
text = cq.Workplane().text("X", 12, 1, False, True)

# Get the bounding box, which will have xmin, ymin, etc in local coordinates
bbox = text.val().BoundingBox()

# Alernative way to get the center that is not needed
# cen = text.val().CenterOfBoundBox()

# Move the bounding box and draw a rect to represent it (this was displayed in CQ-editor)
bb = cq.Workplane().moveTo(bbox.center.x, bbox.center.y).rect(bbox.xmax-bbox.xmin, bbox.ymax-bbox.ymin).extrude(1)

Source Google Groups

19. Sweep a Circle in the Normal Direction

pts = [
    (1, 1, 1),
    (1, 2, 2),
    (1, 3, 3),
]
p = cq.Workplane("XY").spline(pts, includeCurrent=True)
dire = p.val().tangentAt(0)
plane = cq.Plane((0,0,0), normal=dire)
s = cq.Workplane(plane).circle(1).sweep(p)

Source GitHub

20. Serialization to Enable Multiprocessing of Multiple Parts at Once

Paired with the helper shown here.

from multiprocessing import Pool
import cadquery as cq
from cq_serialize import register as register_cq_helper

register_cq_helper()

def make_box(size: float):
    return cq.Workplane("XY").box(size, size, size).findSolid()

with Pool() as p:
    boxes = p.map(make_box, range(1, 10))

Source GitHub

21. Getting pip Install Line to Work in zsh

You have to add single quotes around the package because of the way zsh interprets [ and ].

pip install 'cadquery[ipython]==2.2.0b0'

Source GitHub

22. How to Tell When clean=true Is Causing Problems

If you see ShapeUpgrade_UnifySameDomain in a CadQuery script's trace, then the issue is likely related to clean=True. Try clean=False instead. Source Google Groups

23. Chamfer Curved (Non-Planar) Edges

head = (
    cq.Workplane("XZ")
    .lineTo(head_width2, 0)
    .ellipseArc(head_width2, head_height, angle1=0, angle2=90)
    .close()
    .revolve(360, axisStart=(0, 0, 0), axisEnd=(0, 1, 0))
    .cut(sock)
    .cut(sock.translate((1.5 * eye_offset, 0, 0)))
    .faces("not %Plane")
    .edges("not <Z")
    .edges("not <Y")
    .chamfer(1)
)

Source Google Groups

24. Export an SVG on a Workplane with Sketch

s = cq.Sketch().circle(1)
cq.exporters.export(s.faces().val(), "out.svg", opt={"projectionDir": (0, 0, 1)})

Source GitHub

25. Have a model execute in CQ-editor and as part of another Python script seamlessly

# Create the plate and show it in CQ-editor (if we are executing it that way)
if 'show_object' in globals():
    plate = generate()
    show_object(plate)

Source GitHub

25. Install CadQuery on Apple Silicon

$ arch -x86_64 brew install miniconda
$ arch -x86_64 conda install -c cadquery -c conda-forge cadquery=master
$ arch -x86_64 conda install -c cadquery -c conda-forge cq-editor=master
$ arch -x86_64 /opt/homebrew/Caskroom/miniconda/base/bin/python

Source GitHub

26. The Difference Between Fixed and FixedPoint Assembly Constraints

  • Fixed fixes all 6 degrees of freedom and FixedPoint fixes only 3 translational degrees of freedom. Source GitHub

27. Find the Intersection of a Cylinder and a Line

from cadquery import *

c = Workplane().cylinder(5,1)
l = Workplane().moveTo(5,0).lineTo(-5,0)
res =  c.intersect(l).edges().val()

start = res.startPoint()
stop = res.endPoint()
lengt = res.Length()

Source GitHub

28. Install CQ-editor via pip

# Install cadquery and any other packages you are developing with `pip install -e .` while in those repo directories
# Install cadquery deps manually.
# cd into local copy of CQ-editor repo
pip install -e .

Source (kind of) GitHub

29. Tips for Decreasing Model Creation Time

  • Work in 2D as long as possible
  • Avoid boolean ops
  • If you must use boolean ops, do not use them in loops
  • If possible, use bool ops with glue=True
  • Turn off clean (set clean=False)

Source Google Groups

30. Setting Units Globally for STEP Export

import OCP

w = OCP.STEPControl.STEPControl_Writer()
OCP.Interface.Interface_Static.SetCVal_s("write.step.unit","UM")

Source Google Groups

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment