The data structure of ON_SimpleArray

Dear Sir/Madam:

I have just test a C++ sample SampleSplitCurve and it runs well. But I am very confused about the data structure of ON_SimpleArray crv_t. After adding a line in the code, the output result is the same. For example I spilt a line for (1,1,0) to (1,11,0). The output is 0,2,4. Would you please explain me the problem and how to print the correct result of crv_t?

Many Thanks,
Meng

// The one and only CCommandSampleSplitCurve object
static class CCommandSampleSplitCurve theSampleSplitCurveCommand;

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

const CRhinoObjRef& crv_obj_ref = go.Object(0);
const CRhinoObject* crv_obj = crv_obj_ref.Object();
const ON_Curve* crv = crv_obj_ref.Curve();
if (0 == crv_obj || 0 == crv)
return CRhinoCommand::failure;

ON_SimpleArray crv_t;
CRhinoCommand::result rc = PickCurveParameters(context.m_doc, *crv, crv_t);
if (rc != CRhinoCommand::success)
return rc;

ON_3dmObjectAttributes atts(crv_obj->Attributes());

int i;
for (i = 0; i < crv_t.Count() - 1; i++)
{
RhinoApp().Print(L"Point = %f,%f,%f\n", crv_t[i,0], crv_t[i,1], crv_t[i,2]);
ON_Interval interval(crv_t[i], crv_t[i + 1]);
if (crv->Domain().Includes(interval))
{
ON_Curve* new_crv = ON_TrimCurve(crv, interval);
if (new_crv)
{
CRhinoCurveObject
new_crv_obj = new CRhinoCurveObject(atts);
new_crv_obj->SetCurve(new_crv);
context.m_doc.AddObject(new_crv_obj);
}
}
}

context.m_doc.DeleteObject(crv_obj_ref);
context.m_doc.Redraw();

return CRhinoCommand::success;
}

CRhinoCommand::result CCommandSampleSplitCurve::PickCurveParameters(CRhinoDoc& doc, const ON_Curve& crv, ON_SimpleArray& crv_t)
{
crv_t.Empty();

CRhinoGetCurvePoints gp;
gp.Constrain(crv);
int l_option = gp.AddCommandOption(RHCMDOPTNAME(L"Length"));
/int s_option =/ gp.AddCommandOption(RHCMDOPTNAME(L"Segments"));
CRhinoGet::result res = gp.GetPoints();
if (res == CRhinoGet::option)
{
const CRhinoCommandOption* option = gp.Option();
if (0 == option)
return CRhinoCommand::failure;
if (option->m_option_index == l_option)
return DivideCurveLength(doc, crv, crv_t);
else
return DivideCurveSegments(doc, crv, crv_t);
}
else if (res != CRhinoGet::point)
return CRhinoCommand::cancel;

ON_3dPointArray points;
int i, point_count = gp.Points(points);
for (i = 0; i < point_count; i++)
{
double t = 0;
if (crv.GetClosestPoint(points[i], &t))
crv_t.Append(t);
}

crv_t.Append(crv.Domain().Min());
crv_t.Append(crv.Domain().Max());
crv_t.QuickSort(&ON_CompareIncreasing);

return CRhinoCommand::success;
}


2
1

For others reading this, here is a link to the SDK sample.

cmdSampleSplitCurve.cpp

@Qingxiang - if you review this block of code:

ON_SimpleArray<double> crv_t;
CRhinoCommand::result rc = PickCurveParameters(context.m_doc, *crv, crv_t);
if (rc != CRhinoCommand::success)
  return rc;

Here, the command is declaring a simple array of doubles (crv_t). The array is passed to the PickCurveParameters function, which fills in the array with curve parameters (think parametric equation).

Because the array contains doubles, and not points, your print function should look like this:

int i;
for (i = 0; i < crv_t.Count() - 1; i++)
{
  RhinoApp().Print(L"Curve parameter = %f\n", crv_t[i]);

Hope this helps.

– Dale

@dale Thanks for your help. I find the crv_t is an array of the accumulated length of the curve.

I have another question. Can If I get the coordinates (x,y,z) of the segment points. Can the ON_SimpleArray be used store the coordinates?

I just use ON_3dPointArray to store the point array. Do you have any better suggestion.

Thanks for your help again!
Qinxiang

@dale I have tested the ON_SimpleArray<ON_3dPoint> m_my_array, it solve my problem perfactly.

Many thanks,
Qingxiang

No, “crv_t” is an array of curve parameters.

Parametric equation - Wikipedia

– Dale