Rhino document objects are constant

Question: I’ve written the following function, which appends a point to an existing Rhino point cloud object:

bool AppendToRhinoPointCloudObject(
  unsigned int doc_runtime_sn,
  unsigned int obj_runtime_sn,
  double x, double y, double z
)
{
  bool rc = false;
  const CRhinoObject* obj = CRhinoObject::FromRuntimeSerialNumber(doc_runtime_sn, obj_runtime_sn);
  if (nullptr != obj)
  {
    const CRhinoPointCloudObject* pcObject = CRhinoPointCloudObject::Cast(obj);
    if (nullptr != pcObject)
    {
      const ON_PointCloud& pc = pcObject->PointCloud();
      pc.m_P.Append(ON_3dPoint(x, y, z)); // Add
      rc = true;
    }
  }  
  return rc;
}

However, when I build the project, I am getting the following compiler error:

error C2663: 'ON_SimpleArray<ON_3dPoint>::Append': 2 overloads have no legal conversion for 'this' pointer

Answer: Rhino documents are constant. That is, they cannot be directly modified.

The process for modifying a document object is:

1.) Get the Rhino object.
2.) Make a copy of the Rhino object’s geometry.
3.) Modify the copy of the geometry.
4.) Modify the Rhino object, to use the new geometry, by calling CRhinoDoc::ReplaceObject.

Here is how you might consider modifying the above function:

unsigned int AppendToRhinoPointCloudObject(
  unsigned int doc_runtime_sn,
  unsigned int obj_runtime_sn,
  double x, double y, double z
)
{
  unsigned int rc = 0;

  ON_3dPoint point(x, y, z);
  if (!point.IsValid())
    return rc;

  CRhinoDoc* doc = CRhinoDoc::FromRuntimeSerialNumber(doc_runtime_sn);
  if (nullptr == doc)
    return rc;

  const CRhinoObject* obj = doc->LookupObjectByRuntimeSerialNumber(obj_runtime_sn);
  if (nullptr == obj)
    return rc;

  const ON_PointCloud* pc_old = ON_PointCloud::Cast(obj->Geometry());
  if (nullptr == pc_old)
    return rc;

  const bool bHasPointColors = pc_old->HasPointColors();
  const bool bHasPointNormals = pc_old->HasPointNormals();

  ON_PointCloud pc_new(*pc_old); // Copy
  pc_new.m_P.Append(point); // Add
  if (bHasPointColors)
  {
    if (obj->Attributes().ColorSource() == ON::color_from_object)
    {
      pc_new.m_C.Append(obj->Attributes().m_color);
    }
    else
    {
      ON_3dmObjectAttributes def_attr;
      doc->GetDefaultObjectAttributes(def_attr);
      pc_new.m_C.Append(def_attr.m_color);
    }
  }
  if (bHasPointNormals)
      pc_new.m_N.Append(ON_3dVector::UnsetVector);

  CRhinoPointCloudObject* pc_new_obj = new CRhinoPointCloudObject();
  pc_new_obj->SetPointCloud(pc_new);

  bool res = doc->ReplaceObject(CRhinoObjRef(obj), pc_new_obj);
  if (res)
    rc = pc_new_obj->RuntimeSerialNumber(); // Return replacement object runtime serial number
  else
    delete pc_new_obj; // Don't leak

  return rc;
}

Hope this helps.

– Dale

1 Like