General philosophy behind Rhino - Python integration?


while I am further setting foot into the unknown grounds of the Rhino-Python integration I quite often feel that I stumble, because I am lacking the knowledge of some general principles of the Rhino-Python integration.

For example:

The SporphSpaceMorph creator requires point2D types as input for some parameters. However, I couldn’t find a creator for point2D. I used a workaround by creating a point3D and then rs.coerce2Dpoint(…) to make it work. So, either I just didn’t find the creator for the point2D (which means that some explanation would be helpful where to find what, i.e. the general philosophy of the class structure) or the creator is simply missing.

Another example:
I want to set the color of object I created. By default they have the color of the layer they’re placed in. Then you set the .Attributes.ObjectColor = System.Drawing.Color. and - nothing happens, because one has to set the ColorSource as well (which isn’t really obvious seen from outside). Then the search starts for the pre-defined property “ColorFromObject” which I finally found in Rhino.DocObjectsObjectAttributes.ColorSource.PropertyType.ColorFromObject.
This took a lot of guess work because the class tree in the Rhino online documentation doesn’t properly reflect the class structure in Python. In general: Quite often there are useful examples in C# but when I try to translate them into Python, the class structure doesn’t match.

Or another one:
When do I have to use .CommitChanges() to make changes visible after I changed something? Always after each change? Or possibly only after multiple changes to the same object? Do I always have to CommitChanges() for each object separately? Is there a general “CommitAll()”?

Is a Brep, for example, a RhinoObject? In some respect it appears to be (it has the attributes, for example), but with the geometry property I had difficulties. (The Python for Rhino5 introduction say that RhinoObjects have Object data, Object Attributes and Object Geometry.) The problem occurred when I got a list of RhinoObjects (that’s at least what the documentation says) using scriptcontext.doc.Groups.GroupMembers() and tried to access the Geometry object inside. This only worked using Rhino.DocObjects.RhinoObject.Geometry.GetValue(). I would have expected to access the geometry simply by “.(get)Geometry()”, for example. Having to go through a separate (static) method in a completely different class tree isn’t what I would have expected from an object oriented approach.

Thus, it appears that some general explanation why some things are implemented the way they are implemented would be very helpful.

Anyone feels up to the task to deliver something like that? Maybe a new version of the “Python for Rhinoceros 5” for Version 6? The cited text in my opinion focuses too much on Python basics (can be found elsewhere), special examples of limited use and general aspects of Nurbs etc. which can be found elsewhere too (however how to access the properties of Nurbs in Rhino-Python is of interest). The “uv” parameter space representation of 3D surfaces is probably useful since not normally known by users.
All the examples in this text are geared towards user interaction, but this is usually not what you want when you are automating things. Automating things usually means that you want to use a parametric geometry approach, i.e. defining geometry by parameters rather than by “point and click”.

I am sorry for writing such an extensive post, but I felt it to be necessary in order to explain what I meant with the “philosophy” behind the Rhino-Python integration aspects.

Kind regards,


You can look at the Rhinocommon api documentation to understand the underlying implementation and class structure hiding behind rhinoscriptsyntax. It is a dotNet project and I found /find it hard to get into, coming from a CPython background.

There are also developer samples and you can use this script to see specifically how each rhinoscriptsyntax method is implemented :slight_smile:


The problem for a newcomer is that the documentation is designed to present the minutiae, not provide any overview. It is laborious enough to follow the object hierarchy but getting a broad picture of the relationships between objects is completely impractical. One hopes the public bottom-up documentation is supplemented by top-down views private to Mcneel…


Agreed. This page starts well but lacks a good overview of the class structure / philosophy, unless I’ve missed it…

1 Like

Hi Junk,

I’d like to share some insight on how I learned to transition from only rhinoscriptsytax into RhinoCommon withing python.

Take the example of

I setup the script below and add a breakpoint :red_circle: before coercing the 2D point

If I hit start debugging after the stop at line 6 I can choose to step into the script:

This gets me to the script with the coercemethod and i see what happens there:
I notice how the Point2d is created by passing the x and y value like so:

return Rhino.Geometry.Point2d(point[0], point[1])

At lines below these x and y coordinates are retrieved from different properties depending on the type of argument for point.

So back to my initial script I know now how to directly create a Point2d:

import Rhino

my_point2d = Rhino.Geometry.Point2d(x,y)

Also notice how the editor provides help on the classes while writing them up:

In addition the left treeview is a great resource to find possible classes their methods properties etc:

I also have this link at hand to do searches find examples and additional info:



Hi all,

thanks for the helpful hints and sources of information.
Hopefully one of these days an employee of McNeel will find the time to write such an improve “Python for Rhinoceros 6”…


Hi B.

I’d like to point out how straightforward this is without the need to go other routes:

import scriptcontext as sc

rhino_objects = sc.doc.Groups.GroupMembers(0) #assuming  group present and not empty

for rhino_object in rhino_objects:
    geometry = rhino_object.Geometry
    print geometry

Have a look at this page for the ...Groups.GroupMembers() method

It clearly indicates the return value is an array of RhinoObjects with a direct link to this page:

There you see that one of the properties of that a RhinoObject has is Geometry

I’d say you don’t get a more object oriented approach than this.
Or am I misinterpreting what issues you have?


Hi Willem,

thanks, for your help. What you write was my first approach, but for
some reason it didn’t work.

Now, I tracked down what went wrong the frist time:

Apparantly I stumbled over the fact that in the C# example for the morph
usage, members are usually not directly assigned externally but received
by calling
a method as in

geom = objref.Geometry()|

In Python this is not the case:

geom = objref.Geometry|

But I still think an intro to the general concepts of the Python
integration with Rhino would be nice. :slight_smile:
For example: Why bother with rhinoscriptsyntax if everything is
available through the Rhino (common) .NET integration?

Thanks again,

Hi William,

a small addition: It wasn’t just me who screwed up this geometry assignment:

Look at the Python example there and you’ll find:

‘’’ for i in range(go.ObjectCount): objref = go.Object(i); g =
objref.Geometry(); unroll.AddFollowingGeometry(g) ‘’’ According to my
experience now, this example probably won’t work. Kind regards, B. |

I think this is to make life easier for people who are not familiar with object oriented programming. The scripting model is much easier and uses fewer lines of code for simple tasks.

The rhinoscriptsyntax set of functions are designed to mirror the methods provided by RhinoScript, so as to assist those wanting to migrate VBScript to Python. Of course, you don’t have to use them.

By the way, rhinoscriptsyntax is written in Python and just call into RhinoCommon. Here is the source code.

– Dale

1 Like

The clue is in the name :smiley: