-
-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
32 changed files
with
6,069 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
""" | ||
build123d imports | ||
name: test_always_equal.py | ||
by: Gumyr | ||
date: January 22, 2025 | ||
desc: | ||
This python module contains tests for the build123d project. | ||
license: | ||
Copyright 2025 Gumyr | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
|
||
import unittest | ||
|
||
|
||
class AlwaysEqual: | ||
def __eq__(self, other): | ||
return True | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
""" | ||
build123d imports | ||
name: test_assembly.py | ||
by: Gumyr | ||
date: January 22, 2025 | ||
desc: | ||
This python module contains tests for the build123d project. | ||
license: | ||
Copyright 2025 Gumyr | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
|
||
import re | ||
import unittest | ||
|
||
from build123d.topology import Compound, Solid | ||
|
||
|
||
class TestAssembly(unittest.TestCase): | ||
@staticmethod | ||
def create_test_assembly() -> Compound: | ||
box = Solid.make_box(1, 1, 1) | ||
box.orientation = (45, 45, 0) | ||
box.label = "box" | ||
sphere = Solid.make_sphere(1) | ||
sphere.label = "sphere" | ||
sphere.position = (1, 2, 3) | ||
assembly = Compound(label="assembly", children=[box]) | ||
sphere.parent = assembly | ||
return assembly | ||
|
||
def assertTopoEqual(self, actual_topo: str, expected_topo_lines: list[str]): | ||
actual_topo_lines = actual_topo.splitlines() | ||
self.assertEqual(len(actual_topo_lines), len(expected_topo_lines)) | ||
for actual_line, expected_line in zip(actual_topo_lines, expected_topo_lines): | ||
start, end = re.split(r"at 0x[0-9a-f]+,", expected_line, 2, re.I) | ||
self.assertTrue(actual_line.startswith(start)) | ||
self.assertTrue(actual_line.endswith(end)) | ||
|
||
def test_attributes(self): | ||
box = Solid.make_box(1, 1, 1) | ||
box.label = "box" | ||
sphere = Solid.make_sphere(1) | ||
sphere.label = "sphere" | ||
assembly = Compound(label="assembly", children=[box]) | ||
sphere.parent = assembly | ||
|
||
self.assertEqual(len(box.children), 0) | ||
self.assertEqual(box.label, "box") | ||
self.assertEqual(box.parent, assembly) | ||
self.assertEqual(sphere.parent, assembly) | ||
self.assertEqual(len(assembly.children), 2) | ||
|
||
def test_show_topology_compound(self): | ||
assembly = TestAssembly.create_test_assembly() | ||
expected = [ | ||
"assembly Compound at 0x7fced0fd1b50, Location(p=(0.00, 0.00, 0.00), o=(-0.00, 0.00, -0.00))", | ||
"├── box Solid at 0x7fced102d3a0, Location(p=(0.00, 0.00, 0.00), o=(45.00, 45.00, -0.00))", | ||
"└── sphere Solid at 0x7fced0fd1f10, Location(p=(1.00, 2.00, 3.00), o=(-0.00, 0.00, -0.00))", | ||
] | ||
self.assertTopoEqual(assembly.show_topology("Solid"), expected) | ||
|
||
def test_show_topology_shape_location(self): | ||
assembly = TestAssembly.create_test_assembly() | ||
expected = [ | ||
"Solid at 0x7f3754501530, Position(1.0, 2.0, 3.0)", | ||
"└── Shell at 0x7f3754501a70, Position(1.0, 2.0, 3.0)", | ||
" └── Face at 0x7f3754501030, Position(1.0, 2.0, 3.0)", | ||
] | ||
self.assertTopoEqual( | ||
assembly.children[1].show_topology("Face", show_center=False), expected | ||
) | ||
|
||
def test_show_topology_shape(self): | ||
assembly = TestAssembly.create_test_assembly() | ||
expected = [ | ||
"Solid at 0x7f6279043ab0, Center(1.0, 2.0, 3.0)", | ||
"└── Shell at 0x7f62790438f0, Center(1.0, 2.0, 3.0)", | ||
" └── Face at 0x7f62790439f0, Center(1.0, 2.0, 3.0)", | ||
] | ||
self.assertTopoEqual(assembly.children[1].show_topology("Face"), expected) | ||
|
||
def test_remove_child(self): | ||
assembly = TestAssembly.create_test_assembly() | ||
self.assertEqual(len(assembly.children), 2) | ||
assembly.children = list(assembly.children)[1:] | ||
self.assertEqual(len(assembly.children), 1) | ||
|
||
def test_do_children_intersect(self): | ||
( | ||
overlap, | ||
pair, | ||
distance, | ||
) = TestAssembly.create_test_assembly().do_children_intersect() | ||
self.assertFalse(overlap) | ||
box = Solid.make_box(1, 1, 1) | ||
box.orientation = (45, 45, 0) | ||
box.label = "box" | ||
sphere = Solid.make_sphere(1) | ||
sphere.label = "sphere" | ||
sphere.position = (0, 0, 0) | ||
assembly = Compound(label="assembly", children=[box]) | ||
sphere.parent = assembly | ||
overlap, pair, distance = assembly.do_children_intersect() | ||
self.assertTrue(overlap) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
""" | ||
build123d imports | ||
name: test_axis.py | ||
by: Gumyr | ||
date: January 22, 2025 | ||
desc: | ||
This python module contains tests for the build123d project. | ||
license: | ||
Copyright 2025 Gumyr | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
|
||
# Always equal to any other object, to test that __eq__ cooperation is working | ||
import copy | ||
import unittest | ||
|
||
import numpy as np | ||
from OCP.gp import gp_Ax1, gp_Dir, gp_Pnt | ||
from build123d.geometry import Axis, Location, Plane, Vector | ||
from build123d.topology import Edge | ||
|
||
|
||
class AlwaysEqual: | ||
def __eq__(self, other): | ||
return True | ||
|
||
|
||
class TestAxis(unittest.TestCase): | ||
"""Test the Axis class""" | ||
|
||
def test_axis_init(self): | ||
test_axis = Axis((1, 2, 3), (0, 0, 1)) | ||
self.assertAlmostEqual(test_axis.position, (1, 2, 3), 5) | ||
self.assertAlmostEqual(test_axis.direction, (0, 0, 1), 5) | ||
|
||
test_axis = Axis((1, 2, 3), direction=(0, 0, 1)) | ||
self.assertAlmostEqual(test_axis.position, (1, 2, 3), 5) | ||
self.assertAlmostEqual(test_axis.direction, (0, 0, 1), 5) | ||
|
||
test_axis = Axis(origin=(1, 2, 3), direction=(0, 0, 1)) | ||
self.assertAlmostEqual(test_axis.position, (1, 2, 3), 5) | ||
self.assertAlmostEqual(test_axis.direction, (0, 0, 1), 5) | ||
|
||
test_axis = Axis(Edge.make_line((1, 2, 3), (1, 2, 4))) | ||
self.assertAlmostEqual(test_axis.position, (1, 2, 3), 5) | ||
self.assertAlmostEqual(test_axis.direction, (0, 0, 1), 5) | ||
|
||
test_axis = Axis(edge=Edge.make_line((1, 2, 3), (1, 2, 4))) | ||
self.assertAlmostEqual(test_axis.position, (1, 2, 3), 5) | ||
self.assertAlmostEqual(test_axis.direction, (0, 0, 1), 5) | ||
|
||
with self.assertRaises(ValueError): | ||
Axis("one", "up") | ||
with self.assertRaises(ValueError): | ||
Axis(one="up") | ||
|
||
def test_axis_from_occt(self): | ||
occt_axis = gp_Ax1(gp_Pnt(1, 1, 1), gp_Dir(0, 1, 0)) | ||
test_axis = Axis(occt_axis) | ||
self.assertAlmostEqual(test_axis.position, (1, 1, 1), 5) | ||
self.assertAlmostEqual(test_axis.direction, (0, 1, 0), 5) | ||
|
||
def test_axis_repr_and_str(self): | ||
self.assertEqual(repr(Axis.X), "((0.0, 0.0, 0.0),(1.0, 0.0, 0.0))") | ||
self.assertEqual(str(Axis.Y), "Axis: ((0.0, 0.0, 0.0),(0.0, 1.0, 0.0))") | ||
|
||
def test_axis_copy(self): | ||
x_copy = copy.copy(Axis.X) | ||
self.assertAlmostEqual(x_copy.position, (0, 0, 0), 5) | ||
self.assertAlmostEqual(x_copy.direction, (1, 0, 0), 5) | ||
x_copy = copy.deepcopy(Axis.X) | ||
self.assertAlmostEqual(x_copy.position, (0, 0, 0), 5) | ||
self.assertAlmostEqual(x_copy.direction, (1, 0, 0), 5) | ||
|
||
def test_axis_to_location(self): | ||
# TODO: Verify this is correct | ||
x_location = Axis.X.location | ||
self.assertTrue(isinstance(x_location, Location)) | ||
self.assertAlmostEqual(x_location.position, (0, 0, 0), 5) | ||
self.assertAlmostEqual(x_location.orientation, (0, 90, 180), 5) | ||
|
||
def test_axis_located(self): | ||
y_axis = Axis.Z.located(Location((0, 0, 1), (-90, 0, 0))) | ||
self.assertAlmostEqual(y_axis.position, (0, 0, 1), 5) | ||
self.assertAlmostEqual(y_axis.direction, (0, 1, 0), 5) | ||
|
||
def test_axis_to_plane(self): | ||
x_plane = Axis.X.to_plane() | ||
self.assertTrue(isinstance(x_plane, Plane)) | ||
self.assertAlmostEqual(x_plane.origin, (0, 0, 0), 5) | ||
self.assertAlmostEqual(x_plane.z_dir, (1, 0, 0), 5) | ||
|
||
def test_axis_is_coaxial(self): | ||
self.assertTrue(Axis.X.is_coaxial(Axis((0, 0, 0), (1, 0, 0)))) | ||
self.assertFalse(Axis.X.is_coaxial(Axis((0, 0, 1), (1, 0, 0)))) | ||
self.assertFalse(Axis.X.is_coaxial(Axis((0, 0, 0), (0, 1, 0)))) | ||
|
||
def test_axis_is_normal(self): | ||
self.assertTrue(Axis.X.is_normal(Axis.Y)) | ||
self.assertFalse(Axis.X.is_normal(Axis.X)) | ||
|
||
def test_axis_is_opposite(self): | ||
self.assertTrue(Axis.X.is_opposite(Axis((1, 1, 1), (-1, 0, 0)))) | ||
self.assertFalse(Axis.X.is_opposite(Axis.X)) | ||
|
||
def test_axis_is_parallel(self): | ||
self.assertTrue(Axis.X.is_parallel(Axis((1, 1, 1), (1, 0, 0)))) | ||
self.assertFalse(Axis.X.is_parallel(Axis.Y)) | ||
|
||
def test_axis_angle_between(self): | ||
self.assertAlmostEqual(Axis.X.angle_between(Axis.Y), 90, 5) | ||
self.assertAlmostEqual( | ||
Axis.X.angle_between(Axis((1, 1, 1), (-1, 0, 0))), 180, 5 | ||
) | ||
|
||
def test_axis_reverse(self): | ||
self.assertAlmostEqual(Axis.X.reverse().direction, (-1, 0, 0), 5) | ||
|
||
def test_axis_reverse_op(self): | ||
axis = -Axis.X | ||
self.assertAlmostEqual(axis.direction, (-1, 0, 0), 5) | ||
|
||
def test_axis_as_edge(self): | ||
edge = Edge(Axis.X) | ||
self.assertTrue(isinstance(edge, Edge)) | ||
common = (edge & Edge.make_line((0, 0, 0), (1, 0, 0))).edge() | ||
self.assertAlmostEqual(common.length, 1, 5) | ||
|
||
def test_axis_intersect(self): | ||
common = (Axis.X.intersect(Edge.make_line((0, 0, 0), (1, 0, 0)))).edge() | ||
self.assertAlmostEqual(common.length, 1, 5) | ||
|
||
common = (Axis.X & Edge.make_line((0, 0, 0), (1, 0, 0))).edge() | ||
self.assertAlmostEqual(common.length, 1, 5) | ||
|
||
intersection = Axis.X & Axis((1, 0, 0), (0, 1, 0)) | ||
self.assertAlmostEqual(intersection, (1, 0, 0), 5) | ||
|
||
i = Axis.X & Axis((1, 0, 0), (1, 0, 0)) | ||
self.assertEqual(i, Axis.X) | ||
|
||
intersection = Axis((1, 2, 3), (0, 0, 1)) & Plane.XY | ||
self.assertAlmostEqual(intersection.to_tuple(), (1, 2, 0), 5) | ||
|
||
arc = Edge.make_circle(20, start_angle=0, end_angle=180) | ||
ax0 = Axis((-20, 30, 0), (4, -3, 0)) | ||
intersections = arc.intersect(ax0).vertices().sort_by(Axis.X) | ||
np.testing.assert_allclose(tuple(intersections[0]), (-5.6, 19.2, 0), 1e-5) | ||
np.testing.assert_allclose(tuple(intersections[1]), (20, 0, 0), 1e-5) | ||
|
||
intersections = ax0.intersect(arc).vertices().sort_by(Axis.X) | ||
np.testing.assert_allclose(tuple(intersections[0]), (-5.6, 19.2, 0), 1e-5) | ||
np.testing.assert_allclose(tuple(intersections[1]), (20, 0, 0), 1e-5) | ||
|
||
i = Axis((0, 0, 1), (1, 1, 1)) & Vector(0.5, 0.5, 1.5) | ||
self.assertTrue(isinstance(i, Vector)) | ||
self.assertAlmostEqual(i, (0.5, 0.5, 1.5), 5) | ||
self.assertIsNone(Axis.Y & Vector(2, 0, 0)) | ||
|
||
l = Edge.make_line((0, 0, 1), (0, 0, 2)) ^ 1 | ||
i: Location = Axis.Z & l | ||
self.assertTrue(isinstance(i, Location)) | ||
self.assertAlmostEqual(i.position, l.position, 5) | ||
self.assertAlmostEqual(i.orientation, l.orientation, 5) | ||
|
||
self.assertIsNone(Axis.Z & Edge.make_line((0, 0, 1), (1, 0, 0)).location_at(1)) | ||
self.assertIsNone(Axis.Z & Edge.make_line((1, 0, 1), (1, 0, 2)).location_at(1)) | ||
|
||
# TODO: uncomment when generalized edge to surface intersections are complete | ||
# non_planar = ( | ||
# Solid.make_cylinder(1, 10).faces().filter_by(GeomType.PLANE, reverse=True) | ||
# ) | ||
# intersections = Axis((0, 0, 5), (1, 0, 0)) & non_planar | ||
|
||
# self.assertTrue(len(intersections.vertices(), 2)) | ||
# np.testing.assert_allclose( | ||
# intersection.vertices()[0].to_tuple(), (-1, 0, 5), 5 | ||
# ) | ||
# np.testing.assert_allclose( | ||
# intersection.vertices()[1].to_tuple(), (1, 0, 5), 5 | ||
# ) | ||
|
||
def test_axis_equal(self): | ||
self.assertEqual(Axis.X, Axis.X) | ||
self.assertEqual(Axis.Y, Axis.Y) | ||
self.assertEqual(Axis.Z, Axis.Z) | ||
self.assertEqual(Axis.X, AlwaysEqual()) | ||
|
||
def test_axis_not_equal(self): | ||
self.assertNotEqual(Axis.X, Axis.Y) | ||
random_obj = object() | ||
self.assertNotEqual(Axis.X, random_obj) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Oops, something went wrong.