[Bug or Mistake?] Is FlowAlongSrf supposed to be exact for cylinders?

I think this is a bug, but not sure.

I understand that FlowAlongSrf will be approximate and introduce distortions for non-developable surfaces.

However, I was hoping FlowAlongSrf would be exact for cylinders and cones. I am trying to design some helical-grooves for a pin-in-groove mechanism. Unexpectedly, I came across the following deviation, as illustrated below.

If I take a cylinder and UnrollSrf, I get a rectangle. Any line that I draw inside the rectangle should (in theory) be rolled back into a helix on the original surface. So I am using FlowAlongSurf to roll the rectangle back into a cylinder.

Superficially, the helix looks fine. However, if I create a “true” helix using the CurveTools>Helix, I get a significantly different curve. The deviation is about 0.4mm for a cylinder with R=30mm and H=80mm. So that is way larger than any tolerance. See attached pictures and .3dm file.

Is this a bug, or is this how FlowAlongSrf is supposed to work? I was expecting FlowAlongSrf to be usable for mechanical engineering.

Here is a .zip of the .3dm file and the screenshots.

FlowAlongSurf Bug (1.0.1).zip (1.7 MB)

The parameterization of a true cylinder is not “even.” You would need to work with an approximated rebuilt Degree 3 cylinder to do what you’re trying to do, if your workflow even makes sense.

Hi Jim Carruthers,

Whoa… wow? I know that NURBS can be mathematically exact for representing cylinders. So, I automatically assumed, the parameterization would be done by arc-length, and thus “even”. It didn’t occur to me that UnrollSrf or FlowAlongSrf would not be based on arclength…

Any reason they wouldn’t be based on arclength? Is it just to save on computation?

Look at the curvature graph of the cylinder. When you measure the length of the flowed line that is as long as the plane, they differ. When you measure the circumference of the cylinder and length of plane, they’re identical.

Parameterization is not by arc length.

NURBs can represent a cylinder exactly by using a rational surface (not all weights equal to 1). UnrollSrf and UnrollSrfUV always create non-rational surfaces (all weights equal to 1). This can cause deviations.

Rebuild the cylinder as a non-rational surface which is sufficiently close to the exact rational surface.. For instance use degree 5 with 8 control points in the circumferential direction.

Use UnrollSrfUV instead of UnrollSrf.

from the rhinocommon docs of ArcCurve:

an ArcCurve is a sub-curve of a circle, with a constant speed parameterization. The parameterization is an affine linear reparameterization of the underlying arc m_arc onto the domain m_t.

so if you draw an arc, extrude it as surface (_useExtrusion = no) and use
_applyCrv you get:

Maximum deviation = 0.00733608 between the helix and the applied curves. (which is still to much if the initial statement on the parameterization is correct / precise)

Maybe @menno can tell us more on the parameterization of arc, circles, cylinders, surfaces of revolution…

meantime use Davids workflow / workaround (_rebuild, _unrollSrfUV)

flowalong_vs_applyCrv.3dm (3.0 MB)

Okay! So this is very interesting because:

(1) Mathematically, NURBS can represent conics exactly, with no approximation.
(2) Rhino3d does not use the “full” mathematical power of NURBS (probably for reasons (3)) in FlowAlongSrf, and related functions UnrollSrf and UnrollSrfUV.
(3) My guess is that although Rhino3d can handle NURBS, it is probably very computationally expensive (ie: slow) to do so. Also, because rational NURBS (ie: with varying weights) are more general than non-rational B-splines, they are probably more difficult to control numerically. ie: more difficult to make numerically stable. Since, in some sense, I guess, they can “misbehave” in more ways than non-rational splines.

Perhaps I was too naive in assuming that Rhino would “always” use mathematically exact representations of conics (ie: quadratic curves and surfaces) when possible. I suppose it is much more difficult to make a full-blown NURBS geometry engine than a non-rational b-spline one.

This is good to know.

As for my own purposes, I’ll probably just write my own Grasshopper scripts to do the “rolling” and “unrolling” for the special case of cones and cylinders. The general case of developable surfaces would be too hard to make numerically robust for someone like me (I think it would require solving differential equations numerically). But cones and cylinders are so simple, it should be reasonable to handle them in numerically stable ways.

btw, I’m currently working through Farin’s book on splines and nurbs.

Correct. NURBS can represent the shape of conics exactly. That does not mean the parameterization equals the arc length.

INCORRECT
Rhino uses “the “full” mathematical power of NURBS” when modeling conics including spheres, cylinders, ellipsoids, parboloids, etc.
But Rhino does not unroll a rational surface so that the parameterization exactly matches an original rational surface. What UnrollSrf does is create a non-rational unrolled surface with parameterization which is close to what the exact parameterization would be. But in some situations that parameterization may not be close enough.

Also incorrect. Rhino’s geometry engine is full NURBS.

Rhino’s handling of unrolling developable surfaces and flowing is numerically stable. It isn’t done as you were assuming or desire.

Hi David,

You misunderstood a few points I was making, but perhaps I did not explain myself fully. Here is actually what I meant:

The Rhino geometry engine has the machinery to handle NURBS. However not all Rhino functions/features use the full “expressive” capabilities of NURBS. For example, while the core engine can handle conics exactly, the “add-on” feature of FlowAlongSrf does not.

This is probably due to practical reasons involving the amount of computation required, as well as possibly, issues with numerical stability.

And THIS is why it’s surprising to me: Rhino’s NURBS engine can represent cylinders exactly (as well as spheres and other conics). However, Rhino has chosen a computationally more efficient but slightly less accurate approach to FlowAlongSrf.

in principle, and in practical terms, the special cases of cylinders and cones could be handled in a more accurate way. Cones and cylinders are the most simple developable surfaces. And the point of developable surfaces is that they can be unrolled/re-rolled without distortion.

So, one would imagine that Rhino would choose to do it as accurately as specified by the tolerance settings in the document. And if Rhino can’t, then it would be nice to be informed that some operation was out of tolerance, or that a comment in the manual or help file would explain or warn about this.

What I’m asking is why, for the specific cases of cones and cylinders, is FlowAlongSrf using an approximation that has an unexpected tolerance? We know that Rhino explicitly recognizes cylindrical surfaces and circular curves.

I don’t mean to belabor the point too much. But I am not saying (or rather, I did not mean to say) that Rhino doesn’t handle NURBS. What I mean to say, is that Rhino can handle NURBS (and therefore conics exactly), so in theory it could apply FlowAlongSrf to cylinders very accurately. So I’m simply surprised it does not. And I’m wondering why not.

I don’t think this is an unreasonable question to ask why?

Maybe I should look at the Bend command which I think, should “roll” a rectangle into a cylinder “exactly.”

I’m not sure what is going on. I’ve logged a YouTrack item for the developer of FlowAlongSrf to take a look at https://mcneel.myjetbrains.com/youtrack/issue/RH-96400

Thanks Menno!

The problem is that FlowAlongSrf is a function that maps from one parameter space of one surface to another surface. This means that for a mapping from from a Non Uniform Rational B-spline function to a Uniform B-spline you would expect there would be distortion due to the parameter spaces of the two surfaces not being uniformly the same.

Back more than 25 years ago there were complaints about this distortion when using FlowAlongSrf. Something was done by Rhino developers to address this problem, but as you can see its still not completely accurate, but its better than it used to be.

If you want more accurate results, make your cylinder as a revolve surface instead of a NURBS surface. . Keep in mind that won’t produce a result that precisely matches the result of the Helix command. This is because the Helix result is only an approximation and so is the FlowAlongSrf result. Both are made by finding enough points (the points are accurate) that can be used to create a NURBS curve that should be within the model tolerance.

Hi jim,

I think I’m not asking FlowAlongSrf to be accurate in all cases. Just accurate in the cases of cylinders and cones, because they are so common and so mathematically simple.

Here are some screenshots from a Grasshopper script I wrote. While not efficient, it is more accurate than I need. The apparent deviations are below 0.15 microns (!) and 2e-9 degrees (!).

If you look at the Grasshopper script, you’ll see it’s really-really simple. It’s just brute-force sampling, and in the examples it generates three times as many control points as compared to Rhino’s Helix tool. I’m sure I could have it sample less and still get a very good result.

So a really simple Rhino script produces a result that is orders of magnitude more accurate than FlowAlongSrf but specifically for cylinders only. I would imagine Rhino developers to use a much more sophisticated methods that generate lighter geometry that is comparably as accurate. Just test if FlowAlongSrf is being applied to a cylinder. If yes, then do accurate cylinder mapping.

Those of you talking about various parameter-spaces of various splines, my reaction is: Well, sure. But there is nothing that is stopping you from re-paramterizating based on arc-length for cylinders only. It’s just a conversion from cylindrical coordinates, as you can see in the provided script. That is first semester vector calculus.

Ditto for cones.

But I do greatly appreciate the fact that for non-cylinders and non-cones re-mapping the parameterization is a hard problem, and I do not expect Rhino to accurately solve those cases. I say that as someone who has struggled with numerical accuracy and stability while doing graduate research.

Here’s a .zip of the .gh, .3dm, and screenshots.

Wrap Cylinder (1.0.0).zip (1.3 MB)

I completely agree and it should have been done a decade ago. I was just explaining what got us to where we are today.

Actually mapping from one parameter space to another is not all that difficult. The problem is that when mapping from a not rational 2D space to a rational 3d space you get distortion that is unwanted. An attempt to fix this problem was made years ago but as you point out even an amateur can do better.

Most people who use FlowAlongSrf don’t care about the result being super accurate. All they need is something that looks reasonable from a distance, but I support your request for greater accuracy. There is no excuse for making commands sloppy for no good reason

Sure, but isn’t the mapping completely known from the math? I mean, I don’t think this mapping problem is some complicated “find solutions that satisfy a non-linear black-box.” My understanding (based on homogeneous coordinates (ie: non-uniform weighted NURBS)) is that we know what is in the box, and we have NURBS machinery to handle it.

Mappings between rational and non-rational spaces are why NURBS can exactly represent conics, but non-rational splines cannot.

Isn’t this only a problem if one were to insist on using non-rational splines (for some things but not other things)? And if the answer is yes, then it is an interesting question as to why are we insisting on this?

I imagine there are good answers to this question, however they may be difficult to explain, or even undesirable to explain. Because, in some sense, the answer could be,“To make our algorithms fast and robust we gave up some accuracy.”

The analogy would be “good, fast, cheap, only pick two out of three.” And then there is always someone (like me?) who complains about the missing third quality.

But honestly, I’m good with an answer like that, so long as I’m told that “As a design choice, we picked these two out of the three. The tradeoff was difficult, but this is what we decided.”

For me, my special-case is very simple, and I am only dealing with 2d curves. So the mapping is exceptionally simple. It could be that even this simple mapping gets complicated on intricate 3d breps and tight tolerances. I don’t know, I’m not an expert in this area. But I would be OK if some expert said,“I can’t easily explain why, but we chose these particular trade-offs.”

P.S. A minor technical note:
Non-uniform Rational B-splines are more general than non-rational B-splines. More precisely, non-rational B-splines are a subset of non-uniform rational B-splines. So mapping from non-rational to rational is easier than the other way around. So isn’t “not rational 2d space” mapping to “rational 3d space” the easy case?

Also, when the distortion is exactly known, mathematically, and the distortion is invertible, then we usually just correct for the distortion, right? The only problem is if the inversion leaves the space of solutions that we are restricting ourselves to using (or if the inversion is numerically unstable). But then, that restriction is by our own choice.

RH-96400 is fixed in Rhino BETA

Thanks Brian and Menno!