mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Split test_direct_api.py in many smaller tests
This commit is contained in:
parent
5e6f3b3337
commit
23e035a1ce
34 changed files with 6158 additions and 10 deletions
321
tests/test_direct_api/test_mixin1_d.py
Normal file
321
tests/test_direct_api/test_mixin1_d.py
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
"""
|
||||
build123d direct api tests
|
||||
|
||||
name: test_mixin1_d.py
|
||||
by: Gumyr
|
||||
date: January 21, 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 under the License is 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 build123d.build_enums import CenterOf, GeomType, PositionMode, Side, SortBy
|
||||
from build123d.geometry import Axis, Location, Plane, Vector
|
||||
from build123d.objects_part import Box, Cylinder
|
||||
from build123d.topology import Compound, Edge, Face, Wire
|
||||
from tests.base_test import DirectApiTestCase
|
||||
|
||||
|
||||
class TestMixin1D(DirectApiTestCase):
|
||||
"""Test the add in methods"""
|
||||
|
||||
def test_position_at(self):
|
||||
self.assertVectorAlmostEquals(
|
||||
Edge.make_line((0, 0, 0), (1, 1, 1)).position_at(0.5),
|
||||
(0.5, 0.5, 0.5),
|
||||
5,
|
||||
)
|
||||
# Not sure what PARAMETER mode returns - but it's in the ballpark
|
||||
point = (
|
||||
Edge.make_line((0, 0, 0), (1, 1, 1))
|
||||
.position_at(0.5, position_mode=PositionMode.PARAMETER)
|
||||
.to_tuple()
|
||||
)
|
||||
self.assertTrue(all([0.0 < v < 1.0 for v in point]))
|
||||
|
||||
wire = Wire([Edge.make_line((0, 0, 0), (10, 0, 0))])
|
||||
self.assertVectorAlmostEquals(wire.position_at(0.3), (3, 0, 0), 5)
|
||||
self.assertVectorAlmostEquals(
|
||||
wire.position_at(3, position_mode=PositionMode.LENGTH), (3, 0, 0), 5
|
||||
)
|
||||
self.assertVectorAlmostEquals(wire.edge().position_at(0.3), (3, 0, 0), 5)
|
||||
self.assertVectorAlmostEquals(
|
||||
wire.edge().position_at(3, position_mode=PositionMode.LENGTH), (3, 0, 0), 5
|
||||
)
|
||||
|
||||
circle_wire = Wire(
|
||||
[
|
||||
Edge.make_circle(1, start_angle=0, end_angle=180),
|
||||
Edge.make_circle(1, start_angle=180, end_angle=360),
|
||||
]
|
||||
)
|
||||
p1 = circle_wire.position_at(math.pi, position_mode=PositionMode.LENGTH)
|
||||
p2 = circle_wire.position_at(math.pi / circle_wire.length)
|
||||
self.assertVectorAlmostEquals(p1, (-1, 0, 0), 14)
|
||||
self.assertVectorAlmostEquals(p2, (-1, 0, 0), 14)
|
||||
self.assertVectorAlmostEquals(p1, p2, 14)
|
||||
|
||||
circle_edge = Edge.make_circle(1)
|
||||
p3 = circle_edge.position_at(math.pi, position_mode=PositionMode.LENGTH)
|
||||
p4 = circle_edge.position_at(math.pi / circle_edge.length)
|
||||
self.assertVectorAlmostEquals(p3, (-1, 0, 0), 14)
|
||||
self.assertVectorAlmostEquals(p4, (-1, 0, 0), 14)
|
||||
self.assertVectorAlmostEquals(p3, p4, 14)
|
||||
|
||||
circle = Wire(
|
||||
[
|
||||
Edge.make_circle(2, start_angle=0, end_angle=180),
|
||||
Edge.make_circle(2, start_angle=180, end_angle=360),
|
||||
]
|
||||
)
|
||||
self.assertVectorAlmostEquals(
|
||||
circle.position_at(0.5),
|
||||
(-2, 0, 0),
|
||||
5,
|
||||
)
|
||||
self.assertVectorAlmostEquals(
|
||||
circle.position_at(2 * math.pi, position_mode=PositionMode.LENGTH),
|
||||
(-2, 0, 0),
|
||||
5,
|
||||
)
|
||||
|
||||
def test_positions(self):
|
||||
e = Edge.make_line((0, 0, 0), (1, 1, 1))
|
||||
distances = [i / 4 for i in range(3)]
|
||||
pts = e.positions(distances)
|
||||
for i, position in enumerate(pts):
|
||||
self.assertVectorAlmostEquals(position, (i / 4, i / 4, i / 4), 5)
|
||||
|
||||
def test_tangent_at(self):
|
||||
self.assertVectorAlmostEquals(
|
||||
Edge.make_circle(1, start_angle=0, end_angle=90).tangent_at(1.0),
|
||||
(-1, 0, 0),
|
||||
5,
|
||||
)
|
||||
tangent = (
|
||||
Edge.make_circle(1, start_angle=0, end_angle=90)
|
||||
.tangent_at(0.0, position_mode=PositionMode.PARAMETER)
|
||||
.to_tuple()
|
||||
)
|
||||
self.assertTrue(all([0.0 <= v <= 1.0 for v in tangent]))
|
||||
|
||||
self.assertVectorAlmostEquals(
|
||||
Edge.make_circle(1, start_angle=0, end_angle=180).tangent_at(
|
||||
math.pi / 2, position_mode=PositionMode.LENGTH
|
||||
),
|
||||
(-1, 0, 0),
|
||||
5,
|
||||
)
|
||||
|
||||
def test_tangent_at_point(self):
|
||||
circle = Wire(
|
||||
[
|
||||
Edge.make_circle(1, start_angle=0, end_angle=180),
|
||||
Edge.make_circle(1, start_angle=180, end_angle=360),
|
||||
]
|
||||
)
|
||||
pnt_on_circle = Vector(math.cos(math.pi / 4), math.sin(math.pi / 4))
|
||||
tan = circle.tangent_at(pnt_on_circle)
|
||||
self.assertVectorAlmostEquals(tan, (-math.sqrt(2) / 2, math.sqrt(2) / 2), 5)
|
||||
|
||||
def test_tangent_at_by_length(self):
|
||||
circle = Edge.make_circle(1)
|
||||
tan = circle.tangent_at(circle.length * 0.5, position_mode=PositionMode.LENGTH)
|
||||
self.assertVectorAlmostEquals(tan, (0, -1), 5)
|
||||
|
||||
def test_tangent_at_error(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Edge.make_circle(1).tangent_at("start")
|
||||
|
||||
def test_normal(self):
|
||||
self.assertVectorAlmostEquals(
|
||||
Edge.make_circle(
|
||||
1, Plane(origin=(0, 0, 0), z_dir=(1, 0, 0)), start_angle=0, end_angle=60
|
||||
).normal(),
|
||||
(1, 0, 0),
|
||||
5,
|
||||
)
|
||||
self.assertVectorAlmostEquals(
|
||||
Edge.make_ellipse(
|
||||
1,
|
||||
0.5,
|
||||
Plane(origin=(0, 0, 0), z_dir=(1, 1, 0)),
|
||||
start_angle=0,
|
||||
end_angle=90,
|
||||
).normal(),
|
||||
(math.sqrt(2) / 2, math.sqrt(2) / 2, 0),
|
||||
5,
|
||||
)
|
||||
self.assertVectorAlmostEquals(
|
||||
Edge.make_spline(
|
||||
[
|
||||
(1, 0),
|
||||
(math.sqrt(2) / 2, math.sqrt(2) / 2),
|
||||
(0, 1),
|
||||
],
|
||||
tangents=((0, 1, 0), (-1, 0, 0)),
|
||||
).normal(),
|
||||
(0, 0, 1),
|
||||
5,
|
||||
)
|
||||
with self.assertRaises(ValueError):
|
||||
Edge.make_line((0, 0, 0), (1, 1, 1)).normal()
|
||||
|
||||
def test_center(self):
|
||||
c = Edge.make_circle(1, start_angle=0, end_angle=180)
|
||||
self.assertVectorAlmostEquals(c.center(), (0, 1, 0), 5)
|
||||
self.assertVectorAlmostEquals(
|
||||
c.center(CenterOf.MASS),
|
||||
(0, 0.6366197723675814, 0),
|
||||
5,
|
||||
)
|
||||
self.assertVectorAlmostEquals(c.center(CenterOf.BOUNDING_BOX), (0, 0.5, 0), 5)
|
||||
|
||||
def test_location_at(self):
|
||||
loc = Edge.make_circle(1).location_at(0.25)
|
||||
self.assertVectorAlmostEquals(loc.position, (0, 1, 0), 5)
|
||||
self.assertVectorAlmostEquals(loc.orientation, (0, -90, -90), 5)
|
||||
|
||||
loc = Edge.make_circle(1).location_at(
|
||||
math.pi / 2, position_mode=PositionMode.LENGTH
|
||||
)
|
||||
self.assertVectorAlmostEquals(loc.position, (0, 1, 0), 5)
|
||||
self.assertVectorAlmostEquals(loc.orientation, (0, -90, -90), 5)
|
||||
|
||||
def test_locations(self):
|
||||
locs = Edge.make_circle(1).locations([i / 4 for i in range(4)])
|
||||
self.assertVectorAlmostEquals(locs[0].position, (1, 0, 0), 5)
|
||||
self.assertVectorAlmostEquals(locs[0].orientation, (-90, 0, -180), 5)
|
||||
self.assertVectorAlmostEquals(locs[1].position, (0, 1, 0), 5)
|
||||
self.assertVectorAlmostEquals(locs[1].orientation, (0, -90, -90), 5)
|
||||
self.assertVectorAlmostEquals(locs[2].position, (-1, 0, 0), 5)
|
||||
self.assertVectorAlmostEquals(locs[2].orientation, (90, 0, 0), 5)
|
||||
self.assertVectorAlmostEquals(locs[3].position, (0, -1, 0), 5)
|
||||
self.assertVectorAlmostEquals(locs[3].orientation, (0, 90, 90), 5)
|
||||
|
||||
def test_project(self):
|
||||
target = Face.make_rect(10, 10, Plane.XY.rotated((0, 45, 0)))
|
||||
circle = Edge.make_circle(1).locate(Location((0, 0, 10)))
|
||||
ellipse: Wire = circle.project(target, (0, 0, -1))
|
||||
bbox = ellipse.bounding_box()
|
||||
self.assertVectorAlmostEquals(bbox.min, (-1, -1, -1), 5)
|
||||
self.assertVectorAlmostEquals(bbox.max, (1, 1, 1), 5)
|
||||
|
||||
def test_project2(self):
|
||||
target = Cylinder(1, 10).faces().filter_by(GeomType.PLANE, reverse=True)[0]
|
||||
square = Wire.make_rect(1, 1, Plane.YZ).locate(Location((10, 0, 0)))
|
||||
projections: list[Wire] = square.project(
|
||||
target, direction=(-1, 0, 0), closest=False
|
||||
)
|
||||
self.assertEqual(len(projections), 2)
|
||||
|
||||
def test_is_forward(self):
|
||||
plate = Box(10, 10, 1) - Cylinder(1, 1)
|
||||
hole_edges = plate.edges().filter_by(GeomType.CIRCLE)
|
||||
self.assertTrue(hole_edges.sort_by(Axis.Z)[-1].is_forward)
|
||||
self.assertFalse(hole_edges.sort_by(Axis.Z)[0].is_forward)
|
||||
|
||||
def test_offset_2d(self):
|
||||
base_wire = Wire.make_polygon([(0, 0), (1, 0), (1, 1)], close=False)
|
||||
corner = base_wire.vertices().group_by(Axis.Y)[0].sort_by(Axis.X)[-1]
|
||||
base_wire = base_wire.fillet_2d(0.4, [corner])
|
||||
offset_wire = base_wire.offset_2d(0.1, side=Side.LEFT)
|
||||
self.assertTrue(offset_wire.is_closed)
|
||||
self.assertEqual(len(offset_wire.edges().filter_by(GeomType.LINE)), 6)
|
||||
self.assertEqual(len(offset_wire.edges().filter_by(GeomType.CIRCLE)), 2)
|
||||
offset_wire_right = base_wire.offset_2d(0.1, side=Side.RIGHT)
|
||||
self.assertAlmostEqual(
|
||||
offset_wire_right.edges()
|
||||
.filter_by(GeomType.CIRCLE)
|
||||
.sort_by(SortBy.RADIUS)[-1]
|
||||
.radius,
|
||||
0.5,
|
||||
4,
|
||||
)
|
||||
h_perimeter = Compound.make_text("h", font_size=10).wire()
|
||||
with self.assertRaises(RuntimeError):
|
||||
h_perimeter.offset_2d(-1)
|
||||
|
||||
# Test for returned Edge - can't find a way to do this
|
||||
# base_edge = Edge.make_circle(10, start_angle=40, end_angle=50)
|
||||
# self.assertTrue(isinstance(offset_edge, Edge))
|
||||
# offset_edge = base_edge.offset_2d(2, side=Side.RIGHT, closed=False)
|
||||
# self.assertTrue(offset_edge.geom_type == GeomType.CIRCLE)
|
||||
# self.assertAlmostEqual(offset_edge.radius, 12, 5)
|
||||
# base_edge = Edge.make_line((0, 1), (1, 10))
|
||||
# offset_edge = base_edge.offset_2d(2, side=Side.RIGHT, closed=False)
|
||||
# self.assertTrue(isinstance(offset_edge, Edge))
|
||||
# self.assertTrue(offset_edge.geom_type == GeomType.LINE)
|
||||
# self.assertAlmostEqual(offset_edge.position_at(0).X, 3)
|
||||
|
||||
def test_common_plane(self):
|
||||
# Straight and circular lines
|
||||
l = Edge.make_line((0, 0, 0), (5, 0, 0))
|
||||
c = Edge.make_circle(2, Plane.XZ, -90, 90)
|
||||
common = l.common_plane(c)
|
||||
self.assertAlmostEqual(common.z_dir.X, 0, 5)
|
||||
self.assertAlmostEqual(abs(common.z_dir.Y), 1, 5) # the direction isn't known
|
||||
self.assertAlmostEqual(common.z_dir.Z, 0, 5)
|
||||
|
||||
# Co-axial straight lines
|
||||
l1 = Edge.make_line((0, 0), (1, 1))
|
||||
l2 = Edge.make_line((0.25, 0.25), (0.75, 0.75))
|
||||
common = l1.common_plane(l2)
|
||||
# the z_dir isn't know
|
||||
self.assertAlmostEqual(common.x_dir.Z, 0, 5)
|
||||
|
||||
# Parallel lines
|
||||
l1 = Edge.make_line((0, 0), (1, 0))
|
||||
l2 = Edge.make_line((0, 1), (1, 1))
|
||||
common = l1.common_plane(l2)
|
||||
self.assertAlmostEqual(common.z_dir.X, 0, 5)
|
||||
self.assertAlmostEqual(common.z_dir.Y, 0, 5)
|
||||
self.assertAlmostEqual(abs(common.z_dir.Z), 1, 5) # the direction isn't known
|
||||
|
||||
# Many lines
|
||||
common = Edge.common_plane(*Wire.make_rect(10, 10).edges())
|
||||
self.assertAlmostEqual(common.z_dir.X, 0, 5)
|
||||
self.assertAlmostEqual(common.z_dir.Y, 0, 5)
|
||||
self.assertAlmostEqual(abs(common.z_dir.Z), 1, 5) # the direction isn't known
|
||||
|
||||
# Wire and Edges
|
||||
c = Wire.make_circle(1, Plane.YZ)
|
||||
lines = Wire.make_rect(2, 2, Plane.YZ).edges()
|
||||
common = c.common_plane(*lines)
|
||||
self.assertAlmostEqual(abs(common.z_dir.X), 1, 5) # the direction isn't known
|
||||
self.assertAlmostEqual(common.z_dir.Y, 0, 5)
|
||||
self.assertAlmostEqual(common.z_dir.Z, 0, 5)
|
||||
|
||||
def test_edge_volume(self):
|
||||
edge = Edge.make_line((0, 0), (1, 1))
|
||||
self.assertAlmostEqual(edge.volume, 0, 5)
|
||||
|
||||
def test_wire_volume(self):
|
||||
wire = Wire.make_rect(1, 1)
|
||||
self.assertAlmostEqual(wire.volume, 0, 5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue