Este documento presenta una guía básica sobre fundamentos de scripting para un taller de diseño asistido por computadora. Incluye una introducción al scripting y RhinoScript, la estructura básica de un script, el manejo de datos con variables como arrays y bucles, y ejemplos de scripts. El taller será impartido del 14 al 17 de abril de 2008 en Barcelona, España.
1. Guía básica de fundamentos del script
Taller Design by Scripting
Postgrado en Diseño, Entorno y Arquitectura
ELISAVA Escola Superior de Disseny
Barcelona, 14 – 17 de abril, 2008
Instructores:
Carlos de la Barrera
Ernesto Bueno
Asistente:
Ruther Paullo
Asesora pedagógica:
Rita Patrón
www.designemergente.com
2. Guía básica de fundamentos del script
Taller Design by Scripting
Guía básica de fundamentos del script
dado como base de trabajo del taller
Tabla de contenido
1. Introducción
1.1. Scripting
1.1.1. ¿Pero qué es un script?
1.2. Monkey Editor para Rhino 4
1.3. Ayuda de RhinoScript
2. Estructura de un script
3. Manejo de datos con variables
3.1. Tipos de datos
3.2. Trabajar con variables
3.2.1. Arrays
3.2.2. Arrays bidimensionales
3.3. Loops incrementales
4. Funciones personalizadas.
Extra Ball!
Sugerencias para el proyecto
Nuestra Web
Recursos Web
1. Introducción
Éste es un workshop para aprender a hacer con el Rhino cosas más avanzadas que la modelación de
NURBS.
El RhinoScript es una herramienta que podemos usar en Rhino para hacer que el ordenador nos ayude a
resolver situaciones, tanto en términos de geometría como de automatización de tareas tediosas, o cálculo
de cosas complejas que nos ayuden a resolver el diseño o a personalizarlo, pero de manera sistemática
(porque no tenemos ni el tiempo ni las ganas de resolverlo manualmente).
El RhinoScript es un tipo de Visual Basic Script (VBScript) adaptado para funcionar en Rhino. El VBScript es
la técnica de scripting basada en el lenguaje Visual Basic, que es un lenguaje muy intuitivo.
1.1. Scripting
Es el método creativo (método de programación) que van a aprender en éste taller. En especial su
aplicación al diseño (¡no se asusten!).
Programación implica composición. Cuando decoramos nuestra casa, cuando nos vestimos o incluso
cuando hablamos componemos de diferentes maneras y usando diferentes herramientas, sin embargo lo
que tiene en común decorar nuestra casa y hablar es que —como todos los tipos de composición— están
basados en procesos.
El Scripting es un tipo de composición que ordena, que compone procesos. Es un método que se está
haciendo cada vez más universal. Diferentes disciplinas lo están incluyendo en la investigación y desarrollo
teórico y práctico, entre ellas la arquitectura y el diseño.
1.1.1. ¿Pero qué es un script?
El nombre script, en informática, se refiere al texto escrito por un usuario (como nosotros) para hacer de
guión de instrucciones para que —en su sentido más general— un programa haga un grupo de tareas
automáticamente.
Un informático les dirá que el script es un tipo de programa interpretado —que no es capaz de ejecutarse
a sí mismo (un simple programita hecho en texto, que no tiene sufijo .EXE), sino que requiere ser
interpretado por otros programas para funcionar— hecho para interactuar con otros programas, con
Pág. 1 de 8
3. Guía básica de fundamentos del script
usuarios o para combinar componentes. O sea, que puede complementar —e incluso aumentar— las
funciones de una aplicación (como Rhino).
De esto podemos extraer que sí, un script es un programa, pero uno muy sencillo; y no hace falta te
gradúes en programación para saber hacer y usar scripts.
De hecho, el término script lo tomaron prestado de las artes escénicas.
Se podría decir —en un sentido más simple— que un script es como el guión de una película, en el cual se
describe la historia que se quiere contar y se dan instrucciones para que las acciones (los procedimientos)
puedan ser interpretadas por los actores (los programas).
¿No sería genial que, además de ser el público, pudieses reescribir parte de los diálogos y las escenas de
una película para ver, por ejemplo, un final que te guste más?
1.2. Monkey Editor para Rhino 4
El Monkey es un editor de RhinoScript. Es un plug-in para el Rhino, que se descarga gratis del sitio de
McNeel. Con él vas a escribir y desarrollar tus scripts.
Es un programa supersencillo que te ayuda a escribir y entender el script, coloreando automáticamente lo
que vas escribiendo para que diferencies rápidamente los comandos Visual Basic de los otros tipos de
datos. También hace autocompletación de métodos RhinoScript y ofrece otras cosas como convenientes
accesos al documento de ayuda de RhinoScript.
Para que no nos liemos en el taller, lo primero que tienes que hacer es elegir los mismos colores que todos
vamos a usar. Eso lo haces yendo al menú:
View » Colours
Dejaremos la mayoría de los colores que vienen por defecto. Sólo cambiaremos los strings al color magenta
oscuro (el último de los colores extendidos “Magenta”) y los comentarios al color verde oscuro
(“DarkGreen”). Esto nos facilitará mucho el trabajo en el taller.
1.3. Ayuda de RhinoScript
Hay muchas maneras de acceder al documento de ayuda de RhinoScript, como: yendo al comando Help
desde el Monkey, o simplemente pulsando F1. Pero una muy conveniente es buscar el método deseado en
el browser de métodos RhinoScript y, antes de arrastrarlo al script para usarlo, hacer doble clic sobre él.
Esto abre el documento de ayuda justo en la página del método consultado.
Te recomendamos que consultes constantemente la ayuda. Es la clave para entender cómo y cuándo usar
qué método.
También te recomendamos que consultes la ayuda VBScript para las funciones básicas, que como te la
damos aparte, no la puedes llamar desde el Monkey.
Pág. 2 de 8
4. Guía básica de fundamentos del script
2. Estructura de un script
La siguiente es la primera parte del script base con el que trabajaremos en el taller. En el Monkey, lo
primero que ves con los colores son los tipos de código: En azul, los comandos VBScript; en verde (si ya lo
cambiaste), los comentarios; y en magenta oscuro, un mensaje (luego te explicaremos).
Si lo ejecutas, verás que crea una matriz de puntos sobre cualquier superficie NURBS que le pongas (luego
podrás usar esos puntos para construir lo que tú quieras).
1 Option Explicit
2 'Script Base (fragmento)
3 'Script written by <carlos de la b>
4 'Script version lunes, 31 de marzo de 2008 18:46:18
5
6 Call FaceSurface()
7 Sub FaceSurface()
8
9 'Variables
10 Dim strSurface
11 Dim arrDomainU, arrDomainV
12 Dim ParamU, ParamV, arrPoint
13 Dim i, j
14 Dim SecU, SecV
15
16 'Cantidad de divisiones
17 SecU = 10
18 SecV = 10
19
20 'Input
21 strSurface = Rhino.GetObject("Selecciona una superficie")
22 If IsNull(strSurface) Then Exit Sub
23
24 arrDomainU = Rhino.SurfaceDomain(strSurface, 0)
25 arrDomainV = Rhino.SurfaceDomain(strSurface, 1)
26
27 'Looping!
28 For i = 0 To SecU
29 For j = 0 To SecV
30
31 'Divisiones
32 ParamU = arrDomainU(0) + i * ((arrDomainU(1) - arrDomainU(0) ) / SecU)
33 ParamV = arrDomainV(0) + j * ((arrDomainV(1) - arrDomainV(0) ) / SecV)
34
35 arrPoint = Rhino.EvaluateSurface(strSurface, Array(ParamU, ParamV))
36 Call Rhino.AddPoint(arrPoint)
37
38 Next
39 Next
40
41 End Sub
En él puedes ver el área Option Explicit (primeras 4 líneas), que es el encabezado del script, donde
especificas ésta modalidad de VBScript, pones el título y otros datos que nos ayuden a identificarlo.
Luego va la llamada principal (línea 6), con el comando Call, para que el Rhino ejecute la subrutina
principal, que aquí estamos llamando “FaceSurface”.
Seguido viene la subrutina principal (líneas 7 a 41), delimitada entre los comandos Sub y End Sub. Dentro
de ella puedes poner todos los procedimientos del script (como en éste caso), o sólo los iniciales con
llamadas a procedimientos secundarios (el caso nuestro script completo). Estos procedimientos son
combinaciones de comandos a través del uso de variables, que verás enseguida.
Después pueden ir los procedimientos secundarios (cualquier procedimiento que escribamos después de
la línea 41 de éste ejemplo). Ellos pueden ser otras subrutinas o funciones, que previamente sean llamadas
desde la subrutina principal.
Pág. 3 de 8
5. Guía básica de fundamentos del script
3. Manejo de datos con variables
Si tan sólo necesitaras que el Rhino hiciera una cantidad de tareas independientes automáticamente,
bastaría hacer llamadas de los comandos necesarios, uno detrás de otro. Pero como quieres hacer más
tareas con la información obtenida con esos comandos, necesitas usar variables.
Una variable es un posicionador de valor, como una caja que en la que se mete el valor de un dato. Si el
dato que obtienes con un comando lo guardas en una variable, luego lo puedes usar como parámetro para
crear algo más, combinando comandos.
Según lo que necesites, una variable aloja un determinado tipo de dato, es decir, una variante del tipo de
información que estás manejando: un número, una palabra, un objeto, etc.
3.1. Tipos de datos
Existe más de una docena de tipos de datos que se pueden manejar en RhinoScript. En principio, en el
taller nos concentraremos en 3: enteros, reales y strings.
Un entero o integer, es un número del conjunto de los enteros (números positivos o negativos, sin
decimales, como por ejemplo: 0, 1, -16, 31).
Un real o double, es un número del conjunto de los reales (números positivos o negativos, incluyendo
decimales, como por ejemplo: 0.1, -14.75, 22.5).
Un string es un dato de texto. Es alfanumérico, es decir, admite cualquier caracter, letra o número. (En una
variable que definas como string, puedes escribir números, pero el ordenador los alojará como texto, o sea,
que no puedes hacer operaciones con ellos como sumarlos). Ejemplo:
"Selecciona una superficie"
Cuando consultes un método en la ayuda, presta mucha atención al tipo de dato que necesita y que se
obtiene con el método seleccionado. Dependiendo de lo que retorne puede ser lo que estés buscando o no.
3.2. Trabajar con variables
Hay tres pasos que necesita una variable:
1. Declarar la variable: con el comando Dim, decirle al programa qué nombre quieres usar.
2. Asignar la variable: darle a un valor para almacenar.
3. Usar la variable: recuperar el valor almacenado para usarlo en el programa.
Si ves en lo que te hemos mostrado del script, por ejemplo, la variable que llamamos “SecU” está declarada
en la línea 14, en la línea 17 se le asigna como valor el numero 10, y se usa en las líneas 28 y 32 para
hacer dos cosas diferentes.
Si necesitas cambiar el parámetro, sólo tienes que reescribir el valor asignado y el resultado cambiará sin
tener que tocar las instrucciones en las que se usa. Por eso es una variable.
También puedes ver que la variable “strSurface”, que en la línea 10 se declara, en la línea 21 se le asigna
un valor, y se usa en las líneas 22, 24, 25 y 35.
Ésta variable aloja un valor —asignado— del tipo string (el prefijo “str” te ayuda a reconocerlo). Éste valor se
obtiene del método GetObject. Si consultas la ayuda, verás que es un método para trabajar con objetos,
que retorna el ObjectID del objeto, su código identificador dentro del Rhino. O sea, que manejas el objeto,
no a través de una definición geométrica, sino de un string que lo identifica.
3.2.1. Arrays
Son variables que pueden alojar más de un dato. Un array es un arreglo, un conjunto ordenado de datos. El
orden de los espacios que se reservan dentro del array para alojar datos se llama índice. El primer dato
dentro de un array es de índice 0; el segundo, índice 1; el tercero, índice 2, etc.
En la línea 24 del script, la variable “arrDomainU” es un array (reconócelo por el prefijo “arr”) que, según el
método SurfaceDomain, aloja dos datos, el de índice 0, que es el origen del dominio y el de índice 1 el fin.
En la línea 32, es usada separando los datos por su índice: arrDomainU(0) y arrDomainU(1).
Pág. 4 de 8
6. Guía básica de fundamentos del script
En la línea 35, las variables “paramU” y “paramV” son usadas para armar un array, para poder usar el
método EvaluateSurface que, como ves en la ayuda, retorna otro array, ésta vez de tres datos: las
coordenadas 3D del punto, que luego son usadas para dibujarlo con AddPoint.
3.2.2. Arrays bidimensionales
En los casos anteriores, los arrays están hechos de un conjunto de dos o tres datos. También pueden ser
de más de un conjunto, como los bidimensionales.
Un array bidimensional lo constituyen dos grupos de conjuntos de datos, creando una matriz de 2 por n. En
el siguiente script lo vemos:
20 'Array bidimensional
21 ReDim Colec2D(SecU, SecV)
22
23 'Input
24 strSurface = Rhino.GetObject("Selecciona la superficie")
25 If IsNull(strSurface) Then Exit Sub
26
27 arrDomainU = Rhino.SurfaceDomain(strSurface, 0)
28 arrDomainV = Rhino.SurfaceDomain(strSurface, 1)
29
30 'Looping!
31 For i = 0 To SecU
32 For j = 0 To SecV
33
34 'Divisiones
35 ParamU = arrDomainU(0) + i * ((arrDomainU(1) - arrDomainU(0) ) / SecU)
36 ParamV = arrDomainV(0) + j * ((arrDomainV(1) - arrDomainV(0) ) / SecV)
37
38 arrPoint = Rhino.EvaluateSurface(strSurface, Array(ParamU, ParamV))
39 Call Rhino.AddPoint (arrPoint)
40
41 Colec2D(i,j) = arrPoint
42
43 Next
44 Next
45
46 Call Rhino.HideObject(strSurface)
47
48 Dim nPt1, nPt2, nPt3, nPt4
49
50 'Looping!
51 For i = 0 To (SecU - 1)
52 For j = 0 To (SecV - 1)
53
54 nPt1 = Colec2D(i, j)
55 nPt2 = Colec2D(i + 1, j)
56 nPt3 = Colec2D(i + 1, j + 1)
57 nPt4 = Colec2D(i, j + 1)
58
59 'Llamadas de funciones
60 Dim Curve: Curve = FuncCrv(nPt1, nPt2, nPt3, nPt4)
61 Dim NormalLine: NormalLine = FuncNormal(nPt1, nPt2, nPt3, nPt4)
62 Dim Constructor: Constructor = FuncConst(nPt1, nPt2, nPt3, nPt4, Curve, NormalLine)
63
64 Next
65 Next
66
67 End Sub
68
Ésta es la subrutina principal del script base completo (las primeras 19 líneas no cambian). En la línea 21 se
declara el array bidimensional, que al especificar sus dimensiones (SecU, SecV), tiene que ser declarado
con el comando ReDim, en vez de Dim.
Pág. 5 de 8
7. Guía básica de fundamentos del script
3.3. Loops incrementales
Son loops de estructura For ... Next. Un loop incremental es un bucle que ejecuta de forma iterativa el
código que lo contiene, incrementando cada vez el valor de la variable de iteración (i) hasta llegar al valor
que completa el comando To (SecU).
Los loops incrementales se pueden anidar, es decir, hacer un loop dentro de un loop. Éste es el caso de
todos los loops del script base. De ésta manera, el loop interno se ejecuta SecV veces por cada vez que se
ejecuta el loop externo, que en total son SecU veces. O sea, que estamos generando una matriz de SecU
por SecV.
En la línea 41 estamos asignando esa matriz al array bidimensional.
Te alentamos a descubras el resto del código con tus compañeros, con apoyo de los documentos de ayuda.
4. Funciones personalizadas
Por último, el script tiene varias funciones personalizadas, en el área de los procedimientos secundarios.
Los bloques se delimitan entre los comandos Function y End Function, y sólo son ejecutados cuando
son llamamos desde un procedimiento anterior (en éste caso, la subrutina principal).
Las tres funciones están siendo llamadas en las líneas 60, 61 y 62.
Son funciones que puedes hacer cuando necesites componer un grupo de tareas personalizadas, que no
exista ya entre los métodos RhinoScript y las funciones VBScript, o simplemente para ejecutar un grupo de
código desde más de un nivel del script, evitando tener que escribirlo varias veces.
La declaración de las funciones lleva una lista de argumentos (entre paréntesis, separados por comas), que
son como una declaración interna de variables que serán usadas pasando los valores argumentados en la
llamada de la función. Nota que los nombres no tienen que coincidir, pero sí el orden: la variable nPt1
define el argumento Pt1, la nPt2 el Pt2, etc.
Pág. 6 de 8
8. Guía básica de fundamentos del script
69 'Funciones
70 Function FuncCrv(Pt1, Pt2, Pt3, Pt4)
71
72 Dim Curva: Curva = Rhino.AddCurve(Array(Pt1, Pt2, Pt3, Pt4, Pt1))
73
74 FuncCrv = Curva
75 End Function
76
77 Function FuncNormal(Pt1, Pt2, Pt3, Pt4)
78
79 Dim DomU, DomV, Quad, normal, LineNormal
80 Dim ParamU, ParamV, arrPt
81
82 Quad = Rhino.AddSrfPt(Array(Pt1, Pt2, Pt3, Pt4))
83
84 DomU = Rhino.SurfaceDomain(Quad, 0)
85 DomV = Rhino.SurfaceDomain(Quad, 1)
86
87 ParamU = DomU(0) + ( (DomU(1) - DomU(0) ) / 2)
88 ParamV = DomV(0) + ( (DomV(1) - DomV(0) ) / 2)
89
90 arrPt = Rhino.EvaluateSurface(Quad, Array(ParamU, ParamV))
91
92 normal = Rhino.SurfaceNormal(Quad, Array(ParamU, ParamV))
93 LineNormal = Rhino.addLine(arrPt, Rhino.VectorAdd(arrPt, normal))
94
95 Call Rhino.DeleteObject(Quad)
96
97 'Aquí determinas la extensión del eje
98 LineNormal = Rhino.ExtendCurveLength(LineNormal, 0, 1, 3.00)
99
100 FuncNormal = LineNormal
101 End Function
102
103 Function FuncConst(Pt1, Pt2, Pt3, Pt4, Curve, vector)
104
105 Dim Edge
106 Edge = Rhino.addPolyline(Array(Pt1, Pt2, Pt3, Pt4, Pt1))
107
108 Call Rhino.MoveObject (Curve, Rhino.CurveStartPoint(vector), Rhino.CurveEndPoint(vector))
109 Call Rhino.ScaleObject (Curve, Rhino.CurveEndPoint(vector), Array(0.8, 0.8, 0.8))
110 Call Rhino.AddLoftSrf (Array(Curve, Edge), , ,3)
111 End Function
Dentro de cada función puedes colocar la cantidad de instrucciones que quieras o asignar valor a la función
y usarla como si fuera una variable. Si lo haces, te recomendamos que sea al final del procedimiento, como
puedes ver en las líneas 74 y 100.
Te alentamos a que ejecutes el script completo sobre tus superficies y que descubras el funcionamiento de
éstos procedimientos con tus compañeros, con apoyo de los documentos de ayuda.
Las variables que definas dentro de un procedimiento secundario, sólo servirán para combinar comandos
dentro del procedimiento. Una vez que se haya ejecutado, y se regrese a la subrutina principal no podrás
usarlos. Es decir, no declares una variable dentro de una función para luego usarla en la subrutina principal,
porque ahí no está declarada.
Pág. 7 de 8
9. Guía básica de fundamentos del script
Extra Ball!
Sugerencias para el proyecto
Mientras decides qué tipo de adaptación al entorno quieres implementar en tu proyecto, trata de probar el
script modificando los parámetros y sustituyendo o colocando más métodos y funciones.
Podrías intentar, por ejemplo, con éstos métodos:
Interacción e información:
• GetInteger
• GetReal
• GetPoint
• Print
• MessageBox
Evaluación:
• DivideCurve
• EvaluateSurface
• SurfaceNormal
• SurfaceFrame
• SurfaceCurvature
• DistanceToPlane
Geometría:
• AddCurve
• AddArc3Pt
• AddBox
• AddLoftSrf
Transformación:
• MoveObject
• RotateObject
• ScaleObject
Nuestra Web
Grupo de Diseño Emergente Sudamericano
http://www.designemergente.org/
Recursos Web
Stylianos Dritsas - jeneratiff.
http://www.jeneratiff.com/doku.php
Marc Fornes - theverymany.
http://www.theverymany.net/
RhinoScript Wiki.
http://en.wiki.mcneel.com/default.aspx/McNeel/RhinoScript.html
David Rutten - RhinoScript101 for Rhinoceros 4.0 (PDF)
http://en.wiki.mcneel.com/default.aspx/McNeel/RhinoScript101.html
Skylar Tibbits - SJET.
http://sjet.wordpress.com/
Como anexo, se incluye el script base, para ser impreso y usado como cuaderno de anotaciones durante el
taller.
Pág. 8 de 8
10. Una breve y suculenta descripción de
un script.
‘Nunca olvidar incluir esta frase!!!
Option Explicit
‘Script written by <carlos de la b>
‘Script copyrighted by <carlos de la b>
‘Script version lunes, 31 de marzo de 2008 18:46:18
Call FaceSuperficie()
Sub FaceSuperficie()
‘Aquí declaramos las variables, como una lista de ingredientes
Dim strSurface
Dim arrDomU, arrDomV
Dim arrParU, arrParV, arrPt
Dim i, j
Dim secu, secv
‘Indicamos el número de divisiones de la superfice
secu = 20
secv = 20
‘Ahora creamos una caja vacia , para poner todos los puntos dentro
ReDim colec2d(secu, secv)
‘Con esta órden seleccionamos la superficie
strSurface = Rhino.GetObject (“Select Surface”, 8)
If IsNull(strSurface) Then Exit Sub
‘Ahora definimos nuestras coordenadas locales en la superficie
arrDomU = Rhino.SurfaceDomain (strSurface, 0)
arrDomV = Rhino.SurfaceDomain (strSurface, 1)
11. ‘Esta es la manera de hacer los loops, que no es más que la cantidad
de veces que haremos correr el script
For i = 0 To secu
For j = 0 To secv
‘Aqui indicamos donde estarán ubicados todos los puntos en la superficie
arrParU = arrDomU(0)+ i *((arrDomU(1) - arrDomU(0))/ secu)
arrParV = arrDomV(0)+ j *((arrDomV(1) - arrDomV(0))/ secv)
arrPt = Rhino.EvaluateSurface(strSurface,Array(arrParU,arrParV))
‘Estas ordenes harán que se impriman los puntos sobre la superficie y
luego la esconderá
Call Rhino.AddPoint (arrPt)
Call Rhino.HideObject(strSurface)
‘Aqui se colecciona las coordenadas de cada punto y se almacenan en
la caja vacia creada anteriormente
colec2d(i,j) = arrPt
Next
Next
‘Aqui renombramos los puntos
Dim Npt1, Npt2, Npt3, Npt4
‘Usamos este par de loops para pasar por cada uno de los puntos creados
For i = 0 To (secu - 1)
For j = 0 To (secv - 1)
‘Ubicación de los puntos
Npt1 = colec2d(i, j)
Npt2 = colec2d(i + 1, j)
Npt3 = colec2d(i + 1, j + 1)
Npt4 = colec2d(i, j + 1)
Next
Next
End Sub
* el script que cambiará tu vida....