mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 10:41:20 -08:00
264 lines
8.7 KiB
Python
264 lines
8.7 KiB
Python
"""
|
|
build123d imports
|
|
|
|
name: test_cad_objects.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 math
|
|
import unittest
|
|
|
|
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
|
|
from OCP.gp import gp, gp_Ax2, gp_Circ, gp_Elips, gp_Pnt
|
|
from build123d.build_enums import CenterOf
|
|
from build123d.geometry import Plane, Vector
|
|
from build123d.topology import Edge, Face, Wire
|
|
|
|
|
|
class TestCadObjects(unittest.TestCase):
|
|
def _make_circle(self):
|
|
circle = gp_Circ(gp_Ax2(gp_Pnt(1, 2, 3), gp.DZ_s()), 2.0)
|
|
return Edge.cast(BRepBuilderAPI_MakeEdge(circle).Edge())
|
|
|
|
def _make_ellipse(self):
|
|
ellipse = gp_Elips(gp_Ax2(gp_Pnt(1, 2, 3), gp.DZ_s()), 4.0, 2.0)
|
|
return Edge.cast(BRepBuilderAPI_MakeEdge(ellipse).Edge())
|
|
|
|
def test_edge_wrapper_center(self):
|
|
e = self._make_circle()
|
|
|
|
self.assertAlmostEqual(e.center(CenterOf.MASS), (1.0, 2.0, 3.0), 3)
|
|
|
|
def test_edge_wrapper_ellipse_center(self):
|
|
e = self._make_ellipse()
|
|
w = Wire([e])
|
|
self.assertAlmostEqual(Face(w).center(), (1.0, 2.0, 3.0), 3)
|
|
|
|
def test_edge_wrapper_make_circle(self):
|
|
halfCircleEdge = Edge.make_circle(radius=10, start_angle=0, end_angle=180)
|
|
|
|
# np.testing.assert_allclose((0.0, 5.0, 0.0), halfCircleEdge.centerOfBoundBox(0.0001),1e-3)
|
|
self.assertAlmostEqual(halfCircleEdge.start_point(), (10.0, 0.0, 0.0), 3)
|
|
self.assertAlmostEqual(halfCircleEdge.end_point(), (-10.0, 0.0, 0.0), 3)
|
|
|
|
def test_edge_wrapper_make_tangent_arc(self):
|
|
tangent_arc = Edge.make_tangent_arc(
|
|
Vector(1, 1), # starts at 1, 1
|
|
Vector(0, 1), # tangent at start of arc is in the +y direction
|
|
Vector(2, 1), # arc cureturn_values 180 degrees and ends at 2, 1
|
|
)
|
|
self.assertAlmostEqual(tangent_arc.start_point(), (1, 1, 0), 3)
|
|
self.assertAlmostEqual(tangent_arc.end_point(), (2, 1, 0), 3)
|
|
self.assertAlmostEqual(tangent_arc.tangent_at(0), (0, 1, 0), 3)
|
|
self.assertAlmostEqual(tangent_arc.tangent_at(0.5), (1, 0, 0), 3)
|
|
self.assertAlmostEqual(tangent_arc.tangent_at(1), (0, -1, 0), 3)
|
|
|
|
def test_edge_wrapper_make_ellipse1(self):
|
|
# Check x_radius > y_radius
|
|
x_radius, y_radius = 20, 10
|
|
angle1, angle2 = -75.0, 90.0
|
|
arcEllipseEdge = Edge.make_ellipse(
|
|
x_radius=x_radius,
|
|
y_radius=y_radius,
|
|
plane=Plane.XY,
|
|
start_angle=angle1,
|
|
end_angle=angle2,
|
|
)
|
|
|
|
start = (
|
|
x_radius * math.cos(math.radians(angle1)),
|
|
y_radius * math.sin(math.radians(angle1)),
|
|
0.0,
|
|
)
|
|
end = (
|
|
x_radius * math.cos(math.radians(angle2)),
|
|
y_radius * math.sin(math.radians(angle2)),
|
|
0.0,
|
|
)
|
|
self.assertAlmostEqual(arcEllipseEdge.start_point(), start, 3)
|
|
self.assertAlmostEqual(arcEllipseEdge.end_point(), end, 3)
|
|
|
|
def test_edge_wrapper_make_ellipse2(self):
|
|
# Check x_radius < y_radius
|
|
x_radius, y_radius = 10, 20
|
|
angle1, angle2 = 0.0, 45.0
|
|
arcEllipseEdge = Edge.make_ellipse(
|
|
x_radius=x_radius,
|
|
y_radius=y_radius,
|
|
plane=Plane.XY,
|
|
start_angle=angle1,
|
|
end_angle=angle2,
|
|
)
|
|
|
|
start = (
|
|
x_radius * math.cos(math.radians(angle1)),
|
|
y_radius * math.sin(math.radians(angle1)),
|
|
0.0,
|
|
)
|
|
end = (
|
|
x_radius * math.cos(math.radians(angle2)),
|
|
y_radius * math.sin(math.radians(angle2)),
|
|
0.0,
|
|
)
|
|
self.assertAlmostEqual(arcEllipseEdge.start_point(), start, 3)
|
|
self.assertAlmostEqual(arcEllipseEdge.end_point(), end, 3)
|
|
|
|
def test_edge_wrapper_make_circle_with_ellipse(self):
|
|
# Check x_radius == y_radius
|
|
x_radius, y_radius = 20, 20
|
|
angle1, angle2 = 15.0, 60.0
|
|
arcEllipseEdge = Edge.make_ellipse(
|
|
x_radius=x_radius,
|
|
y_radius=y_radius,
|
|
plane=Plane.XY,
|
|
start_angle=angle1,
|
|
end_angle=angle2,
|
|
)
|
|
|
|
start = (
|
|
x_radius * math.cos(math.radians(angle1)),
|
|
y_radius * math.sin(math.radians(angle1)),
|
|
0.0,
|
|
)
|
|
end = (
|
|
x_radius * math.cos(math.radians(angle2)),
|
|
y_radius * math.sin(math.radians(angle2)),
|
|
0.0,
|
|
)
|
|
self.assertAlmostEqual(arcEllipseEdge.start_point(), start, 3)
|
|
self.assertAlmostEqual(arcEllipseEdge.end_point(), end, 3)
|
|
|
|
def test_face_wrapper_make_rect(self):
|
|
mplane = Face.make_rect(10, 10)
|
|
|
|
self.assertAlmostEqual(mplane.normal_at(), (0.0, 0.0, 1.0), 3)
|
|
|
|
# def testCompoundcenter(self):
|
|
# """
|
|
# Tests whether or not a proper weighted center can be found for a compound
|
|
# """
|
|
|
|
# def cylinders(self, radius, height):
|
|
|
|
# c = Solid.make_cylinder(radius, height, Vector())
|
|
|
|
# # Combine all the cylinders into a single compound
|
|
# r = self.eachpoint(lambda loc: c.located(loc), True).combinesolids()
|
|
|
|
# return r
|
|
|
|
# Workplane.cyl = cylinders
|
|
|
|
# # Now test. here we want weird workplane to see if the objects are transformed right
|
|
# s = (
|
|
# Workplane("XY")
|
|
# .rect(2.0, 3.0, for_construction=true)
|
|
# .vertices()
|
|
# .cyl(0.25, 0.5)
|
|
# )
|
|
|
|
# self.assertEqual(4, len(s.val().solids()))
|
|
# np.testing.assert_allclose((0.0, 0.0, 0.25), s.val().center, 1e-3)
|
|
|
|
def test_translate(self):
|
|
e = Edge.make_circle(2, Plane((1, 2, 3)))
|
|
e2 = e.translate(Vector(0, 0, 1))
|
|
|
|
self.assertAlmostEqual(e2.center(CenterOf.MASS), (1.0, 2.0, 4.0), 3)
|
|
|
|
def test_vertices(self):
|
|
e = Edge.cast(BRepBuilderAPI_MakeEdge(gp_Pnt(0, 0, 0), gp_Pnt(1, 1, 0)).Edge())
|
|
self.assertEqual(2, len(e.vertices()))
|
|
|
|
def test_edge_wrapper_radius(self):
|
|
# get a radius from a simple circle
|
|
e0 = Edge.make_circle(2.4)
|
|
self.assertAlmostEqual(e0.radius, 2.4)
|
|
|
|
# radius of an arc
|
|
e1 = Edge.make_circle(
|
|
1.8, Plane(origin=(5, 6, 7), z_dir=(1, 1, 1)), start_angle=20, end_angle=30
|
|
)
|
|
self.assertAlmostEqual(e1.radius, 1.8)
|
|
|
|
# test value errors
|
|
e2 = Edge.make_ellipse(10, 20)
|
|
with self.assertRaises(ValueError):
|
|
e2.radius
|
|
|
|
# radius from a wire
|
|
w0 = Wire.make_circle(10, Plane(origin=(1, 2, 3), z_dir=(-1, 0, 1)))
|
|
self.assertAlmostEqual(w0.radius, 10)
|
|
|
|
# radius from a wire with multiple edges
|
|
rad = 2.3
|
|
plane = Plane(origin=(7, 8, 0), z_dir=(1, 0.5, 0.1))
|
|
w1 = Wire(
|
|
[
|
|
Edge.make_circle(rad, plane, 0, 10),
|
|
Edge.make_circle(rad, plane, 10, 25),
|
|
Edge.make_circle(rad, plane, 25, 230),
|
|
]
|
|
)
|
|
self.assertAlmostEqual(w1.radius, rad)
|
|
|
|
# test value error from wire
|
|
w2 = Wire.make_polygon(
|
|
[
|
|
Vector(-1, 0, 0),
|
|
Vector(0, 1, 0),
|
|
Vector(1, -1, 0),
|
|
]
|
|
)
|
|
with self.assertRaises(ValueError):
|
|
w2.radius
|
|
|
|
# (I think) the radius of a wire is the radius of it's first edge.
|
|
# Since this is stated in the docstring better make sure.
|
|
no_rad = Wire(
|
|
[
|
|
Edge.make_line(Vector(0, 0, 0), Vector(0, 1, 0)),
|
|
Edge.make_circle(1.0, start_angle=90, end_angle=270),
|
|
]
|
|
)
|
|
with self.assertRaises(ValueError):
|
|
no_rad.radius
|
|
yes_rad = Wire(
|
|
[
|
|
Edge.make_circle(1.0, start_angle=90, end_angle=270),
|
|
Edge.make_line(Vector(0, -1, 0), Vector(0, 1, 0)),
|
|
]
|
|
)
|
|
self.assertAlmostEqual(yes_rad.radius, 1.0)
|
|
many_rad = Wire(
|
|
[
|
|
Edge.make_circle(1.0, start_angle=0, end_angle=180),
|
|
Edge.make_circle(3.0, Plane((2, 0, 0)), start_angle=180, end_angle=359),
|
|
]
|
|
)
|
|
self.assertAlmostEqual(many_rad.radius, 1.0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|