Strangeness with Surface.Pullback and surface reparameterization

I have found the problem, but I am still left wondering why this happens.

If you run the code below on the surface and curves in the attached document, you see that the re-sampled curves have a big deviation with the original curves. That is caused by the fact that the Pullback is done on the BrepFace and the parameters are applied to the NurbsSurface of the BrepFace. Why does .ToNurbsSurface() change the parameterization of the surface? It probably has something to do with the fact that the original surface is a surface-of-revolution?

pullback-oddity.3dm (93.4 KB)

public Result RunCommand(RhinoDoc doc, RunMode mode)
{
    ObjRef sRef;
    ObjRef[] cRefs;
    Result res = RhinoGet.GetOneObject("Srf", false, ObjectType.Brep, out sRef);
    if (res != Result.Success) return res;

    res = RhinoGet.GetMultipleObjects("crvs", false, ObjectType.Curve, out cRefs);
    if (res != Result.Success) return res;

    Brep srf = sRef.Brep();

    Curve[] curves = cRefs.Select(r => r.Curve()).ToArray();

    Curve[] c2d = new Curve[curves.Length];

    for (int i = 0; i < curves.Length; ++i)
    {
        // pullback on brepface
        c2d[i] = srf.Faces[0].Pullback(curves[i], 1e-6);
    }

    NurbsSurface ns = srf.Faces[0].ToNurbsSurface();

    foreach (var c2 in c2d)
    {
        Point3d[] uvs;
        c2.DivideByCount(100, true, out uvs);
        List<Point3d> resampled = new List<Point3d>();
        foreach (var uv in uvs)
        {
            // apply brep face parameters on nurbs surface. FAIL
            resampled.Add(ns.PointAt(uv.X, uv.Y));
        }

        doc.Objects.AddPolyline(resampled);
    }

    return Result.Success;
}

Shown below is a simplified study of this problem: a cylindrical-shaped RevSurface with an elliptical NurbsCurve. The PolylineCurve intersects (yellow) the original curve at the octants (closest to the control point pattern of the NurbsSurface). The curve deviation is up through 0.0025 in the other places even though 1e-6 is used for the Pullback tolerance.

1 Like

Hi @menno,

Instead of doing this:

NurbsSurface ns = srf.Faces[0].ToNurbsSurface();

You should do this:

var srf = srf.Faces[0].UnderlyingSurface();

But you may already know this…

– Dale

I found out the hard way :smile:

What I don’t understand is why the nurbs representation has a different surface parameterization than the surface of revolution. The latter is, in my understanding, a sub-class of the nurbs surface, but that does not seem to be the case…(sub-class: mathematically speaking: all rev-surfs can be expressed as a NURBS, but not the other way around),

It seems from this topic Brep Face conversion problem that calling RebuildTrimsForV2 is the solution to this problem. Does that pinpoint what the difference is in surface parameterization of Rev vs. Nurb surfaces?

Both RevSurface and NurbsSurface inherit from Rhino.Geometry.Surface. RevSurface, howerver, is not a subclass of NurbsSurface, or vice versa.

An option for using parameters from a RevSurface with it’s NURB form is to use Surface.GetNurbsFormParameterFromSurfaceParameter, new in the Rhino WIP.

RevSurface rs = srf.Faces[0].UnderlyingSurface() as RevSurface;
NurbsSurface ns = rs.ToNurbsSurface();

...

foreach (var uv in uvs)
{
  double s, t;
  rs.GetNurbsFormParameterFromSurfaceParameter(uv.X, uv.Y, out s, out t);
  resampled.Add(ns.PointAt(s, t));
}

– Dale