Skip to content

Commit e2e4c2d

Browse files
reworked method to use v1 style protos
test passing
1 parent 4755f9d commit e2e4c2d

File tree

3 files changed

+88
-124
lines changed

3 files changed

+88
-124
lines changed

src/ansys/geometry/core/_grpc/_services/v0/bodies.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -173,31 +173,43 @@ def create_sweeping_chain(self, **kwargs) -> dict: # noqa: D102
173173

174174
@protect_grpc
175175
def sweep_with_guide(self, **kwargs): # noqa: D102
176-
from ansys.api.geometry.v0.bodies_pb2 import SweepWithGuideRequest
176+
from ansys.api.dbu.v0.dbumodels_pb2 import EntityIdentifier
177+
from ansys.api.geometry.v0.bodies_pb2 import (
178+
SweepWithGuideRequest,
179+
SweepWithGuideRequestData,
180+
)
177181

178-
# Create the request - assumes all inputs are valid and of the proper type
182+
# Create request object - assumes all inputs are valid and of the proper type
179183
request = SweepWithGuideRequest(
180-
name=kwargs["name"],
181-
parent=kwargs["parent_id"],
182-
plane=from_plane_to_grpc_plane(kwargs["sketch"].plane),
183-
geometries=from_sketch_shapes_to_grpc_geometries(
184-
kwargs["sketch"].plane, kwargs["sketch"].edges, kwargs["sketch"].faces
185-
),
186-
path=from_trimmed_curve_to_grpc_trimmed_curve(kwargs["path"]),
187-
guide=from_trimmed_curve_to_grpc_trimmed_curve(kwargs["guide"]),
188-
tight_tolerance= kwargs["tight_tolerance"],
184+
request_data=[
185+
SweepWithGuideRequestData(
186+
name=data.name,
187+
parent=EntityIdentifier(id=data.parent_id),
188+
plane=from_plane_to_grpc_plane(data.sketch.plane),
189+
geometries=from_sketch_shapes_to_grpc_geometries(
190+
data.sketch.plane, data.sketch.edges, data.sketch.faces
191+
),
192+
path=from_trimmed_curve_to_grpc_trimmed_curve(data.path),
193+
guide=from_trimmed_curve_to_grpc_trimmed_curve(data.guide),
194+
tight_tolerance=data.tight_tolerance,
195+
)
196+
for data in kwargs["sweep_data"]
197+
],
189198
)
190199

191200
# Call the gRPC service
192201
resp = self.stub.SweepWithGuide(request=request)
193202

194203
# Return the response - formatted as a dictionary
195204
return {
196-
"id": resp.id,
197-
"name": resp.name,
198-
"master_id": resp.master_id,
199-
"is_surface": resp.is_surface,
200-
}
205+
"bodies": [{
206+
"id": body.id,
207+
"name": body.name,
208+
"master_id": body.master_id,
209+
"is_surface": body.is_surface,
210+
}]
211+
for body in resp.bodies
212+
}
201213

202214
@protect_grpc
203215
def create_extruded_body_from_face_profile(self, **kwargs) -> dict: # noqa: D102

src/ansys/geometry/core/designer/component.py

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
# SOFTWARE.
2222
"""Provides for managing components."""
2323

24+
from dataclasses import dataclass
2425
from enum import Enum, unique
2526
from functools import cached_property
2627
from typing import TYPE_CHECKING, Any, Optional, Union
@@ -134,6 +135,17 @@ def get_multiplier(self) -> int:
134135
"""
135136
return 1 if self is ExtrusionDirection.POSITIVE else -1
136137

138+
@dataclass
139+
class SweepWithGuideData:
140+
"""Data class for sweep with guide parameters."""
141+
142+
name: str
143+
parent_id: str
144+
sketch: Sketch
145+
path: TrimmedCurve
146+
guide: TrimmedCurve
147+
tight_tolerance: bool = False
148+
137149

138150
class Component:
139151
"""Provides for creating and managing a component.
@@ -710,51 +722,30 @@ def sweep_chain(
710722
@min_backend_version(26, 1, 0)
711723
@check_input_types
712724
@ensure_design_is_active
713-
def sweep_with_guide(
714-
self,
715-
name: str,
716-
sketch: Sketch,
717-
path: TrimmedCurve,
718-
guide: TrimmedCurve,
719-
tight_tolerance: bool
720-
):
725+
def sweep_with_guide(self, sweep_data: list[SweepWithGuideData]) -> list[Body]:
721726
"""Create a body by sweeping a sketch along a path with a guide curve.
722727
723728
The newly created body is placed under this component within the design assembly.
724729
725730
Parameters
726731
----------
727-
name : str
728-
User-defined label for the new solid body.
729-
sketch : Sketch
730-
Two-dimensional sketch source for the sweep.
731-
path : TrimmedCurve
732-
The path to sweep the profile along.
733-
guide : TrimmedCurve
734-
The guide curve to control the sweep.
735-
tight_tolerance : bool
736-
Whether to use tight tolerance for the sweep.
732+
sweep_data: SweepWithGuideData
733+
Data for the sweep operation, including the sketch, path, and guide curve.
737734
738735
Returns
739736
-------
740-
Body
741-
Created body from the given sketch.
737+
list[Body]
738+
Created bodies from the given sweep data.
742739
743740
Warnings
744741
--------
745742
This method is only available starting on Ansys release 26R1.
746743
"""
747744
self._grpc_client.log.debug(f"Sweeping the profile {self.id}. Creating body...")
748745
response = self._grpc_client.services.bodies.sweep_with_guide(
749-
name=name,
750-
parent_id=self.id,
751-
sketch=sketch,
752-
path=path,
753-
guide=guide,
754-
tight_tolerance=tight_tolerance,
755-
backend_version=self._grpc_client.backend_version,
746+
sweep_data=sweep_data
756747
)
757-
return self.__build_body_from_response(response)
748+
return [self.__build_body_from_response(body_data) for body_data in response.get("bodies")]
758749

759750
@min_backend_version(24, 2, 0)
760751
@check_input_types

tests/integration/test_design.py

Lines changed: 41 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
SurfaceType,
4141
)
4242
from ansys.geometry.core.designer.body import CollisionType, FillStyle, MasterBody
43+
from ansys.geometry.core.designer.component import SweepWithGuideData
4344
from ansys.geometry.core.designer.face import FaceLoopType
4445
from ansys.geometry.core.designer.part import MasterComponent, Part
4546
from ansys.geometry.core.errors import GeometryExitedError, GeometryRuntimeError
@@ -56,6 +57,7 @@
5657
UnitVector3D,
5758
Vector3D,
5859
)
60+
from ansys.geometry.core.math.matrix import Matrix44
5961
from ansys.geometry.core.misc import DEFAULT_UNITS, UNITS, Accuracy, Angle, Distance, checks
6062
from ansys.geometry.core.misc.auxiliary import DEFAULT_COLOR
6163
from ansys.geometry.core.parameters.parameter import ParameterType, ParameterUpdateStatus
@@ -2813,90 +2815,49 @@ def test_sweep_with_guide(modeler: Modeler):
28132815
"""Test creating a body by sweeping a profile with a guide curve."""
28142816
design = modeler.create_design("SweepWithGuide")
28152817

2816-
# Set up path points array
2817-
path_points = []
2818-
path_points.append(Point3D([0.0, 0.0, 0.15]))
2819-
path_points.append(Point3D([0.05, 0.0, 0.1]))
2820-
path_points.append(Point3D([0.1, 0.0, 0.05]))
2821-
path_points.append(Point3D([0.15, 0.0, 0.1]))
2822-
path_points.append(Point3D([0.2, 0.0, 0.15]))
2823-
2824-
npoints = len(path_points)
2825-
for i in range(2):
2826-
for j in range(1, npoints):
2827-
orgp = path_points[j]
2828-
p = Point3D([orgp[0] + (i + 1) * path_points[npoints - 1][0], orgp[1], orgp[2]])
2829-
path_points.append(p)
2830-
2831-
# Insert values at the beginning and end
2832-
start_point = [
2833-
Point3D(
2834-
[
2835-
path_points[npoints - 2][0] - path_points[npoints - 1][0],
2836-
path_points[npoints - 2][1],
2837-
path_points[npoints - 2][2],
2838-
],
2839-
)
2818+
# Create path points for the sweep path
2819+
path_points = [
2820+
Point3D([0.0, 0.0, 0.15]),
2821+
Point3D([0.05, 0.0, 0.1]),
2822+
Point3D([0.1, 0.0, 0.05]),
2823+
Point3D([0.15, 0.0, 0.1]),
2824+
Point3D([0.2, 0.0, 0.15]),
28402825
]
2841-
path_points = start_point + path_points
2842-
end_point = Point3D(
2843-
[
2844-
path_points[2][0] + (1 + 2) * path_points[npoints][0],
2845-
path_points[2][1],
2846-
path_points[2][2],
2847-
],
2848-
)
2849-
path_points.append(end_point)
2850-
2851-
# Create the NURBS curve through the points
2852-
nurbs_curve = NURBSCurve.fit_curve_from_points(path_points, 3)
2826+
nurbs_path = NURBSCurve.fit_curve_from_points(path_points, degree=3)
28532827
n_l_points = len(path_points)
2854-
yarn_path = nurbs_curve.trim(
2855-
Interval(1.0 / (n_l_points - 1), (n_l_points - 2.0) / (n_l_points - 1))
2856-
)
2857-
2858-
# Create the lenticular profile sketch
2859-
yarn_path_eval = nurbs_curve.project_point(path_points[1])
2860-
p = yarn_path_eval.position
2861-
d = yarn_path_eval.first_derivative.normalize()
2862-
2863-
# Define Hughes-Moeller algorithm for finding orthonormal base
2864-
def hughes_moeller(axis_direction):
2865-
"""Find the orthonornal base using hughes moeller algorithm."""
2866-
n = axis_direction
2867-
if np.abs(n[0]) > np.abs([n[2]]):
2868-
b2 = np.array(([-n[1], n[0], 0.0]))
2869-
else:
2870-
b2 = np.array((0.0, -n[2], n[1]))
2871-
b2 *= np.sqrt(np.dot(b2, b2))
2872-
b1 = np.cross(b2, n)
2873-
return b1, b2
2874-
2875-
a = 0.043134775028197354
2876-
aspect_ratio = 0.1
2877-
p1, p2 = hughes_moeller(np.array([d.x, d.y, d.z]))
2878-
plane = Plane(origin=p, direction_x=Vector3D(p1), direction_y=Vector3D(p2))
2879-
lenticular_profile = Sketch(plane)
2880-
radius = (a / aspect_ratio + a * aspect_ratio) / 2.0
2881-
2882-
c1 = Point2D([-radius + a * aspect_ratio, 0.0])
2883-
c2 = Point2D([radius - a * aspect_ratio, 0.0])
2884-
s1 = Point2D([0.0, a])
2885-
e1 = Point2D([0.0, -a])
2886-
2887-
lenticular_profile.arc(s1, e1, c1, True)
2888-
lenticular_profile.arc(e1, s1, c2, True)
2889-
2890-
# Sweep the sketch
2891-
sweep_body = design.sweep_with_guide(
2892-
name="Yarn",
2893-
sketch=lenticular_profile,
2894-
path=[yarn_path],
2895-
guide=None,
2828+
path_interval = Interval(1.0 / (n_l_points - 1), (n_l_points - 2.0) / (n_l_points - 1))
2829+
trimmed_path = nurbs_path.trim(path_interval)
2830+
2831+
# Create a simple circular profile sketch
2832+
profile_plane = Plane(origin=path_points[1])
2833+
profile_sketch = Sketch(profile_plane)
2834+
profile_sketch.circle(Point2D([0, 0]), 0.01) # 0.01 radius
2835+
2836+
# Create guide curve points (offset from path)
2837+
guide_points = [Point3D([p.x.m, p.y.m + 0.01, p.z.m]) for p in path_points]
2838+
guide_curve = NURBSCurve.fit_curve_from_points(guide_points, degree=3)
2839+
guide_interval = Interval(1.0 / (n_l_points - 1), (n_l_points - 2.0) / (n_l_points - 1))
2840+
trimmed_guide = guide_curve.trim(guide_interval)
2841+
2842+
# Sweep the profile along the path with the guide curve
2843+
sweep_data = [SweepWithGuideData(
2844+
name="SweptBody",
2845+
parent_id=design.id,
2846+
sketch=profile_sketch,
2847+
path=trimmed_path,
2848+
guide=trimmed_guide,
28962849
tight_tolerance=True,
2897-
)
2850+
)]
2851+
sweep_body = design.sweep_with_guide(sweep_data=sweep_data)[0]
2852+
2853+
design.export_to_scdocx("C:\\Users\\jkerstet\\Downloads\\sweep_body.scdocx")
28982854

2899-
sweep_body.plot(screenshot="C:\\Users\\jkerstet\\Downloads\\sweep_body.png")
2855+
assert sweep_body is not None
2856+
assert sweep_body.name == "SweptBody"
2857+
assert sweep_body.is_surface
2858+
assert len(sweep_body.faces) == 1
2859+
assert len(sweep_body.edges) == 2
2860+
assert len(sweep_body.vertices) == 0
29002861

29012862

29022863
def test_create_body_from_loft_profile(modeler: Modeler):

0 commit comments

Comments
 (0)