CadQuery resources

50 views
Skip to first unread message

D Del Vento

unread,
Jan 16, 2025, 8:18:46 PMJan 16
to CadQuery
A bit of background on me:

- software engineer, with limited machining experience back in the day (I took a lathe and mill class in school and I built maybe a dozen parts). Note "back in the day" means when CNC was just starting to appear and everything I did was manual

- I have a 3D printer, interested in getting a 3D mill

- I hate graphic-based CADs (or anything mostly GUI, FWIW), so I was looking into things like OpenSCAD when found CQ which of course is much better since I can leverage the whole python ecosystem to compute whatever I need "in place"

So far I'm loving it, but as probably most I am deeply confused by many unexpected behaviors (examples below). I know about https://cadquery.readthedocs.io/en/latest/index.html but that does not really explain any of the things I stumbled on, so I am wondering if there is anything else that I should consult, or if "banging my head on the keyboard" and "bothering other people in this forum" are the recommended approach.

Here are some examples of deeply confusing things. 

# this makes a hole (i.e. removes material)
result = cq.Workplane("front").circle(3.0)
result = result.center(2, 0.0).rect(0.5, 0.5)
result = result.extrude(0.25)

# this otherwise identical code adds material!!!!!
result = cq.Workplane("front").circle(3.0)
result = result.center(3, 0.0).rect(0.5, 0.5)
result = result.extrude(0.25)

In a different context (Sketch) mode="s" solves this ambiguity, but in this case it is an unexpected argument.

Same thing with fillet, this works

result = cq.Sketch().circle(3.0)
result = result.rect(0.5, 0.5, mode="s").vertices().fillet(0.24)

but then I cannot extrude it. If I try to to the .vertices().fillet(0.24) to the context of the workplane which I can extrude, it complains that it cannot find a solid on the stack (sure, because I want to fillet the rectangle before extruding it!)

Similar problem with lofts: this follow example from the documentation is great

result = ( cq.Workplane("front") .box(4.0, 4.0, 0.25) .faces(">Z") .circle(1.5) .workplane(offset=3.0) .rect(0.75, 0.5) .loft(combine=True) ) but then what if I don't want that box for base? I haven't found any other solution other than making a dummy one and then cutting it.And I could go on with more, but my point here is not any specific question about any of these, nor a generic whining about the API, just an ask for "where I can learn about these things. I can vaguely get an intuition that a rectangle in a Sketch is different than a rectangle on a Workplane, and as such they behave differently. But how can I learn about it? Trial and error is proving frustrating because I start designing an object and then I arrive at a showstopper like this and have either to start from scratch with another approach, or go back to "compute distances with geometrical formulas, then use cut and add". The latter works, but it is tedious, error prone, hard to make sure it's correctly parametrized (e.g. when my 3D printer needs a slightly rescaled object because the fit is not quite perfect). And frankly it somewhat defeats the purpose of using CQ in the first place...Thanks,

Lorenz

unread,
Jan 16, 2025, 10:27:05 PMJan 16
to CadQuery
Hi,

Regarding the first two Workplane examples, here the CQ Face method makeFromWires constructs the face with OCCT BRepBuilderAPI_MakeFace.  This creates holes from inner wires.  In the second example the behavior changes because the rect wire crosses the bounds of the circle.

I'd suggest try working with Sketch when creating planar faces.  Also you might try the Free function API.  As docs state it "has no hidden state, but may result in more verbose code."  Here is a free function example constructing a similar face.:

from cadquery.func import *

circ1 = face(circle(3.0))
rect1 = face(rect(0.5, 0.5)).moved(x=2)
result1 = extrude(circ1 - rect1, (0, 0, 0.25))

rect2 = face(rect(0.5, 0.5)).moved(x=3)
# you choose to add or subtract the rect2
result2 = extrude(circ1 - rect2, (0, 0, 0.25))
result3 = extrude(clean(circ1 + rect2), (0, 0, 0.25))



> but then I cannot extrude it.
Sorry I didn't follow.  I guess this is not what you wanted.

sk1 = cq.Sketch().circle(3.0)
sk1 = sk1.rect(0.5, 0.5, mode="s").vertices().fillet(0.1)
result = cq.Workplane("XZ").placeSketch(sk1).extrude(2)



> what if I don't want that box for base?

example:

result = (
    cq.Workplane().circle(1.5).workplane(offset=3.0).rect(0.75, 0.5).loft(combine=True)
)

or with Sketch (similar to docs example):

sk1 = cq.Sketch().circle(1.5)
sk2 = cq.Sketch().rect(0.75, 0.5)
result2 = cq.Workplane().placeSketch(sk1, sk2.moved(z=3)).loft()


or with free function (also see similar docs example):

from cadquery.func import *
result3 = loft(circle(1.5), rect(0.75, 0.5).moved(z=3), cap=True)

D Del Vento

unread,
Jan 17, 2025, 9:30:22 AMJan 17
to CadQuery
Regarding the first two Workplane examples, here the CQ Face method makeFromWires constructs the face with OCCT BRepBuilderAPI_MakeFace.  This creates holes from inner wires.  In the second example the behavior changes because the rect wire crosses the bounds of the circle.

Yes, of course I understand that. But it's definitely a surprising effect, especially when the "hole" has a complex shape (as in the case which lead me to this discovery) and crosses the bounds of the "circle" (in that case it was another shape) by a marginal amount.
 
I'd suggest try working with Sketch when creating planar faces.  

Thanks. I'll try to follow that advice.
 
Also you might try the Free function API.  As docs state it "has no hidden state, but may result in more verbose code."  

The verbosity is okay. Can it do some "magic" alignment for example putting things in a specific position, such as "put this rectangle in a position in which its vertices are exactly on the circle"? These things would be extremely nice and useful, even the very basic ones (but of course having something like full-fledged solvespace power would be fantastic).
 
> but then I cannot extrude it.
Sorry I didn't follow.  I guess this is not what you wanted.

sk1 = cq.Sketch().circle(3.0)
sk1 = sk1.rect(0.5, 0.5, mode="s").vertices().fillet(0.1)
result = cq.Workplane("XZ").placeSketch(sk1).extrude(2)

That's exactly what I wanted. The thing that didn't work was extruding directly the Sketch without "placing" it on the workplane. 
 
> what if I don't want that box for base?
example:

or with Sketch (similar to docs example):
or with free function (also see similar docs example):

Wow, thanks for these examples, these are extremely useful to improve my understanding on how CQ is used!! Maybe that's all I need (just maybe).

I suggest to have the three approaches in the documentation, described in the same page, better if early on! These are illuminating for a newcomer! Should I make a PR?

Thanks again


Lorenz

unread,
Jan 17, 2025, 10:49:19 PMJan 17
to CadQuery
> The thing that didn't work was extruding directly the Sketch without "placing" it on the workplane.

It's possible to interface with Sketch without the Workplane integration. Use the Sketch `val` method to get the selected shape. You can then interface Sketch with say the free function API.


from cadquery import Sketch
from cadquery.func import *

sk1 = Sketch().circle(3.0)

sk1 = sk1.rect(0.5, 0.5, mode="s").vertices().fillet(0.1)
sk1 = sk1.reset()  # must reset previous selection before face selection
result = extrude(sk1.faces().val(), (0, 0, 2))



> Can it do some "magic" alignment for example putting things in a specific position, such as "put this rectangle in a position in which its vertices are exactly on the circle"? These things would be extremely nice and useful, even the very basic ones (but of course having something like full-fledged solvespace power would be fantastic).

Take a look at Assembly.  There is a solver feature to find object locations that satisfy the specified constraints.


> I suggest to have the three approaches in the documentation, described in the same page, better if early on! These are illuminating for a newcomer! Should I make a PR?

There is an open GitHub issue #1602 on doc examples.  The Examples are very Workplane-centric currently and haven't been significantly updated since the introduction of Sketch and other developments.  That might be a good place to start.
Reply all
Reply to author
Forward
0 new messages