What is the reason why NURBS cannot be converted to Bezier?

I’m trying this:

import rhino3dm
import math

dimension = 3
is_rational = False
order = 3
cv_count = 6

nc = rhino3dm.NurbsCurve(dimension, is_rational, order, cv_count)

nc.Points[0] = rhino3dm.Point4d(0.0, 0.0, 100.0, 1.0)
nc.Points[1] = rhino3dm.Point4d(25.0, 100.0, 75.0, 1.0)
nc.Points[2] = rhino3dm.Point4d(50.0, 25.0, 50.0, 1.0)
nc.Points[3] = rhino3dm.Point4d(75.0, 75.0, 25.0, 1.0)
nc.Points[4] = rhino3dm.Point4d(100.0, 50.0, 0.0, 1.0)

nc.Knots[0] = 0.0
nc.Knots[1] = 0.0
nc.Knots[2] = 0.0
nc.Knots[3] = 1.0
nc.Knots[4] = 2.0
nc.Knots[5] = 2.0
nc.Knots[6] = 2.0


if nc.HasBezierSpans:
    res = nc.MakePiecewiseBezier(setEndWeightsToOne=True)
    print(res)
else:
    print("No Bezier Spans")

model = rhino3dm.File3dm()
model.Objects.Add(nc)
model.Write("bezier.3dm", 0)

What is it in this particular NURBS that it cannot be converted?
What should be the correct approach?
If I use Rhino’s command ConvertToBezier I’m getting two curves.

which language is that? python command did not work. maybe if you post the curve before it was converted to have a look but generally i think converttobezier always splits up a curve into simple portions of 3 cps. @davidcockey may know more

bezier.3dm (2.9 KB)

that’s pure CPython, using the rhino3dm module.

I’d like to do with python what the ConvertToBezier command does. without using rhinoinside (compute-rhino3d)

Hi @ivelin.peychev,

The ConvertToBezier command uses the ON_NurbsCurve::ConvertSpanToBezier and ON_NurbsSurface::ConvertSpanToBezier functions. The source code to these function is available in the openNURBS repo on GitHub if needed.

As neither RhinoCommon nor Rhino3dm expose this, I’ve logged issues.

https://mcneel.myjetbrains.com/youtrack/issue/RH-71249
https://mcneel.myjetbrains.com/youtrack/issue/RH3DM-151

– Dale

1 Like

Hi @dale ,

Thanks for the link,

I’ve checked the functions you mentioned and I found something curious.

so, in the nurbs from the code above I ran the following checks:

# to convert to Beziers Nurbs has to have spans
print(f"nc.SpanCount = {nc.SpanCount}")

# to convert the spans to bezier spans it has to:
print(f"len(nc.Knots) = {len(nc.Knots)}")
print(f"nc.SpanCount >= 1 = {nc.SpanCount >= 1}")
print(f"order >= 2 = {order >= 2}")
print(f"cv_count >= order = {cv_count >= order}")
print(f"len(nc.Knots) == (nc.SpanCount+1)*(order-1) = {len(nc.Knots) == (nc.SpanCount+1)*(order-1)}")
print(f"nc.Knots[0] == nc.Knots[order-2] = {nc.Knots[0] == nc.Knots[order-2]}")
print(f"nc.Knots[cv_count-1] == nc.Knots[len(nc.Knots)-1] = {nc.Knots[cv_count-1] == nc.Knots[len(nc.Knots)-1]}")

print(f"nc.HasBezierSpans = {nc.HasBezierSpans}")

Get result:

nc.SpanCount = 2
len(nc.Knots) = 7
nc.SpanCount >= 1 = True
order >= 2 = True
cv_count >= order = True
len(nc.Knots) == (nc.SpanCount+1)*(order-1) = False
nc.Knots[0] == nc.Knots[order-2] = True
nc.Knots[cv_count-1] == nc.Knots[len(nc.Knots)-1] = True
nc.HasBezierSpans = False

Understandable since one of the check fails, there are no Bezier spans and the NURBS cannot be converted.

But then what kind of magic does the ConvertToBezier command do, because using the command it creates two curves from the spans?

RH-71249 is fixed in Rhino 7 Service Release 25 Release Candidate

1 Like

Hi @brian,

When will the python module be updated?

Thanks in advance.

I’m not sure. @fraguada will need to take a look when he gets a chance. @stevebaer is this as simple as releasing updated rhino3dm based on current openNURBS?

We would need to add new python bindings and update rhino3dm. I’m working on trying to get a new build of rhino3dm put together, but have been running into issues lately stemming from the Visual Studio compiler crashing. I don’t know when we will have an updated rhino3dm at this point

1 Like

Hello @stevebaer ,

Do you have an update on this topic?

Thanks in advance.

We found a work around to the crash with Visual Studio and are now back on track with building rhino3dm. @fraguada is in the process of getting all of the libraries updated to be based on Rhino 8 source and will be adding features to rhino3dm after that.

1 Like

This binding has been added to the js and py bindings. Pre-release builds are available (for 15 days) here: edit convertSpanToBezier for js · mcneel/rhino3dm@53bd0b2 · GitHub