Skip to content

Commit 995d139

Browse files
Free function api (#1469)
* Initial free functions * Mypy fixes * Add a mypy plugin that handles _get* * More helpers and fixes * black * More hooks * More ops and primitives * Fill with constraints and cap * Minimal docstrings and mypy fix * Bool op operators for Shape * Extra docstring * Added spline primitive * Added alternative constructors * Update solid * Add shape normalization * Add text * Added moved overload * Another moved overload * Convert location constructor to multimethod * Additional Loc constructor * Extra vertex constructor * Additional cone overload * Start with tests * Fix compouund normalization * Bool op tests * Additional Location overload * test moved and fix bool ops * Different cap params * More tests * Test revolve and offset * Test sweep and loft * Add bool ops * More tests * Test text * Improve coverage for utils * More move[d] and Location overloads * Start working on some docs * Update index * Doc fix * Typo fix * More move/moved overloads * Small doc update * Better Location coverage * Fix angle units in Location * More docs and a usability fix * Cosmetics * Mypy fix * Remove dead code * Coverage tweaks * More docs' * Box centering and box/plane arg order * Docs cosmetics - nicer sweep * Apply suggestions Co-authored-by: Jeremy Wright <[email protected]> * Add docstrings * Doc tweaks * Bump multimethod version * Add occ_impl.shapes * Mention free funcs in the primer * Typos * Typo * Punctuation --------- Co-authored-by: Jeremy Wright <[email protected]>
1 parent 5522037 commit 995d139

13 files changed

+1942
-64
lines changed

cadquery/occ_impl/geom.py

+76-57
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import math
1+
from math import pi, radians, degrees
22

33
from typing import overload, Sequence, Union, Tuple, Type, Optional
44

@@ -14,6 +14,8 @@
1414
gp_XYZ,
1515
gp_EulerSequence,
1616
gp,
17+
gp_Quaternion,
18+
gp_Extrinsic_XYZ,
1719
)
1820
from OCP.Bnd import Bnd_Box
1921
from OCP.BRepBndLib import BRepBndLib
@@ -22,6 +24,7 @@
2224
from OCP.TopLoc import TopLoc_Location
2325

2426
from ..types import Real
27+
from ..utils import multimethod
2528

2629
TOL = 1e-2
2730

@@ -682,7 +685,7 @@ def rotated(self, rotate=(0, 0, 0)):
682685
# NB: this is not a geometric Vector
683686
rotate = Vector(rotate)
684687
# Convert to radians.
685-
rotate = rotate.multiply(math.pi / 180.0)
688+
rotate = rotate.multiply(pi / 180.0)
686689

687690
# Compute rotation matrix.
688691
T1 = gp_Trsf()
@@ -848,11 +851,11 @@ def add(
848851

849852
def enlarge(self, tol: float) -> "BoundBox":
850853
"""Returns a modified (expanded) bounding box, expanded in all
851-
directions by the tolerance value.
854+
directions by the tolerance value.
852855
853856
This means that the minimum values of its X, Y and Z intervals
854-
of the bounding box are reduced by the absolute value of tol, while
855-
the maximum values are increased by the same amount.
857+
of the bounding box are reduced by the absolute value of tol, while
858+
the maximum values are increased by the same amount.
856859
"""
857860
tmp = Bnd_Box()
858861
tmp.Add(self.wrapped)
@@ -942,75 +945,91 @@ class Location(object):
942945

943946
wrapped: TopLoc_Location
944947

945-
@overload
946-
def __init__(self) -> None:
947-
"""Empty location with not rotation or translation with respect to the original location."""
948-
...
949-
950-
@overload
948+
@multimethod
951949
def __init__(self, t: VectorLike) -> None:
952950
"""Location with translation t with respect to the original location."""
953-
...
954951

955-
@overload
952+
T = gp_Trsf()
953+
T.SetTranslationPart(Vector(t).wrapped)
954+
955+
self.wrapped = TopLoc_Location(T)
956+
957+
@__init__.register
958+
def __init__(
959+
self,
960+
x: Real = 0,
961+
y: Real = 0,
962+
z: Real = 0,
963+
rx: Real = 0,
964+
ry: Real = 0,
965+
rz: Real = 0,
966+
) -> None:
967+
"""Location with translation (x,y,z) and 3 rotation angles."""
968+
969+
T = gp_Trsf()
970+
971+
q = gp_Quaternion()
972+
q.SetEulerAngles(gp_Extrinsic_XYZ, radians(rx), radians(ry), radians(rz))
973+
974+
T.SetRotation(q)
975+
T.SetTranslationPart(Vector(x, y, z).wrapped)
976+
977+
self.wrapped = TopLoc_Location(T)
978+
979+
@__init__.register
956980
def __init__(self, t: Plane) -> None:
957981
"""Location corresponding to the location of the Plane t."""
958-
...
959982

960-
@overload
983+
T = gp_Trsf()
984+
T.SetTransformation(gp_Ax3(t.origin.toPnt(), t.zDir.toDir(), t.xDir.toDir()))
985+
T.Invert()
986+
987+
self.wrapped = TopLoc_Location(T)
988+
989+
@__init__.register
961990
def __init__(self, t: Plane, v: VectorLike) -> None:
962991
"""Location corresponding to the angular location of the Plane t with translation v."""
963-
...
964992

965-
@overload
966-
def __init__(self, t: TopLoc_Location) -> None:
993+
T = gp_Trsf()
994+
T.SetTransformation(gp_Ax3(Vector(v).toPnt(), t.zDir.toDir(), t.xDir.toDir()))
995+
T.Invert()
996+
997+
self.wrapped = TopLoc_Location(T)
998+
999+
@__init__.register
1000+
def __init__(self, T: TopLoc_Location) -> None:
9671001
"""Location wrapping the low-level TopLoc_Location object t"""
968-
...
9691002

970-
@overload
971-
def __init__(self, t: gp_Trsf) -> None:
1003+
self.wrapped = T
1004+
1005+
@__init__.register
1006+
def __init__(self, T: gp_Trsf) -> None:
9721007
"""Location wrapping the low-level gp_Trsf object t"""
973-
...
9741008

975-
@overload
976-
def __init__(self, t: VectorLike, ax: VectorLike, angle: float) -> None:
1009+
self.wrapped = TopLoc_Location(T)
1010+
1011+
@__init__.register
1012+
def __init__(self, t: VectorLike, ax: VectorLike, angle: Real) -> None:
9771013
"""Location with translation t and rotation around ax by angle
9781014
with respect to the original location."""
979-
...
9801015

981-
def __init__(self, *args):
1016+
T = gp_Trsf()
1017+
T.SetRotation(gp_Ax1(Vector().toPnt(), Vector(ax).toDir()), radians(angle))
1018+
T.SetTranslationPart(Vector(t).wrapped)
1019+
1020+
self.wrapped = TopLoc_Location(T)
1021+
1022+
@__init__.register
1023+
def __init__(self, t: VectorLike, angles: Tuple[Real, Real, Real]) -> None:
1024+
"""Location with translation t and 3 rotation angles."""
9821025

9831026
T = gp_Trsf()
9841027

985-
if len(args) == 0:
986-
pass
987-
elif len(args) == 1:
988-
t = args[0]
989-
990-
if isinstance(t, (Vector, tuple)):
991-
T.SetTranslationPart(Vector(t).wrapped)
992-
elif isinstance(t, Plane):
993-
cs = gp_Ax3(t.origin.toPnt(), t.zDir.toDir(), t.xDir.toDir())
994-
T.SetTransformation(cs)
995-
T.Invert()
996-
elif isinstance(t, TopLoc_Location):
997-
self.wrapped = t
998-
return
999-
elif isinstance(t, gp_Trsf):
1000-
T = t
1001-
else:
1002-
raise TypeError("Unexpected parameters")
1003-
elif len(args) == 2:
1004-
t, v = args
1005-
cs = gp_Ax3(Vector(v).toPnt(), t.zDir.toDir(), t.xDir.toDir())
1006-
T.SetTransformation(cs)
1007-
T.Invert()
1008-
else:
1009-
t, ax, angle = args
1010-
T.SetRotation(
1011-
gp_Ax1(Vector().toPnt(), Vector(ax).toDir()), angle * math.pi / 180.0
1012-
)
1013-
T.SetTranslationPart(Vector(t).wrapped)
1028+
q = gp_Quaternion()
1029+
q.SetEulerAngles(gp_Extrinsic_XYZ, *map(radians, angles))
1030+
1031+
T.SetRotation(q)
1032+
T.SetTranslationPart(Vector(t).wrapped)
10141033

10151034
self.wrapped = TopLoc_Location(T)
10161035

@@ -1035,6 +1054,6 @@ def toTuple(self) -> Tuple[Tuple[float, float, float], Tuple[float, float, float
10351054
rot = T.GetRotation()
10361055

10371056
rv_trans = (trans.X(), trans.Y(), trans.Z())
1038-
rv_rot = rot.GetEulerAngles(gp_EulerSequence.gp_Extrinsic_XYZ)
1057+
rx, ry, rz = rot.GetEulerAngles(gp_EulerSequence.gp_Extrinsic_XYZ)
10391058

1040-
return rv_trans, rv_rot
1059+
return rv_trans, (degrees(rx), degrees(ry), degrees(rz))

0 commit comments

Comments
 (0)