If you have a copy of the Rhino WIP, you might try `Rhino.Geometry.Curve.ExtremeParameters`

.

Hi Dale,

Thanks for your quick answer, as always! the point is I would like to do it for a Rhino 5 plugin.

I guess I will have to do it by approach

Thank you anyway.

Best regards

Hi,

Is there a solid way that gets you the precise max / min points? I’ve been looking for online literature about it but haven’t found anything useful. At the moment I am iteratively sampling the curve’s domain, so it can take a while to get a reasonable result…

There is a way - and we’ve added a method to RhinoCommon in the Rhino WIP to do this.

`Rhino.Geometry.Curve.ExtremeParameters`

Hi dale,

Thanks for that, I saw it mentioned somewhere else, but I’m not sure how to

get the newer Rhinocommon? Is the WIP mature enough to switch over? Or is

there a way to use the new Rhinocommon with Rhino 5?

Much thanks!

Tom Svilans, M. Arch.

m: +44 (0)75 1926 0882

e: tom.svilans@gmail.com

w: tomsvilans.com

## ···

On Thu, Mar 17, 2016 at 4:36 PM, Dale Fugier wrote:dale http://discourse.mcneel.com/users/dale McNeel

March 17tom_svilans:

Is there a solid way that gets you the precise max / min points?

There is a way - and we’ve added a method to RhinoCommon in the Rhino WIP

to do this.Rhino.Geometry.Curve.ExtremeParameters

## Visit Topic

http://discourse.mcneel.com/t/get-curve-maximum-curvature-points/28693/5

or reply to this email to respond## In Reply To

tom_svilans http://discourse.mcneel.com/users/tom_svilans

March 17

Hi, Is there a solid way that gets you the precise max / min points? I’ve

been looking for online literature about it but haven’t found anything

useful. At the moment I am iteratively sampling the curve’s domain, so it

can take a while to get a reasonable result…Visit Topic

http://discourse.mcneel.com/t/get-curve-maximum-curvature-points/28693/5

or reply to this email to respondTo stop receiving notifications for this particular topic, click here

http://discourse.mcneel.com/t/get-curve-maximum-curvature-points/28693/unsubscribe.

To unsubscribe from these emails, change your user preferences

http://discourse.mcneel.com/my/preferences

Ah, wasn’t aware of that. Cheers!

Tom Svilans, M. Arch.

m: +44 (0)75 1926 0882

e: tom.svilans@gmail.com

w: tomsvilans.com

## ···

On Thu, Mar 17, 2016 at 5:49 PM, Dale Fugier wrote:dale http://discourse.mcneel.com/users/dale McNeel

March 17tom_svilans:

Is the WIP mature enough to switch over?

Why don’t you ask those on Serengeti?

http://discourse.mcneel.com/c/serengeti

## Visit Topic

http://discourse.mcneel.com/t/get-curve-maximum-curvature-points/28693/7

or reply to this email to respond## In Reply To

tom_svilans http://discourse.mcneel.com/users/tom_svilans

March 17

Hi dale, Thanks for that, I saw it mentioned somewhere else, but I’m not

sure how to get the newer Rhinocommon? Is the WIP mature enough to switch

over? Or is there a way to use the new Rhinocommon with Rhino 5? Much

thanks! Tom Svilans, M. Arch. m: +44 (0)75 1926 0882 e:

tom.svilans@gmail.c…Visit Topic

http://discourse.mcneel.com/t/get-curve-maximum-curvature-points/28693/7

or reply to this email to respondTo stop receiving notifications for this particular topic, click here

http://discourse.mcneel.com/t/get-curve-maximum-curvature-points/28693/unsubscribe.

To unsubscribe from these emails, change your user preferences

http://discourse.mcneel.com/my/preferences

Hi there,

Sorry for resurrecting that thread, but there’s still something I don’t get with the ‘ExtremeParameters’ method.

What I want to achieve: get the curvature extremas parameters displayed by the ‘Curvature’ command (aka. max. curvature points, for both planar and 3D curves) into Rhinocommon.

Curve.ExtremeParameters requires a 3d vector:

What is that vector excatly for? The doc is not so much explaining IMO…

I understand, that this vector determines in which order the output parameters are sorted in the returned array, but I does not seem to be the case, as different vectors output completely different parameters arrays…

As a result, the ‘ExtremeParameters’ method always returns different points (round points) that the ‘Curvature’ command does (white squares):

Any explanation will be welcome!

Hi @jeffoulet

The functions need to know what axis to calculate the extreme points. For example, with the original image, the axis would be the world x-axis.

– Dale

Hi @dale,

Thank you for the explanation but I still have the feeling to be off the track…

Why does ‘ExtremeParameters’ require a direction vector as the Rhino ‘Curvature’ command is not prompting for anything?

The curve’s local maximum curvature locations should be independent from any direction: if I have two copies of one curve, but one of them rotated, the ‘Curvature’ command always indicates me the maximal curvature location to be at the same place:

Or maybe we are just not talking about the same thing?

What I definitely need is the Rhinocommon method underlying the Rhino ‘Curvature’ command.

Hi @jeffoulet.

`ExtremeParameters`

returns local extrema. The `Curvature`

command marks inflection points.

Does this help?

SampleCsExtractInflectionPoints.cs

– Dale

Hi @dale,

Many thanks, It helps a lot to understand the logic use to find the inflection points.

However, I’m looking for max. curvature positions (the white dots of the ‘Curvature’ command), both for 2D and 3D curves.

Here’s one proposed method:

It numerically constructs the hodograph of the curve and solves the locations of curvature extremes by geometrically finding the hodograph intersections with the x-axis.

I was wondering if there is any nicer method to get these points. I assume the ‘Curvature’ command does not proceed as the above proposed grasshopper definition.

Hi @jeffoulet,

Ah yes, sorry about that. Here is what you are looking for:

SampleCsExtractMinMaxRadiusPoints.cs

It seems reasonable that RhinoCommon would have curve methods that would do this for you. I’ve added the ‘wishes’ to the pile.

https://mcneel.myjetbrains.com/youtrack/issue/RH-53747

– Dale

Hi @dale,

Sorry for bumping this thread, but I just noticed some strange behavior: it seems that for some curves, some minimal radius points aren’t properly identified, see screenshot below:

- purple: inflection points
- black: min. radius point as per ‘GetMinMaxRadiusPoints’ method (here)

By doubling the number of points (l. 46), the point gets sometime marked, sometime not (higher factors required):

Sample curves: MinRadius_curves.3dm (45.6 KB)

Same issue occurs with the ‘Curvature’ Rhino command, where some points aren’t highlighted:

What would then be the appropriate factor, to ensure that no point gets omitted?

Thanks in advance

Hi @jeffoulet,

Are you using my sample code or are you using the new RhinoCommon methods? Can you post your curves and your code?

– Dale

Hi @dale,

I’m using the unmodified C# ‘SampleCsExtractMinMaxRadiusPoints.cs’ sample provided on github.

The ‘Curvature’ command in v6 also produce similar results.

If you consider the sample curve attached:

sample_curve.3dm (37.2 KB)

## Expected result:

- both curves’s start and end points should be marked (as they’re actual maximal curvature locations)

## Current result:

- only start point is marked and still slightly lies off the right location

As @spb rightly pointed out, certainly related to this: Inconsistent maximum curvature locations

After trying to dig in the code step by step, I think I understand that edge cases for curve’s start and end aren’t fully handled.

For instance at start point:

for i = 1, we have following situation:

Therefore

`bLeft = true`

and `bRight = true`

, we then go into this case:
```
if (bLeft && bRight)
{
if (FindMinRadius(nurb, t0, t2, kk1, epsilon, out var pt))
points.Add(pt);
}
```

…where the `FindMinRadius’ function seems to converge to the mid parameter between t0 and t2.

For end point, we have `kk0 < kk1 < kk2`

(also `bLeft && kk2 > kk1`

). I don’t see this case to be handled in the three if statements of the `GetMinMaxRadiusPoints`

function.

Here’s my dirty kinda-fix version that seems at least to output start and end points:

```
public static bool GetMinMaxRadiusPoints(Curve curve, List<Point3d> points, RhinoDoc doc)
{
var nurb = curve?.ToNurbsCurve();
if (nurb == null)
return false;
var start_count = points.Count;
var count = nurb.Points.Count * 8;
var mul = 1.0 / count;
var epsilon = nurb.Domain.Length > 1.0
? RhinoMath.ZeroTolerance
: nurb.Domain.Length * RhinoMath.ZeroTolerance;
var t0 = 0.0;
var t1 = 0.0;
var kk0 = 0.0;
var kk1 = 0.0;
for (var i = 0; i <= count; i++)
{
var t2 = nurb.Domain.ParameterAt(i * mul);
var k = nurb.CurvatureAt(t2);
//doc.Objects.AddPoint(nurb.PointAt(t2));
//doc.Views.Redraw();
if (k.IsValid)
{
var kk2 = k * k;
var bLeft = kk0 < kk1 - RhinoMath.ZeroTolerance;
var bRight = kk2 < kk1 - RhinoMath.ZeroTolerance;
if (bLeft && bRight)
{
if (FindMinRadius(nurb, t0, t2, kk1, epsilon, out var pt))
points.Add(pt);
}
else if (bLeft && kk2 < kk1 + RhinoMath.ZeroTolerance)
{
var t = nurb.Domain.ParameterAt((t1 + t2) * 0.5);
k = nurb.CurvatureAt(t);
if (k.IsValid)
{
double kk = k * k;
if (kk1 < kk - RhinoMath.ZeroTolerance)
{
if (FindMinRadius(nurb, t1, t2, kk, epsilon, out var pt))
points.Add(pt);
}
}
}
else if (bRight && kk0 < kk1 + RhinoMath.ZeroTolerance)
{
var t = nurb.Domain.ParameterAt((t0 + t1) * 0.5);
k = nurb.CurvatureAt(t);
if (k.IsValid)
{
var kk = k * k;
if (kk1 < kk - RhinoMath.ZeroTolerance)
{
if (FindMinRadius(nurb, t0, t1, kk, epsilon, out var pt))
points.Add(pt);
}
}
}
//---------------------------------------
//Check for last segment
else if (i == count)
{
if (FindMinRadius(nurb, t0, t2, kk2, epsilon, out var pt))
points.Add(pt);
}
//---------------------------------------
t0 = t1;
kk0 = kk1;
t1 = t2;
kk1 = kk2;
}
}
return points.Count - start_count > 0;
}
private static bool FindMinRadius(NurbsCurve nurb, double t0, double t1, double kk, double epsilon, out Point3d pt)
{
pt = Point3d.Unset;
Vector3d k;
var done = false;
if (null == nurb)
return false;
for (var i = 0; i < 10000; i++)
{
if (done || t1 - t0 < epsilon)
{
var t = (t0 + t1) * 0.5;
k = nurb.CurvatureAt(t);
pt = nurb.PointAt(t);
return k.IsValid;
}
var tl = t0 * 0.75 + t1 * 0.25;
k = nurb.CurvatureAt(tl);
if (!k.IsValid)
break;
done = tl == t0;
var kkl = k * k;
var tr = t0 * 0.25 + t1 * 0.75;
k = nurb.CurvatureAt(tr);
if (!k.IsValid)
break;
done = tr == t1;
var kkr = k * k;
if (kkl > kkr && kkl > kk)
{
kk = kkl;
t1 = (t0 + t1) * 0.5;
}
else if (kkr > kkl && kkr > kk)
{
kk = kkr;
t0 = (t0 + t1) * 0.5;
}
//---------------------------------------
//Case max. curvature is at start point
else if (kkl > kkr && kkl < kk)
{
t1 = (t0 + t1) * 0.5;
}
//Case max. curvature is at end point
else if (kkr > kkl && kkr < kk)
{
t0 = (t0 + t1) * 0.5;
}
//---------------------------------------
else
{
t0 = tl;
t1 = tr;
}
}
return false;
}
```

Please feel free to correct me if I’m telling nonsense, which is highly likely.

Hi @jeffoulet,

Can you review this and see if its related?

https://mcneel.myjetbrains.com/youtrack/issue/RH-56657

One thing I noticed is the local max curvature (per the Help file) is found where the curvature decreases on *both* sides, so dealing with curves that acclerate right to the end may be dodgy.

– Dale