[C++] ON_PolylineCurve closes my curve when I don't want to

Hello,

My plugin generates a series of point segments that eventually form a polyline (the segments are not sorted wrt curve parameter t). To interact with them as a single Rhino object, I use an empty ON_PolylineCurve to which I add the segments with Append.

The problem is that Rhino is closing the curve, with a straight line between the end points.
For example, I have segments [A,B], [B, C] and [C, D] forming a polyline. If I append them in this order: [C, D], [A, B], [B, C], Rhino will add a line between A and D.

How can I prevent this? Maybe the solution would be to sort the segments wrt parameter t, but I don’t really know the way to do it.

Many thanks,
Pablo

Hi @pagarcia,

Can you provide a simple example that repeats this?

– Dale

To interact with them as a single Rhino object

Would an alternative be to group them?

Hi Menno,

How do you group objects in the C++ SDK?

Pablo

Something along the lines of

    ON_SimpleArray<const CRhinoObject*> groupMembers;

    // this is where your line pieces should be
    const int nLines(10); 
    ON_Line lines[nLines];

    // add each line as an individual curve and store its rhino-object pointer
    for(int i = 0; i < nLines; ++i)
    {
        const CRhinoObject* pObj = context.m_doc.AddCurveObject(lines[i]);
        if (pObj)
        {
            groupMembers.Append(pObj);
        }
    }

    // create a group with an unused name (this will avoid problems with existing groups)
    ON_Group g;
    ON_wString groupName;
    context.m_doc.m_group_table.GetUnusedGroupName(groupName);
    g.SetGroupName(groupName);    

    // use the object pointers to define a new group
    context.m_doc.m_group_table.AddGroup(g, groupMembers);

Thank you Menno! I’m not into groups yet but I’ll take a look.

Pablo

Hi @dale,

Here I attach an example reproducing it. I have the points A, ab, B, bc, C, cd, D (sorry if the notation is confusing) forming the segments [A,B], [B, C], [C, D] and I want a PolylineCurve joining them, regardless the order in which I append the segments.

This piece of code does it well:

ON_3dPoint A(0.0, 0.0, 0.0);
ON_3dPoint ab(0.25, 0.1, 0.0);
ON_3dPoint B(0.5, 0.5, 0.0);
ON_3dPoint bc(0.75, 0.9, 0.0);
ON_3dPoint C(1.0, 1.0, 0.0);
ON_3dPoint cd(1.5, 0.5, 0.0);
ON_3dPoint D(2.0, 0.0, 0.0);

ON_3dPointArray segmentAB; segmentAB.Append(A); segmentAB.Append(ab); segmentAB.Append(B);
ON_3dPointArray segmentBC; segmentBC.Append(B); segmentBC.Append(bc); segmentBC.Append(C);
ON_3dPointArray segmentCD; segmentCD.Append(C); segmentCD.Append(cd); segmentCD.Append(D);

ON_SimpleArray<ON_PolylineCurve*> curves(3);
ON_PolylineCurve* joinedCurve = new ON_PolylineCurve();

curves[0] = new ON_PolylineCurve(segmentAB);
curves[1] = new ON_PolylineCurve(segmentBC);
curves[2] = new ON_PolylineCurve(segmentCD);

joinedCurve->Append( *curves[0] );
joinedCurve->Append( *curves[1] );
joinedCurve->Append( *curves[2] );

CRhinoCurveObject* curveObject = new CRhinoCurveObject();
curveObject->SetCurve( joinedCurve );
context.m_doc.AddObject( curveObject );
context.m_doc.Redraw();

as it gives the right polyline curve:

However, in my plugin most usually the segments are not sorted. So, I usually have, for example, this change in the code, appending first [C, D] and then [A, B], [B, C]:

joinedCurve->Append( *curves[2] );
joinedCurve->Append( *curves[0] );
joinedCurve->Append( *curves[1] );

then the polyline does this weird change:

Do you know what could be happening? Maybe I’m obliged to put the segments in the right order of parameterization?

Many thanks,
Pablo

DemoPolylineCurve.zip (12.0 MB)

Hi @pagarcia,

ON_PolylineCurve::Append isn’t fancy. All it does is remove the last point, in the polyline curve’s array of points, and then appends the points from the input curve. So the order you append curves does matter.

If you don’t want to pay attention to orders, then just join the curve segments.

ON_3dPoint A(0.0, 0.0, 0.0);
ON_3dPoint ab(0.25, 0.1, 0.0);
ON_3dPoint B(0.5, 0.5, 0.0);
ON_3dPoint bc(0.75, 0.9, 0.0);
ON_3dPoint C(1.0, 1.0, 0.0);
ON_3dPoint cd(1.5, 0.5, 0.0);
ON_3dPoint D(2.0, 0.0, 0.0);

ON_3dPointArray segmentAB; segmentAB.Append(A); segmentAB.Append(ab); segmentAB.Append(B);
ON_3dPointArray segmentBC; segmentBC.Append(B); segmentBC.Append(bc); segmentBC.Append(C);
ON_3dPointArray segmentCD; segmentCD.Append(C); segmentCD.Append(cd); segmentCD.Append(D);

ON_SimpleArray<const ON_Curve*> curves(3);
curves.Append(new ON_PolylineCurve(segmentAB));
curves.Append(new ON_PolylineCurve(segmentBC));
curves.Append(new ON_PolylineCurve(segmentCD));

double tol = 2.1 * context.m_doc.AbsoluteTolerance();
ON_SimpleArray<ON_Curve*> out_curves;

BOOL rc = RhinoMergeCurves(curves, out_curves, tol);

for (int i = 0; i < curves.Count(); i++)
  delete curves[i]; // Don't leak...

if (rc)
{
  for (int i = 0; i < out_curves.Count(); i++)
  {
    CRhinoCurveObject* curveObject = new CRhinoCurveObject();
    curveObject->SetCurve(out_curves[i]);
    context.m_doc.AddObject(curveObject);
  }
  context.m_doc.Redraw();
}

– Dale

Thank you Dale! I also found a way to order them.

Pablo