Skip to content

Commit 86631a0

Browse files
authored
geometry.py -> rework Location overloads and add input parsing function
1 parent da6b3ae commit 86631a0

File tree

1 file changed

+100
-123
lines changed

1 file changed

+100
-123
lines changed

src/build123d/geometry.py

Lines changed: 100 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,57 @@ def _parse_intersect_args(*args, **kwargs):
126126
return axis, plane, vector, location, shape
127127

128128

129+
def _parse_location_args(*args, **kwargs):
130+
position, orientation, ordering, plane, location, top_loc, gp_trsf = (None,) * 7
131+
132+
position = kwargs.pop("position", None)
133+
orientation = kwargs.pop("orientation", None)
134+
ordering = kwargs.pop("ordering", None)
135+
plane = kwargs.pop("plane", None)
136+
location = kwargs.pop("location", None)
137+
top_loc = kwargs.pop("top_loc", None)
138+
gp_trsf = kwargs.pop("gp_trsf", None)
139+
140+
# Handle unexpected kwargs
141+
if kwargs:
142+
raise ValueError(f"Unexpected argument(s): {', '.join(kwargs.keys())}")
143+
144+
# Handle positional inputs
145+
if args:
146+
if isinstance(args[0], (Vector, Iterable)):
147+
position = args[0]
148+
if len(args) > 1:
149+
if isinstance(args[1], (Vector, Iterable)):
150+
orientation = args[1]
151+
else:
152+
raise TypeError(f"Unexpected input type: {type(args[1])}")
153+
if len(args) > 2:
154+
if isinstance(args[2], (Extrinsic, Intrinsic)):
155+
ordering = args[2]
156+
else:
157+
raise TypeError(f"Unexpected input type: {type(args[2])}")
158+
elif isinstance(args[0], Plane):
159+
plane = args[0]
160+
elif isinstance(args[0], Location):
161+
location = args[0]
162+
elif isinstance(args[0], TopLoc_Location):
163+
toploc_loc = args[0]
164+
elif isinstance(args[0], gp_Trsf):
165+
gp_trsf = args[0]
166+
elif len(args) > 3:
167+
raise ValueError(f"More arguments than allowed: {args=}")
168+
else:
169+
raise TypeError(f"Unexpected input type: {list(type(arg) for arg in args)}")
170+
171+
if not orientation:
172+
orientation = Vector()
173+
174+
if not ordering:
175+
ordering = Intrinsic.XYZ
176+
177+
return position, orientation, ordering, plane, location, top_loc, gp_trsf
178+
179+
129180
class Vector:
130181
"""Create a 3-dimensional vector
131182
@@ -1376,148 +1427,74 @@ class Location:
13761427
Extrinsic.ZYZ: gp_EulerSequence.gp_Extrinsic_ZYZ,
13771428
}
13781429

1379-
@overload
1380-
def __init__(self): # pragma: no cover
1381-
"""Empty location with not rotation or translation with respect to the original location."""
1382-
1383-
@overload
1384-
def __init__(self, location: Location): # pragma: no cover
1385-
"""Location with another given location."""
1386-
1387-
@overload
1388-
def __init__(self, translation: VectorLike, angle: float = 0): # pragma: no cover
1389-
"""Location with translation with respect to the original location.
1390-
If angle != 0 then the location includes a rotation around z-axis by angle"""
1391-
1392-
@overload
1393-
def __init__(
1394-
self, translation: VectorLike, rotation: RotationLike | None = None
1395-
): # pragma: no cover
1396-
"""Location with translation with respect to the original location.
1397-
If rotation is not None then the location includes the rotation (see also Rotation class)
1398-
"""
1399-
14001430
@overload
14011431
def __init__(
14021432
self,
1403-
translation: VectorLike,
1404-
rotation: RotationLike,
1433+
position: VectorLike,
1434+
orientation: RotationLike,
14051435
ordering: Extrinsic | Intrinsic,
1406-
): # pragma: no cover
1407-
"""Location with translation with respect to the original location.
1408-
If rotation is not None then the location includes the rotation (see also Rotation class)
1409-
ordering defaults to Intrinsic.XYZ, but can also be set to Extrinsic
1436+
):
1437+
"""Location with position that defaults to the global origin.
1438+
If orientation is not None then the location includes the orientation
1439+
(see also Rotation class). Ordering defaults to Intrinsic.XYZ,
1440+
but can also be set to members of the Extrinsic enum.
14101441
"""
14111442

14121443
@overload
1413-
def __init__(self, plane: Plane): # pragma: no cover
1444+
def __init__(self, plane: Plane):
14141445
"""Location corresponding to the location of the Plane."""
14151446

14161447
@overload
1417-
def __init__(self, plane: Plane, plane_offset: VectorLike): # pragma: no cover
1418-
"""Location corresponding to the angular location of the Plane with
1419-
translation plane_offset."""
1448+
def __init__(self, location: Location):
1449+
"""Location given another location."""
14201450

14211451
@overload
1422-
def __init__(self, top_loc: TopLoc_Location): # pragma: no cover
1423-
"""Location wrapping the low-level TopLoc_Location object t"""
1452+
def __init__(self, top_loc: TopLoc_Location):
1453+
"""Location wrapping the low-level TopLoc_Location object top_loc"""
14241454

14251455
@overload
1426-
def __init__(self, gp_trsf: gp_Trsf): # pragma: no cover
1427-
"""Location wrapping the low-level gp_Trsf object t"""
1456+
def __init__(self, gp_trsf: gp_Trsf):
1457+
"""Location wrapping the low-level gp_Trsf object gp_trsf"""
14281458

1429-
@overload
1430-
def __init__(
1431-
self, translation: VectorLike, direction: VectorLike, angle: float
1432-
): # pragma: no cover
1433-
"""Location with translation t and rotation around direction by angle
1434-
with respect to the original location."""
1459+
# actual constructor \/
1460+
def __init__(self, *args, **kwargs):
1461+
(
1462+
position,
1463+
orientation,
1464+
ordering,
1465+
plane,
1466+
location,
1467+
top_loc,
1468+
gp_trsf,
1469+
) = _parse_location_args(*args, **kwargs)
14351470

1436-
def __init__(self, *args):
1437-
# pylint: disable=too-many-branches
14381471
transform = gp_Trsf()
14391472

1440-
if len(args) == 0:
1441-
pass
1442-
1443-
elif len(args) == 1:
1444-
translation = args[0]
1445-
1446-
if isinstance(translation, (Vector, Iterable)):
1447-
transform.SetTranslationPart(Vector(translation).wrapped)
1448-
elif isinstance(translation, Plane):
1449-
coordinate_system = gp_Ax3(
1450-
translation._origin.to_pnt(),
1451-
translation.z_dir.to_dir(),
1452-
translation.x_dir.to_dir(),
1453-
)
1454-
transform.SetTransformation(coordinate_system)
1455-
transform.Invert()
1456-
elif isinstance(args[0], Location):
1457-
self.wrapped = translation.wrapped
1458-
return
1459-
elif isinstance(translation, TopLoc_Location):
1460-
self.wrapped = translation
1461-
return
1462-
elif isinstance(translation, gp_Trsf):
1463-
transform = translation
1464-
else:
1465-
raise TypeError("Unexpected parameters")
1466-
1467-
elif len(args) == 2:
1468-
ordering = Intrinsic.XYZ
1469-
if isinstance(args[0], (Vector, Iterable)):
1470-
if isinstance(args[1], (Vector, Iterable)):
1471-
rotation = [radians(a) for a in args[1]]
1472-
quaternion = gp_Quaternion()
1473-
quaternion.SetEulerAngles(self._rot_order_dict[ordering], *rotation)
1474-
transform.SetRotation(quaternion)
1475-
elif isinstance(args[0], (Vector, tuple)) and isinstance(
1476-
args[1], (int, float)
1477-
):
1478-
angle = radians(args[1])
1479-
quaternion = gp_Quaternion()
1480-
quaternion.SetEulerAngles(
1481-
self._rot_order_dict[ordering], 0, 0, angle
1482-
)
1483-
transform.SetRotation(quaternion)
1484-
1485-
# set translation part after setting rotation (if exists)
1486-
transform.SetTranslationPart(Vector(args[0]).wrapped)
1487-
else:
1488-
translation, origin = args
1489-
coordinate_system = gp_Ax3(
1490-
Vector(origin).to_pnt(),
1491-
translation.z_dir.to_dir(),
1492-
translation.x_dir.to_dir(),
1493-
)
1494-
transform.SetTransformation(coordinate_system)
1495-
transform.Invert()
1496-
elif len(args) == 3:
1497-
if (
1498-
isinstance(args[0], (Vector, Iterable))
1499-
and isinstance(args[1], (Vector, Iterable))
1500-
and isinstance(args[2], (int, float))
1501-
):
1502-
translation, axis, angle = args
1503-
transform.SetRotation(
1504-
gp_Ax1(Vector().to_pnt(), Vector(axis).to_dir()), angle * pi / 180.0
1505-
)
1506-
elif (
1507-
isinstance(args[0], (Vector, Iterable))
1508-
and isinstance(args[1], (Vector, Iterable))
1509-
and isinstance(args[2], (Extrinsic, Intrinsic))
1510-
):
1511-
translation = args[0]
1512-
rotation = [radians(a) for a in args[1]]
1513-
ordering = args[2]
1514-
quaternion = gp_Quaternion()
1515-
quaternion.SetEulerAngles(self._rot_order_dict[ordering], *rotation)
1516-
transform.SetRotation(quaternion)
1517-
else:
1518-
raise TypeError("Unsupported argument types for Location")
1473+
if position and orientation and ordering:
1474+
o_radians = [radians(a) for a in orientation]
1475+
quaternion = gp_Quaternion()
1476+
quaternion.SetEulerAngles(
1477+
self._rot_order_dict[ordering], *o_radians
1478+
) # TODO: change to self
1479+
transform.SetRotation(quaternion)
1480+
transform.SetTranslationPart(Vector(position).wrapped)
1481+
elif plane:
1482+
coordinate_system = gp_Ax3(
1483+
plane._origin.to_pnt(),
1484+
plane.z_dir.to_dir(),
1485+
plane.x_dir.to_dir(),
1486+
)
1487+
transform.SetTransformation(coordinate_system)
1488+
transform.Invert()
1489+
elif location:
1490+
self.wrapped = location.wrapped
1491+
return
1492+
elif top_loc:
1493+
self.wrapped = toploc_loc
1494+
return
1495+
elif gp_trsf:
1496+
transform = translation
15191497

1520-
transform.SetTranslationPart(Vector(translation).wrapped)
15211498
self.wrapped = TopLoc_Location(transform)
15221499

15231500
@property

0 commit comments

Comments
 (0)