mirror of
https://github.com/gumyr/build123d.git
synced 2026-03-11 01:02:00 -07:00
fix: change function name to make_gordon_surface
fix: change the test name accordingly fix: corrected the type error for Edge.wrapped fix: change min version of ocp_gordon to 0.1.12 modified: pyproject.toml modified: src/build123d/topology/two_d.py modified: tests/test_direct_api/test_face.py
This commit is contained in:
parent
64267ab3f7
commit
925d12ff7c
3 changed files with 117 additions and 105 deletions
|
|
@ -44,7 +44,7 @@ dependencies = [
|
|||
"ipython >= 8.0.0, < 10",
|
||||
"lib3mf >= 2.4.1",
|
||||
"ocpsvg >= 0.5, < 0.6",
|
||||
"ocp_gordon >= 0.1.10",
|
||||
"ocp_gordon >= 0.1.12",
|
||||
"trianglesolver",
|
||||
"sympy",
|
||||
"scipy",
|
||||
|
|
|
|||
|
|
@ -865,38 +865,6 @@ class Face(Mixin2D, Shape[TopoDS_Face]):
|
|||
raise ValueError("Can't extrude empty object")
|
||||
return Face(TopoDS.Face_s(_extrude_topods_shape(obj.wrapped, direction)))
|
||||
|
||||
@classmethod
|
||||
def gordon_surface(
|
||||
cls,
|
||||
profiles: Iterable[Edge],
|
||||
guides: Iterable[Edge],
|
||||
tolerance: float = 3e-4,
|
||||
) -> Face:
|
||||
"""
|
||||
Creates a Gordon surface from a network of profile and guide curves.
|
||||
|
||||
Args:
|
||||
profiles (Iterable[Edge]): Edges representing profile curves.
|
||||
guides (Iterable[Edge]): Edges representing guide curves.
|
||||
tolerance (float, optional): Tolerance for surface creation and
|
||||
intersection calculations.
|
||||
|
||||
Returns:
|
||||
Face: the interpolated Gordon surface
|
||||
"""
|
||||
ocp_profiles = [BRep_Tool.Curve_s(edge.wrapped, 0, 1) for edge in profiles]
|
||||
ocp_guides = [BRep_Tool.Curve_s(edge.wrapped, 0, 1) for edge in guides]
|
||||
|
||||
gordon_bspline_surface = interpolate_curve_network(
|
||||
ocp_profiles, ocp_guides, tolerance=tolerance
|
||||
)
|
||||
|
||||
return cls(
|
||||
BRepBuilderAPI_MakeFace(
|
||||
gordon_bspline_surface, Precision.Confusion_s()
|
||||
).Face()
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def make_bezier_surface(
|
||||
cls,
|
||||
|
|
@ -946,6 +914,47 @@ class Face(Mixin2D, Shape[TopoDS_Face]):
|
|||
|
||||
return cls(BRepBuilderAPI_MakeFace(bezier, Precision.Confusion_s()).Face())
|
||||
|
||||
@classmethod
|
||||
def make_gordon_surface(
|
||||
cls,
|
||||
profiles: Iterable[Edge],
|
||||
guides: Iterable[Edge],
|
||||
tolerance: float = 3e-4,
|
||||
) -> Face:
|
||||
"""
|
||||
Creates a Gordon surface from a network of profile and guide curves.
|
||||
|
||||
Args:
|
||||
profiles (Iterable[Edge]): Edges representing profile curves.
|
||||
guides (Iterable[Edge]): Edges representing guide curves.
|
||||
tolerance (float, optional): Tolerance for surface creation and
|
||||
intersection calculations.
|
||||
|
||||
Raises:
|
||||
ValueError: Input edge cannot be empty
|
||||
|
||||
Returns:
|
||||
Face: the interpolated Gordon surface
|
||||
"""
|
||||
|
||||
def to_geom_curve(edge: Edge):
|
||||
if edge.wrapped is None:
|
||||
raise ValueError("input edge cannot be empty")
|
||||
return BRep_Tool.Curve_s(edge.wrapped, 0, 1)
|
||||
|
||||
ocp_profiles = [to_geom_curve(edge) for edge in profiles]
|
||||
ocp_guides = [to_geom_curve(edge) for edge in guides]
|
||||
|
||||
gordon_bspline_surface = interpolate_curve_network(
|
||||
ocp_profiles, ocp_guides, tolerance=tolerance
|
||||
)
|
||||
|
||||
return cls(
|
||||
BRepBuilderAPI_MakeFace(
|
||||
gordon_bspline_surface, Precision.Confusion_s()
|
||||
).Face()
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def make_plane(
|
||||
cls,
|
||||
|
|
|
|||
|
|
@ -359,6 +359,81 @@ class TestFace(unittest.TestCase):
|
|||
self.assertAlmostEqual(loc.position, (0.0, 1.0, 1.5), 5)
|
||||
self.assertAlmostEqual(loc.orientation, (0, -90, 0), 5)
|
||||
|
||||
def test_make_gordon_surface(self):
|
||||
def create_test_curves(
|
||||
num_profiles: int = 3,
|
||||
num_guides: int = 4,
|
||||
u_range: float = 1.0,
|
||||
v_range: float = 1.0,
|
||||
):
|
||||
profiles: list[Edge] = []
|
||||
guides: list[Edge] = []
|
||||
|
||||
intersection_points = [
|
||||
[(0.0, 0.0, 0.0) for _ in range(num_guides)]
|
||||
for _ in range(num_profiles)
|
||||
]
|
||||
|
||||
for i in range(num_profiles):
|
||||
for j in range(num_guides):
|
||||
u = i * u_range / (num_profiles - 1)
|
||||
v = j * v_range / (num_guides - 1)
|
||||
z = 0.2 * math.sin(u * math.pi) * math.cos(v * math.pi)
|
||||
intersection_points[i][j] = (u, v, z)
|
||||
|
||||
for i in range(num_profiles):
|
||||
points = [intersection_points[i][j] for j in range(num_guides)]
|
||||
profiles.append(Spline(points))
|
||||
|
||||
for j in range(num_guides):
|
||||
points = [intersection_points[i][j] for i in range(num_profiles)]
|
||||
guides.append(Spline(points))
|
||||
|
||||
return profiles, guides
|
||||
|
||||
profiles, guides = create_test_curves()
|
||||
|
||||
tolerance = 3e-4
|
||||
gordon_surface = Face.make_gordon_surface(profiles, guides, tolerance=tolerance)
|
||||
|
||||
self.assertIsInstance(
|
||||
gordon_surface, Face, "The returned object should be a Face."
|
||||
)
|
||||
|
||||
def point_at_uv_against_expected(u: float, v: float, expected_point: Vector):
|
||||
point_at_uv = gordon_surface.position_at(u, v)
|
||||
self.assertAlmostEqual(
|
||||
point_at_uv.X,
|
||||
expected_point.X,
|
||||
delta=tolerance,
|
||||
msg=f"X coordinate mismatch at ({u},{v})",
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
point_at_uv.Y,
|
||||
expected_point.Y,
|
||||
delta=tolerance,
|
||||
msg=f"Y coordinate mismatch at ({u},{v})",
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
point_at_uv.Z,
|
||||
expected_point.Z,
|
||||
delta=tolerance,
|
||||
msg=f"Z coordinate mismatch at ({u},{v})",
|
||||
)
|
||||
|
||||
point_at_uv_against_expected(
|
||||
u=0.0, v=0.0, expected_point=guides[0].position_at(0.0)
|
||||
)
|
||||
point_at_uv_against_expected(
|
||||
u=1.0, v=0.0, expected_point=profiles[0].position_at(1.0)
|
||||
)
|
||||
point_at_uv_against_expected(
|
||||
u=0.0, v=1.0, expected_point=guides[0].position_at(1.0)
|
||||
)
|
||||
point_at_uv_against_expected(
|
||||
u=1.0, v=1.0, expected_point=profiles[-1].position_at(1.0)
|
||||
)
|
||||
|
||||
def test_make_surface(self):
|
||||
corners = [Vector(x, y) for x in [-50.5, 50.5] for y in [-24.5, 24.5]]
|
||||
net_exterior = Wire(
|
||||
|
|
@ -502,78 +577,6 @@ class TestFace(unittest.TestCase):
|
|||
]
|
||||
)
|
||||
|
||||
def test_gordon_surface(self):
|
||||
def create_test_curves(
|
||||
num_profiles: int = 3,
|
||||
num_guides: int = 4,
|
||||
u_range: float = 1.0,
|
||||
v_range: float = 1.0,
|
||||
):
|
||||
profiles: list[Edge] = []
|
||||
guides: list[Edge] = []
|
||||
|
||||
intersection_points = [
|
||||
[(0.0, 0.0, 0.0) for _ in range(num_guides)]
|
||||
for _ in range(num_profiles)
|
||||
]
|
||||
|
||||
for i in range(num_profiles):
|
||||
for j in range(num_guides):
|
||||
u = i * u_range / (num_profiles - 1)
|
||||
v = j * v_range / (num_guides - 1)
|
||||
z = 0.2 * math.sin(u * math.pi) * math.cos(v * math.pi)
|
||||
intersection_points[i][j] = (u, v, z)
|
||||
|
||||
for i in range(num_profiles):
|
||||
points = [intersection_points[i][j] for j in range(num_guides)]
|
||||
profiles.append(Spline(points))
|
||||
|
||||
for j in range(num_guides):
|
||||
points = [intersection_points[i][j] for i in range(num_profiles)]
|
||||
guides.append(Spline(points))
|
||||
|
||||
return profiles, guides
|
||||
|
||||
profiles, guides = create_test_curves()
|
||||
|
||||
tolerance = 3e-4
|
||||
gordon_surface = Face.gordon_surface(profiles, guides, tolerance=tolerance)
|
||||
|
||||
self.assertIsInstance(
|
||||
gordon_surface, Face, "The returned object should be a Face."
|
||||
)
|
||||
|
||||
def point_at_uv_against_expected(u: float, v: float, expected_point: Vector):
|
||||
point_at_uv = gordon_surface.position_at(u, v)
|
||||
self.assertAlmostEqual(
|
||||
point_at_uv.X,
|
||||
expected_point.X,
|
||||
delta=tolerance,
|
||||
msg=f"X coordinate mismatch at ({u},{v})",
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
point_at_uv.Y,
|
||||
expected_point.Y,
|
||||
delta=tolerance,
|
||||
msg=f"Y coordinate mismatch at ({u},{v})",
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
point_at_uv.Z,
|
||||
expected_point.Z,
|
||||
delta=tolerance,
|
||||
msg=f"Z coordinate mismatch at ({u},{v})",
|
||||
)
|
||||
|
||||
point_at_uv_against_expected(
|
||||
u=1.0, v=0.0, expected_point=profiles[0].position_at(1.0)
|
||||
)
|
||||
point_at_uv_against_expected(
|
||||
u=0.0, v=1.0, expected_point=guides[0].position_at(1.0)
|
||||
)
|
||||
point_at_uv_against_expected(
|
||||
u=1.0, v=1.0, expected_point=profiles[-1].position_at(1.0)
|
||||
)
|
||||
|
||||
# def test_to_arcs(self):
|
||||
# with BuildSketch() as bs:
|
||||
# with BuildLine() as bl:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue