Skip to content

feat: nurbs sketching and surface support #2104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/2104.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Nurbs sketching and surface support
58 changes: 54 additions & 4 deletions src/ansys/geometry/core/_grpc/_services/v0/conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
from ansys.geometry.core.sketch.edge import SketchEdge
from ansys.geometry.core.sketch.ellipse import SketchEllipse
from ansys.geometry.core.sketch.face import SketchFace
from ansys.geometry.core.sketch.nurbs import SketchNurbs
from ansys.geometry.core.sketch.polygon import Polygon
from ansys.geometry.core.sketch.segment import SketchSegment

Expand Down Expand Up @@ -404,6 +405,7 @@ def from_sketch_shapes_to_grpc_geometries(
converted_sketch_edges = from_sketch_edges_to_grpc_geometries(edges, plane)
geometries.lines.extend(converted_sketch_edges[0])
geometries.arcs.extend(converted_sketch_edges[1])
geometries.nurbs_curves.extend(converted_sketch_edges[2])

for face in faces:
if isinstance(face, SketchCircle):
Expand All @@ -429,6 +431,8 @@ def from_sketch_shapes_to_grpc_geometries(
one_curve_geometry.ellipses.append(geometries.ellipses[0])
elif len(geometries.polygons) > 0:
one_curve_geometry.polygons.append(geometries.polygons[0])
elif len(geometries.nurbs_curves) > 0:
one_curve_geometry.nurbs_curves.append(geometries.nurbs_curves[0])
return one_curve_geometry

else:
Expand All @@ -438,7 +442,7 @@ def from_sketch_shapes_to_grpc_geometries(
def from_sketch_edges_to_grpc_geometries(
edges: list["SketchEdge"],
plane: "Plane",
) -> tuple[list[GRPCLine], list[GRPCArc]]:
) -> tuple[list[GRPCLine], list[GRPCArc], list[GRPCNurbsCurve]]:
"""Convert a list of ``SketchEdge`` to a gRPC message.

Parameters
Expand All @@ -450,21 +454,25 @@ def from_sketch_edges_to_grpc_geometries(

Returns
-------
tuple[list[GRPCLine], list[GRPCArc]]
Geometry service gRPC line and arc messages. The unit is meters.
tuple[list[GRPCLine], list[GRPCArc], list[GRPCNurbsCurve]]
Geometry service gRPC line, arc, and NURBS curve messages. The unit is meters.
"""
from ansys.geometry.core.sketch.arc import Arc
from ansys.geometry.core.sketch.nurbs import SketchNurbs
from ansys.geometry.core.sketch.segment import SketchSegment

arcs = []
segments = []
nurbs_curves = []
for edge in edges:
if isinstance(edge, SketchSegment):
segments.append(from_sketch_segment_to_grpc_line(edge, plane))
elif isinstance(edge, Arc):
arcs.append(from_sketch_arc_to_grpc_arc(edge, plane))
elif isinstance(edge, SketchNurbs):
nurbs_curves.append(from_sketch_nurbs_to_grpc_nurbs_curve(edge, plane))

return (segments, arcs)
return (segments, arcs, nurbs_curves)


def from_sketch_arc_to_grpc_arc(arc: "Arc", plane: "Plane") -> GRPCArc:
Expand Down Expand Up @@ -496,6 +504,48 @@ def from_sketch_arc_to_grpc_arc(arc: "Arc", plane: "Plane") -> GRPCArc:
)


def from_sketch_nurbs_to_grpc_nurbs_curve(curve: "SketchNurbs", plane: "Plane") -> GRPCNurbsCurve:
"""Convert a ``SketchNurbs`` class to a NURBS curve gRPC message.

Parameters
----------
nurbs : SketchNurbs
Source NURBS data.
plane : Plane
Plane for positioning the NURBS curve.

Returns
-------
GRPCNurbsCurve
Geometry service gRPC NURBS curve message. The unit is meters.
"""
from ansys.api.geometry.v0.models_pb2 import (
ControlPoint as GRPCControlPoint,
NurbsData as GRPCNurbsData,
)

# Convert control points
control_points = [
GRPCControlPoint(
position=from_point2d_to_grpc_point(plane, pt),
weight=curve.weights[i],
)
for i, pt in enumerate(curve.control_points)
]

# Convert nurbs data
nurbs_data = GRPCNurbsData(
degree=curve.degree,
knots=from_knots_to_grpc_knots(curve.knots),
order=curve.degree + 1,
)

return GRPCNurbsCurve(
control_points=control_points,
nurbs_data=nurbs_data,
)


def from_sketch_ellipse_to_grpc_ellipse(ellipse: "SketchEllipse", plane: "Plane") -> GRPCEllipse:
"""Convert a ``SketchEllipse`` class to an ellipse gRPC message.

Expand Down
11 changes: 9 additions & 2 deletions src/ansys/geometry/core/connection/conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ def sketch_shapes_to_grpc_geometries(
GRPCGeometries
Geometry service gRPC geometries message. The unit is meters.
"""
from ansys.geometry.core.sketch.circle import SketchCircle
from ansys.geometry.core.sketch.ellipse import SketchEllipse
from ansys.geometry.core.sketch.polygon import Polygon

geometries = GRPCGeometries()

converted_sketch_edges = sketch_edges_to_grpc_geometries(edges, plane)
Expand Down Expand Up @@ -197,8 +201,8 @@ def sketch_shapes_to_grpc_geometries(


def sketch_edges_to_grpc_geometries(
edges: list[SketchEdge],
plane: Plane,
edges: list["SketchEdge"],
plane: "Plane",
) -> tuple[list[GRPCLine], list[GRPCArc]]:
"""Convert a list of ``SketchEdge`` to a gRPC message.

Expand All @@ -214,6 +218,9 @@ def sketch_edges_to_grpc_geometries(
tuple[list[GRPCLine], list[GRPCArc]]
Geometry service gRPC line and arc messages. The unit is meters.
"""
from ansys.geometry.core.sketch.arc import Arc
from ansys.geometry.core.sketch.segment import SketchSegment

arcs = []
segments = []
for edge in edges:
Expand Down
1 change: 1 addition & 0 deletions src/ansys/geometry/core/designer/geometry_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
point3d_to_grpc_point,
unit_vector_to_grpc_direction,
)
from ansys.geometry.core.designer.body import Body
from ansys.geometry.core.designer.component import Component
from ansys.geometry.core.designer.mating_conditions import (
AlignCondition,
Expand Down
5 changes: 1 addition & 4 deletions src/ansys/geometry/core/shapes/curves/nurbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,7 @@ def fit_curve_from_points(
from geomdl import fitting

# Convert points to a format suitable for the fitting function
converted_points = []
for pt in points:
pt_raw = [*pt]
converted_points.append(pt_raw)
converted_points = [[*pt] for pt in points]

# Fit the curve to the points
curve = fitting.interpolate_curve(converted_points, degree)
Expand Down
6 changes: 5 additions & 1 deletion src/ansys/geometry/core/sketch/edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def length(self) -> Quantity:
"""Length of the edge."""
raise NotImplementedError("Each edge must provide the length definition.")

def contains_point(self, point: Point2D, tol: float = 1e-6) -> bool:
"""Check if the edge contains the given point within a tolerance."""
raise NotImplementedError("Each edge must provide the contains_point method.")

@property
def visualization_polydata(self) -> "pv.PolyData":
"""VTK polydata representation for PyVista visualization.
Expand All @@ -76,7 +80,7 @@ def plane_change(self, plane: "Plane") -> None:
Notes
-----
This implies that their 3D definition might suffer changes. By default, this
metho does nothing. It is required to be implemented in child ``SketchEdge``
method does nothing. It is required to be implemented in child ``SketchEdge``
classes.
"""
pass
Loading
Loading