Skip to content

Commit

Permalink
Fixed Issue #428, added Joints.location property, improved some joint…
Browse files Browse the repository at this point in the history
… symbols
  • Loading branch information
gumyr committed Jun 6, 2024
1 parent 98595b1 commit 7b540e1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 26 deletions.
55 changes: 35 additions & 20 deletions src/build123d/joints.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,16 @@ class RigidJoint(Joint):
"""

@property
def location(self) -> Location:
"""Location of joint"""
return self.parent.location * self.relative_location

@property
def symbol(self) -> Compound:
"""A CAD symbol (XYZ indicator) as bound to part"""
size = self.parent.bounding_box().diagonal / 12
return Compound.make_triad(axes_scale=size).locate(
self.parent.location * self.relative_location
)
return Compound.make_triad(axes_scale=size).locate(self.location)

def __init__(
self,
Expand Down Expand Up @@ -217,6 +220,11 @@ class RevoluteJoint(Joint):
ValueError: angle_reference must be normal to axis
"""

@property
def location(self) -> Location:
"""Location of joint"""
return self.parent.location * self.relative_axis.location

@property
def symbol(self) -> Compound:
"""A CAD symbol representing the axis of rotation as bound to part"""
Expand All @@ -226,8 +234,9 @@ def symbol(self) -> Compound:
[
Edge.make_line((0, 0, 0), (0, 0, radius * 10)),
Edge.make_circle(radius),
Edge.make_line((0, 0, 0), (radius, 0, 0)),
]
).move(self.parent.location * self.relative_axis.location)
).move(self.location)

def __init__(
self,
Expand Down Expand Up @@ -292,15 +301,10 @@ def relative_to(
self._angle = angle
# Avoid strange rotations when angle is zero by using 360 instead
angle = 360.0 if angle == 0.0 else angle
rotation = Location(
Plane(
origin=(0, 0, 0),
x_dir=self.angle_reference.rotate(self.relative_axis, angle),
z_dir=self.relative_axis.direction,
)
)
return (
self.relative_axis.location * rotation * other.relative_location.inverse()
self.relative_axis.location
* Rotation(0, 0, angle)
* other.relative_location.inverse()
)


Expand All @@ -325,6 +329,11 @@ class LinearJoint(Joint):
"""

@property
def location(self) -> Location:
"""Location of joint"""
return self.parent.location * self.relative_axis.location

@property
def symbol(self) -> Compound:
"""A CAD symbol of the linear axis positioned relative to_part"""
Expand All @@ -336,7 +345,7 @@ def symbol(self) -> Compound:
),
Edge.make_circle(radius),
]
).move(self.parent.location * self.relative_axis.location)
).move(self.location)

def __init__(
self,
Expand Down Expand Up @@ -496,6 +505,11 @@ class CylindricalJoint(Joint):

# pylint: disable=too-many-instance-attributes

@property
def location(self) -> Location:
"""Location of joint"""
return self.parent.location * self.relative_axis.location

@property
def symbol(self) -> Compound:
"""A CAD symbol representing the cylindrical axis as bound to part"""
Expand All @@ -506,13 +520,9 @@ def symbol(self) -> Compound:
(0, 0, self.linear_range[0]), (0, 0, self.linear_range[1])
),
Edge.make_circle(radius),
Edge.make_line((0, 0, 0), (radius, 0, 0)),
]
).move(self.parent.location * self.relative_axis.location)

# @property
# def axis_location(self) -> Location:
# """Current global location of joint axis"""
# return self.parent.location * self.relative_axis.location
).move(self.location)

def __init__(
self,
Expand Down Expand Up @@ -634,6 +644,11 @@ class BallJoint(Joint):
"""

@property
def location(self) -> Location:
"""Location of joint"""
return self.parent.location * self.relative_location

@property
def symbol(self) -> Compound:
"""A CAD symbol representing joint as bound to part"""
Expand All @@ -657,7 +672,7 @@ def symbol(self) -> Compound:
"Z", radius / 5, align=(Align.CENTER, Align.CENTER)
).locate(circle_z.location_at(0.125) * Rotation(90, 0, 0)),
]
).move(self.parent.location * self.relative_location)
).move(self.location)

def __init__(
self,
Expand Down
6 changes: 6 additions & 0 deletions src/build123d/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -8346,6 +8346,12 @@ def relative_to(self, other: Joint) -> Location:
"""Return relative location to another joint"""
raise NotImplementedError

@property
@abstractmethod
def location(self) -> Location: # pragma: no cover
"""Location of joint"""
raise NotImplementedError

@property
@abstractmethod
def symbol(self) -> Compound: # pragma: no cover
Expand Down
50 changes: 44 additions & 6 deletions tests/test_joints.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@
import copy
import unittest

from build123d.build_enums import CenterOf, GeomType
from build123d.build_enums import Align, CenterOf, GeomType
from build123d.build_part import BuildPart
from build123d.geometry import Axis, Location, Vector, VectorLike
from build123d.geometry import Axis, Location, Rotation, Vector, VectorLike
from build123d.joints import (
BallJoint,
CylindricalJoint,
LinearJoint,
RevoluteJoint,
RigidJoint,
)
from build123d.objects_part import Box, Cylinder, Sphere
from build123d.topology import Plane, Solid
from build123d.objects_part import Box, Cone, Cylinder, Sphere
from build123d.topology import Edge, Plane, Solid


class DirectApiTestCase(unittest.TestCase):
Expand Down Expand Up @@ -121,7 +121,45 @@ def test_revolute_joint_with_angle_reference(self):

self.assertVectorAlmostEquals(j2.symbol.location.position, (0, 0, 1), 6)
self.assertVectorAlmostEquals(j2.symbol.location.orientation, (0, 0, 90), 6)
self.assertEqual(len(j1.symbol.edges()), 2)
self.assertEqual(len(j1.symbol.edges()), 3)

def test_revolute_joint_absolute_locations(self):
b1 = Box(10, 10, 1)
b2 = Box(5, 5, 1)
j1 = RigidJoint("j1", b1, Location((-4, -4, 0.5)))
j2 = RevoluteJoint("j2", b2, Axis((2.5, 2.5, 0), (0, -1, 0)))

j1.connect_to(j2, angle=0)

self.assertVectorAlmostEquals(j1.location.position, j2.location.position, 5)
self.assertVectorAlmostEquals(
j1.location.orientation, j2.location.orientation, 5
)

def test_linear_revolute_joint(self):
base = Box(10, 10, 2)
arm = Box(2, 1, 2, align=(Align.CENTER, Align.CENTER, Align.MIN))

base_top_edges = (
base.edges().filter_by(Axis.X, tolerance=30).sort_by(Axis.Z)[-2:]
)
linear_axis = Axis(Edge.make_mid_way(*base_top_edges, 0.33))
j1 = LinearJoint(
"slot",
base,
axis=linear_axis,
linear_range=(0, base_top_edges[0].length),
)
j2 = RevoluteJoint("pin", arm, axis=Axis.Z, angular_range=(0, 360))

j1.connect_to(j2, position=6, angle=60)

target_location = Rotation(0, 0, 60)
target_location.position = linear_axis.position + linear_axis.direction * 6
self.assertVectorAlmostEquals(target_location.position, j2.location.position, 5)
self.assertVectorAlmostEquals(
target_location.orientation, j2.location.orientation, 5
)

def test_revolute_joint_without_angle_reference(self):
revolute_base = Solid.make_cylinder(1, 1)
Expand Down Expand Up @@ -277,7 +315,7 @@ def test_cylindrical_joint(self):
self.assertVectorAlmostEquals(
j1.symbol.location.orientation, (-180, 0, -180), 6
)
self.assertEqual(len(j1.symbol.edges()), 2)
self.assertEqual(len(j1.symbol.edges()), 3)

# Test invalid position
with self.assertRaises(ValueError):
Expand Down

0 comments on commit 7b540e1

Please sign in to comment.