Tuples that contain single element.
Let's start with Command: EditPythonScript
a=[1] print a, print type(a)
If you put ',' at the end of print statement, "start a new line" is not performed.
You may get:
[1] <type 'list'>
a=[1,2] print a, print type(a)
You may get:
[1, 2] <type 'list'>
Let's try tuples cases. First, try
a=(1,2) print a, print type(a)
the you get
(1, 2) <type 'tuple'>
** However ** when you run
a=(1) print a, print type(a)
you get
1 <type 'int'>
In order to make sure to let a as a tuple type object
a=(1,) print a, print type(a)
Safely, you get
(1,) <type 'tuple'>
In turn, let's try
a=(1,2,(3)) print a, print type(a)
You get
(1, 2, 3) <type 'tuple'>
If you want to let the third element a tuple type object, you can write:
a=(1,2,(3,)) print a, print type(a)
You may get
(1, 2, (3,)) <type 'tuple'>
Conguraturation :)
GhPython and transmitting variables
Let's move on to Grasshopper and GhPython environment.
Type Command: Grasshopper
and place two GhPython components on your canvas.
Name them as "fromPython" and "toPython".
Connect them like
In the "toPython" component, type
print x
Plus, in the "fromPython" component, type
a=1
Hit "Test" button. You may get
Congratulation :)
The type should not be integer. For example,
** However, ** if you try to transmit a list or a tuple type object, you may get
This is completely different from the expected result. We expected that (1,2,3) is printed out.
This may caused because the Grasshopper automatically unpack list or tuple type objects and your python script code is called repeatedly for each element in the list or tuple object. Therefore, we should wrap a tuple type object (1,2,3) by another tuple type object. In the fromPython component let's rewrite as
a=((1,2,3),)
Then, you may get
If you want to transfer a nested tuple like ((1,2),3), if you make sure that it is wraped by another tuple, the structure is not destroyed by the Grasshopper.
Unpacking
When you received a tuple like x=((1,2),3) you can unpack it by stating like ((x,y),R)=x
print x ((x,y),R)=x #unpacking print x, print y, print R print ((x,y),R)
You may get
((1, 2), 3)

1 2 3

((1, 2), 3)
Combination with rhinoscriptsyntax
Once you received a tuple, you can create geometries such as points and circles.
In the toPython component, let's try
import rhinoscriptsyntax as rs print x ((x0,y0),R)=x #unpacking a=rs.AddCircle((x0,y0,0),R)
You get
Applying an interactive user interface
Set up two input parameters "P" and "r" for the "fromPython" component.
Specify "P" as Point3d type object.
Specify "r" as float type value.
Modify the code written in "fromPython" as
import Rhino.Geometry as rg a=(((P.X,P.Y),r),)
Connect "P" with a Point parameter component.
Connect "r" with a floating point slider component.
(Be sure the maximum value of the slider is greater than 1.0 otherwise you can not see the created circle)
Then you can change the position and radius of the circle in an interactive way.
Using Grasshopper list
Rightclick "x" in the "toPython" component and specify it as a "List Access" type parameter.
Now, modify the script code in the "toPython" component as:
import rhinoscriptsyntax as rs print x a=list() for ((x0,y0),R) in x: a.append(rs.AddCircle((x0,y0,0),R))
You get the same result but it has been rewritten in the "list and for" style.
Therefore, if you just duplicate the "fromPython" component,
you get
Gaussian hill
single hill
Set up a GhPython component like
Set up the input parameters as
P:Point3d
A,C:Floating point numbers
Then write a script that transmit ((P.X,P.Y),A,C) to another GhPython component.
import Rhino.Geometry as rg a=(((P.X,P.Y),A,C),)
Place another GhPython component which is to receive the tuple. Connect them like
Plus, write the scirpt which receive the tuple and generate a surface.
import rhinoscriptsyntax as rs import math dots=list() for i in rs.frange(5.0,5.0,0.5): for j in rs.frange(5.0,5.0,0.5): dots.append((i,j)) ((x0,y0),A,C)=hill#Unpacking func=lambda (x,y):(A*math.exp(((xx0)**2+(yy0)**2)/(2*(C**2)))) z=map(func,dots) a=list() for ((x,y),z) in zip(dots,z): a.append(rs.AddPoint(x,y,z))
You may get
list of hills
Let's rename the input parameter "hill" to "hills".
Plus, specify "hills" as "List Access" type parameter.
Comment out the unpacking line.
Modify the lambda function as
((x0,y0),A,C)=hill #Unpacking func=lambda (x,y),((x0,y0),A,C):(A* math.exp(((xx0)**2+(yy0)**2)/(2*(C**2))))
Add a new function that compute the sum of lambda functions
def Func(xy): z=0 for hill in hills: z+=func(xy,hill) return z
Finally, replace z=map(func,dots) with z=map(Func,dots).
The following is our final code.
import rhinoscriptsyntax as rs import math dots=list() for i in rs.frange(5.0,5.0,0.5): for j in rs.frange(5.0,5.0,0.5): dots.append((i,j)) ((x0,y0),A,C)=hill #Unpacking func=lambda (x,y),((x0,y0),A,C):(A* math.exp(((xx0)**2+(yy0)**2)/(2*(C**2)))) def Func(xy): z=0 for hill in hills: z+=func(xy,hill) return z z=map(Func,dots) a=list() for ((x,y),z) in zip(dots,z): a.append(rs.AddPoint(x,y,z))
You may get the same result as the previous one.
But, it is rewritten in a "list and for" style.
Therefore, you can dupulicate the "Hill" components
and then you can get