Sphere and cylinder trim bug

Can anyone reproduce this?

  1. Draw a sphere of 70mm diameter
  2. Draw a cylinder of 40mm through it
  3. Intersect → The intersection curve is measured as 40mm diameter.
  4. Use it to trim the sphere
  5. The trimmed edge reports a slightly different diameter at each point you sample.

DupEdge a trimmed edge.
CrvDeviation between the duplicated edge curve and the circle used for trimming. The maximum deviation of distance will be less than the absolute tolerance.

When a surface is trimmed an edge curve is created. This edge curve will be a non-rational degree 3 curve with sufficient number of control points that it is within the absolute tolerance of the theoretical edge. In most instances the theoretical edge cannot be represented exactly by a NURBS curve. Rhino is not “smart” enough to know about special cases such as your example where the theoretical edge can be exactly represented by a special type of curve such as a circle.

A circle cannot be represented exactly by a non-rational degree 3 curve. (With a sufficient number of control points the deviation between the non-rational degree 3 curve and an exact circle can be reduced to within any non-zero tolerance, but there will always be some deviation.) Since the curve deviaties from an exact circle the local radius/diameter of curvature will also deviate from the radius/diameter of the circle. Note a small, local distance deviation between two curves will usually result in a much larger deviation in radius of curvature. That is how geometry works.

Hi David,

When I do as Duncan instructs and the centreline of the cylinder passes through the centre of the sphere I get a consistent diameter of 40.0000000, so Rhino is recognising the circularity of the hole.

I surmise that Duncan is getting different diameters because his cylinder is slightly off centre from the sphere.

Regards
Jeremy

EDIT: As @jim rightly points out below I didn’t follow the OP’s steps at all correctly. It just goes to show the danger of posting when you’ve had too much/too little coffee. Or are developing a messiah complex.

The problem is you didn’t do what the OP did.

In the original post, the intersection is a circle and not a spline curve. That shows that the cylinder axis does pass thru the center of the sphere and Rhino recognizes the intersection as a circle (arc).

But that is an intersection. The OP is asking about a trimmed edge.

The only time that Rhino recognizes a trim as a circle is when that circle coincides with an isocurve that is a circle. This only happens in one case → when the axis of the sphere and the axis of the cylinder coincide. The trimmed edge of the cylinder is a precise circle whenever the cylinder axis passes thru the .sphere center point.

You can see that the axis of the sphere is not the same as the axis of the cylinder.
They are at right angles.

IMO this is a bug. Rhino correctly recognizes the intersection as a circle and should also recognize the edge of trimmed sphere as a circle when it is supposed to be precisely a circle.

You are absolutely right! Thanks for the correction.

Regards
Jeremy

@dale I have a lot of respect for jim’s opinions, so I bring this thread to your attention for consideration.

maybe @sfp is the one to have a look at this topic.

Thanks for the ping, @AlW — Jim is right.

Trimmed edges are normally made by pulling the trim curve into the surface’s parameter space and pushing it back up into 3D, which produces a fitted NURBS curve. The exact circle gets discarded on the way. Reproduced here with a 0.001mm tolerance: the intersection is an exact circle at D40.0000000, but the trimmed edge samples between 39.9996174 and 40.0004667. Its radius of curvature swings 19.77 to 20.14 — roughly 430× the positional error, which is the effect David described and why the readings look worse than the tolerance implies.

But we already skip that refit in two cases: when the trim lands on an isocurve (why Jeremy got 40.0000000 with the axes aligned — Jim’s diagnosis is exactly right), and when the surface is planar. So the behavior exists, it just doesn’t cover this case. We’re handed an exact circle that provably lies on the sphere and refit it anyway.

We’d like to fix the general case: if the curve already lies on the surface within tolerance, use it as the edge. I logged this specific issue.

Thanks,

– Dale

Thank you all for the in-depth engagement and the bug filing :folded_hands:

I did notice Rhino correctly recognises the intersection as a circle, and hence I was so confused why the diameter would fluctuate after the trim.

This might be irrelevant as the source for the problem has been determined, but I found a workaround that helped me in the meantime:

  1. Draw the cylinder so it intersects only once
  2. BooleanDifference it away from the sphere
  3. ExtractSrf the parts you don’t want

This will make the diameter stay exactly 40mm along the entire trim edge.

In this case, the sphere/cylinder intersection is correctly computed as a circle.

The case that the intersect needs to be looked at is the intersection of two true spheres. In that case Rhino makes a pretty ugly spline curve as the intersection curve instead of a true circle.

You could just have joined the cylinder and the sphere after trimming both. This would make the joined edge a true circle and the sphere would retain that edge definition after using ExtractSrf (or exploding). I imagine this is because the joined edge adopts the edge of the cylinder.

there is (many?) more of those basic geometrical intersections that fail in terms of not providing the mathematically correct result:

cylinder - plane (projecting a circle to a planar surface gives expected result)
plane (planar surface) - sphere

; - (

How important is the exact mathematical solution for the trim edge compared to an approximate solution that is within the user specified absolute tolerance of the exact solution? Why is it important?

For example if you trim a sphere and a plane with each other, and then join the results the only way a user would know the trimmed edge curves are not exact circles is if someone examines them in detail.

When you work in fabrication, obtaining clean circles and ellipses is vital for DXF export.

i thought this simple example should already show some aspects:

→ an approximated circle does not have a center snap. (front)

→ if projected curves are also used for further surfaces the approximation is derived… a simple extrusion (front row cylinder + planar surface)

→ if the edge is used for attached surfaces (second row) _blendSrf the benefit is not obvious

→ it needs some fiddeling (loft + matchSrf) to get a perfect solution (back)

@Tom_P @jim

Please feel free to send me direct messages with as many of these special cases as you like and I can make YT issues for them all.

If you can also explain why not having these results is blocking you, that will help me prioritize it higher.

In most cases, the fitted curves should be sufficient.

Sam

@DuncanW

Can you please say more about this? If there is a strong use case for it, it will help us find a way to prioritize the work higher. But a single sentence explanation is not nearly enough. I need to understand why the current way of working is falling down and what problems clean circles and ellipses would solve for you.

Sam

Not centre snapping is often a pitfall I encounter with this approach to circles. I have never understoood why this happens until Jim pointed out what is happening here.

What I don’t understand, is that for something that is spherical and acting as a trim on a plane, is the coordinate transform of the circle into that plane not possible? Shouldn’t Rhino in these more trivial cases search for local planar surfaces, and transform the circle into that plane? Or at least, try and check if the roundness of the expected trim/intersect is better treated as a circle to within the document tolerance?

@David and anyone else who is curious:

The problem with B-reps is that there are two representations of each “trim curve”. Please check this nice diagram out: Rhino - Brep Data Structure

Each trim curve is represented in 2D and in 3D. The reason for this redundancy is that in 3D, there is only one 3D trim or “edge” curve, regardless of whether one or two faces is incident on it. In 2D, there is always one version of this curve per face. I believe users primarily interact with the 3D trim curves and are frequently unaware of the existence of the 2D curves.

Different operations are easier or harder with these 2D and 3D curves. Sometimes using the 2D curve is natural, sometimes using the 3D curve is. Consequently, many Rhino functions use on or the other. The natural way to do a trim is as Dale described, and involves passing through the 2D trim domain of the surface on the way to final 3D edge curve. Of course, along the way, the 2D trim curves are also computed, and are extremely important.

The trouble with the example being discussed in this thread is that while the 3D trim curve is simple to write as a NURBS (it’s just a circle…), the 2D trim curve is not.

Here is a simple demonstration: let’s say the surface is S(u, v) = (cos(u)cos(v), sin(u)cos(v), sin(v)). Its axis is just the z axis. If we intersect it with a cylinder which is centered about the origin and whose axis is the x axis, we are effectively intersecting it with constant x planes; e.g., x = C where -1 < C < 1 (assuming we don’t just get a single point of intersection at the antipodal points of the sphere).

To write down the 2D trim curve, we can solve for v. Since x = C, we have cos(u)cos(v) = C, or v = arccos(C sec(u)). As far as I’m aware, this curve is transcendental, and cannot be written as a rational, even though the 3D trim curve can.

It is arguably worthwhile to go ahead and get the 3D trim curve correct, but there will always be the need to approximate the 2D trim curve in this case (and indeed, in basically all similar cases).

So this is really down to marginal effort. There is a lot of Rhino to write… If the 3D case is important for you, please give a detailed explanation of why, beyond “shouldn’t Rhino do this already?”.

Incidentally, the NURBS curve versions of circles are quite ugly things (they have bad parametrizations, their degree grows rapidly if you take derivatives, etc.). If it were me, I would probably prefer a nice degree 3 or higher B-splines with reasonably spaced knots. NURBS (as in, rational B-splines) cause all kinds of headaches later down the line.

Sam

Yes, I understand these cases now, many thanks.

Off the back of this; how does one ever expect a robust implementation of concentric constraints if Rhino cannot identify a circle?

I realise there are loads of other great features, and surfacing is finally getting some attention, but I think constraint is a very topical case for wanting correct circles.

Also, there are a few instances where export and selecting concentric cases is important.

@sfp
many thanks for your explanations and insights…

(cos(u)cos(v), sin(u)cos(v), sin(v))

… oh a sphere with R = 1 …

not sure if the results are really

but i remember the construction of 2 objects where I came across these issues:

vegetable peeler

bistro table base

priority ?

From my side it s more a “nice to have” and an academic / intellectual / educational attitude or approach. Nothing that needs a top level priority.
And we are talking about 2 aspects: intersection curves and trim curves.

intersections

I would appreciate if an intersection is a circle, it is technically a correct ArcCurve - not an approximation.

thanks for digging in - kind regards - tom