@@ -245,7 +245,7 @@ def split(self, keepTop: bool = False, keepBottom: bool = False) -> "Workplane":
245
245
246
246
# drill a hole in the side
247
247
c = Workplane().box(1,1,1).faces(">Z").workplane().circle(0.25).cutThruAll()
248
-
248
+
249
249
# now cut it in half sideways
250
250
c = c.faces(">Y").workplane(-0.5).split(keepTop=True)
251
251
"""
@@ -327,7 +327,7 @@ def all(self) -> List["Workplane"]:
327
327
328
328
def size (self ) -> int :
329
329
"""
330
- Return the number of objects currently on the stack
330
+ Return the number of objects currently on the stack
331
331
"""
332
332
return len (self .objects )
333
333
@@ -444,7 +444,7 @@ def workplane(
444
444
* The centerOption paramter sets how the center is defined.
445
445
Options are 'CenterOfMass', 'CenterOfBoundBox', or 'ProjectedOrigin'.
446
446
'CenterOfMass' and 'CenterOfBoundBox' are in relation to the selected
447
- face(s) or vertex (vertices). 'ProjectedOrigin' uses by default the current origin
447
+ face(s) or vertex (vertices). 'ProjectedOrigin' uses by default the current origin
448
448
or the optional origin parameter (if specified) and projects it onto the plane
449
449
defined by the selected face(s).
450
450
* The Z direction will be normal to the plane of the face,computed
@@ -714,17 +714,17 @@ def _selectObjects(
714
714
tag : Optional [str ] = None ,
715
715
) -> "Workplane" :
716
716
"""
717
- Filters objects of the selected type with the specified selector,and returns results
717
+ Filters objects of the selected type with the specified selector,and returns results
718
718
719
- :param objType: the type of object we are searching for
720
- :type objType: string: (Vertex|Edge|Wire|Solid|Shell|Compound|CompSolid)
721
- :param tag: if set, search the tagged CQ object instead of self
722
- :type tag: string
723
- :return: a CQ object with the selected objects on the stack.
719
+ :param objType: the type of object we are searching for
720
+ :type objType: string: (Vertex|Edge|Wire|Solid|Shell|Compound|CompSolid)
721
+ :param tag: if set, search the tagged CQ object instead of self
722
+ :type tag: string
723
+ :return: a CQ object with the selected objects on the stack.
724
724
725
- **Implementation Note**: This is the base implementation of the vertices,edges,faces,
726
- solids,shells, and other similar selector methods. It is a useful extension point for
727
- plugin developers to make other selector methods.
725
+ **Implementation Note**: This is the base implementation of the vertices,edges,faces,
726
+ solids,shells, and other similar selector methods. It is a useful extension point for
727
+ plugin developers to make other selector methods.
728
728
"""
729
729
cq_obj = self ._getTagged (tag ) if tag else self
730
730
# A single list of all faces from all objects on the stack
@@ -1571,7 +1571,7 @@ def polarLine(
1571
1571
:param float distance: distance of the end of the line from the current point
1572
1572
:param float angle: angle of the vector to the end of the line with the x-axis
1573
1573
:return: the Workplane object with the current point at the end of the new line
1574
- """
1574
+ """
1575
1575
x = math .cos (math .radians (angle )) * distance
1576
1576
y = math .sin (math .radians (angle )) * distance
1577
1577
@@ -1672,6 +1672,9 @@ def spline(
1672
1672
listOfXYTuple : Iterable [VectorLike ],
1673
1673
tangents : Optional [Sequence [VectorLike ]] = None ,
1674
1674
periodic : bool = False ,
1675
+ parameters : Optional [Sequence [float ]] = None ,
1676
+ scale : bool = True ,
1677
+ tol : Optional [float ] = None ,
1675
1678
forConstruction : bool = False ,
1676
1679
includeCurrent : bool = False ,
1677
1680
makeWire : bool = False ,
@@ -1681,8 +1684,41 @@ def spline(
1681
1684
1682
1685
:param listOfXYTuple: points to interpolate through
1683
1686
:type listOfXYTuple: list of 2-tuple
1684
- :param tangents: tuple of Vectors specifying start and finish tangent
1687
+ :param tangents: vectors specifying the direction of the tangent to the
1688
+ curve at each of the specified interpolation points.
1689
+
1690
+ If only 2 tangents are given, they will be used as the initial and
1691
+ final tangent.
1692
+
1693
+ If some tangents are not specified (i.e., are None), no tangent
1694
+ constraint will be applied to the corresponding interpolation point.
1695
+
1696
+ The spline will be C2 continuous at the interpolation points where
1697
+ no tangent constraint is specified, and C1 continuous at the points
1698
+ where a tangent constraint is specified.
1685
1699
:param periodic: creation of periodic curves
1700
+ :param parameters: the value of the parameter at each interpolation point.
1701
+ (The intepolated curve is represented as a vector-valued function of a
1702
+ scalar parameter.)
1703
+
1704
+ If periodic == True, then len(parameters) must be
1705
+ len(intepolation points) + 1, otherwise len(parameters) must be equal to
1706
+ len(interpolation points).
1707
+ :param scale: whether to scale the specified tangent vectors before
1708
+ interpolating.
1709
+
1710
+ Each tangent is scaled, so it's length is equal to the derivative of
1711
+ the Lagrange interpolated curve.
1712
+
1713
+ I.e., set this to True, if you want to use only the direction of
1714
+ the tangent vectors specified by ``tangents``, but not their magnitude.
1715
+ :param tol: tolerance of the algorithm (consult OCC documentation)
1716
+
1717
+ Used to check that the specified points are not too close to each
1718
+ other, and that tangent vectors are not too short. (In either case
1719
+ interpolation may fail.)
1720
+
1721
+ Set to None to use the default tolerance.
1686
1722
:param includeCurrent: use current point as a starting point of the curve
1687
1723
:param makeWire: convert the resulting spline edge to a wire
1688
1724
:return: a Workplane object with the current point at the end of the spline
@@ -1707,9 +1743,6 @@ def spline(
1707
1743
1708
1744
*WARNING* It is fairly easy to create a list of points
1709
1745
that cannot be correctly interpreted as a spline.
1710
-
1711
- Future Enhancements:
1712
- * provide access to control points
1713
1746
"""
1714
1747
1715
1748
vecs = [self .plane .toWorldCoords (p ) for p in listOfXYTuple ]
@@ -1721,15 +1754,23 @@ def spline(
1721
1754
allPoints = vecs
1722
1755
1723
1756
if tangents :
1724
- t1 , t2 = Vector (tangents [0 ]), Vector (tangents [1 ])
1725
- tangents_g : Optional [Tuple [Vector , Vector ]] = (
1726
- self .plane .toWorldCoords (t1 ) - self .plane .origin ,
1727
- self .plane .toWorldCoords (t2 ) - self .plane .origin ,
1728
- )
1757
+ tangents_g : Optional [Sequence [Vector ]] = [
1758
+ self .plane .toWorldCoords (t ) - self .plane .origin
1759
+ if t is not None
1760
+ else None
1761
+ for t in tangents
1762
+ ]
1729
1763
else :
1730
1764
tangents_g = None
1731
1765
1732
- e = Edge .makeSpline (allPoints , tangents = tangents_g , periodic = periodic )
1766
+ e = Edge .makeSpline (
1767
+ allPoints ,
1768
+ tangents = tangents_g ,
1769
+ periodic = periodic ,
1770
+ parameters = parameters ,
1771
+ scale = scale ,
1772
+ ** ({"tol" : tol } if tol else {}),
1773
+ )
1733
1774
1734
1775
if makeWire :
1735
1776
rv_w = Wire .assembleEdges ([e ])
@@ -2735,7 +2776,7 @@ def extrude(
2735
2776
2736
2777
extrude always *adds* material to a part.
2737
2778
2738
- The returned object is always a CQ object, and depends on wither combine is True, and
2779
+ The returned object is always a CQ object, and depends on whether combine is True, and
2739
2780
whether a context solid is already defined:
2740
2781
2741
2782
* if combine is False, the new value is pushed onto the stack.
@@ -2781,7 +2822,7 @@ def revolve(
2781
2822
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
2782
2823
:return: a CQ object with the resulting solid selected.
2783
2824
2784
- The returned object is always a CQ object, and depends on wither combine is True, and
2825
+ The returned object is always a CQ object, and depends on whether combine is True, and
2785
2826
whether a context solid is already defined:
2786
2827
2787
2828
* if combine is False, the new value is pushed onto the stack.
@@ -2937,7 +2978,7 @@ def union(
2937
2978
"""
2938
2979
Unions all of the items on the stack of toUnion with the current solid.
2939
2980
If there is no current solid, the items in toUnion are unioned together.
2940
-
2981
+
2941
2982
:param toUnion:
2942
2983
:type toUnion: a solid object, or a CQ object having a solid,
2943
2984
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape (default True)
@@ -2975,12 +3016,31 @@ def union(
2975
3016
2976
3017
return self .newObject ([r ])
2977
3018
3019
+ def __or__ (self , toUnion : Union ["Workplane" , Solid , Compound ]) -> "Workplane" :
3020
+ """
3021
+ Syntactic sugar for union.
3022
+ Notice that `r = a | b` is equivalent to `r = a.union(b)` and `r = a + b`.
3023
+
3024
+ Example::
3025
+ Box = Workplane("XY").box(1, 1, 1, centered=(False, False, False))
3026
+ Sphere = Workplane("XY").sphere(1)
3027
+ result = Box | Sphere
3028
+ """
3029
+ return self .union (toUnion )
3030
+
3031
+ def __add__ (self , toUnion : Union ["Workplane" , Solid , Compound ]) -> "Workplane" :
3032
+ """
3033
+ Syntactic sugar for union.
3034
+ Notice that `r = a + b` is equivalent to `r = a.union(b)` and `r = a | b`.
3035
+ """
3036
+ return self .union (toUnion )
3037
+
2978
3038
def cut (
2979
3039
self , toCut : Union ["Workplane" , Solid , Compound ], clean : bool = True
2980
3040
) -> "Workplane" :
2981
3041
"""
2982
3042
Cuts the provided solid from the current solid, IE, perform a solid subtraction
2983
-
3043
+
2984
3044
:param toCut: object to cut
2985
3045
:type toCut: a solid object, or a CQ object having a solid,
2986
3046
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
@@ -3010,12 +3070,25 @@ def cut(
3010
3070
3011
3071
return self .newObject ([newS ])
3012
3072
3073
+ def __sub__ (self , toUnion : Union ["Workplane" , Solid , Compound ]) -> "Workplane" :
3074
+ """
3075
+ Syntactic sugar for cut.
3076
+ Notice that `r = a - b` is equivalent to `r = a.cut(b)`.
3077
+
3078
+ Example::
3079
+
3080
+ Box = Workplane("XY").box(1, 1, 1, centered=(False, False, False))
3081
+ Sphere = Workplane("XY").sphere(1)
3082
+ result = Box - Sphere
3083
+ """
3084
+ return self .cut (toUnion )
3085
+
3013
3086
def intersect (
3014
3087
self , toIntersect : Union ["Workplane" , Solid , Compound ], clean : bool = True
3015
3088
) -> "Workplane" :
3016
3089
"""
3017
3090
Intersects the provided solid from the current solid.
3018
-
3091
+
3019
3092
:param toIntersect: object to intersect
3020
3093
:type toIntersect: a solid object, or a CQ object having a solid,
3021
3094
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
@@ -3045,6 +3118,19 @@ def intersect(
3045
3118
3046
3119
return self .newObject ([newS ])
3047
3120
3121
+ def __and__ (self , toUnion : Union ["Workplane" , Solid , Compound ]) -> "Workplane" :
3122
+ """
3123
+ Syntactic sugar for intersect.
3124
+ Notice that `r = a & b` is equivalent to `r = a.intersect(b)`.
3125
+
3126
+ Example::
3127
+
3128
+ Box = Workplane("XY").box(1, 1, 1, centered=(False, False, False))
3129
+ Sphere = Workplane("XY").sphere(1)
3130
+ result = Box & Sphere
3131
+ """
3132
+ return self .intersect (toUnion )
3133
+
3048
3134
def cutBlind (
3049
3135
self , distanceToCut : float , clean : bool = True , taper : Optional [float ] = None
3050
3136
) -> "Workplane" :
@@ -3140,10 +3226,7 @@ def _extrude(
3140
3226
:return: OCCT solid(s), suitable for boolean operations.
3141
3227
3142
3228
This method is a utility method, primarily for plugin and internal use.
3143
- It is the basis for cutBlind,extrude,cutThruAll, and all similar methods.
3144
-
3145
- Future Enhancements:
3146
- extrude along a profile (sweep)
3229
+ It is the basis for cutBlind, extrude, cutThruAll, and all similar methods.
3147
3230
"""
3148
3231
3149
3232
# group wires together into faces based on which ones are inside the others
@@ -3633,7 +3716,7 @@ def text(
3633
3716
3634
3717
extrude always *adds* material to a part.
3635
3718
3636
- The returned object is always a CQ object, and depends on wither combine is True, and
3719
+ The returned object is always a CQ object, and depends on whether combine is True, and
3637
3720
whether a context solid is already defined:
3638
3721
3639
3722
* if combine is False, the new value is pushed onto the stack.
@@ -3666,7 +3749,7 @@ def text(
3666
3749
def section (self , height : float = 0.0 ) -> "Workplane" :
3667
3750
"""
3668
3751
Slices current solid at the given height.
3669
-
3752
+
3670
3753
:param float height: height to slice at (default: 0)
3671
3754
:return: a CQ object with the resulting face(s).
3672
3755
"""
@@ -3687,7 +3770,7 @@ def section(self, height: float = 0.0) -> "Workplane":
3687
3770
def toPending (self ) -> "Workplane" :
3688
3771
"""
3689
3772
Adds wires/edges to pendingWires/pendingEdges.
3690
-
3773
+
3691
3774
:return: same CQ object with updated context.
3692
3775
"""
3693
3776
@@ -3697,22 +3780,31 @@ def toPending(self) -> "Workplane":
3697
3780
return self
3698
3781
3699
3782
def offset2D (
3700
- self , d : float , kind : Literal ["arc" , "intersection" , "tangent" ] = "arc"
3783
+ self ,
3784
+ d : float ,
3785
+ kind : Literal ["arc" , "intersection" , "tangent" ] = "arc" ,
3786
+ forConstruction : bool = False ,
3701
3787
) -> "Workplane" :
3702
3788
"""
3703
3789
Creates a 2D offset wire.
3704
-
3705
- :param float d: thickness. Negative thickness denotes offset to inside.
3790
+
3791
+ :param d: thickness. Negative thickness denotes offset to inside.
3706
3792
:param kind: offset kind. Use "arc" for rounded and "intersection" for sharp edges (default: "arc")
3707
-
3793
+ :param forConstruction: Should the result be added to pending wires?
3794
+
3708
3795
:return: CQ object with resulting wire(s).
3709
3796
"""
3710
3797
3711
3798
ws = self ._consolidateWires ()
3712
3799
rv = list (chain .from_iterable (w .offset2D (d , kind ) for w in ws ))
3713
3800
3714
3801
self .ctx .pendingEdges = []
3715
- self .ctx .pendingWires = rv
3802
+ if forConstruction :
3803
+ for wire in rv :
3804
+ wire .forConstruction = True
3805
+ self .ctx .pendingWires = []
3806
+ else :
3807
+ self .ctx .pendingWires = rv
3716
3808
3717
3809
return self .newObject (rv )
3718
3810
0 commit comments