Object UserData - RhinoCommon - Samples & Help


#1

Hi All,

I want to add object user data, specifically curve and point data, to a surface or BRep, and in my plug-in this data is represented by lists of curves and point3ds. I want to do this so that the user can move the surface/BRep around and save/load the document with that data intact, so that that data can be analysed using other bits of my plug-in.

I’ve looked at the UserData sample here: http://wiki.mcneel.com/developer/rhinocommonsamples/userdata. I have tried running the C# code for the UserData derived class through a C# to VB.Net converter, and have chopped it about to try to add the data I’m interested in, without success. To some extent I’m bogged down by the fact that my plug-in data is in list form, and the dictionary element of the sample doesn’t seem to support lists of curves/point3ds easily.

The page mentions using the UserDictionary as a way of storing data - is there a sample (preferably in VB.Net) somewhere showing the code/steps to utilise the dictionary? Similarly, is the UserDictionary the best way to store this data or should I continue to try to use a Custom UserData Class?

Thanks in advance.


(Menno Deij - van Rijswijk) #2

The dictionary in the sample is not what you should use to store a list of points. I would do something along the lines of:

// writing of a list of points:
IList<Point3d> list; // defined somewhere else
int nPoints = list.Count; 
archive.WriteInt(nPoints);
for(int i = 0; i < nPoints; ++i)
    archive.WritePoint3d(list[i]);


// reading of a list of points
int nPoints = archive.ReadInt();
List<Point3d> points = new List<Point3d>(nPoints);
for(int i = 0; i < nPoints; ++i)
    points.Add(archive.ReadPoint3d());

The write and read methods should be the same: what you put in should come out. If you want to create some version information on the data in the file, you can do this:

private const int Major = 0;
private const int Minor = 0;

// writing:
archive.Write3dmVersionChunk(Major, Minor);
// write the rest like above

// reading
int major = -1, minor = -1;
archive.Read3dmChunkVersion(out major, out minor);

if (major == 0 && minor == 0)
    // read the rest like above

Now, if your writing code changes in the future, you can increase the Major or Minor version number and create additional reading code. Any information out there that was written with the “old” way of writing is still readable with the “old” reading code.


#3

Works perfectly for adding points associated with the surface, after saving/loading. Thanks!

To add a list of curves as well, would I need to use a separate UserData Class with a system similar to that for the points, but with Read/Write for curves instead? I don’t actually see ReadCurve or WriteCurve in the SDK however - presumably I’d need WriteGeometry.

I have multiple lists of curves - but I can’t see how I would identify which bits of the UserData are what - e.g. when reading the Data, how does archive.ReadPoint3d() (and similar functions) know what bits to read?


(Menno Deij - van Rijswijk) #4

In that case you need to serialize

  1. if the curve is rational (boolean)
  2. the curve control point locations
  3. the curve control point weights
  4. the curve knot values

These values determine the curve completely. You can re-create the curve from these data.

The archive does not know which bits to read - you should know what went into the archive, and read it back in exactly the same order. Therefore I made the suggestion for versioning. If you version your data when writing it, you can read back the version first and decide based on the version how to further read the data.