Skip to content

Commit dd66488

Browse files
nurbs surface trim working
1 parent c719f67 commit dd66488

File tree

3 files changed

+127
-5
lines changed

3 files changed

+127
-5
lines changed

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
MaterialProperty as GRPCMaterialProperty,
4545
Matrix as GRPCMatrix,
4646
NurbsCurve as GRPCNurbsCurve,
47+
NurbsSurface as GRPCNurbsSurface,
4748
Plane as GRPCPlane,
4849
Point as GRPCPoint,
4950
Polygon as GRPCPolygon,
@@ -54,6 +55,7 @@
5455
TrimmedCurve as GRPCTrimmedCurve,
5556
TrimmedSurface as GRPCTrimmedSurface,
5657
)
58+
from ansys.geometry.core.shapes.surfaces.nurbs import NURBSSurface
5759
import pint
5860

5961
from ansys.geometry.core.errors import GeometryRuntimeError
@@ -770,6 +772,53 @@ def from_nurbs_curve_to_grpc_nurbs_curve(curve: "NURBSCurve") -> GRPCNurbsCurve:
770772
)
771773

772774

775+
def from_nurbs_surface_to_grpc_nurbs_surface(surface: "NURBSSurface") -> GRPCNurbsSurface:
776+
"""Convert a ``NURBSSurface`` to a NURBS surface gRPC message.
777+
778+
Parameters
779+
----------
780+
surface : NURBSSurface
781+
Surface to convert.
782+
783+
Returns
784+
-------
785+
GRPCNurbsSurface
786+
Geometry service gRPC ``NURBSSurface`` message.
787+
"""
788+
from ansys.api.geometry.v0.models_pb2 import (
789+
ControlPoint as GRPCControlPoint,
790+
NurbsData as GRPCNurbsData,
791+
)
792+
793+
# Convert control points
794+
control_points = [
795+
GRPCControlPoint(
796+
position=from_point3d_to_grpc_point(pt),
797+
weight=surface.weights[i],
798+
)
799+
for i, pt in enumerate(surface.control_points)
800+
]
801+
802+
# Convert nurbs data
803+
nurbs_data_u = GRPCNurbsData(
804+
degree=surface.degree_u,
805+
knots=from_knots_to_grpc_knots(surface.knotvector_u),
806+
order=surface.degree_u + 1,
807+
)
808+
809+
nurbs_data_v = GRPCNurbsData(
810+
degree=surface.degree_v,
811+
knots=from_knots_to_grpc_knots(surface.knotvector_v),
812+
order=surface.degree_v + 1,
813+
)
814+
815+
return GRPCNurbsSurface(
816+
control_points=control_points,
817+
nurbs_data_u=nurbs_data_u,
818+
nurbs_data_v=nurbs_data_v,
819+
)
820+
821+
773822
def from_grpc_nurbs_curve_to_nurbs_curve(curve: GRPCNurbsCurve) -> "NURBSCurve":
774823
"""Convert a NURBS curve gRPC message to a ``NURBSCurve``.
775824
@@ -976,6 +1025,14 @@ def from_surface_to_grpc_surface(surface: "Surface") -> tuple[GRPCSurface, GRPCS
9761025
minor_radius=surface.minor_radius.m,
9771026
)
9781027
surface_type = GRPCSurfaceType.SURFACETYPE_TORUS
1028+
elif isinstance(surface, NURBSSurface):
1029+
grpc_surface = GRPCSurface(
1030+
origin=origin,
1031+
reference=reference,
1032+
axis=axis,
1033+
nurbs_surface=from_nurbs_surface_to_grpc_nurbs_surface(surface),
1034+
)
1035+
surface_type = GRPCSurfaceType.SURFACETYPE_NURBS
9791036

9801037
return grpc_surface, surface_type
9811038

src/ansys/geometry/core/shapes/surfaces/nurbs.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from beartype import beartype as check_input_types
2828

2929
from ansys.geometry.core.math import Point3D
30+
from ansys.geometry.core.math.constants import UNITVECTOR3D_X, UNITVECTOR3D_Z
3031
from ansys.geometry.core.math.matrix import Matrix44
3132
from ansys.geometry.core.math.vector import UnitVector3D, Vector3D
3233
from ansys.geometry.core.shapes.parameterization import (
@@ -57,7 +58,13 @@ class NURBSSurface(Surface):
5758
5859
"""
5960

60-
def __init__(self, geomdl_object: "geomdl_nurbs.Surface" = None):
61+
def __init__(
62+
self,
63+
origin: Point3D,
64+
reference: UnitVector3D,
65+
axis: UnitVector3D,
66+
geomdl_object: "geomdl_nurbs.Surface" = None,
67+
):
6168
"""Initialize ``NURBSSurface`` class."""
6269
try:
6370
import geomdl.NURBS as geomdl_nurbs # noqa: N811
@@ -68,6 +75,9 @@ def __init__(self, geomdl_object: "geomdl_nurbs.Surface" = None):
6875
) from e
6976

7077
self._nurbs_surface = geomdl_object if geomdl_object else geomdl_nurbs.Surface()
78+
self._origin = Point3D([0.0, 0.0, 0.0])
79+
self._reference = UNITVECTOR3D_X
80+
self._axis = UNITVECTOR3D_Z
7181

7282
@property
7383
def geomdl_nurbs_surface(self) -> "geomdl_nurbs.Surface":
@@ -109,6 +119,21 @@ def knotvector_v(self) -> list[Real]:
109119
def weights(self) -> list[Real]:
110120
"""Get the weights of the control points."""
111121
return self._nurbs_surface.weights
122+
123+
@property
124+
def origin(self) -> Point3D:
125+
"""Get the origin of the surface."""
126+
return self._origin
127+
128+
@property
129+
def dir_x(self) -> UnitVector3D:
130+
"""Get the reference direction of the surface."""
131+
return self._reference
132+
133+
@property
134+
def dir_z(self) -> UnitVector3D:
135+
"""Get the axis direction of the surface."""
136+
return self._axis
112137

113138
@classmethod
114139
@check_input_types
@@ -120,6 +145,9 @@ def from_control_points(
120145
knots_v: list[Real],
121146
control_points: list[Point3D],
122147
weights: list[Real] = None,
148+
origin: Point3D = Point3D([0.0, 0.0, 0.0]),
149+
reference: UnitVector3D = UNITVECTOR3D_X,
150+
axis: UnitVector3D = UNITVECTOR3D_Z,
123151
) -> "NURBSSurface":
124152
"""Create a NURBS surface from control points and knot vectors.
125153
@@ -139,13 +167,19 @@ def from_control_points(
139167
Weights for the control points. If not provided, all weights are set to 1.
140168
delta : float, optional
141169
Evaluation delta for the surface. Default is 0.01.
170+
origin : Point3D, optional
171+
Origin of the surface. Default is (0, 0, 0).
172+
reference : UnitVector3D, optional
173+
Reference direction of the surface. Default is (1, 0, 0).
174+
axis : UnitVector3D, optional
175+
Axis direction of the surface. Default is (0, 0, 1).
142176
143177
Returns
144178
-------
145179
NURBSSurface
146180
Created NURBS surface.
147181
"""
148-
nurbs_surface = cls()
182+
nurbs_surface = cls(origin, reference, axis)
149183
nurbs_surface._nurbs_surface.degree_u = degree_u
150184
nurbs_surface._nurbs_surface.degree_v = degree_v
151185

@@ -182,6 +216,9 @@ def fit_surface_from_points(
182216
size_v: int,
183217
degree_u: int,
184218
degree_v: int,
219+
origin: Point3D = Point3D([0.0, 0.0, 0.0]),
220+
reference: UnitVector3D = UNITVECTOR3D_X,
221+
axis: UnitVector3D = UNITVECTOR3D_Z,
185222
) -> "NURBSSurface":
186223
"""Fit a NURBS surface to a set of points.
187224
@@ -197,6 +234,12 @@ def fit_surface_from_points(
197234
Degree of the surface in the U direction.
198235
degree_v : int
199236
Degree of the surface in the V direction.
237+
origin : Point3D, optional
238+
Origin of the surface. Default is (0, 0, 0).
239+
reference : UnitVector3D, optional
240+
Reference direction of the surface. Default is (1, 0, 0).
241+
axis : UnitVector3D, optional
242+
Axis direction of the surface. Default is (0, 0, 1).
200243
201244
Returns
202245
-------
@@ -215,7 +258,7 @@ def fit_surface_from_points(
215258
degree_v=degree_v,
216259
)
217260

218-
nurbs_surface = cls()
261+
nurbs_surface = cls(origin, reference, axis)
219262
nurbs_surface._nurbs_surface.degree_u = degree_u
220263
nurbs_surface._nurbs_surface.degree_v = degree_v
221264

tests/integration/test_design.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
from ansys.geometry.core.shapes.parameterization import (
7777
Interval,
7878
)
79+
from ansys.geometry.core.shapes.surfaces.nurbs import NURBSSurface
7980
from ansys.geometry.core.sketch import Sketch
8081

8182
from ..conftest import are_graphics_available
@@ -3244,13 +3245,34 @@ def test_surface_body_creation(modeler: Modeler):
32443245
assert body.is_surface
32453246
assert body.faces[0].area.m == pytest.approx(39.4784176044)
32463247

3248+
# nurbs surface
3249+
points = [
3250+
Point3D([0, 0, 0]), Point3D([0, 1, 1]),
3251+
Point3D([0, 2, 0]), Point3D([1, 0, 1]),
3252+
Point3D([1, 1, 2]), Point3D([1, 2, 1]),
3253+
Point3D([2, 0, 0]), Point3D([2, 1, 1]),
3254+
Point3D([2, 2, 0]),
3255+
]
3256+
degree_u = 2
3257+
degree_v = 2
3258+
surface = NURBSSurface.fit_surface_from_points(
3259+
points=points, size_u=3, size_v=3, degree_u=degree_u, degree_v=degree_v
3260+
)
3261+
3262+
trimmed_surface = surface.trim(BoxUV(Interval(0, 1), Interval(0, 1)))
3263+
body = design.create_body_from_surface("nurbs_surface", trimmed_surface)
3264+
assert len(design.bodies) == 5
3265+
assert body.is_surface
3266+
assert body.faces[0].area.m == pytest.approx(7.44626609)
3267+
design.export_to_scdocx("C:\\Users\\jkerstet\\Downloads\\nurbs_surface.scdocx")
3268+
32473269
# SOLID BODIES
32483270

32493271
# sphere
32503272
surface = Sphere([0, 0, 0], 1)
32513273
trimmed_surface = surface.trim(BoxUV(Interval(0, np.pi * 2), Interval(-np.pi / 2, np.pi / 2)))
32523274
body = design.create_body_from_surface("sphere_solid", trimmed_surface)
3253-
assert len(design.bodies) == 5
3275+
assert len(design.bodies) == 6
32543276
assert not body.is_surface
32553277
assert body.faces[0].area.m == pytest.approx(np.pi * 4)
32563278

@@ -3259,7 +3281,7 @@ def test_surface_body_creation(modeler: Modeler):
32593281
trimmed_surface = surface.trim(BoxUV(Interval(0, np.pi * 2), Interval(0, np.pi * 2)))
32603282
body = design.create_body_from_surface("torus_solid", trimmed_surface)
32613283

3262-
assert len(design.bodies) == 6
3284+
assert len(design.bodies) == 7
32633285
assert not body.is_surface
32643286
assert body.faces[0].area.m == pytest.approx(39.4784176044 * 2)
32653287

0 commit comments

Comments
 (0)