Proper way to create NurbsCurve in .net

Dear Rhino team,

Kindly excuse me in advance if i am asking wrong question at wrong place.
I am very fresh user of Rhino and came across one problem.
I am trying to create NurbsCurve all seems works well, however I have small misunderstanding when reading DXF entity`s (Spline) i am getting following data:

  1. 134 control points.
  2. 137 knots.
  3. degree 3. ( update : Typo degree = 2)

When NurbsCurve object is created the props “NurbsCurveKnotList Knots” is the list of size 134 element, and i am just stupid cannot get my head around how i can fit 137 knots to array size of 134 element :slight_smile:

Was playing around whole day and reading the docus but no success.
I will highly appreciate for any help, and once again sorry if i am asking stupid question.

What are you trying to do?

Nurbs curve follow the rule:
number of control points + degree - 1 = number of knots

Not possible.
Those would fit if the degree is 4.


2 Likes

did you see/read this article:

The knots are a list of (degree+N-1) numbers, where N is the number of control points.

1 Like

Hi Riccardo,

I am trying to learn API of Rhino to create some pluggin for our customer.
Basically I am reading DXF file with aspose library and I am getting those values by traversing through the entities, maybe library just giving wrong value as you point out it should follow the formula.
I also stumbled across good math books explaining nurbs and it says the same.

Hi Tom,
Oh yeah I did for sure. I tried to go over theory before jumping to the code.
Seems aspose lib which I am using to parse the dxf returns me wrong information.
I was just confused if interpreting formula wrong or doing something not correctly

@maje90 I just found I made typo on the screenshot degree is 2

Even worse… I don’t know what to say.

@maje90 I am just curious as Wikipedia says

Furthermore, the number of knots m, the degree p and the number of control points n are connected by the formula n=m−p−1.

So in my case:
Control points = 137 - 2 - 1 → 134 which seems to be correct

I assume I figure out that I have to remove first and last knot to get 135 knots.
Any way thanks guys

Hi @Vartan_Saakian,

Some evening reading for you.

SampleCsAddNurbsCurve.cs

SampleCsNurbsCircle.cs

SampleCsAddNurbsCircle.cs

Also, Rhino reads .dxf files. Is there a reason you don’t just Rhino’s reader?

Thanks,

– Dale

4 Likes

Hi @dale thanks a lot for your time and response.
I will definitely read through your suggestion - 100% need to boost my knowledge as feeling like blind groundhog…
I removed 1 and last knot and i am getting very good result apart that some beiziers sadly null and missing :slight_smile:

Oh i did knew i can do this with Rhino… i have to give a try.
P.S
I also found that i am currently using Rhino3dm nuget and not RhinoCommon but sadly it is still not targeting .net 8 which makes it incompatible with the rest of our internal code.

Any way huge thanks will go through

Hi @Vartan_Saakian,

Can you post the dxf file that contains the spline you are trying to convert to Rhino NURBS?

Thanks,

– Dale

Hi @dale surely,

To give a bit of context we do laser machines and one of our important customer use Rhino and he love it much so we are building some special solution for him.
Basically our laser consumes polylines, beziers and arc, and to get best quality i am trying to get beziers out of splines.

So far result is pretty good however i have some beziers gets back “null” after calling →

BezierCurve bezierCurves = nurbsCurve.ConvertSpanToBezier(i);

when i plot the result the Rhino does amazing job but yeah i guess i am doing something wrong.
The red line is original piece of spline
The green one is result of the code bellow. Almost everything is there apart of small bezier missing (just one example).

private PathShape Convert(
            List<PointF> controlPoints,
            List<double> knots,
            List<double> weights,
            int degree,
            bool isRational,
            AffineTransform transform
        )
        {
            var nurbsCurve = new NurbsCurve(3, isRational, degree + 1, controlPoints.Count);

            for (int i = 0; i < nurbsCurve .Points.Count; i++)
            {
                var point = new Point3d((double)controlPoints[i].X, (double)controlPoints[i].Y, 0);
// weight are zero at this DXF file so can be ignored for this sample.
                nurbsCurve .Points[i] = new ControlPoint(point, 0);
            }

// Remove first and last knot (0,1) https://developer.rhino3d.com/guides/opennurbs/superfluous-knots/
            knots.RemoveAt(0);
            knots.RemoveAt(knots.Count() - 1);

            for (int i = 0; i < nurbsCurve .Knots.Count; i++)
            {
                nurbsCurve2.Knots[i] = knots[i];
            }

            var result = new List<SimpleSegment>();
            for (int i = 0; i < nurbsCurve2.SpanCount; i++)
            {
                BezierCurve bezierCurves = nurbsCurve2.ConvertSpanToBezier(i);
                if (bezierCurves is null)
                {
                    ... // find why this happens ?
                }
                var countOfVertex = bezierCurves.ControlVertexCount;
                if (countOfVertex == 3)
                {
// quadratic bezier curve
                }
                else (countOfVertex == 4)
                {
// cubic bezier
                }
            }
....

Rhino-export_Végétations_Papier.dxf (1.0 MB)

1 Like

Hi @Vartan_Saakian,

Using Aspose.CAD and Rhino3dm, I was able to cobble together a sample that produces results like Rhino.

Program.cs (4.5 KB)

I believe the Aspose.CAD NuGet evaluation limits you to 100 entities, as I’m only getting 100 splines. Both Rhino and AutoCAD import 112 splines.

Vartan.3dm (749.8 KB)

– Dale

2 Likes

@dale you are my savior!!!

Added to your code possibility to Explode nurb to smaller bezier and result is great at least with one customer file :slight_smile:
Laser will be finally happy process beziers instead of poly-lines.

This way all works with (Rhino3dm nuget).

P.S
Not sure what was wrong with →

BezierCurve bezierCurves = nurbsCurve.ConvertSpanToBezier(i);

Maybe some bug.

Never used Rhino very nice software :slight_smile: great possibility to list all the details about entity by simply entering some comands.

Try replacing:

if (curve.IsValidWithLog(out string log))
  file3dm.Objects.AddCurve(curve);

with this:

if (curve.IsValidWithLog(out string log))
{
  //file3dm.Objects.AddCurve(curve);
  for (int si = 0; si < curve.SpanCount; si++)
  {
    BezierCurve bezier = curve.ConvertSpanToBezier(si);
    if (null != bezier)
      file3dm.Objects.AddCurve(bezier.ToNurbsCurve());
  }
}

– Dale

2 Likes