Skip to content

Commit

Permalink
Merge pull request #644 from jdegenstein/jernArcFix1
Browse files Browse the repository at this point in the history
Fix JernArc not always co-planar with input plane
  • Loading branch information
jdegenstein authored Jun 23, 2024
2 parents ce72ee2 + bab54c7 commit 2cd6365
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 10 deletions.
27 changes: 21 additions & 6 deletions src/build123d/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,13 +465,28 @@ def to_dir(self) -> gp_Dir:
"""Convert to OCCT gp_Dir object"""
return gp_Dir(self.wrapped.XYZ())

def transform(self, affine_transform: Matrix) -> Vector:
"""Apply affine transformation"""
# to gp_Pnt to obey build123d transformation convention (in OCP.vectors do not translate)
pnt = self.to_pnt()
pnt_t = pnt.Transformed(affine_transform.wrapped.Trsf())
def transform(self, affine_transform: Matrix, is_direction: bool = False) -> Vector:
"""Apply affine transformation
return Vector(gp_Vec(pnt_t.XYZ()))
Args:
affine_transform (Matrix): affine transformation matrix
is_direction (bool, optional): Should self be transformed as a vector or direction?
Defaults to False (vector)
Returns:
Vector: transformed vector
"""
if not is_direction:
# to gp_Pnt to obey build123d transformation convention (in OCP.vectors do not translate)
pnt = self.to_pnt()
pnt_t = pnt.Transformed(affine_transform.wrapped.Trsf())
return_value = Vector(gp_Vec(pnt_t.XYZ()))
else:
# to gp_Dir for transformation of "direction vectors" (no translation or scaling)
dir = self.to_dir()
dir_t = dir.Transformed(affine_transform.wrapped.Trsf())
return_value = Vector(gp_Vec(dir_t.XYZ()))
return return_value

def rotate(self, axis: Axis, angle: float) -> Vector:
"""Rotate about axis
Expand Down
2 changes: 1 addition & 1 deletion src/build123d/objects_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,12 @@ def __init__(

start = WorkplaneList.localize(start)
self.start = start
start_tangent = WorkplaneList.localize(tangent).normalized()
if context is None:
jern_workplane = Plane.XY
else:
jern_workplane = copy.copy(WorkplaneList._get_context().workplanes[0])
jern_workplane.origin = start
start_tangent = Vector(tangent).transform(jern_workplane.reverse_transform, is_direction=True)

arc_direction = copysign(1.0, arc_size)
self.center_point = start + start_tangent.rotate(
Expand Down
21 changes: 18 additions & 3 deletions tests/test_build_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,24 @@ def test_intersecting_line(self):

def test_jern_arc(self):
with BuildLine() as jern:
JernArc((1, 0), (0, 1), 1, 90)
self.assertTupleAlmostEquals((jern.edges()[0] @ 1).to_tuple(), (0, 1, 0), 5)

j1 = JernArc((1, 0), (0, 1), 1, 90)
self.assertTupleAlmostEquals((jern.line @ 1).to_tuple(), (0, 1, 0), 5)
self.assertAlmostEqual(j1.radius, 1)
self.assertAlmostEqual(j1.length, pi/2)

with BuildLine(Plane.XY.offset(1)) as offset_l:
off1 = JernArc((1, 0), (0, 1), 1, 90)
self.assertTupleAlmostEquals((offset_l.line @ 1).to_tuple(), (0, 1, 1), 5)
self.assertAlmostEqual(off1.radius, 1)
self.assertAlmostEqual(off1.length, pi/2)

plane_iso = Plane(origin=(0, 0, 0), x_dir=(1, 1, 0), z_dir=(1, -1, 1))
with BuildLine(plane_iso) as iso_l:
iso1 = JernArc((0, 0), (0, 1), 1, 180)
self.assertTupleAlmostEquals((iso_l.line @ 1).to_tuple(), (-sqrt(2), -sqrt(2), 0), 5)
self.assertAlmostEqual(iso1.radius, 1)
self.assertAlmostEqual(iso1.length, pi)

with BuildLine() as l:
l1 = JernArc(start=(0, 0, 0), tangent=(1, 0, 0), radius=1, arc_size=360)
self.assertTrue(l1.is_closed)
Expand Down
21 changes: 21 additions & 0 deletions tests/test_direct_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3688,6 +3688,27 @@ def test_hash(self):
self.assertEqual(len(vectors), 4)
self.assertEqual(len(unique_vectors), 3)

def test_vector_transform(self):
a = Vector(1, 2, 3)
pxy = Plane.XY
pxy_o1 = Plane.XY.offset(1)
self.assertEqual(a.transform(pxy.forward_transform, is_direction=False), a)
self.assertEqual(
a.transform(pxy.forward_transform, is_direction=True), a.normalized()
)
self.assertEqual(
a.transform(pxy_o1.forward_transform, is_direction=False), Vector(1, 2, 2)
)
self.assertEqual(
a.transform(pxy_o1.forward_transform, is_direction=True), a.normalized()
)
self.assertEqual(
a.transform(pxy_o1.reverse_transform, is_direction=False), Vector(1, 2, 4)
)
self.assertEqual(
a.transform(pxy_o1.reverse_transform, is_direction=True), a.normalized()
)

def test_intersect(self):
v1 = Vector(1, 2, 3)
self.assertVectorAlmostEquals(v1 & Vector(1, 2, 3), (1, 2, 3), 5)
Expand Down

0 comments on commit 2cd6365

Please sign in to comment.