Programming
intro [with RhinoScript].
================================================================================
1. The command line and macros.
2. Scripting: variables and loops
3.The Basic Language and VBScript
4. For-next loops.
5. Conditional Statements.
6. Comments.
7. Subroutines.
8...and Functions.
9. Randomness.
10. Arrays.
11. Conclusion and sample code.
================================================================================
1. The command line and
macros.
*********************************************************************************************
Those of you familiar with Rhino may have already seen that one can use
the command line in the interface for typing the commands instead of clicking
in the toolbars. For example, for drawing a polyline we could write (in
the command prompt):
Command: Polyline
---and then we could enter the points we are prompted for in numeric form
(X,Y,Z):
Start of polyline: 0,0,0
Next point of polyline ( Undo ): 1,0,1
Next point of polyline. Press Enter when done ( Undo ): 0,0,2
---and enter to finish.
Next point of polyline. Press Enter when done ( Close Undo ):
We could also enter this in the form of a MACRO, that
is, a prepared text that will do the same thing that the lines above.
So if you copy and paste the lines below in to the Rhino command line,
you will see it executing all your entries at once:
---------------------------------------------------------------------------------------------------------------------------------------------
Polyline
0,0,0
1,0,1
0,0,2
enter
---------------------------------------------------------------------------------------------------------------------------------------------
now for making a cone, for example, we could type cone, and
enter one by one the parameters:
Command: Cone
Base of cone ( Vertical Diameter 3Point Tangent AroundCurve ): 5,5,5
Radius <10.000> ( Diameter ): 10
End of cone: 5,5,10
or we could instead write somewhere else and paste the following lines
into the command line:
---------------------------------------------------------------------------------------------------------------------------------------------
Cone
5,5,5
10
5,5,10
---------------------------------------------------------------------------------------------------------------------------------------------
One could then write basically all the operations of making a drawing
and 'play' them by pasting them in the command line. This could be useful
if we are going to do exactly the same operation many times, but it is
quite limited as soon as we want to vary what we do.
2. Scripting:
variables and loops
*********************************************************************************************
Scripting gives the ability to 'program' in Rhino. That means that one
can in principle write and execute any process that can be stated in a
logical and unambiguous form.
To begin with, we will locate the help for RhinoScript ( using Help is
one of the most important parts of learning any program or feature). The
help for RhinoScript is under:
Help>>Plug-ins>>RhinoScript.
You can follow the first example and see how you can script your own message
box. Through RhinoScript one can create toolboxes, tools, etc that look
and feel like any other standard tool of Rhino. In theory one could extend
Rhino as much as one would feel like, adding completely new tools, importing
different type files...etc, as long as you know how to program it. In
fact many computer programs (CAD and Modeling packages, text editors,
html...etc) share the same capabilities.
You can find a relatively simple to use reference to the scripting language
used in Rhino, called VBScript, here
and
here. We will have a look at VBScript a bit later
(or go to vbscript if you are eager).
So the first you need to do is to open a window to be able to write your
script. You do this by typing in the command line:
EditScript in the command line and pressing Enter.
(or alternatively from the Rhino menu: Tools>>RhinoScript>>Edit)
Now we will write a simple script for making the cone above:
---------------------------------------------------------------------------------------------------------------------------------------------
Rhino.AddCone Array(5,5,5), Array(5,5,10), 10
---------------------------------------------------------------------------------------------------------------------------------------------
I know that I should use this instruction because I checked in the RhinoScript
help and saw a description of the fields required! (not because I know
it by heart, use the help!). This may be a more complicated way of writing
the same thing described above, but this allows me to control parameters
every time a cone is drawn. if I would write 10 (or one million) different
cones I would do something like this:
---------------------------------------------------------------------------------------------------------------------------------------------
Dim a
a=1
Do While a<10
Rhino.AddCone Array(a*10,0,0), Array(0,0,5), a
a=a+1
Loop
---------------------------------------------------------------------------------------------------------------------------------------------
Copy and paste the text in to the EditScript window, and see
what happens.
What we have here are two very important things: first we have defined
a variable, called a, and secondly we have a
loop, something that is repeated until a condition is fulfilled.
Since computer languages are based in natural or spoken languages (most
frequently English) it is perhaps not that difficult to understand what
is happening in the code above:
First we are defining or dimensioning (Dim) a variable
called a.
Dim a
A variable is a number without a fixed value, it can be thought
as a 'box' inside the computer in which we can put different values, and
when executing the program, the computer will use whatever value it is
there. we put values in the 'box' of the variable by saying
a=1
for example, to put a value of 1. Variables are one of the most important
parts of a computer program, they are the 'data' it will deal with.
We could have called the variable anything we wanted, as long as it is
not any word used anywhere else with other meaning. We can for example
change a for fifafo or bananas
everywhere in the script where a appears, and it would not make
any difference.
Now we want to repeat something. With Do while... we
tell the computer to do something between when we say this and when we
say loop.
Do while...
...
...
...
...
Loop
The while obviously means to repeat something while a
condition is met. We say here a<10, or said in other
words:
do everything between here and where it says loop while the value stored
in a is smaller than 10.
What we tell it to do is:
Rhino.AddCone Array(a*10,0,0), Array(0,0,5), a
If you have executed the code you have seen that it is not drawing the
same cone all the time, it changes the position and the radius every time
(10 times). This is because if you look at the line above you will see
that it says:
Rhino.AddCone Array(a*10,0,0), Array(0,0,5), a
that is, every time the variable a appears
in the code, it looks at the value that is stored in it (remember,the
a variable is like a 'box'), and puts that value instead. a*10
means 'a multiplied by ten', so it puts in that place the value
stored in a multiplied by ten.
After that we say:
a=a+1
which means store in a the value that was previously there plus one. This
way a will become bigger by one every time the loop is
done, until a becomes bigger than 10, which will make
the while bit stop doing the loop...
A little note about the Array word:
You have realise that we write Array word, and parenthesis,
for giving points (X,Y,Z) to the computer. We will look at Arrays at some
other point, right now the important thing to know is that arrays are
a bit like variables, but instead of consisting of one 'box', arrays are
'piles of boxes', like a number of pigeonholes or shelves, and in each
box or pigeonhole one can store different values, just like in a variable.
So arrays are collections of variables. We will learn how to use them
later, but for the time been it is just necessary to say that 3D and 2D
points need to be passed to Rhino by arrays (one has to give it the whole
set of boxes at the same time) and cannot be passed one by one (the values
in each of the boxes, x,y and z).
3.The Basic Language and
VBScript
*********************************************************************************************
What you have been programming in, and what RhinoScript uses, is a programming
language called Basic developed during the sixties, and
widely used because of its simplicity. RhinoScript uses in fact a 'dialect'
of basic called VBScript, (Visual Basic Script) developed
by Microsoft and common in many Windows applications. Computer languages
were designed, in the early years of computation, as a form of communication
between machines and people. Many computer languages (among them Basic)had
as their goal to be as close as possible to natural or spoken languages,
in order to make them easy to use. We could write for example the lines
above like this:
Dimension, or make space, for a variable called
a
and make a to be (=)
1
Do the things bellow While a is smaller than
(<) 10
now, you, the program Rhino , Add
a Cone with the following data: Array(a*10,0,0),
Array(0,0,5), a
and now make the value in a to be (=)
what it was before in a plus (+) 1
and here is the end of the Loop that it was started above
in the do
An important thing to notice about VBScript is that one can write things
in capitals or small letters, and the computer does not care (it does
care when it comes to most other programming languages).
4. For-next loops.
*********************************************************************************************
Another way of writing loops, is the for-next loop.
From the previous exercise you may have realised that there are a couple
of things common in loops one has to keep track of. One is usually to
initialise, that is, to set a variable to its initial value. In the previous
case we did that when we set variable a to 1
by saying a=1 . Another thing we had to do was to increase
or modify the variable with a=a+1, and then call the
loop. We can write the above instructions instead with a for-next loop,
like this:
---------------------------------------------------------------------------------------------------------------------------------------------
Dim a
for a=1 to 10
Rhino.AddCone Array(a*10,0,0), Array(0,0,5), a
next
---------------------------------------------------------------------------------------------------------------------------------------------
and since we are tired of drawing cones we can change it for something
else. like spheres, or toruses. In the RhinoScript help the description
for defining a new torus is:
Rhino.AddTorus (arrBase, dblMajorRadius, dblMinorRadius [, arrDirection])
and it is explained that the arrBase needs to be a point (X,Y,Z) described
as an array (like those in the cone), and that dblMajorRadius and dblMinorRadius
are numbers and arrDirection is an optional array like the ones we had
before. So lets re-write it; remember to remove the parenthesis from the
definition (we will see the reason for this later):
---------------------------------------------------------------------------------------------------------------------------------------------
Dim a
for a=1 to 10
Rhino.AddTorus Array(a*10,0,0), a*5, 3 , Array(a*50,0,5)
next
---------------------------------------------------------------------------------------------------------------------------------------------
now, we will see how to make a loop inside a loop, which is also a standard
procedure in programming:
---------------------------------------------------------------------------------------------------------------------------------------------
Dim a, b
for a=1 to 10
for b=0 to 5
Rhino.AddTorus Array(a*10,b*10,0), a*0.1+5, 3 , Array(a*50,-b,5)
next
next
---------------------------------------------------------------------------------------------------------------------------------------------
We have also changed a few of the variables when drawing the Toruses.
Another thing we can do with a for-next loop is to step,
that is to increment the values of the variable by more than one. So if
we write the previous code with a step instruction we
get:
---------------------------------------------------------------------------------------------------------------------------------------------
Dim a, b
for a=1 to 10 step 3
for b=0 to 5 step 2
Rhino.AddTorus Array(a*10,b*10,0), a*0.1+5, 3 , Array(a*50,-b,5)
next
next
---------------------------------------------------------------------------------------------------------------------------------------------
5.Conditional
Statements.
*********************************************************************************************
All these loops and their control is what defines the 'logical flow' of
a program. Together with the next statement we are going to look at, they
constitute what is usually called the flow control of a program. The statement
we will look at is the if...then, end if.
Lets take out original code and put a (rather trivial) if statement:
---------------------------------------------------------------------------------------------------------------------------------------------
Dim a
for a=1 to 10
if a <> 6 then
Rhino.AddTorus Array(a*10,0,0), a*5, 3 , Array(a*50,0,5)
end if
next
---------------------------------------------------------------------------------------------------------------------------------------------
If you run the code above you will see that when a was
6, it has left a gap in the toruses. The <> sign means different,
so what it says above is:
if a is different (<> ) than 6
then
do all that is between this line and the one that says
end if
of course one should do something perhaps a bit more interesting with
it, but we will get there. The things one can put in an if, or a while
as those we have seen above are:
Equality =
Inequality <>
Less than <
Greater than
>
Less than or equal to <=
Greater than or equal to >=
Object equivalence Is
(we won't use this one)
More than one condition can be added in an If statement
through the use of boolean or logical operators Not,
And and Or. Try writing in the above
example:
if Not a <> 6 then
or:
if a <> 6 And a<> 8 then
or:
if a =6 Or a= 8 then
see the differences. Asa remainder, a good reference for VBScript is here.
6.Comments.
*********************************************************************************************
We will introduce here a very useful feature of most computer
languages: often code it is difficult to understand, especially when it
gets only slightly complicated, not only by others looking at what one
has written, by but oneself. If one looks at a piece of code written a
a while ago that one has forgotten, or a very tricky part that took some
time to 'crack' , for example, it is often the case that it becomes difficult
to understand ones own decissions andwork. In most languages it is possible
to 'annotate' the code, to write text that can be read by oneself or someone
else, but that wont be read by the computer, that is, that are not part
of the code. This is done through comments. Comments in basic, VBScript
and therefore RhinoScript are done through (
' ) quotation mark. So I could annotate the code we have been
using, like this:
---------------------------------------------------------------------------------------------------------------------------------------------
'this is a bit of a silly program just to illustrate comments
'Anything after the quotation mark will be ignored by the computer
Dim a, b 'here
a and b variables are declared
for a=1 to 10 step 3 'this is
the beginning of the first loop
for b=0 to 5 step 2 'this
is the beginning of the second loop
Rhino.AddTorus Array(a*10,b*10,0), a*0.1+5, 3 , Array(a*50,-b,5) 'this
is the drawing bit
next 'this
is the end of the second loop
next 'this
is the end of thefirst loop
---------------------------------------------------------------------------------------------------------------------------------------------
If you copy and paste the code above, you will see that everything
after the (') quotation will be ignored (and usually highlighted in a
different colour) by the computer, and therefore the code will work exactly
the same as without the comments. It is very good practice to comment
things, and in general it improves the readability of the code enormously.
7.Subrutines.
*********************************************************************************************
Another important thing to know is the use of subroutines. Subroutines
make possible to name and call a part of the code. In most cases you will
have at least a 'main' subroutine which will encompass all of your code.
This will not only define the scope of variables (you don't need to worry
too much about this now), but it will allow you to save and run your RhinoScript
code without needing to open it in the edit window. For example we could
take the code above again and write:
---------------------------------------------------------------------------------------------------------------------------------------------
Sub makingdoughnuts() 'this is the beginning of the subroutine, I give
it any name, and
'and
put parenthesis after...
Dim a, b
for a=1 to 10 step 3
for b=0 to 5 step 2
Rhino.AddTorus Array(a*10,b*10,0), a*0.1+5, 3 , Array(a*50,-b,5)
next
next
End Sub 'this
is the end of the subroutine
---------------------------------------------------------------------------------------------------------------------------------------------
Now, if you can open a text editor, write your code there instead of the
editscript window inside Rhino, and save it as thenameofyourfile.rvb,
that is anything with the *.rvb extension. You can load it in Rhino with
the LoadScript command, and run it with the RunScript
command. You can also make it run automatically every time you load it
by 'calling' the subroutine at the end of your code, like this:
---------------------------------------------------------------------------------------------------------------------------------------------
Sub makingdoughnuts()
Dim a, b
for a=1 to 10 step 3
for b=0 to 5 step 2
Rhino.AddTorus Array(a*10,b*10,0), a*0.1+5, 3 , Array(a*50,-b,5)
next
next
End Sub
makingdoughnouts '<-- here we call it...
---------------------------------------------------------------------------------------------------------------------------------------------
The thing with subroutines is that one can divide the code in different
parts and 'call' them, in fact one can use the subroutine to extend a
language as much as one wants by adding one's owns instructions... we
will look at this in more depth through examples later on, and especially
in relation to having access to variables from different parts of the
code.
---------------------------------------------------------------------------------------------------------------------------------------------
Option Explicit 'we right this in the first line from
now on...it only tells the computer
'to force us to declare all variables by using Dim, it makes
'debugging' easier...
Sub makingdoughnuts() 'so we keep the subroutine,
and then we make a new one bellow, that we
'(makingtherows())
that we call from within the main...in the for
Dim a
For a=1 To 10 Step 3
makingtherows a'we pass a, because the Rhino instruction for
drawing the toruses needs 'to know
'its value...
Next
End Sub
Sub makingtherows(a) 'here the subrutine makingtherows is
called. We have to pass a here from
'the
main loop, and this is the way we do it... (between parenthesis)
Dim b
For b=0 To 5 Step 2
Rhino.AddTorus Array(a*10,b*10,0), a*0.1+5, 3 , Array(a*50,-b,5)
Next
End Sub
makingdoughnuts '<-- here we call it...
---------------------------------------------------------------------------------------------------------------------------------------------
8....and Functions.
*********************************************************************************************
Similar to subroutines, Functions return (they send back) a value. An
example of a function (again, a bit absurd in principle, only for illustration)
could be one for calculating the multiplication by three of a variable.
function multbythree (num) 'we declare a function with"
function", instead of "Sub"<
Dim sillynumber
sillynumber=num*3
multbythree=sillynumber 'for being able to use it, the last line
of the function must be:
'the name of the function=the value to calculate
End Function 'and instead of end sub we use end function
now we can make a little program for illustration of its use (copy and
paste the lines bellow, last line is the call to "drawlines"):
---------------------------------------------------------------------------------------------------------------------------------------------
Option explicit 'as we mentioned above, for making debugging
easier
Sub drawlines() 'the main sub
Dim counter
Dim yposition 'a variable to keep the y position
For counter=1 To 5
yposition= 10*counter
' first line
Rhino.AddLine Array(10,yposition ,0), Array(10+counter,yposition,0)
'and second line with the length multiplied by three (and y position 5
bigger)
yposition= 10*counter+5 'we move the line 5 units in
y
Rhino.AddLine Array(10,yposition ,0), Array(10+multbythree(counter),yposition,0)
Next
End Sub
'now the function as we had it above...
function multbythree (num)
Dim sillynumber
sillynumber=num*3
multbythree=sillynumber
End Function
drawlines
---------------------------------------------------------------------------------------------------------------------------------------------
9. Randomness.
*********************************************************************************************
Before continuing, we will look at a simple instruction that is quite
fun to use, to generate randomness. Rnd will generate
a random number between 0 and 1. So imagine we want to make a lot of random
points, we would write:
---------------------------------------------------------------------------------------------------------------------------------------------
randomize
'randomize is needed for starting or 'seeding' the random generator, otherwise
it will produce the
'same series of random-like numbers every time we start Rhino.
Dim anothercounteryet
for anothercounteryet=0 to 100
Rhino.AddPoint Array(Rnd*10,Rnd*10,Rnd*10) ' here the calls to
Rnd
next
---------------------------------------------------------------------------------------------------------------------------------------------
10. Arrays.
*********************************************************************************************
We have previously mentioned Arrays. Arrays, if you remember, are pigeonholes
or collection of 'boxes' or variables, that we have been using until now
to pass points to Rhino. We will see how to use them further, and their
properties. Arrays, and particularly arrays of points, are important in
RhinoScript to draw lines. We can take the code we have been using before
to draw the toruses and rewrite it like this:
---------------------------------------------------------------------------------------------------------------------------------------------
Option explicit
Sub main()
Dim a
Dim myarraythingy(10) 'this is the declaration of an array. The
number between parenthesis is
'
the index of the last object
for a=1 to 10
myarraythingy(0)=a*10
myarraythingy(1)=0
myarraythingy(2)=0
Rhino.AddTorus myarraythingy, a*5, 3 , Array(a*50,0,5)
next
End Sub
---------------------------------------------------------------------------------------------------------------------------------------------
As you can see we declare an array, myarraythingy, very
much the same way we declare a variable. The difference is that when we
asign values to it, we write
myarraythingy(0)=a*10
myarraythingy(1)=0
myarraythingy(2)=0
...
That is, we use an index for different values in the array. Remember
what we said, that an array is like a collection of pigeonholes that can
each hold different values, so we need those indexes for knowing which
of the pigeonholes we are talking about. In this case we use only three
(0,1,2) for the (X,Y,Z) of a point. The pigeonholes of an array can contain
anything, in fact, they can contain other arrays. Arrays of arrays of
points are very used in Rhino for describing lines, surfaces, etc. So
here it goes a simple example:
---------------------------------------------------------------------------------------------------------------------------------------------
Option Explicit
Sub Crazylines
'we have to indicate the index of the last index (10) of the array when
we declare it, if it is an array of 'arrays:
Dim Theamazingarrayofpoints (10)
Dim i
Randomize
For i=0 To 10
'now we can refer to any of the 'pigeonholes' of the array by index, (it
can be a variable, and it is
' often the case, like here with i ) and store another array in it (a
point)
Theamazingarrayofpoints(i) = Array(Rnd * 1000,Rnd * 1000,Rnd *
1000)
Next
'if you check the AddCurve description in the RhinoScript help,
you will see that it needs an array of points...
Rhino.AddCurve Theamazingarrayofpoints
End Sub
Crazylines
---------------------------------------------------------------------------------------------------------------------------------------------
Test changing the amount of points in the for loop and in the
declaration of the array...
You can also access the individual (X,Y,Z) values of the arrays by writing
them as:
Theamazingarrayofpoints(5)(1), for example. You can test this by adding
a couple of lines before the Next:
Theamazingarrayofpoints(i)(0)=0
or:
Rhino.print Theamazingarrayofpoints(i)(0)
which is a very useful command to print in the command line and check
the values of things, by the way. Just as an extension of this we could
add a Dim j at the beginning of the code (where
Dim i is) and then write:
Rhino.print "x,y,z"
For j=0 to 2
Rhino.print Theamazingarrayofpoints(i)(j)
next
just before the next in the code above.
*********************************************************************************************
So this very much wraps it up...I have tried to keep the code to the minimum,
so these are the bare bones of RhinoScript. In the other hand, almost
anything can be written using the code above. There are in most cases
more than one, often quite many ways of writing a piece of code that will
do the same thing, and this is an important thing to keep in mind. There
may be ways of writing something that are more complicated or adequate,
in a particular situation, than others (we have seen a very simple example
with the while loops and the for-next loops) , but in general they will
all be compatible with each other.
Again, as a reminder, check the reference to RhinoScript in the RhinoScript
help, use the reference to VBScript here,
and 'google' for information when you want to find out something. There
is quite a lot of information around about VBScript, you may find also
interesting information about RhinoScript. A good and quite complete tutorial
for RhinoScript is available here.
For writing the code outside Rhino a good text editor is ConText,
which will highlight your RhinoScript code (as VBScript).
More resources at:
McNeel
Wiki (scripts to download, tips, etc).
Sample code:
random walker
, Enneper
points
, Enneper surface
, fractal
branching
,
fractal cubes
, complex roof
...........................................................................................................................................
for modulation:
combinatorial
cubes ,
combinatorial
modules ,
modulated
random walk,
alternate
modules
*********************************************************************************************
pablo miranda carranza
|