Serialisation of GeometryBase Types


(Dimitrie) #1

You’re going to get this question, sooner or later :slight_smile:
I’ve successfully created a mesh from a cone, all from calls to the server. But the mesh looks like:

 {
    "version": 10000,
    "archive3dm": 60,
    "opennurbs": -1945343931,
    "data": "+n8CAEAJAAAAAAAA+/8CABQAAAAAAAAA5NTXTkfp0xG/5QAQgwEi8C25G1z8/wIACAkAAAAAAAA4YwAAAEAAAAAAAAA..."
}

Your classic base64 blob, that doesn’t decode to an ideal “vertices” “faces” etc. I think this is a deeper serialisation question of the rhino/open nurbs data types, so i’m willing to get lessons thrown at me!


(Steve Baer) #2

This is how we serialize our RhinoCommon.Geometry.GeometryBase data types. If you were using Rhino3dmIO and C#, the data would have been automatically deserialized into a Rhino.Geometry.Mesh class. Since you are playing in a different sandbox, you would need to make additional calls to the compute server to get information about the mesh.


(Dimitrie) #3

I’ve changed the title, now that my question is a bit more clear in my head: is there a chance/what would it take so that serialisation of GeometryBase types could be made more transparent/readable and sandbox independent?

I know this is not an easy one!


(Steve Baer) #4

We may be able to set up some sort of API where you request specific properties to be returned; maybe some sort of GraphQL type system. Maybe the API can be set up so you can chain things together to return the properties that you want to work with.

Any ideas on what a good API would look like for this?


(Dimitrie) #5

Maybe just a simple query string? for example getting the faces and vertices of a brep’s displayValue. All you need to do is append ?fields=type,displayValue.vertices,displayValue.faces to your query.

Graphql can be cool, but for starters imho a simple ?fields=vertices,normals or the corollary ?omit=normals would be amazing.


(Steve Baer) #6

I like that idea. I’ll see if I can get something like this wired up where you can specify for all of datatype X returned, give me [X.Vertices, X.Normals, X.Faces] instead. Something like

?return.Mesh=Vertices,Normals,Faces&return.Curve=Length,BoundingBox


(Steve Baer) #7

Wow, that worked a lot easier that I thought it would. You can now pass a querystring of ?return.ObjectTpe=Property1,Property2,...

Here is a sample for getting the diameter from two circles

curl -H "api_token: steve@mcneel.com" -H "Content-Type: application/json" 
-d '[[{"X":1.0,"Y":2.0,"Z":3.0},12],[{"X":1.0,"Y":2.0,"Z":4.0},30]]' 
"https://compute.rhino3d.com/Rhino/Geometry/Circle/New?multiple=true&return.Circle=Diameter"

Here is a sample for getting Vertices and Faces from a computed mesh (note, I need to clean up JSON serialization for bounding boxes, planes, circles, arcs, and spheres still). This one is a sphere so it is still a little ugly.

curl -H "api_token: steve@mcneel.com" -H "Content-Type: application/json" 
-d '[{"IsValid":true,"BoundingBox":{"IsValid":true,"Min":{"X":-11.0,"Y":-10.0,"Z":-9.0},"Max":{"X":13.0,"Y":14.0,"Z":15.0},"Center":
{"X":1.0,"Y":2.0,"Z":3.0},"Area":3456.0,"Volume":13824.0,"Diagonal":
{"X":24.0,"Y":24.0,"Z":24.0}},"Diameter":24.0,"Radius":12.0,"EquitorialPlane":{"Origin":
{"X":1.0,"Y":2.0,"Z":3.0},"XAxis":{"X":1.0,"Y":0.0,"Z":0.0},"YAxis":{"X":0.0,"Y":1.0,"Z":0.0},"ZAxis":
{"X":0.0,"Y":0.0,"Z":1.0},"Normal":{"X":0.0,"Y":0.0,"Z":1.0}},"EquatorialPlane":{"Origin":
{"X":1.0,"Y":2.0,"Z":3.0},"XAxis":{"X":1.0,"Y":0.0,"Z":0.0},"YAxis":{"X":0.0,"Y":1.0,"Z":0.0},"ZAxis":
{"X":0.0,"Y":0.0,"Z":1.0},"Normal":{"X":0.0,"Y":0.0,"Z":1.0}},"Center":
{"X":1.0,"Y":2.0,"Z":3.0},"NorthPole":{"X":1.0000000000000007,"Y":2.0,"Z":15.0},"SouthPole":
{"X":1.0000000000000007,"Y":2.0,"Z":-9.0}},10,10]' 
"https://compute.rhino3d.com/Rhino/Geometry/Mesh/CreateFromSphere?return.Mesh=Vertices,Faces"

(Steve Baer) #8

I updated compute.rhino3d.com yesterday to have the JSON passed around be a little cleaner for more data types. The above sample for get mesh vertices and faces now looks like

curl -H "api_token: steve@mcneel.com" -H "Content-Type: application/json" 
-d '[{"EquatorialPlane":{"Origin":{"X":1.0,"Y":2.0,"Z":3.0},"XAxis":
{"X":1.0,"Y":0.0,"Z":0.0},"YAxis":{"X":0.0,"Y":1.0,"Z":0.0},"ZAxis":
{"X":0.0,"Y":0.0,"Z":1.0}},"Radius":12.0}, 10, 10]' 
"https://compute.rhino3d.com/Rhino/Geometry/Mesh/CreateFromSphere?return.Mesh=Vertices,Faces"

(Steve Baer) #9

Well, unfortunately that change broke serialization for some plug-ins.
https://discourse.mcneel.com/t/rhino-6-4-point3f-vector3f-deserialization/60120

I’ll find a different way to clean the JSON being passed around.


(Dimitrie) #10

I don’t have access to that topic! But you’ve thought of [JsonIgnore] decorators? If the backend uses JsonConvert…


(Steve Baer) #11

Oops, that was a private post from a plug-in developer reporting that the serialization changes broke their file IO. I don’t want to use the JsonIgnore attributes as that would require a reference to Json.NET to be added to RhinoCommon and I want to keep RhinoCommon dependencies to only assemblies that are included with the .NET framework.

There are other serialization mechanisms that Json.NET provides that I’m pretty sure I can make it work. The ISerializable implementation would have made this very easy, but it breaks the Rhino SDK so it can’t be done.