Python Basics
Introduction
What is Python?
Python is an interpreted, object-oriented, high-level programming language with dynamic semantics. Its high-level built in data structures, combined with dynamic typing and dynamic binding, make it very attractive for Rapid Application Development, as well as for use as a scripting or glue language to connect existing components together. Python’s simple, easy to learn syntax emphasizes readability and therefore reduces the cost of program maintenance. Python supports modules and packages, which encourages program modularity and code reuse. The Python interpreter and the extensive standard library are available in source or binary form without charge for all major platforms, and can be freely distributed.
You may need Python in Rhino and Grasshopper if you want to:
-
Automate a repetitive task in Rhino much faster than you could do manually.
-
Perform tasks in Rhino or Grasshopper that you don’t have access to in the standard set of Rhino commands or Grasshopper components.
-
Generate geometry using algorithms.
Why do we use Python?
Python is meant to be a simple language to read and write. Python also runs both the Windows and Mac versions of Rhino. Since Rhino Python scripting is available on both platforms, the same Python scripts can run on both breeds of Rhino!
But more importantly: Python is very popular outside of Rhino! Much of what you learn about Python can be applied in many other domains.
Rhino already has a scripting language called RhinoScript why do we need another? RhinoScript is a very easy to use scripting language on Windows. We will continue to support Rhinoscript. But, RhinoScript is based on an little older technology making it less flexible then the more modern Python language. RhinoScript cannot be supported on the Mac platform. It also unfortunately is not supported by the community to the same level as Python.
References & Resources
First Python Script in Grasshopper
Your First Python Script in Grasshopper
Basics
Hello world
import rhinoscriptsyntax as rs
#Comment
text = "hello world"
print text
Create a point
import rhinoscriptsyntax as rs
# Create a point
a = rs.AddPoint(0,0,0)
For loop
import rhinoscriptsyntax as rs
#Iterate through list
for i in range(10):
print(i)
Lists
import rhinoscriptsyntax as rs
#Create a list
a = [] # Empty list
for i in range(10):
p = rs.AddPoint(i,0,0) # Create a point
a.append(p) # append points to empty list
If condition
import rhinoscriptsyntax as rs
#Create a if condition
a = []
for i in range(10):
if(i < 2):
p = rs.AddPoint(i,0,0)
elif(i < 5):
p = rs.AddPoint(i,0,6)
else:
p = rs.AddPoint(i,0,2)
a.append(p)
Math module
import rhinoscriptsyntax as rs
import math #Import math library
a = []
for x in range (100):
y = math.sin(x)
pt = rs.AddPoint(x,y,0)
a.append(pt)
Random module
import rhinoscriptsyntax as rs
import math
import random #Import random library
a = []
for x in range (100):
y = math.sin(random.random()*x)
pt = rs.AddPoint(x,y,0)
a.append(pt)
Inputs
Integer and Float Input
Integers and floats are two different kinds of numerical data. An integer (more commonly called an int
) is a number without a decimal point. A float is a floating-point number, which means it is a number that has a decimal place. Floats are used when more precision is needed.
#Building a cube point grid
#input type - x : int, y : int, z : int
import rhinoscriptsyntax as rs
a = []
for i in range(x): #Array of values in x direction
for j in range(y): #Array of values in y direction
for k in range(z): #Array of values in z direction
p = rs.AddPoint(i, j, k)
a.append(p)
Point Input
Define type hint as Point 3D
# input type pt : Point3d (ListAccess)
import rhinoscriptsyntax as rs
a = [] #Empty list 1
b = [] #Empty list 2
c = [] #Empty list 3
for pt in pts:
if(pt.X % 3):
a.append(pt)
elif(pt.Y % 2):
b.append(pt)
else:
c.append(pt)
Point Input II: Rhino Geometry
# Add geometry and react to attractor
# input - pts : Point3d (List Access), attr : Point3d (Item Access)
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg # Geometry library
a = []
for pt in pts:
dist = rs.Distance(pt, attr) #Get distances
circle = rs.AddCircle(pt, 0.1*dist)
a.append(circle)
Functions
A function is a block of organized, reusable code that is used to perform a single, related action and only runs when it is called
.
You can pass data, known as parameters
, into a function.
A function can return data as a result.
Example:
def my_function():
print("Hello from a function")
Calling a Function
To call a function, use the function name followed by parenthesis:
def my_function():
print("Hello from a function")
my_function()
Parameters
Information can be passed to functions as parameter
.
Parameters are specified after the function name, inside the parentheses. You can add as many parameters as you want, just separate them with a comma.
def my_function(fname):
print(fname + "1")
my_function("point")
my_function("line")
my_function("surface")
Simple Function
Build a cube point grid
#building a cube point grid
#input type - x : int, y : int, z : int
import rhinoscriptsyntax as rs
# function definition
def drawPoints(x,y,z):
points = []
for i in range(x):
for j in range(y):
for k in range(z):
p = rs.AddPoint(i, j, k)
points.append(p)
return points
# main
a = []
for i in range(x):
for j in range (y):
for k in range (z):
pts = drawPoints(x,y,z)
a.extend(pts) # add all points
Baking and objects attributes
Bake geometry
# bake boxes with colors
# input type - bool (Item Access)
import scriptcontext as sc
import Rhino.DocObjects as rd
import Rhino.Geometry as rg
import System.Drawing as sd
import Rhino
sc.doc = Rhino.RhinoDoc.ActiveDoc
if bake:
x = 10
z = 10
boxsize = 1
for i in range(x):
for j in range(z):
box = rg.Box( rg.Plane.WorldXY, rg.Interval(i, i+boxsize-0.1), rg.Interval(0,1), rg.Interval(j, j+boxsize-0.1) )
brep = rg.Brep.CreateFromBox(box)
attr = rd.ObjectAttributes()
attr.ColorSource = rd.ObjectColorSource.ColorFromObject
attr.ObjectColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
sc.doc.Objects.AddBrep(brep, attr)
Bake materials
# bake boxes with materials
# input type - bool (Item Access)
import scriptcontext as sc
import Rhino.DocObjects as rd
import Rhino.Geometry as rg
import System.Drawing as sd
import Rhino
sc.doc = Rhino.RhinoDoc.ActiveDoc
if bake:
x = 10
z = 10
boxsize = 1
for i in range(x):
for j in range(z):
box = rg.Box( rg.Plane.WorldXY, rg.Interval(i, i+boxsize-0.1), rg.Interval(0,1), rg.Interval(j, j+boxsize-0.1) )
brep = rg.Brep.CreateFromBox(box)
materialIndex = sc.doc.Materials.Add()
material = sc.doc.Materials[materialIndex]
material.DiffuseColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.CommitChanges()
attr = rd.ObjectAttributes()
attr.MaterialSource = rd.ObjectMaterialSource.MaterialFromObject
attr.MaterialIndex = materialIndex
sc.doc.Objects.AddBrep(brep, attr)
Bake attributes
# bake boxes with Attributes
# input type - bool (Item Access)
import scriptcontext as sc
import Rhino.DocObjects as rd
import Rhino.Geometry as rg
import System.Drawing as sd
import Rhino
sc.doc = Rhino.RhinoDoc.ActiveDoc
if bake:
x = 10
z = 10
boxsize = 1
for i in range(x):
for j in range(z):
box = rg.Box( rg.Plane.WorldXY, rg.Interval(i, i+boxsize-0.1), rg.Interval(0,1), rg.Interval(j, j+boxsize-0.1) )
brep = rg.Brep.CreateFromBox(box)
materialIndex = sc.doc.Materials.Add()
material = sc.doc.Materials[materialIndex]
material.AmbientColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.DiffuseColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.EmissionColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.ReflectionColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.SpecularColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.Transparency = i/z
material.TransparentColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
material.Shine = 1
material.CommitChanges()
attr = rd.ObjectAttributes()
attr.MaterialSource = rd.ObjectMaterialSource.MaterialFromObject
attr.MaterialIndex = materialIndex
sc.doc.Objects.AddBrep(brep, attr)
Bake into layers
# bake boxes into layers
# input type - bool (Item Access)
import scriptcontext as sc
import Rhino.DocObjects as rd
import Rhino.Geometry as rg
import System.Drawing as sd
import Rhino
sc.doc = Rhino.RhinoDoc.ActiveDoc
if bake:
x = 10
z = 10
boxsize = 1
for i in range(x):
for j in range(z):
box = rg.Box( rg.Plane.WorldXY, rg.Interval(i, i+boxsize-0.1), rg.Interval(0,1), rg.Interval(j, j+boxsize-0.1) )
brep = rg.Brep.CreateFromBox(box)
attr = rd.ObjectAttributes()
attr.ColorSource = rd.ObjectColorSource.ColorFromObject
attr.ObjectColor = sd.Color.FromArgb(i/x*255, j/z*255, 150)
layerName = "layer_" + str(i)
layerIndex = sc.doc.Layers.Find(layerName, True)
if layerIndex < 0:
layer = rd.Layer()
layer.Name = layerName
layerIndex = sc.doc.Layers.Add(layer)
attr.LayerIndex = layerIndex
sc.doc.Objects.AddBrep(brep, attr)
OOP
Object Oriented Programming
Classes are useful mechanism for organization above what we have already mentioned: variables, flow control and functions. Classes give us another level of functionality and actually define a specific type of programming called Object-Oriented Programming.
Simple Class
#input type - pts : List Access, Point3D
import rhinoscriptsyntax as rs
class ClassPt:
def __init__(self, pts):
self.center = pts
self.radius = radius
def getCircle(self):
circle = rs.AddCircle(self.center, self.radius)
a.append(circle)
a = []
for pt in pts:
obj = ClassPt(pt)
obj.getCircle()
Class with constructor
#input type - pts : List Access, Point3D
import rhinoscriptsyntax as rs
class ClassPt:
def __init__(self, pts):
self.center = pts
self.radius = radius
def getCircle(self):
circle = rs.AddCircle(self.center, self.radius)
a.append(circle)
a = []
for pt in pts:
obj = ClassPt(pt)
obj.getCircle()