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?
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.
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));
}