I am facing a problem when using the C# component in Grasshopper and I can’t seam to figure out what I am doing wrong, except that there is something fuzzy going on with the data types.
I input a tree of points in the component. When I print out the DataType of one entry in the tree, like so:
iTree.Branch(path)[0].GetType()
it outputs
Rhino.Geometry.Point3d
which is expected. So far so good.
However, when I try to add this point into another list, like so:
List<Point3d> tempList = new List<Point3d>;
tempList.Add(iTree.Branch(path)[0]);
it gives me the following error message:
Converting "object" to "Rhino.Geometry.Point3d" not possible
and I don’t understand why my point is suddenly an “object” and not a “Point3d” anymore…
It would be great if someone could try to clarify this for me, because I have the feeling that the code is not the problem rather that I am missing something regarding data types.
What is happening there is called boxing. Which basically means to convert a value type to nd object, in other words a value type to a reference type. Hard to tell why this is happening in your file unless you share your code.
What a value really is and what the code thinks it is are two different things. A collection of Point3d structures can only contain points, because Point3d is an end of the line type; nothing inherits from Point3d.
On the other hand a collection of Rhino.Geometry.Curve instances can contain a number of different types. Maybe it’s filled only with LineCurve instances, maybe only NurbsCurve instances, maybe it contains only null values, or maybe it contains a mixture of all of these. It cannot however contain any Point3d values because that type does not derive from Curve.
A collection of GeometryBase data is even more flexible. It could contain curves, meshes, surfaces, extrusions, sub-d shapes, … However you still will not find any Point3d values in it, because Point3d does not derive from GeometryBase.
If you want a collection which can contain anything at all, you must base it on object, which is the base type for everything.
So, now we have a collection with an object constraint which contains as one of its elements a Point3d. You know it, I know it, your computer knows it when you ask it, but your code doesn’t know it. Your code is compiled before any actual collection is created and thus before it can contain genuine values of some type or other. Therefore your code won’t compile if it has to assume things which might not hold true at runtime.
Moving Point3d values from an object constrained collection into a Point3d constrained collection requires you specifically cast the value first:
List<Point3d> ConvertToPoints(List<object> values)
{
var points = new List<Point3d>();
foreach (var obj in values)
if (obj is Point3d)
points.Add((Point3d)obj);
return points;
}
I am trying to implement this in my code but am not sure where it would go. I start by getting points from a specific layer in the Rhino document, and then I need to convert them to Point3d to perform further operations. I am relatively new to coding so I would appreciate if anybody can really spell out the order of the code.
// Get Points from Rhino
Rhino.DocObjects.RhinoObject Pts = doc.Objects.FindByLayer(“pts”);