Skip to content
1 change: 1 addition & 0 deletions doc/changelog.d/2137.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Workflow 2b nurbs fixes
37 changes: 35 additions & 2 deletions src/ansys/geometry/core/shapes/curves/nurbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from beartype import beartype as check_input_types
import numpy as np
from scipy.integrate import quad

from ansys.geometry.core.math import Matrix44, Point3D
from ansys.geometry.core.math.vector import Vector3D
Expand Down Expand Up @@ -56,7 +57,7 @@ class NURBSCurve(Curve):

"""

def __init__(self):
def __init__(self, geomdl_object: "geomdl_nurbs.Curve" = None):
"""Initialize ``NURBSCurve`` class."""
try:
import geomdl.NURBS as geomdl_nurbs # noqa: N811
Expand All @@ -66,7 +67,7 @@ def __init__(self):
"Please install it using `pip install geomdl`."
) from e

self._nurbs_curve = geomdl_nurbs.Curve()
self._nurbs_curve = geomdl_object if geomdl_object else geomdl_nurbs.Curve()

@property
def geomdl_nurbs_curve(self) -> "geomdl_nurbs.Curve":
Expand Down Expand Up @@ -99,6 +100,38 @@ def weights(self) -> list[Real]:
"""Get the weights of the control points."""
return self._nurbs_curve.weights

def length(self, num_points: int = None) -> Real:
"""Calculate the length of the NURBS curve.

Parameters
----------
num_points : int, default: None
Number of points to sample along the curve for length calculation.

Returns
-------
Real
Length of the NURBS curve.
"""
if num_points is None:
num_spans = len(self._nurbs_curve.knotvector) - (2 * self._nurbs_curve.degree) - 1
num_points = max(
num_spans * 10, 50
) # 10 samples per span, floor of 50 ensures accuracy

self._nurbs_curve.sample_size = num_points

def arc_length_func(u):
deriv = self._nurbs_curve.derivatives(u, order=1)[1]
return np.linalg.norm(deriv)

# Integrate over the curve's domain
start_u = self._nurbs_curve.knotvector[self._nurbs_curve.degree]
end_u = self._nurbs_curve.knotvector[-(self._nurbs_curve.degree + 1)]

length, _ = quad(arc_length_func, start_u, end_u)
return length

@classmethod
@check_input_types
def from_control_points(
Expand Down
Loading