Rhinocommon equivalent to _convert command, tolerances best practice

(Plug in for Rhino 7, Visual Studio 2019, c#)

Background

I am preparing curves for a CNC.
Tolerances / Accuracy vs. Minimum Amount of Data / Points matter a lot.
I can only send Polylines to the machine.
I do not care about computation time.

Rhino s _convert command has a simplify Option.

_convert Equivalent

It looks like the functionality exposed in rhino’s _convert command is split into 3 Rhinocommon methods:
Curve Simplify
ToArcsAndLines
ToPolyline
I am fine with that.
Or do I miss something ?

There is also Polyline ReduceSegements

Tolerances - best practice ?

my main question:
If I use Curve Simplify combined with ToPolyline - what s the best practice handling tolerances ?

I have a fixed amount of deviation that is allowed for the conversion to Polyline (example: 0.01 mm)
If I pass a fixed amount of deviation / tolerance to Simplify first, (example: 0.005 mm)
and the remaining deviation / tolerance (example: 0.005 mm) to ToPolyline second.
The second step (toPolyline) does not get the full local potential of reducing the data, if simplify did not used the full deviation at a certain point.

does rhino’s _convert command handles tolerances more intelligent ?
if yes what s the concept ?
is it exposed to rhinoCommon ?

My guess: passing a smaller amount of the overall tolerance to simplify (example 0.002) and a bigger amount to ToPolyline (example 0.008) will give an acceptable general case…
Or shall I skip the simplify step, create a very dense Polyline (ToPolyline, tolerance 0.001) and then ReduceSegemtnes (tolerance 0.009).

Thanks for your support - kind regards - tom

Hey @Tom_P,

It sounds like the _convert command would do everything you need it to do? If so, you could just use it via scripting and avoid having to reinvent anything.


public static Curve Simplify(RhinoDoc doc, Curve curve)
{
    Guid id = doc.Objects.Add(curve);
    RhinoApp.RunScript("_SelNone", false);
    doc.Objects.Select(id);
    RhinoApp.RunScript("_Convert S=Yes T=0.005 _enter", false);

    // Code to find the new simple curve object
    // Code to delete the simple curve object

    return simpleCurve;
}

– cs

thanks @CallumSykes

I try to keep as much geometry away from the document - and those curves will only be written to a cnc file.
I hate scripted methods - that will require the calling command has a “script-runner” attribute.

Any insights (my main question above) on how the overall tolerance is handled/distributed between the simplify and the toPolyline part of the _convert command ?

Hey @Tom_P ,

Sorry it’s not quite what you need, I know it’s not the cleanest way, but I figured it was worth asking.

I had a look through the code, but I cannot discern a simple answer for you. @dale might be able to though, sorry for roping you in Dale :wink:

– cs

Hi @Tom_P,

There are lots of ways to convert curves to polylines - perhaps to many. Here is the roadmap

The version of Curve.ToPolyline, with 4 parameters, and Curve.ToArcsAndLines both call the same underlying code as Rhino’s Convert command.

Curve Simplify is a lower-level function, used by the Convert command, thus called by the two above methods.

The two other versions of Curve.ToPolyline (with lots of parameters) calls code Rhino’s Pull command when pulling a curve to a mesh.

Polyline ReduceSegements is something used by Grasshopper. That’s about all I know.

If you’re using the methods used by the Convert command, the command help is a good resource.

– Dale

1 Like

@dale thanks a lot for digging in.
if i play around “with my curves” (some of them are already polylines) in rhino using the _convert command - I get best results when the simplify=yes option is set.

does your answer mean, that Curve Simplify is always call behind the scenes when I call Curve.ToPolyline ? (no need for arcs…)

maybe I am just confused that the rhino command has a simplify yes/no option, while the rhino common command does not have a matching parameter…

kind regards -tom

@dale
I still don t get the result I want:

convertCrvTest.3dm (5.5 MB)

starting with the blue Polyline with 12620 Pts
Rhino’s convert will result in in 1938 Pts

did not manage to reproduce this result with RhinoCommon’s Methods:

// #! csharp
using System;
using Rhino;
using Rhino.Input;
using Rhino.Input.Custom;
using Rhino.Geometry;
using Rhino.DocObjects;

// get Curve
ObjRef objRef;
Rhino.Commands.Result result = RhinoGet.GetOneObject("pick crv",false,Rhino.DocObjects.ObjectType.Curve, out objRef);
if (result != Rhino.Commands.Result.Success) return;
if (objRef == null) return;
//
CurveObject crvObj = objRef.Object() as CurveObject;
Curve crv = objRef.Curve();
RhinoDoc doc = objRef.Document;
// feedback - not working (??)
Rhino.RhinoApp.CommandPrompt = "prompt converting ...";
Rhino.RhinoApp.WriteLine("converting");
// distance to move
BoundingBox bbox = crv.GetBoundingBox(true);
double moveX = (bbox.Max.X - bbox.Min.X) * 1.2;
// settings
double dtolerance = 0.15;
double atolerance = Rhino.RhinoMath.ToRadians(15);
double minSegment = 3.0;
// Simplify
Curve simpleCrv = crv.Simplify(CurveSimplifyOptions.All,dtolerance,atolerance);
Transform xform = Transform.Translation(moveX,0,0);
Curve simpleCrvMoved = simpleCrv.DuplicateCurve();
simpleCrvMoved.Transform(xform);
doc.Objects.AddCurve(simpleCrvMoved, new ObjectAttributes(){Name = "simplify"});
// ReduceSegments
if (crv is PolylineCurve plCrv)
{
    Polyline pl = plCrv.ControlPolygon();
    pl.ReduceSegments(atolerance);
    Polyline plMoved = pl.Duplicate();
    Transform xform2 = Transform.Translation(moveX * 2,0,0);
    plMoved.Transform(xform2);
    doc.Objects.AddPolyline(plMoved,new ObjectAttributes(){Name = "reduced"});
}
// ToPolyline
PolylineCurve crvToPl = crv.ToPolyline(dtolerance,atolerance,minSegment,0);
// ---------------------------------------------------------------------------^-parameter maxLength not in documentation 0 to omit ?
if (crvToPl != null)
{
    Transform xform3 = Transform.Translation(moveX * 3,0,0);
    crvToPl.Transform(xform3);
    doc.Objects.AddCurve(crvToPl,new ObjectAttributes(){Name = "ToPolyline"});
}
// simplyfy and ToPolyline
PolylineCurve crvToPl2 = simpleCrv.ToPolyline(dtolerance,atolerance,minSegment,0);
if (crvToPl2 != null)
{
    Transform xform3 = Transform.Translation(moveX * 4,0,0);
    crvToPl2.Transform(xform3);
    doc.Objects.AddCurve(crvToPl2,new ObjectAttributes(){Name = "simplified and ToPolyline"});
}
doc.Views.Redraw();

thanks for your help.

kind regards - tom