Create custom spline definition in c++

Rhino uses NURBS geometry that is constructed from a set of control points, weights, and NURBS basis functions.

I’d like to know if its possible for me to create my own spline definition and use in Rhino that are defined through my own custom basis functions and grips (control points). If so, what would this take? And where can I begin learning how to go about implementing something like this?

Thank you,

Let me rephrase my question…

Lets say I have a special type of spline geometry in mind. I’d imagine when I build this definition, I would inherit from opennurbs_geometry virtual class.

This geometry has its own special routines to evaluate points, and has its own special grips / control points for manipulation.

How do I actually display the geometry as Rhino does for a NURBS surface?
I’m confused on how Rhino takes a geometry class and then draws it. What all is involved so that I can customize how this is done.

Take the NURBS surface for example. This inherits from the opennurbs geometry base class and provides all kinds of functions having to do with a NURBS surface. Where is the code that tells Rhino how to actually draw and display this in the viewport?

How does Rhino handle drawing / displaying in general? Are objects first added to the doc, then is something ilke draw() called for each object? Where is draw() implemented for a geometry class?

Hi @mike8,

The Rhino SDK allows you to create custom objects. But there are restrictions.

Custom objects must inherit from existing Rhino runtime object types. In your case, for example, a custom curve object would inherit from CRhinoCurveObject. There are a number of methods you can override, including CRhinoCurveObject::Draw. You can even implement your own custom grip handler.

When it comes to serializing objects, Rhino will only serialize objects it knows about. Thus, your custom object should save all custom data as user data. When Rhino opens a file with your custom objects, just look for objects with your user data and (when found) convert them to your custom runtime object.

The SDK samples on GitHub demonstrate some of what I mention. For example, the SampleMarker project demonstrates how to inherit a custom object from CRhinoGetPoint. The same technique can be used for inheriting from other Rhino types.

For custom grip support, see the cmdSampleCustomGrips.cpp command in the SampleCommands project.

– Dale


Thank you for the links, and the helpful response.

A couple of questions:

  1. Is it ever necessary or appropriate to inherit from ON_Object or one of its derived classes?

  2. If all Rhino objects must be derived from CRhinoObiect (or one of its derived classes), does this mean for any custom spline definition, in order to add it to the doc and display in the viewport, it must have a representation as a CRhinoObject or collection of CRhinoObjects?

Let me clarify through an example:

Take the T-splines plugin for example. A T spline would be a custom object. I’d expect that it could inherit from CRhinoSurfaceObject. Now, the T spline has its own evaluation routines, but are you saying these cannot be used to draw the T spline surface? And instead, in order to be drawn, the T spline must be decomposed into a collection of CRhinoObjects that rhino knows how to draw, such as rational bezier surfaces?

Hi @mike8,

You’ll want to derive a class from ON_UserData and store your custom object’s data on this.


The T-Splines implemenation used a CRhinoBrepObject-derived class, as there was a way to convert an ON_Brep to a T-Splines and back. In their custom object, they overrode CRhinoBrepObject::Draw to draw their geometry in the manner they chose.

However, in your case, if you spline object can be drawn as a Rhino curve (e.g NURBS for example), then you can just provide a NURBS representation and let Rhino draw your custom curve object just like it draws other NURBS curves. The advantage of this is that you won’t need to implement custom object picking.

– Dale


I just finished going through a few of those projects you linked. Thank you for putting those together.
I am wondering though… if I want to have Grasshopper support in my plugin, what is the best way to go about this?

Let’s take the SampleMarker project for example.

If I want to be able to go into grasshopper and:

  • be able to build one of those MarkerObjects from a grasshopper component
  • be able to reference a MarkerObject thats already on the Rhino Doc and contain that reference in a floating grasshopper parameter

then what is the best way to achieve this.

I know how to create GH components and GH params, but what I am not sure about is how to share the MarkerObject between the Rhino plugin and the Grasshopper plugin.

My initial thought is to create an identical c# class definition, CSMarkerObject that can be created through a component, and handle the conversion to the c++ MarkerObject when it is baked to the Rhino Doc. And then create a gh param that only accepts a rhino point object with the MarkerObject user data. When the param is filled, it creates a CSMarkerObject using the UserData attached to the MarkerObject on the Rhino Doc.

But maybe there’s a better way? Like using a .dll class export?

Hi @mike8,

Grasshopper, of course, is .NET based. So you could either try to recreate the custom object in .NET, or wrap up the C++ object so it can be accessed in in .NET by p/invoke. Wrapping this for .NET isn’t difficult. But it does take some effort.

On my GitHub site is a solution called Moose that somewhat demonstrates how to do all this. Wnen you have time, you might have a look at the solution.

– Dale

Got it. I’ve seen how you do it in Moose and think I understand how to go about it. Thank you for all the help.

Until next time…!

Hi, Fugier,
I create a markerobject and copy it in rhino,but the object turns to a point rather than the object itself!
what is the problem?

Hi @Panda_ASW,

Are you referring to this C++ sample?

If so, then I am unable to repeat what you are reporting.

If I build and load this plug-in, it works as expected when you copy a marker object.

What am I missing?

– Dale