Skip to content
October 18, 2011 / stevebaer

Python Goodies – the sorted function

There are so many nice little features of python. Here’s a good one to learn; the sorted function.

sorted(iterable[, cmp[, key[, reverse]]])
This function takes a list and returns a sorted version of the list. That’s nice…… but I wouldn’t write a blog post about this if that was all this function does. Here’s what I really like about the sorted function, the optional key argument. This argument lets you define a function that tells the sorted function what to use to compare different entries in the list.

I recently attended a Rhino python workshop and a student with a background in RhinoScript was putting together a python script that sorted a bunch of curves based on the Z height of each curve’s start point. This isn’t necessarily hard to do, but it does involve quite a few lines of script to write the sorting routine, and you can potentially write very slow scripts if you aren’t careful about your sorting algorithm.

Here’s how this script could be written in python using the sorted function along with the key parameter. The function asks you to select a bunch of curves and then adds text dots to the start point of every curve sorted by the curve’s start point Z height

import rhinoscriptsyntax as rs

def curvekey(curve):
    point = rs.CurveStartPoint(curve)
    return point[2]

def SortCurvesByZ():
    curves = rs.GetObjects("Select Curves", rs.filter.curve)
    if not curves: return
    sorted_curves = sorted(curves, key=curvekey)
    for i, curve in enumerate(sorted_curves):
        point = rs.CurveStartPoint(curve)
        rs.AddTextDot(i+1, point)

if __name__=="__main__":

Here’s a breakdown of what is happening.

  1. GetObjects is called so that the user can select a bunch of curves
  2. Once we a list, we call the sorted function passing the curves and using the named parameter of key=curvekey
  3. sorted() goes about its job of sorting the list, but since the key parameter was set it knows to call the curvekey function to get a value to use for comparison when sorting.
  4. We defined curvekey as a function that takes a single input parameter. This is what the key parameter in sorted is expecting; a function that takes a single parameter and returns some sort of value that it knows how to compare. curvekey is called for every item in the list and we return a floating point number (the z height of the start point). The floating point number returned is what sorted uses to compare each item’s “value”
  5. sorted returns a new list of curves that are now in sorted order. We just walk through the new list and add text dots so we can see that things are working.

Pretty darn useful function to keep in your python toolbox!

June 27, 2011 / stevebaer

Numpy and Scipy in RhinoPython

Disclaimer: I have very little experience with numpy and scipy so you are going to do better by searching google for support with these libraries. This blog is about getting these libraries to run in Rhino.

Yes it is possible now!!!
Okay, here’s what I did to get numpy/scipy running in Rhino

1 – Install Rhino 5 (32bit version)
numpy/scipy uses C++ DLLs which need to be compiled for a specific platform. Currently numpy/scipy for IronPython will only run in 32bit applications on Windows. I contacted the guys at Enthought and they do plan on releasing a 64bit version for Windows, but they want to make sure everything is working on 32bit first. They have some doubts about being able to release a mono version for you Mac guys out there.

2 – Install numpy/scipy for IronPython
Follow the instructions on this site

3 – Modify settings in RhinoPython
Start Rhino 5 – 32bit version and run “EditPythonScript” to bring up the editor. Go to the options dialog by selecting Tools->Options from the menu

Add site-packages and DLLs to the search paths (see image). This helps RhinoPython find the numpy/scipy packages and associated DLLs.

Check the “Frames Enabled” option since numpy/scipy requires this to be turned on.
I decided to make the “Frames Enabled” an optional engine feature since it does have a performance impact on scripts. Numpy/scipy requires this feature to be turned on.

4 – Run a test

# For now, we need to manually load mtrand before using numpy or scipy
# I'm still trying to figure out why mtrand is not automatically getting
# loaded when numpy/scipy imports it.  If I can fix this, we won't need
# the following two lines
import clr

import numpy
import rhinoscriptsyntax as rs

x_coord = [  0,  1,  2,  3,  4,  5,  6]
y_coord = [0.0,0.1,0.5,2.5,2.5,2.5,4.0]
xyz = zip(x_coord,y_coord,[0]*len(x_coord))

degree = 5
eq = numpy.polyfit(x_coord, y_coord, degree)
fitfunc = numpy.poly1d(eq)

fit_points = []
for i in range(61):
    x = i/10.0
    y = fitfunc(x)
    fit_points.append((x, y, 0))

If you get a polyline in rhino fit through a series of points then you are all all set; if not go back to step 1 and repeat.

This looks like a good place to start if you want to learn more about numpy/scipy

June 17, 2011 / stevebaer

Kinect SDK

YES!!! This could lead to some incredible applications.

Now if they only had a version that clipped to your monitor and tracked your fingers…

June 2, 2011 / stevebaer

Outside the Box 2 – Calling the Shapeways API from Python

I received a question on accessing the ShapeWays API from my last “Outside the Box” blog and figured I should dig in and figure out what is going on. Shapeways has a web service API that uses SOAP and a WSDL page ( as described here

This API is a bit different than the REST API which I wrote a script to access in my previous blog post. In order to use this API, I ended up modifying a script originally put together by Michael Foord (author of “IronPython in Action”) that creates a .NET assembly on the fly for a given WSDL url.

The two scripts are in gists at the end of this post

Place both of these scripts in the same directory and open the “” script. Here’s the script itself

"""Sample script that accesses the shapeways API
import wsdlprovider

wsdl_url = ""
username = "username"
password = "password"
application_id = "rhinotest"

assembly = wsdlprovider.GetWebservice(wsdl_url)
shapeways = assembly.SWwsdlService()
session_id = shapeways.login(username, password, application_id)
if session_id:
    #get list of printers available
    printers = shapeways.getPrinters(session_id, "", application_id)
    if printers:
        for printer in printers:
            print "printer:", printer.title
            for material in printer.materials:
                print " - material ", material.title

The script uses the wsdlprovider script to generate a .NET assembly from the shapeways wsdl url. This assembly has a class in it called SWwsdlService which we create an instance of and call functions on. It looks like a normal class to python, but all of the function calls are sent to ShapeWays over the internet and response are turned into classes that you can use. This sample simply logs into shapeways to get a “session id” and then asks Shapeways for a list of it’s available printers along with what materials each printer supports.

At the time of this blog post, the printed output from this script is

printer: Somatech FDM
- material Grey Robust
printer: Somatech Objet 720
- material Black Detail
- material White Detail
- material Transparent Detail
printer: SLS Printer
- material White Strong & Flexible
printer: Metal Printer matt
- material Gold Plated Glossy
- material Antique Bronze Glossy
- material Antique Bronze Matte
- material Stainless Steel
printer: SLS Color Printer
- material Black Strong & Flexible
printer: Silver Printer
- material Silver Glossy
- material Silver
printer: ZPrinter 650
- material Sandstone
- material Full Color Sandstone
printer: SLS Alumide
- material Alumide
printer: Glass Printer
- material High Gloss Black Glass
- material High Gloss White Glass
- material Milky White Matte Glass
printer: Metal printer Gold
- material Gold Plated Matte
printer: SLS Color Printer New
- material Dark Grey Strong and Flexible
- material Indigo Strong and Flexible
- material Winter Red Strong and Flexible
printer: HD printer
- material Frosted Detail
printer: UHD printer
- material Frosted Ultra Detail
printer: SLS Printer polished
- material White Strong & Flexible Polished
printer: Ceramics printer
- material Glazed Ceramics

Pretty neat!

June 1, 2011 / stevebaer

Multithreaded Python

One of the nice bits that we have access to in Rhino python is the Task Parallel Library that is built into .NET 4

This set of classes and functions makes it relatively easy to write things like parallel for loops in which every iteration of the loop may be processed on different threads. This nice thing about parallel for loops is that they make coding with multiple threads much simpler since the “multi-threading” only occurs inside the for loop and once the loop is finished you know that the all of the threads have completed and you are back on the main execution thread.

Here’s a sample python script which runs many Plane-Brep intersections either on a single thread or using multiple threads.

May 27, 2011 / stevebaer

Outside the Box – Using Web Services from Python

I’ve been trying to learn more about things like web services and APIs provided by internet companies (gotta figure out what all of these buzzwords are.) One thing I’ve noticed is that many companies now provide a REST API which return JSON objects. There are enough resources on the web that describe REST and JSON that I don’t need to repeat it here; I’m just going to get to my python experiments on this technology.

So what does it do?
The python script uses the Google Translate API to translate text from one language to another. Maybe not the most useful new tool for Rhino, but it shows how simple it is to format a request to a web service and get at the results.

Some important things to note:

  1. The scripts in both attachments are exactly the same. There is code in the script to figure out if it is running as a normal Rhino python script or inside of Grasshopper.
  2. The script does different things when it is running in Rhino versus when running in Grasshopper. In Rhino, the script converts text dot text which in Grasshopper the script uses input and output variables.
  3. I’m using the sticky variable to cache results. This way we don’t have to keep going out to Google if we are translating the same text over and over again

Search around on the internet for REST apis that return JSON data. Your python scripts that use these other services will end up looking pretty similar to the samples I posted (unless you don’t like my scripting style;)) Here are some interesting APIs to look at:

May 2, 2011 / stevebaer

Python component for Grasshopper

Giulio Piacentino and I have been working on an update to the grasshopper/python component and finally have something to show off!!! – NOTE: Will only work in Rhino 5

This component is a scripting component similar to the VB.NET and C# components that ship with Grasshopper. You get a component where you can define as many input and output variables as you want and then reference these variables in the python script.
If you double click on the component, you get a light version of the python script editor which you are used to in the EditPythonScript command (keywords are colorized and functions autocomplete when possible)

But there is a cool twist… this component supports the rhinoscriptsyntax functions. The rhinoscriptsyntax functions can be set to generate geometry inside of Grasshopper that does not live in the Rhino document. We are using a concept called “duck typing” to swap the document that the rhinoscriptsyntax functions use from the rhino document to a grasshopper document. This means that the following script

import rhinoscriptsyntax as rs
for x in range(10):

will add 10 points to the Rhino document when run from Rhino’s “RunPythonScript” or “EditPythonScript” functions. The same script will add 10 points to a grasshopper document that can be passed on to other grasshopper components when run inside the syntax of grasshopper.

We are writing this as an open source project which is hosted at
Developers are welcome to download, compile, and tinker with the component source code. If you find bugs or want to add features, let us know and we’ll figure out how to get you more involved in the development process.

You can also log bugs and wishlist items at

Use your python scripting skills in Rhino 5 for Windows, Rhino 5 for Mac, and in Grasshopper for Rhino 5;)