Skip to content

Commit f95227c

Browse files
Changed annotations and simplified the code
* _combineWithBase allows to clean too * added missing clean params
1 parent 8c63fc4 commit f95227c

File tree

1 file changed

+64
-68
lines changed

1 file changed

+64
-68
lines changed

cadquery/cq.py

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262

6363
CQObject = Union[Vector, Location, Shape, Sketch]
6464
VectorLike = Union[Tuple[float, float], Tuple[float, float, float], Vector]
65+
CombineMode = Union[bool, Literal["cut", "a", "s"]] # a : additive, s: subtractive
6566

6667
T = TypeVar("T", bound="Workplane")
6768
"""A type variable used to make the return type of a method the same as the
@@ -2392,7 +2393,7 @@ def each(
23922393
self: T,
23932394
callback: Callable[[CQObject], Shape],
23942395
useLocalCoordinates: bool = False,
2395-
combine: Union[bool, str] = True,
2396+
combine: CombineMode = True,
23962397
clean: bool = True,
23972398
) -> T:
23982399
"""
@@ -2444,13 +2445,14 @@ def each(
24442445
self._addPendingWire(r)
24452446
results.append(r)
24462447

2447-
return self.newObject(results)
2448+
return self._combineWithBase(results, combine, clean)
24482449

24492450
def eachpoint(
24502451
self: T,
24512452
callback: Callable[[Location], Shape],
24522453
useLocalCoordinates: bool = False,
2453-
combine: Union[bool, str] = False,
2454+
combine: CombineMode = False,
2455+
clean: bool = True,
24542456
) -> T:
24552457
"""
24562458
Same as each(), except each item on the stack is converted into a point before it
@@ -2461,6 +2463,7 @@ def eachpoint(
24612463
:param useLocalCoordinates: should points be in local or global coordinates
24622464
:type useLocalCoordinates: boolean
24632465
:param boolean or string combine: True to combine the resulting solid with parent solids if found, "cut" to remove the resulting solid from the parent solids if found.
2466+
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
24642467
24652468
24662469
The resulting object has a point on the stack for each object on the original stack.
@@ -2497,12 +2500,7 @@ def eachpoint(
24972500
if isinstance(r, Wire) and not r.forConstruction:
24982501
self._addPendingWire(r)
24992502

2500-
if combine:
2501-
compound = Compound.makeCompound(res)
2502-
return self._combineWithBase(compound, combine)
2503-
2504-
else:
2505-
return self.newObject(res)
2503+
return self._combineWithBase(res, combine, clean)
25062504

25072505
def rect(
25082506
self: T,
@@ -2961,7 +2959,7 @@ def twistExtrude(
29612959
self: T,
29622960
distance: float,
29632961
angleDegrees: float,
2964-
combine: Union[bool, str] = True,
2962+
combine: CombineMode = True,
29652963
clean: bool = True,
29662964
) -> T:
29672965
"""
@@ -3003,15 +3001,12 @@ def twistExtrude(
30033001

30043002
r = Compound.makeCompound(shapes).fuse()
30053003

3006-
newS = self._combineWithBase(r, combine)
3007-
if clean:
3008-
newS = newS.clean()
3009-
return newS
3004+
return self._combineWithBase(r, combine, clean)
30103005

30113006
def extrude(
30123007
self: T,
30133008
until: Union[float, Literal["next", "last"], Face],
3014-
combine: Union[bool, str] = True,
3009+
combine: CombineMode = True,
30153010
clean: bool = True,
30163011
both: bool = False,
30173012
taper: Optional[float] = None,
@@ -3041,46 +3036,40 @@ def extrude(
30413036
* if combine is true, the value is combined with the context solid if it exists,
30423037
and the resulting solid becomes the new context solid.
30433038
"""
3044-
if combine == "cut":
3045-
return self.cutBlind(until, clean, taper)
3046-
else:
3047-
# Handle `until` multiple values
3048-
if isinstance(until, str) and until in ("next", "last") and combine:
3049-
if until == "next":
3050-
faceIndex = 0
3051-
elif until == "last":
3052-
faceIndex = -1
30533039

3054-
r = self._extrude(None, both=both, taper=taper, upToFace=faceIndex)
3040+
# Handle `until` multiple values
3041+
if isinstance(until, str) and until in ("next", "last") and combine:
3042+
if until == "next":
3043+
faceIndex = 0
3044+
elif until == "last":
3045+
faceIndex = -1
30553046

3056-
elif isinstance(until, Face) and combine:
3057-
r = self._extrude(None, both=both, taper=taper, upToFace=until)
3047+
r = self._extrude(None, both=both, taper=taper, upToFace=faceIndex)
30583048

3059-
elif isinstance(until, (int, float)):
3060-
r = self._extrude(until, both=both, taper=taper, upToFace=None)
3049+
elif isinstance(until, Face) and combine:
3050+
r = self._extrude(None, both=both, taper=taper, upToFace=until)
30613051

3062-
elif isinstance(until, (str, Face)) and combine is False:
3063-
raise ValueError(
3064-
"`combine` can't be set to False when extruding until a face"
3065-
)
3052+
elif isinstance(until, (int, float)):
3053+
r = self._extrude(until, both=both, taper=taper, upToFace=None)
30663054

3067-
else:
3068-
raise ValueError(
3069-
f"Do not know how to handle until argument of type {type(until)}"
3070-
)
3055+
elif isinstance(until, (str, Face)) and combine is False:
3056+
raise ValueError(
3057+
"`combine` can't be set to False when extruding until a face"
3058+
)
30713059

3072-
newS = self._combineWithBase(r, combine)
3060+
else:
3061+
raise ValueError(
3062+
f"Do not know how to handle until argument of type {type(until)}"
3063+
)
30733064

3074-
if clean:
3075-
newS = newS.clean()
3076-
return newS
3065+
return self._combineWithBase(r, combine, clean)
30773066

30783067
def revolve(
30793068
self: T,
30803069
angleDegrees: float = 360.0,
30813070
axisStart: Optional[VectorLike] = None,
30823071
axisEnd: Optional[VectorLike] = None,
3083-
combine: Union[bool, str] = True,
3072+
combine: CombineMode = True,
30843073
clean: bool = True,
30853074
) -> T:
30863075
"""
@@ -3137,10 +3126,8 @@ def revolve(
31373126

31383127
# returns a Solid (or a compound if there were multiple)
31393128
r = self._revolve(angleDegrees, axisStart, axisEnd)
3140-
newS = self._combineWithBase(r, combine)
3141-
if clean:
3142-
newS = newS.clean()
3143-
return newS
3129+
3130+
return self._combineWithBase(r, combine, clean)
31443131

31453132
def sweep(
31463133
self: T,
@@ -3149,7 +3136,7 @@ def sweep(
31493136
sweepAlongWires: Optional[bool] = None,
31503137
makeSolid: bool = True,
31513138
isFrenet: bool = False,
3152-
combine: Union[bool, str] = True,
3139+
combine: CombineMode = True,
31533140
clean: bool = True,
31543141
transition: Literal["right", "round", "transformed"] = "right",
31553142
normal: Optional[VectorLike] = None,
@@ -3189,28 +3176,39 @@ def sweep(
31893176
auxSpine,
31903177
) # returns a Solid (or a compound if there were multiple)
31913178

3192-
newS: T
3193-
newS = self._combineWithBase(r, combine)
3194-
if clean:
3195-
newS = newS.clean()
3196-
return newS
3179+
return self._combineWithBase(r, combine, clean)
31973180

31983181
def _combineWithBase(
3199-
self: T, obj: Shape, combine_mode: Union[bool, str] = True
3182+
self: T,
3183+
obj: Union[Shape, Iterable[Shape]],
3184+
mode: CombineMode = True,
3185+
clean: bool = False,
32003186
) -> T:
32013187
"""
32023188
Combines the provided object with the base solid, if one can be found.
32033189
:param obj: The object to be combined with the context solid
3204-
:param combine_mode: The mode to combine with the base solid (True, False or "cut")
3190+
:param mode: The mode to combine with the base solid (True, False or "cut")
32053191
:return: a new object that represents the result of combining the base object with obj,
32063192
or obj if one could not be found
32073193
"""
3208-
if isinstance(combine_mode, str) and combine_mode == "cut":
3209-
newS = self._cutFromBase(obj)
3210-
elif isinstance(combine_mode, bool) and combine_mode:
3211-
newS = self._fuseWithBase(obj)
3194+
3195+
if mode:
3196+
# since we are going to do something convert the iterable if needed
3197+
if not isinstance(obj, Shape):
3198+
obj = Compound.makeCompound(obj)
3199+
3200+
# dispatch on the mode
3201+
if mode in ("cut", "s"):
3202+
newS = self._cutFromBase(obj)
3203+
elif mode in (True, "a"):
3204+
newS = self._fuseWithBase(obj)
3205+
32123206
else:
3213-
newS = self.newObject([obj])
3207+
# do not combine branch
3208+
newS = self.newObject(obj if not isinstance(obj, Shape) else [obj])
3209+
3210+
if clean:
3211+
newS = newS.clean()
32143212

32153213
return newS
32163214

@@ -3511,7 +3509,9 @@ def cutThruAll(self: T, clean: bool = True, taper: float = 0) -> T:
35113509

35123510
return self.newObject([s])
35133511

3514-
def loft(self: T, ruled: bool = False, combine: Union[bool, str] = True) -> T:
3512+
def loft(
3513+
self: T, ruled: bool = False, combine: CombineMode = True, clean: bool = True
3514+
) -> T:
35153515
"""
35163516
Make a lofted solid, through the set of wires.
35173517
:return: a Workplane object containing the created loft
@@ -3527,7 +3527,7 @@ def loft(self: T, ruled: bool = False, combine: Union[bool, str] = True) -> T:
35273527

35283528
r: Shape = Solid.makeLoft(wiresToLoft, ruled)
35293529

3530-
newS = self._combineWithBase(r, combine)
3530+
newS = self._combineWithBase(r, combine, clean)
35313531

35323532
return newS
35333533

@@ -4137,8 +4137,8 @@ def text(
41374137
fontsize: float,
41384138
distance: float,
41394139
cut: bool = True,
4140-
combine: Union[bool, str] = False,
4141-
clean: Union[bool, str] = True,
4140+
combine: CombineMode = False,
4141+
clean: bool = True,
41424142
font: str = "Arial",
41434143
fontPath: Optional[str] = None,
41444144
kind: Literal["regular", "bold", "italic"] = "regular",
@@ -4201,11 +4201,7 @@ def text(
42014201
if cut:
42024202
combine = "cut"
42034203

4204-
newS = self._combineWithBase(r, combine)
4205-
4206-
if clean:
4207-
newS = newS.clean()
4208-
return newS
4204+
return self._combineWithBase(r, combine, clean)
42094205

42104206
def section(self: T, height: float = 0.0) -> T:
42114207
"""

0 commit comments

Comments
 (0)