File size: 5,827 Bytes
7c72eb2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# Common Patterns

Idiomatic CadQuery recipes for tasks that come up frequently.
Each pattern shows the preferred approach and explains why.

---

## Fluent API Patterns

### Base solid with features on multiple faces

Build the base first, then add features face by face. Tag faces before adding
features that might change topology.

```python
import cadquery as cq

result = (
    cq.Workplane("XY")
    .box(40, 30, 15)
    .faces(">Z").tag("top")
    .faces("<Z").tag("bottom")
    .end()
    .faces(tag="top").workplane()
    .rect(20, 15).cutBlind(-5)          # pocket on top
    .faces(tag="bottom").workplane()
    .hole(6)                             # through hole from bottom
    .edges("|Z").fillet(2)               # fillet vertical edges last
)
```

### Polar pattern of features

Use `.polarArray()` to place features at equal angular intervals.

```python
result = (
    cq.Workplane("XY")
    .cylinder(5, 20)
    .faces(">Z").workplane()
    .polarArray(radius=8, startAngle=0, angle=360, count=6)
    .hole(2, depth=8)
)
```

### Rectangular pattern of features

Use `.rarray()` to place features in a grid.

```python
result = (
    cq.Workplane("XY")
    .box(40, 40, 10)
    .faces(">Z").workplane()
    .rarray(xSpacing=10, ySpacing=10, xCount=3, yCount=3, center=True)
    .hole(3, depth=8)
)
```

### Revolve a profile

Define the profile on a plane that includes the rotation axis, then revolve.
The axis is always on the X axis of the workplane by default.

```python
result = (
    cq.Workplane("XZ")
    .moveTo(5, 0)
    .lineTo(5, 10)
    .lineTo(8, 10)
    .lineTo(8, 6)
    .lineTo(5, 6)
    .close()
    .revolve(angleDegrees=360, axisStart=(0, 0, 0), axisEnd=(0, 1, 0))
)
```

### Sweep a profile along a path

Define the path, then the profile, then sweep. The profile is placed perpendicular
to the path at its start point.

```python
path = (
    cq.Workplane("XZ")
    .moveTo(0, 0)
    .spline([(10, 5), (20, 0)], includeCurrent=True)
)

result = (
    cq.Workplane("YZ")
    .circle(2)
    .sweep(path)
)
```

### Loft between profiles

Chain profiles on the same Workplane — each sketch pushed onto the stack before
`.loft()` becomes a section. Use `.workplane(offset=...)` to move between levels.

```python
result = (
    cq.Workplane("XY")
    .rect(20, 10)
    .workplane(offset=15)
    .circle(6)
    .loft()
)
```

### Shell a solid

Select the face(s) to open before calling `.shell()`. Negative thickness = inward.

```python
# Open-top box
result = cq.Workplane("XY").box(30, 20, 15).faces(">Z").shell(-2)

# Open on two opposite faces
result = cq.Workplane("XY").box(30, 20, 15).faces(">Z").shell(-2)
```

### Reusable sketch profile with `.placeSketch()`

Define the profile once and place it at multiple locations.

```python
slot = (
    cq.Sketch()
    .slot(8, 3)   # length, width
)

result = (
    cq.Workplane("XY")
    .box(40, 20, 8)
    .faces(">Z").workplane()
    .placeSketch(
        slot.moved(cq.Location((-10, 0, 0))),
        slot.moved(cq.Location((10, 0, 0))),
    )
    .cutBlind(-4)
)
```

### Selecting edges for fillet/chamfer

Fillet or chamfer specific edges by combining type and position selectors.

```python
result = (
    cq.Workplane("XY")
    .box(20, 20, 20)
    .edges(">Z").chamfer(1)          # top face perimeter edges
    .edges("<Z").fillet(2)           # bottom face perimeter edges
    .edges("|Z").fillet(1)           # vertical edges
)
```

---

## Free Function API Patterns

### Loft with curvature-continuous cap

Use `loft()` for the side and `cap()` (not `fill()`) for the top when you need
the top to maintain curvature continuity with the side surface.

```python
from cadquery.func import *

r = 5
h = 10

bottom = circle(r)
mid = circle(r * 1.3).moved(z=h * 0.5)
top_edge_guide = circle(r).moved(z=h)

side = loft(bottom, mid, top_edge_guide)
base = fill(side.edges("<Z"))
top = cap(side.edges(">Z"), side)   # curvature-continuous with side

result = solid(side, base, top)
```

### Adding a hole without a boolean

For performance on complex shapes, use `addHole()` instead of subtracting a cylinder.

```python
from cadquery.func import *

w = 1
r = 0.9*w/2

# box
b = box(w, w, w)
# bottom face
b_bot = b.faces('<Z')
# top faces
b_top = b.faces('>Z')

# inner face
inner = extrude(circle(r), (0,0,w))

# add holes to the bottom and top face
b_bot_hole = b_bot.addHole(inner.edges('<Z'))
b_top_hole = b_top.addHole(inner.edges('>Z'))

# construct the final solid
result = solid(
    b.remove(b_top, b_bot).faces(), #side faces
    b_bot_hole, # bottom with a hole
    inner, # inner cylinder face
    b_top_hole, # top with a hole
)
```

### Pattern with `.moved()`

Pass multiple location tuples to `.moved()` to create a compound of copies.

```python
from cadquery.func import *

peg = cylinder(2, 8)

# 4 pegs in a 2x2 grid
result = peg.moved(
    (-5, -5, 0),
    ( 5, -5, 0),
    (-5,  5, 0),
    ( 5,  5, 0),
)
```

### Boolean on 2D shapes

Boolean operators work on faces and wires, not just solids.
Useful for constructing profiles before extruding.

```python
from cadquery.func import *

outer = plane(20, 20)
cutout = plane(10, 10)

profile = outer - cutout   # frame-shaped face with hole
result = extrude(profile, (0, 0, 5))   # hollow frame solid
```

### Text along a spine

`text()` takes positional arguments — keyword args will fail multimethod dispatch.
For planar text, pass a line segment as the spine with `planar=True`.
For text projected onto a curved surface, see the full example in the CadQuery docs.

```python
from cadquery.func import *

from math import pi

# parameters
D = 5
H = 2*D
S = H/10
TH = S/10
TXT = "CadQuery"

c = cylinder(D, H).moved(rz=-135)
spine = (c*plane().moved(z=D)).edges().trim(pi/2, pi)

# planar
r1 = text(TXT, 1, spine, planar=True).moved(z=-S)
```

```