Can not Explode Curve in c++

Hi;

 static ON_SimpleArray<ON_NurbsCurve*> ExplodeCurve(const ON_Curve* curv)
{
	ON_SimpleArray<ON_NurbsCurve*> exCurve;
	if (curv != nullptr)
	{
		const ON_PolyCurve* poly = ON_PolyCurve::Cast(curv);
		if (poly != nullptr)
		{
			ON_PolyCurve* poly1 = const_cast<ON_PolyCurve*>(poly);
			if (poly1 != nullptr)
			{
				if (poly1->Count() <= 1)
				{
					ON_Curve* crvOut = poly1->SegmentCurve(0);
					if (crvOut != nullptr)
						exCurve.Append(crvOut->NurbsCurve());
				}
				else
				{
					for (int i = 0; i < poly1->Count(); i++)
					{
						ON_Curve* crvOut = poly1->SegmentCurve(i);
						if (crvOut != nullptr)
							exCurve.Append(crvOut->NurbsCurve());
					}
				}
			}
		}
		else
		{
			ON_SimpleArray<ON_Curve*> out;
			RhinoDuplicateCurveSegments(curv, out);
			if (out.Count() == 0)
			{
				exCurve.Append(curv->NurbsCurve());
			}
			else
			{
				int outcv = 0;
				for (int i = 0; i < out.Count(); i++)
				{
					if (out[i] != nullptr)
					{
						exCurve.Append(out[i]->NurbsCurve());
					}
				}
			}
		}
	}
	return exCurve;
};
CRhinoCommand::result CCommandTest::RunCommand(const CRhinoCommandContext& context)
{
	CRhinoGetObject go;
	go.SetGeometryFilter(CRhinoGetObject::curve_object);
	go.EnableSubObjectSelect(FALSE);
	go.SetCommandPrompt(L"Select Curve");
	go.EnableGroupSelect(FALSE);
	getind();
	CRhinoGet::result res = go.GetObjects(1, 1);
	if (go.CommandResult() != CRhinoCommand::success)
	{
		return CRhinoCommand::success;
	}

	ON_SimpleArray<ON_NurbsCurve*> exCurve = ExplodeCurve(go.Object(0).Curve());
	RhinoApp().Print(L"%d\n", exCurve.Count());
	RhinoApp().ActiveView()->Redraw();
	return CRhinoCommand::success;
}

why my code can not Explode Curve but the command _Explode is ok ?
Crv Can Not Explode.3dm (26.0 KB)

Hi @suc_kiet,

Try this:

CRhinoCommand::result CCommandTestSucKiet::RunCommand(const CRhinoCommandContext& context)
{
  CRhinoGetObject go;
  go.SetCommandPrompt(L"Select curve to explode");
  go.SetGeometryFilter(CRhinoGetObject::curve_object);
  go.EnableSubObjectSelect(FALSE);
  go.GetObjects(1, 1);
  if (go.CommandResult() != CRhinoCommand::success)
    return CRhinoCommand::success;

  const CRhinoObjRef& objref = go.Object(0);
  const CRhinoCurveObject* pCurveObj = CRhinoCurveObject::Cast(objref.Object());
  if (nullptr == pCurveObj)
    return CRhinoCommand::failure;

  ON_SimpleArray<CRhinoObject*> segments;
  const int segment_count = pCurveObj->GetSubObjects(segments);
  if (segment_count > 0)
  {
    for (int i = 0; i < segment_count; i++)
      context.m_doc.AddObject(segments[i]);
    context.m_doc.DeleteObject(objref);
    RhinoApp().Print("Exploded curve into %d segments.\n", segment_count);
  }
  else
  {
    RhinoApp().Print("Cannot explode curve.\n");
  }
  context.m_doc.Redraw();

  return CRhinoCommand::success;
}

– Dale

Hi @dale ,
Your code works great.
If I want to change the CRhinoObject in segments list to ON_NurbsCurve but don’t want to use context.m_doc.AddObject(), how can I do?

for (int i = 0; i < segment_count; i++)
{
	if (nullptr != segments[i])
	{
		CRhinoObjRef ref1(segments[i]->Id());
		ON_NurbsCurve* nurbs = ref1.Curve()->NurbsCurve();
	}
}

This code not work.

Hi @suc_kiet,

Maybe something like this:

/// <summary>
/// Gets the sub-curves of a Rhino curve object.
/// </summary>
/// <param name="curve_obj">The curve object.</param>
/// <param name="bIncludeSingle">
/// If true and the curve does not have sub-curves, then
/// add a copy of the input curve to the output array.
/// If false and the curve does not have sub-curves, the
/// do nothing.
/// </param>
/// <param name="sub_curves">The output curve array.</param>
/// <returns>The number of curves added to the output curve array.</returns>
/// <remarks>
/// CRITICAL: Memory for the curves in the output array is allocated and
/// becomes the responsibility of the caller.
/// </remarks>
int RhinoGetSubCurves(
  const CRhinoCurveObject* curve_obj, 
  bool bIncludeSingle, 
  ON_SimpleArray<ON_Curve*>& sub_curves
)
{
  const int sub_curve_count = sub_curves.Count();
  if (nullptr != curve_obj)
  {
    ON_SimpleArray<CRhinoObject*> sub_objects;
    const int sub_object_count = curve_obj->GetSubObjects(sub_objects);
    if (sub_object_count > 0)
    {
      for (int i = 0; i < sub_object_count; i++)
      {
        CRhinoCurveObject* sub_curve_obj = CRhinoCurveObject::Cast(sub_objects[i]);
        if (nullptr == sub_curve_obj)
          continue;

        const ON_Curve* sub_curve = sub_curve_obj->Curve();
        if (nullptr != sub_curve)
        {
          ON_Curve* duplicate = sub_curve->DuplicateCurve();
          if (nullptr != duplicate)
            sub_curves.Append(duplicate);
        }

        delete sub_objects[i]; // Don't leak...
        sub_objects[i] = nullptr;
      }
    }
    else if (bIncludeSingle)
    {
      const ON_Curve* curve = curve_obj->Curve();
      if (nullptr != curve)
      {
        ON_Curve* duplicate = curve->DuplicateCurve();
        if (nullptr != duplicate)
          sub_curves.Append(duplicate);
      }
    }
  }

  // Return number added
  return sub_curves.Count() - sub_curve_count;
}

You can use it like this:

CRhinoCommand::result CCommandTest::RunCommand(const CRhinoCommandContext& context)
{
  CRhinoGetObject go;
  go.SetCommandPrompt(L"Select curve to explode");
  go.SetGeometryFilter(CRhinoGetObject::curve_object);
  go.EnableSubObjectSelect(FALSE);
  go.EnableGroupSelect(FALSE);
  go.GetObjects(1, 1);
  if (go.CommandResult() != CRhinoCommand::success)
    return CRhinoCommand::success;

  const CRhinoObjRef& objref = go.Object(0);
  const CRhinoCurveObject* curve_obj = CRhinoCurveObject::Cast(objref.Object());
  if (nullptr == curve_obj)
    return CRhinoCommand::failure;

  ON_SimpleArray<ON_Curve*> sub_curves;
  const int sub_curve_count = RhinoGetSubCurves(curve_obj, false, sub_curves);
  if (sub_curve_count > 0)
  {
    for (int i = 0; i < sub_curve_count; i++)
    {
      ON_Curve* sub_curve = sub_curves[i];
      if (nullptr != sub_curve)
      {
        CRhinoCurveObject* sub_curve_obj = new CRhinoCurveObject();
        sub_curve_obj->SetCurve(sub_curve);
        sub_curves[i] = nullptr;
        context.m_doc.AddObject(sub_curve_obj);
      }
    }
    context.m_doc.DeleteObject(objref);
    RhinoApp().Print("Exploded curve into %d segments.\n", sub_curve_count);
  }
  else
  {
    RhinoApp().Print("Cannot explode curve.\n");
  }
  context.m_doc.Redraw();

  return CRhinoCommand::success;
}

– Dale

Thank you @dale