manual básico de scripting con RhinoCommon en Grasshopper aplicado al diseño generativo de arquitectura
lenguajes C# y python miguel vidal calvet www.frikearq.com edición Octubre 2011
notas previas Esto NO es un manual de programación Este documento no pretende ser una referencia para quien quiera aprender a programar. Este manual es un pequeño compendio de ejercicios, a modo de cuaderno de apuntes, destinado a quien quiera introducirse en la elaboración de scripts para generar diseños. Necesariamente, se pasará por encima de los conceptos básicos de la programación para empezar a escribir código que entienda la máquina. Será una pasada rápida, pero suficiente para ponerse a escribir códgio lo antes posible de una manera solvente. Esto SÍ es un manual de scripting para Rhino elaborado por diseñadores para diseñadores
manual básico de scripting con Grasshopper en C# y python por miguel vidal calvet y guillermo ramírez camarero edición Julio 2011 grasshopper v0.8.0010
manual básico de scripting con Grasshopper en C# y python aplicado al diseño generativo de arquitectura
índice A. Nociones básicas de programación
B. RhinoCommon en Grasshopper
A.1. Introducción a la programación aplicado al diseño generativo
B.1. Microejercicios de iniciación a C# y RhinoCommon
01 Programación orientada a objetos. 02 Interfaz de scripting en Grasshopper
E01 Dibujar cuatro puntos formando los vértices de un cuadrado E02 Dibujar cuatro puntos formando los vértices de un cuadrado a partir de un vértice inicial y un valor de lado E03 Medir las distancias diagonales e imprimirlas en un panel E04 Introducir los puntos en una lista E05 Unir los puntos en diagonal con líneas E06 Dibujar un rectángulo a partir de esos puntos E07 Elaborar una función que fabrica un vectores entre dos puntos E08 Fabricar vectores a partir de los vértices y visualizarlos dándoles color E09 Unir los vértices consecutivamente mediante líneas E10 Extraer los puntos medios de cada segmento de rectángulo y unirlos con líneas
A.2. Tipos de datos, declaración y operaciones con variables 03 Declaración de datos simples: enteros, decimales y booleanos. 04 Declaración de datos compuestos: cadenas de caracteres, listas, y estructura de árbol de datos. A.3. Claúsulas condicionales e Iteración 05 Cláusulas condicionales: cláusulas if ... else y switch. 06 Estructuras terativas: bucles for y while. A.4. Funciones: abstracción 07 Estructura de una Función 08 Valor de una función: return
B.2. Ejemplos de aplicación B2.1 Pabellón temporal de la galería Serpentine del año 2002, Toyo Ito con Cecil Balmond
ANEXOS ANEXO 1. Estructura de RhinoCommon ANEXO 2. Processing ANEXO 3. Glosario de términos
A
Programaci贸n y dise帽o generativo
A1
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
introducción a la programación aplicada al diseño generativo
01. ¿C# o python?
03. ¿Qué es la programación orientada a objetos?
C# es un lenguaje de programación orientada a objetos basado en C y C++, es muy similar a Java, tiene una extensa y actualizada documentación y está construido por una plataforma muy extendida como .NET. Debido a esto, hacen que sea un lenguaje idóneo para dar los primeros pasos en los entornos de programación.
La programación orientada a objetos es un paradigma de programación que usa objetos y sus interacciones para diseñar aplicaciones y programas informáticos.
En cuanto a las similaridades, principalmente con Java, y también C++, hacen que sea sencillo entender y pasar fácilmente a otros entornos útiles para los diseñadores, sobre todo, Processing y Arduino, o también scripting con Maya. También puede ser un buen comienzo para más adelante adoptar con facilidad Python, que probablemente sea un lenguaje de programación estándar para desarrollar scripts en software de 3D y otros.
El estado está compuesto de datos, será uno o varios atributos a los que se habrán asignado unos valores concretos (datos). El comportamiento está definido por los métodos o mensajes a los que sabe responder dicho objeto, es decir, qué operaciones se pueden realizar con él. La identidad es una propiedad de un objeto que lo diferencia del resto, dicho con otras palabras, es su identificador (concepto análogo al de identificador de una variable o una constante).
En cuanto a la documentación, desde un punto de vista meramente práctico, el hecho de estar respaldado por una plataforma potente como .NET (desarrollada por Microsoft), aseguran las actualizaciones y soporte del mismo. Para consultar la referencia, ir a: http://msdn.microsoft.com/en-us/library/kx37x362.aspx
Los objetos son entidades que tienen un determinado estado, comportamiento (método) e identidad:
Un objeto contiene toda la información que permite definirlo e identificarlo frente a otros objetos pertenecientes a otras clases e incluso frente a objetos de una misma clase, al poder tener valores bien diferenciados en sus atributos. A su vez, los objetos disponen de mecanismos de interacción llamados métodos, que favorecen la comunicación entre ellos. Esta comunicación favorece a su vez el cambio de estado en los propios objetos. Esta característica lleva a tratarlos como unidades indivisibles, en las que no se separa el estado y el comportamiento.
Fuente: wikipedia.org p05
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
03. Interfaz de scripting en Grasshopper
Entradas y salidas de variables del componente script
Existen tres componentes de scripting en Grasshopper en los que se puede escribir código en otros tantos lenguajes: - C# Script - VB Script - Python Script
Podemos trabajar con tantas variables como queramos dentro del código que escribamos y también podemos utilizar las entradas del componente para introducir datos de la definición de Grasshopper o de archivos de Rhino. Además, podremos también tener salidas de datos a nuestra elección.
Para extraer estos componentes, ir a la pestaña de Math > Script. Los dos primeros componentes vienen cargados en la instalación de Grasshopper. En el momento de la edición de este manual, el componente de scripting con Python únicamente puede utilizarse con Rhino 5. Para instalarlo, visitar: http://www.food4rhino.com.
Para modificar las entradas de datos, haremos click con el botón con el botón derecho e ir a Input manager ... Además, éstas deben ser formateadas del modo adecuado para trabajar con ellas en nuestro componente. Hablaremos de ello en el siguiente capítulo. A continuación, unas imágenes con los pasos de este proceso
Edición del componente script Para escribir código en estos componentes, hacer doble click en el cuerpo del mismo o bien click con el botón derecho y luego Edit source. Se abrirá una ventana en la que escribiremos nuestro código en donde se lee “// your code here”. Para modificar salidas de datos, hacer click con el botón con el botón derecho e ir a Output manager ... Estos datos están formateados por el componente como Object y Grasshopper lo entiende como Generic Data (dato genérico), así que no es necesario darle ningún formato específico.
escribiremos el código a partir de esta línea
p06
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
La salida out La salida out del componente script tiene dos funciones: - devolver los posibles errores del código - imprimir los datos que deseemos
Esta salida sería como la consola de cualquier entorno de programación. Para visualizar cualquiera de ambos casos anteriores, conectaremos un panel.
La función Print La función Print escribe cadenas de caractares (ver tipos de datos compuestos), es decir, texto en la salida out del componente script. Esta función nos será muy útil para ir comprobando la validez de nuestro código, como veremos a lo largo del manual.
C#
python Print(“hola, cocacola);
NOTA: A partir de ahora, todo el texto con la apariencia del párrafo inmediatamente superior, corresponderá a código que introduciremos en el componente de script a partir de la línea donde se lee el texto “//your code here”, como antes se ha comentado. p07
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
Comentarios en el código Otro asunto que también va a sernos muy útil para hacer nuestros scripts es hacer comentarios dentro del código. Los comentarios son texto que forma parte del código, pero que la máquina va a obviar cuando lo está leyendo. Esto nos puede servir para anotar aspectos relevantes del código o asuntos que son importantes recordar y también para ordenarlo. Esto nos servirá no sólo para no perdernos nosotros mismos sino para posibles futuras segundas o terceras personas que puedan acceder a él. Existen dos maneras de comentar el código - comentario de una sola línea: cualquier texto que escribamos en una línea a partir de los caracteres de barra “//” quedará comentado.
C#
python //la función print sirve para imprimir texto Print(“hola, cocacola);
- comentario multilínea: cualesquiera línea o líneas de texto entre los caracteres de apertura “/*” y de cierrre “*/” quedarán comentadas.
C#
python /* código de prueba escrito como primer ejercicio del manual de scripting de Frikearq :) */ //la función print sirve para imprimir texto Print(“hola, cocacola);
El intérprete lee el código línea a línea de arriba a abajo y de izquierda a derecha. Para que el intérprete cambie de línea, es necesario añadir “;” al final de cada una de ellas, para que entienda que el código continúa en la siguiente línea. p08
A2
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
tipos de datos, declaración y operaciones con variables
05. Tipos de datos primitivos Tipos de datos primitivos que más vamos a utilizar y sus identificadores
C#
tipo de dato
nombre (en inglés)
python
identificador
número entero
integer
int
número decimal
double precision floatingpoint number
double
valor booleano (verdadero o falso)
boolean value (true o false)
bool
caracter
character
char
Y un dato compuesto para empezar ... tipo de dato
nombre (en inglés)
identificador
cadena de caracteres
string
string
NOTA: Una cadena de caracteres, o sea, texto, es un tipo de dato, como el nombre indica, compuesto de una sucesión de caracteres. El motivo por el cual lo mostramos en este punto, es que la salida out imprime cadena de caracteres, esto quiere decir, que para que devuelva cualquier dato hay que convertirlo previamente a string. Esto nos será útil para ir mostrando en pantalla lo que vayamos haciendo.
p09
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
Algunas conversiones de datos habituales Existen funciones para convertir datos de un tipo a otro.
C#
python Convertir ... ... a entero
Convert.ToInt32(valor) o (int)valor
... a decimal
Convert.ToDouble(valor) o (double)valor
... a booleano
Convert.ToBoolean(valor)
... a cadena de caracteres
valor .ToString()
NOTA: En programación, sigue una lógica binaria, de verdadero o falso, en la que al valor numérico entero “0” se le asigna el valor booleano “falso” (false) y al valor numérico entero “1” se le asigna el valor booleano “verdadero” (true).
int entero = 1; double decimal = 2.5; bool verdadero = true; //debemos convertir los datos a cadena de caracteres para poder imprimirlos en pantalla Print(entero.ToString()); Print(decimal.ToString()); Print(verdadero.ToString());
p010
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
04. Variables Una variable es un nombre que se asigna a una cantidad conocida o desconocida de información para poder trabajar con este nombre, independientemente de la información que representa. La mayor parte del trabajo que vamos a realizar con nuestros scripts lo haremos a través de variables. Para trabajar con variables es necesario inicializarlas según el tipo de dato que representa. El esquema básico que sigue el lenguaje de programación C# es el siguiente:
C#
python
Inicialización de variables
identificador de variable
nombre de asignación variable
valor
(el tipo de dato que va a (cualquier nombre contener esa variable) excepto los reservados)
int
a
=
12
;
Asignación de valor a variables
identificador de variable
(el tipo de dato que va a contener esa variable)
int
nombre de asignación variable a
valor
=
12
;
=
12
;
Inicialización y asignación en la misma línea
int
a
p011
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
07. Datos compuestos Antes de comenzar con este apartado, recordamos que para declarar, inicializar y asignar valor a variables de datos compuestos, seguiremos el mismo esquema que habíamos visto en el apartado de variables, pero con una excepción: debemos instanciarlos.
tipo de dato
(en qué formato vamos a almacenar los datos)
identificador nombre asignación instanciación valor (new seguido del = de variable de tipo de dato) (el tipo de variable dato que va a contener esa variable)
(el que queramos)
Listas En programación, las listas son sucesiones ordenadas de elementos. Para declarar e instanciar una lista, seguimos el esquema anterior:
python
C#
List<Point3d> listaPts = new List<Point3d>();
La lista que acabamos de instanciar está vacía, para añadir elementos dentro de ella, utilizamos la función .Add.
listaPts.Add(new Point3d(1, 1, 1)); listaPts.Add(new Point3d(2, 2, 2)); listaPts.Add(new Point3d(3, 3, 3));
Finalmente, igualamos la salida con la lista que hemos fabricado.
A = listaPts;
Para extraer un ítem, utilizamos el siguiente método, que también lo podemos asignar a otra salida del componente, después de haberla añadido con Ouput manager..
B = listaPts[1]; p012
manual de scripting con grasshopper Miguel Vidal Guillermo RamĂrez
Matrices
C# El trabajo con matrices es diferente al de listas. Para inicializar una matriz, es necesario darle un tamaĂąo y no se pueden aĂąadir elementos, sino que es necesario igualar cada item a un valor.
Point3d[] puntos = new Point3d[3]; puntos[0] = new Point3d(1, 1, 1); puntos[1] = new Point3d(2, 2, 2); puntos[2] = new Point3d(3, 3, 3); A = puntos; B = puntos[2];
p013
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
Estructura de árbol de datos
C#
python DataTree<Point3d> puntos = new DataTree<Point3d>(); puntos.Add(new Point3d(1, 1, 1)); puntos.Add(new Point3d(2, 2, 2)); puntos.Add(new Point3d(3, 3, 3)); A = puntos; B = puntos.Branch(0)[0];
También podemos asignar rutas en las que queremos almacenar la estructura de árbol de datos, que declararemos con el tipo GH_Path. GH_Path se construye con números enteros. Las rutas o paths son nombres a las que se le asignan a la estructura de árbol de datos.
DataTree<Point3d> puntos = new DataTree<Point3d>(); GH_Path ruta = new GH_Path(2); puntos.Add(new Point3d(1, 1, 1), ruta); puntos.Add(new Point3d(2, 2, 2), ruta); puntos.Add(new Point3d(3, 3, 3), ruta); A = puntos; B = puntos.Branch(ruta)[0];
p014
A3
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
07. Iteración inicialización
comprobación
si es falso
si es verdadero declaración
actualización (según un rango que establezcamos)
C#
python
for(inicialización; comprobación; rango de actualizacion) { declaración; }
for inicializacion in range(comienzo, rango): declaración
p015
A4
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
08. Funciones: abstracción Las funciones son subrutinas incluidas dentro de un programa más grande y que nos permite resolver una tarea específica. Las funciones son útiles para desarrollar tareas que se van a repetir dentro del programa principal y para, de esta manera, modular el código en apartados pequeños. Las funciones en C# devuelven un único valor, que se asigna con return. Dicha subrutina, cuando es llamada dentro del código principal, hace que la lectura de ese código se detenga y se dirija a ejecutar el código de la subrutina. En ciertos lenguajes de programación, como C#, las funciones son subrutinas que devuelven un valor. En los componentes de Grasshopper, tendremos que añadir el código de la función en el apartado de “//<Custom additional code>“. Nuestra primera función, que fabricará vectores a partir de dos puntos, se llamará Vector2Puntos, y la podremos llamar desde nuestro código como una función más de C# o RhnoCommon.
C#
python Estructura de una función
TIPO QUE DEVUELVE NOMBRE (en caso de que devuelva algún valor) {
(
PARÁMETROS DE LA FUNCIÓN (que hay que declarar en este punto)
OPERACIONES DE LA FUNCIÓN return
)
VALOR QUE QUEREMOS QUE DEVUELVA ;
}
p016
B
RhnoCommon en Grasshopper
B.1
microejercicios de creaci贸n de geometr铆a con RhinoCommon
E01
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
dibujar cuatro puntos formando los vértices de un cuadrado
01. objetivos - trabajar con variables - construir puntos con RhinoCommon
02. conceptos clave double, Point3d 03. procedimiento
C# private void RunScript(object x, object y, ref object A, ref object B, ref object C, ref object D) { //declaramos las variables double lado; // valor numérico decimal Point3d vertice0; //punto3d (una clase de Rhino) Point3d vertice1; Point3d vertice2; Point3d vertice3; // asignamos valores a las variables lado = 20; // para los puntos, invocamos la clase Point3d con new. El valor de las coordenadas X e Y del verticeOrigen (propiedad de una clase) y le sumamos el valor de lado vertice0 = new Point3d(0, 0, 0); vertice1 = new Point3d(0, lado, 0); vertice2 = new Point3d(lado, lado, 0); vertice3 = new Point3d(0, lado, 0); // asignamos cada uno de los puntos a una salida del componente A = vertice0; B = vertice1; C = vertice2; D = vertice3; }
python # en primer lugar, tenemos que importar el módulo de geometría de Rhino import Rhino.Geometry as rg # con “as” asignamos un “apodo” a ese módolu, de esta manera, cada vez que llamamos a una clase de ese módulo, no tendremos que escribir todo su nombre, sino sólo ese “apodo” # declaramos y asignamos la variable de lado lado = 20 # declaramos y asignamos las variables de puntos vertice0 = rg.Point3d.Origin vertice1 = rg.Point3d(lado, 0, 0) vertice2 = rg.Point3d(lado, lado, 0) vertice3 = rg.Point3d(0, lado, 0) # asignamos un vértice a cada una de las salidas del componente a = vertice0 b = vertice1 c = vertice2 d = vertice3
p019
E02
dibujar cuatro puntos formando los vértices de un cuadrado a partir de un vértice inicial y un valor de lado
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
01. objetivos - acceder a propiedades de clases - trabajar con input de datos externos al componente
02. conceptos clave double, Point3d 03. procedimiento Tomamos dos variables exteriores al componente de script: - una primera, que toma valores numéricos de un slider. Deberemos hacer click con el botón derecho en la entrada y luego “Type hint” para que lo entienda como un dato de tipo numérico decimal (double). - otra segunda, a la que llamamos verticeInicial, que toma el valor del vértice incial a partir del cual posicionamos el resto de puntos y que inicializamos como el tipo Point3d de Rhino.
C#
python
private void RunScript(double lado, Point3d verticeOrigen, ref object A, ref object B, ref object C, ref object D){ //declaramos las variables como punto3d (Point3d una clase de Rhino) en una única línea Point3d vertice1,vertice2,vertice3; // asignamos un valor a la variable invocando la clase Point3d con new El valor de las coordenadas X e Y del punto(propiedad de una clase) y le sumamos el valor de lado vertice1 = new Point3d(verticeOrigen.X + lado, verticeOrigen.Y, 0); vertice2 = new Point3d(verticeOrigen.X + lado, verticeOrigen.Y + lado, 0); vertice3 = new Point3d(verticeOrigen.X, verticeOrigen.Y + lado, 0); // asignamos cada uno de los puntos a una salida A = verticeOrigen; B = vertice1; C = vertice2; D = vertice3; }
# en primer lugar, tenemos que importar el módulo de geometría de Rhino import Rhino.Geometry as rg # con “as” asignamos un “apodo” cada vez que llamamos a una clase de ese módulo # declaramos y asignamos las variables de puntos vertice0 = rg.Point3d.Origin vertice1 = rg.Point3d(lado, 0, 0) vertice2 = rg.Point3d(lado, lado, 0) vertice3 = rg.Point3d(0, lado, 0) # asignamos un vértice a cada una de las salidas del componente a = vertice0 b = vertice1 c = vertice2 d = vertice3
p020
E03
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
medir las distancias diagonales e imprimirlas en un panel
01. objetivos - imprimir texto por la salida out del componente de script y utilizar cadenas de caracteres - utilizar funciones matemáticas en el código y los métodos de Math - trabajar con estructuras condicionales
02. conceptos clave double, Point3d, Distance, Print, if, else 03. procedimiento Primero, calculamos la distancia algebraicomente y, luego, medimos la distancia con el método Distance de Pointd3d. Por último, comprobamos que ambas coinciden.
C#
python
//// añadimos el código del ejercicio anterior //// // declaramos y asignamos las variables double diagAlg1 = Math.Sqrt(Math.Pow((vertice2.XverticeOrigen.X), 2)+Math.Pow((vertice2.YverticeOrigen.Y),2));//Math.Sqrt() es una raíz cuadrada double diagAlg2 = Math.Sqrt(Math.Pow((vertice3.X vertice1.X), 2) + Math.Pow((vertice3.Y - vertice1.Y), 2)); double diagPt1 = verticeOrigen.DistanceTo(vertice2); double diagPt2 = vertice1.DistanceTo(vertice3); // Math.Round redondea a los decimales que queramos diagAlg1 = Math.Round(diagAlg1, 2); diagAlg2 = Math.Round(diagAlg2, 2); diagPt1 = Math.Round(diagPt1, 2); diagPt2 = Math.Round(diagPt2, 2); // estructura condicional if((Math.Round(diagAlg1, 2) == Math.Round(diagPt1, 2)) && (Math.Round(diagAlg2, 2) == Math.Round(diagPt2, 2))) { Print(“guay!”); } else { Print(“horror!”); }
### añadimos, primero, el código del ejercicio anterior ### # importamos los módulos que vamos a utilizar import math # declaramos y asignamos las variables de las diagonales diagAlg1 = math.sqrt(math.pow((vertice2.X-vertice0.X), 2)+ math.pow((vertice2.Y-vertice0.Y) ,2)) #math.sqrt() es una raíz cuadrada diagAlg2 = math.sqrt(math.pow((vertice3.X - vertice1.X), 2) + math.pow((vertice3.Y - vertice1.Y), 2)); diagPt1 = vertice0.DistanceTo(vertice2) diagPt2 = vertice1.DistanceTo(vertice3) # round redondea el valor a tantos decimales como queramos diagAlg1 = round(diagAlg1, 2) diagAlg2 = round(diagAlg2, 2) diagPt1 = round(diagPt1, 2) diagPt2 = round(diagPt2, 2) # estructura condicional if((round(diagAlg1, 2) == round(diagPt1, 2)) & (round(diagAlg2, 2) == round(diagPt2, 2))): print(“guay!”) else: print(“horror!”) p021
E04
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
introducir los puntos en una lista
01. objetivos - aprender a declarar, crear y añadir valores a una lista
02. conceptos clave List, new, Add 03. procedimiento
C#
python
private void RunScript(double lado, Point3d verticeOrigen, ref object A) { //declaramos las variables como punto3d (una clase de Rhino) Point3d vertice1 = new Point3d(verticeOrigen.X + lado, verticeOrigen.Y, 0); Point3d vertice2 = new Point3d(verticeOrigen.X + lado, verticeOrigen.Y + lado, 0); Point3d vertice3 = new Point3d(verticeOrigen.X, verticeOrigen.Y + lado, 0); // declaramos una lista de puntos llamada “vertices” List<Point3d> vertices; // utilizamos el constructor predeterminado para crear una lista de de puntos con una capacidad de 0 vertices = new List<Point3d>(); //añadimos valores a la lista en orden vertices.Add(verticeOrigen); vertices.Add(vertice1); vertices.Add(vertice2); vertices.Add(vertice3); // asignamos la lista a una salida A = vertices; }
# importamos los módulos que vamos a utilizar import math import Rhino.Geometry as rg # declaramos y asignamos las variables de puntos vertice0 = rg.Point3d.Origin vertice1 = rg.Point3d(lado, 0, 0) vertice2 = rg.Point3d(lado, lado, 0) vertice3 = rg.Point3d(0, lado, 0) # declaramos una lista a la que nombramos “vertices” vertices = [] # añadimos a los puntos anteriormente crados a esa lista de puntos vertices.append(vertice0) vertices.append(vertice1) vertices.append(vertice2) vertices.append(vertice3) a = vertices
p022
E05
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
dibujar un rectángulo a partir de esos puntos
01. objetivos - aprender a fabricar vectores, planos y rectángulos
02. conceptos clave Plane, Vector3d, Rectangle3d 03. procedimiento
C#
python
//// utilizamos el código del ejercicio anterior, añadiendo una nueva salida, a la que llamamos “R” //////
### utilizamos el mismo código del ejercicio anterior, añadiendo una nueva salida, a la que llamamos “R” ###
// para fabricar un rectángulo, necesitaremos un plano y dos números decimales para el ancho y el alto Rectangle3d rec; // podemos fabricar un plano de distintas maneras, pero vamos a hacerlo a partir de un punto base y dos vectores Plane planoRec; Point3d ptoOrigenPlano = vertices[0]; // podemos declarar la variable y asignarle valor en la misma linea Vector3d vecXPlano = new Vector3d();// para construir un vector necesitamos sus coordenadas XYZ // sobreescribimos las propiedades X, Y y Z del vector vecXPlano.X = vertices[1].X - vertices[0].X; vecXPlano.Y = vertices[1].Y - vertices[0].Y; vecXPlano.Z = vertices[1].Z - vertices[0].Z; // también podemos declarar y construir el vector en la misma línea Vector3d vecYPlano = new Vector3d(vertices[3].X vertices[0].X, vertices[3].Y - vertices[0].Y, vertices[3].Z - vertices[0].Z); planoRec = new Plane(ptoOrigenPlano, vecXPlano, vecYPlano); // ancho y alto: serán la misma medida, un lado double ladoRec = vertices[0].DistanceTo(vertices[1]); rec = new Rectangle3d(planoRec, ladoRec, ladoRec); R = rec;
# para fabricar un rectángulo,necesitaremos, en primer lugar, un plano y, en segundo lugar, dos números decimales para el ancho y el alto. ## PLANO: se define a partir de un punto y dos vectores ptoOrigenPlano = vertices[0] # punto de origen plano vecXPlano = rg.Vector3d.Unset # para definir los vectores, podemos, primero declaramos el vector como unset (“no definido”) y luego pasamos las variables X, Y, Z vecXPlano.X = vertices[1].X - vertices[0].X vecXPlano.Y = vertices[1].Y - vertices[0].Y vecXPlano.Z = vertices[1].Z - vertices[0].Z ## o también podemos declarar y asignar el valor al vector en la misma línea vecYPlano = rg.Vector3d(vertices[3].X - vertices[0].X, vertices[3].Y - vertices[0].Y, vertices[3].Z - vertices[0].Z) planoRec = rg.Plane(ptoOrigenPlano, vecXPlano, vecYPlano) ## ANCHO y ALTO: este caso, serán la misma medida, un lado ladoRec = vertices[0].DistanceTo(vertices[1]) rec = rg.Rectangle3d(planoRec, ladoRec, ladoRec)#rectángulo R = rec # salida de datos p023
E06
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
extraer los puntos medios y tercios de los segmentos del rectángulo anteriormente creado
01. objetivos - aprender cómo trabaja un bucle for - acceder a a métodos de curvas
02. conceptos clave for, List, List item, Add 03. procedimiento Si quieremos llevar a cabo una tarea muy repetitiva o que es iterativa, utlizaremos una secuencia de bucle for. En este caso, se tratará de extraer los puntos medios de todos los segmentos del rectángulo que antes hemos creado.
C#
python
//// utilizamos el mismo código que en el ejercicio anterior E05 con nuevas salidas en el componente, una para los puntos medios y otra para los puntos tercios, a las que llamamos PM y PT respectivamente //// // definimos listas para los puntos medios y tercios List<Point3d> ptosMedios = new List<Point3d>(); List<Point3d> ptosTercios = new List<Point3d>(); // no existe ningún método en la clase Rectangle3d de Rhino para poder acceder a sus segmentos. Para ello, debemos, primero, convertir el rectángulo en polilínea, con el que sí podremos trabajar con los segmentos Polyline pol = rec.ToPolyline(); // bucle para extraer los puntos medios y tercios for(int i = 0; i < pol.SegmentCount; i++) { ptosMedios.Add(pol.SegmentAt(i).PointAt(0.5)); ptosTercios.Add(pol.SegmentAt(i).PointAt(0.333333)); // .SegmentAt() es el método con el que accedemos a las coordenadas locales de una curva para obtener un punto. Una línea está definida localmente en un dominio entre 0 y 1. El punto medio estará en 0.5 y el tercio en 0.333. } PM = ptosMedios; PT = ptosTercios;
### utilizamos el mismo código que en el ejercicio anterior E05 con nuevas salidas en el componente, una para los puntos medios y otra para los puntos tercios, a las que llamamos PM y PT ### # definimos listas para los puntos medios y tercios ptosMedios =[] ptosTercios = [] # no existe ningún método en la clase Rectangle3d de Rhino para poder acceder a sus segmentos. Para ello, debemos, primero, convertir el rectángulo en polilínea, con el que sí podremos trabajar con los segmentos rec = rec.ToPolyline() # hacemos un bucle iterativo para unir puntos consectivamente. Es necesario indentado el código for i in range(0, rec.SegmentCount): # . SegmentCount es el método que nos devuelve el número de segmentos de la polilínea ptosMedios.append(rec.SegmentAt(i).PointAt(0.5)) # .SegmentAt() es el método con el que accedemos a las coordenadas locales de una curva para obtener un punto. Una línea está definida localmente en un dominio entre 0 y 1. El punto medio estará en 0.5 y el tercio en 0.333. PM = ptosMedios PT = ptosTercios p024
E07
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
unir consecutivamente los puntos medios y tercios mediante líneas
01. objetivos - repasar la estructura iterativa del bucle for y la condicional if ... else - aprender a dibujar líneas
02. conceptos clave for, List, List item, Add 03. procedimiento
C#
python
//// utilizamos el mismo código que en el ejercicio anterior con una nueva salida en el componente para las líneas,a la que llamamos “L” //// // declaración de lista de lineas para los lados List<Line> lineas = new List<Line>();
### utilizamos el mismo código que en el ejercicio anterior con una nueva salida en el componente para las líneas, a la que llamamos “L” ### # definimos una lista para las líneas lineas = []
// bucle para unir los vértices consecutivamente for(int i = 0; i < ptosMedios.Count; i++) { // en primer lugar, añadimos una excepción para el último elemento de la lista if(i == ptosMedios.Count - 1) { lineas.Add(new Line(ptosMedios[i], ptosTercios[0])); } // si no colocáramos la excepción al comienzo, obtendríamos un error por acceso a un exceso de índices de lista else { lineas.Add(new Line(ptosMedios[i], ptosTercios[i + 1])); } } L = lineas; // salida de datos
# hacemos un bucle iterativo para unir puntos consectivamente for i in range(0, len(ptosMedios)): # en primer lugar, añadimos una excepción para el último elemento de la lista if(i == len(ptosMedios) - 1): lineas.append(rg.Line(ptosMedios[i], ptosTercios[0])) # para añadir lineas en cada pasada del bucle, utilizamos el método append # si no colocáramos la excepción al comienzo, obtendríamos un error por acceso a un exceso de índices de lista else: lineas.append(rg.Line(ptosMedios[i], ptosTercios[i + 1])) # salida de datos L = lineas p025
E08
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
extraer las intersecciones de las proyecciiones de líneas anteriormente creadas
01. objetivos - conocer cómo se trabaja con intersecciones de geometría
02. conceptos clave Intersection 03. procedimiento Las intersecciones se encuentran en el espacio de nombres (Namespace) Intersect de Rhino. En este ejercicio, vamos a emplear el método para intersecciones de líneas, es decir, Intersect.Intersection.LineLine. Hay que tener en cuenta que el valor que devuelven las funciones de intersección es un booleano: verdadero (true) o falso (false) dependiendo de si hay intersección o no la hay. Vamos a aprender a continuación cómo extraer la geometría fruto de la intersección en los dos lenguajes.
C#
python
//// utilizamos el mismo código que en el ejercicio anterior con una nueva salida a la que llamamos “I” //// List<Point3d> intersecciones = new List<Point3d>(); double a, b; for(int i = 0; i < lineas.Count; i++) { if(i == lineas.Count - 1){ bool hayInterseccion = Rhino.Geometry.Intersect. Intersection.LineLine(lineas[i], lineas[0], out a, out b, 0.0, false); if(hayInterseccion){ intersecciones.Add(lineas[i].PointAt(a)); } } else{ bool hayInterseccion = Rhino.Geometry.Intersect. Intersection.LineLine(lineas[i], lineas[i + 1], out a, out b, 0.0, false); if(hayInterseccion){ intersecciones.Add(lineas[i].PointAt(a)); } } } I = intersecciones;
# utilizamos el mismo código que en el ejercicio anterior con una nueva salida en el componente para los puntos de intersección, a la que llamamos I # lista de intersecciones intersecciones = [] for i in range (0, len(lineas)): if(i == len(lineas) - 1): hayInterseccion, a, b = rg.Intersect.Intersection. LineLine(lineas[i], lineas[0], 0, False) # hayInterseccion (boolean), a y b (double) son los valores que devuelve la función de intersección. El primero nos dice si existe o no esa intersección. Los otros dos son los valores de coordenadas locales de dicha intersección para la primera y la segunda línea respectivamente else: hayInterseccion, a, b = rg.Intersect.Intersection. LineLine(lineas[i], lineas[i + 1], 0, False) intersecciones.append(lineas[i].PointAt(a)) I = intersecciones # comprobamos que las intersecciones de líneas no son las de los tramos de los segmento de línea sino de las líneas como segmentos infinitos p026
E09
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
elaborar una función para fabricar vectores entre dos puntos
01. objetivos - aprender a elaborar funciones
02. conceptos clave function, Vector3d, Rectangle3d 03. procedimiento Este código lo añadimos en el apartado “custom additional code” de tal manera que sirva para llamarlo en cualquier momento dentro del código principal.
//<Custom additional code> Vector3d Vector2Puntos(Point3d ptoA, Point3d ptoB) { Vector3d vec = new Vector3d(ptoB.X - ptoA.X, ptoB.Y ptoA.Y, ptoB.Z - ptoA.Z); return vec; }
p027
manual de scripting con grasshopper Miguel Vidal Guillermo RamĂrez
p028
B2
ejemplos de aplicaci贸n
B2
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
pabellón de la Serpentine Gallery 2002, Toyo Ito con Cecil Balmond
01. objetivos - crear geometría bidimensioneal y tridimensional con RhinoCommon - entender el funcionamiento de estructura de datos en programación orientada a objetos - aprender a trabajar con funciones para modular el código
02. conceptos clave List, DataTree, for, if 03. procedimiento
Fotografía: © David Martin, fuente: flickr.com/photos/avidday
El pabellón temporal del año 2002 de la galería Serpentine, proyectado por Toyo Ito con Cecil Balmond, de Arup, se construye a partir de un algoritmo iterativo que dibuja la cubierta. Partiendo de un cuadrado, se van uniendo consecutivamente los puntos medios con los puntos tercios de sus segmentos.
1. Dibujar el rectángulo inicial 2. Extraer los puntos medios y tercios 3. Dibujar las líneas de unión entre los puntos medios y tercios (líneas auxiliares) 4. Dibujar las líneas de intersección con el rectángulo inicial (líneas de estructura) 5. Dibujar un nuevo rectángulo a partir de puntos medios y tercios 6. Introducir todas las funciones en un bucle iterativo 7. Terminar el dibujo de la cubierta y las fachadas 1. Rectángulo inicial
2. Puntos medios y tercios del rectángulo inicial
3. Líneas auxiliares
4. Líneas de estructura (en la 1ª
iteración son coincidentes con las líneas auxiliares)
5. Nuevo rectángulo
6. Introducir todas las funciones en un bucle iterativo
7. Terminar de modelar la curbierta y fachadas *
* Este apartado del ejercicio, por su complejidad, se realizará con los componentes precargados de Grasshopper., por lo que no se explicará paso a paso en este manua. p030
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
1. Dibujar el rectángulo inicial Nuestro componente de script tendrá dos entradas conectadas a sliders: “li”, que define el lado del cuadrado inicial, y “cota”, que define la cota de arranque de la cubierta; y una salida: “rec_inic”: private void RunScript(double li, double cota, ref object rec_inic) { // declaración de variable Rectangle3d recInic; // asignación de variable recInic = new Rectangle3d(); // inicialización de variable (refiriendose adecuadamente a sus constructores) recInic = new Rectangle3d(new Plane(new Point3d(0, 0, cota), Vector3d.XAxis, Vector3d.YAxis), new Interval(0, li), new Interval(0, li)); // el valor del lado del cuadrado es un slider (li) // asignar la variable construida a la salida rec_inic rec_inic = recInic; }
p031
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
2. Extraer puntos medios y tercios
private void RunScript(double li, double cota, ref object rec_inic) { // declaración, asignación e inicialización de variable en la misma línea Rectangle3d recInic = new Rectangle3d(Plane.WorldXY, new Interval(0, li), new Interval(0, li)); // asignar la variable construida a la salida rec_inic rec_inic = recInic;
// lista contenedora de puntos List<Point3d> ptosMedios = new List<Point3d>(); List<Point3d> ptosTercios = new List<Point3d>(); //dividimos los segmentos // para ello, convertimos el rectángulo en polilínea con Rectangle3d. ToPolyline(), de tal manera que podemos acceder a cada uno de los segmentos con el método SegmentAt(indiceDeSegmento) for(int s = 0; s < recInic.ToPolyline().SegmentCount; s++) { Point3d ptoMedio = recInic.ToPolyline().SegmentAt(s).PointAt(0.5); ptosMedios.Add(ptoMedio);
Point3d ptoTercio = recInic.ToPolyline().SegmentAt(s).PointAt(0.333); ptosTercios.Add(ptoTercio) } // devolvemos las variables por salidas diferentes ptos_medios = ptosMedios; ptos_tercios = ptosTercios;
}
p032
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
3. Dibujar las líneas auxiliares Para dibujar las líneas auxiliares, tendremos que unir el punto medio con el punto tercio del siguiente segmento. Tendremos que incluir una excepción para el último segmento del rectángulo, puesto que si dejamos que la lista vaya hasta el último elemento, el script dará un error. La excepción consistirá en que, cuando llegue al último índice, se una con el primer elemento y no con el siguiente. private void RunScript(double li, ref object rec_inic, ref object ptos_medios, ref object ptos_tercios, ref object LA) { // declaración, asignación e inicialización de variable Rectangle3d recInic = new Rectangle3d(Plane.WorldXY, new Interval(0, li), new Interval(0, li)); rec_inic = recInic; // asignar la variable construida a la salida rec_inic // listas contenedoras de puntos List<Point3d> ptosMedios = new List<Point3d>(); List<Point3d> ptosTercios = new List<Point3d>(); //lista contenedora de lineas List<Line> lineas = new List<Line>(); // convertimos el rectángulo a polilínea con la función .ToPolyline() al principio // y se la asignamos a una variable para no tener que llamarla luego tantas veces Polyline pol = recInic.ToPolyline(); //dividimos los segmentos for(int s = 0; s < pol.SegmentCount; s++) { //variables que se sobreescriben en cada pasada del bucle Point3d ptoMedio = new Point3d(); Point3d ptoTercio = new Point3d(); Line lPmPt = new Line(); //excepción en primer lugar para no caer en error con los índices de p033
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
listas if(s == pol.SegmentCount - 1) { ptoMedio = pol.SegmentAt(s).PointAt(0.5); ptoTercio = pol.SegmentAt(0).PointAt(0.333); lPmPt = new Line(ptoMedio, ptoTercio); } else { ptoMedio = pol.SegmentAt(s).PointAt(0.5); ptoTercio = pol.SegmentAt(s + 1).PointAt(0.333); lPmPt = new Line(ptoMedio, ptoTercio); } //añadimos a las listas ptosMedios.Add(ptoMedio); ptosTercios.Add(ptoTercio); lineas.Add(lPmPt); } // devolvemos las variables por salidas diferentes ptos_medios = ptosMedios; ptos_tercios = ptosTercios; LA = lineas; }
p034
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
4. Dibujar las líneas de estructura (intersección con el rectángulo inicial) Hemos llamado “líneas de estructura” a aquellas que son la proyección de las líneas auxiliares sobre el rectángulo inicial. En la primera iteración, las líneas auxiliares coincidirán con las líneas de estructura, pero en las demás no. Para dibujar estas líneas, primero hallaremos la intersección entre las líneas auxiliares con cada uno de los segmentos del rectángulo inicial. En Rhino, una intersección entre dos líneas se puede tomar como la intersección entre dos líneas similares pero de longitud infinita, así que no es necesario que se intersequen físicamente para que devuelvan los puntos de intersección.
//(...) todo el bloque de código del ejercicio anterior //dividimos los segmentos for(int s = 0; s < pol.SegmentCount; s++) { //(...) todo el bloque de código del ejercicio anterior // INTERSECCIÓN DE DOS LÍNEAS //lista de intersecciones List<Point3d> inter = new List<Point3d>(); // ruta para los datatree GH_Path ruta = new GH_Path(s); // fabricamos un nuevo bucle para las intersecciones con el rectángulo inicial for(int i = 0; i < pol.SegmentCount; i++) { double a; // parametro t de la primera linea double b; // parametro t de la segunda linea bool rc = Rhino.Geometry.Intersect.Intersection. LineLine(lPmPt, pol.SegmentAt(i), out a, out b, 0.0, false); if(rc && (a >= 0 && b >= 0))// algunas de las intersecciones devolverá nulo o fuera de una linea (-1), p035
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
así que colocamos esta excepción para no caer en error { inter.Add(pol.SegmentAt(i).PointAt(b)); } } //añadimos a la lista de puntos e intersecciones ptosInt.AddRange(inter, ruta); lineasEst.Add(new Line (inter[0], inter[1]), ruta); /////////////////////////////////////////// //añadimos a las listas ptosMedios.Add(ptoMedio); ptosTercios.Add(ptoTercio); lineas.Add(lPmPt); } // devolvemos las variables por salidas diferentes ptos_medios = ptosMedios; ptos_tercios = ptosTercios; LA = lineas; PI = ptosInt; LE = lineasEst;
p036
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
5. Dibujar un rectángulo a partir de las líneas auxiliares anteriores Elaboramos una función que devuelva un rectángulo a partir de una lista de líneas, que serán las líneas auxiliares. A dicha función la hemos llamado RectanguloAPartirDeAuxiliares. El resutlatdo de esta función tiene que sobreescribirse en cada iteración. Rectangle3d RectanguloAPartirDeAuxiliares(List<Line> lineasAux) { Rectangle3d rec; //variable que vamos a devolver List<Point3d> verRec = new List<Point3d>(); //vertices del plano del rectangulo Plane pl; //plano del rectángulo // este bucle nos sirve para encontrar los vertices del rectangulo for (int j = 0; j < lineasAux.Count - 1; j++) { bool hayInterseccion; double paramLinea1, paramLinea2; hayInterseccion = Rhino.Geometry.Intersect.Intersection. LineLine(lineasAux[j], lineasAux[j + 1], out paramLinea1, out paramLinea2, 0, false); if(hayInterseccion && (paramLinea2 <= 1)) { //añadimos a la lista de intersecciones en el rectangulo verRec.Add(lineasAux[j + 1].PointAt(paramLinea2)); } } pl = new Plane(verRec[0], verRec[1], verRec[2]);//plano del rectangulo // construimos el nuevo rectangulo return rec = new Rectangle3d(pl, verRec[0].DistanceTo(verRec[1]), verRec[1].DistanceTo(verRec[2])); }
p037
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
6. Introducimos todas las funciones en un bucle iterativo Al introducir todas los pasos anteriores en sus correspondientes funciones y llamarlas desde un código principal, obtendremos la siguiente solución con cada función a continuación: private void RunScript(double li, int nIt, ref object rec_inic, ref object lineas_auxiliares, ref object lineas_estructura) { // rectángulo inicial Rectangle3d recInic = new Rectangle3d(Plane.WorldXY, new Interval(0, li), new Interval(0, li)); DataTree<Line> lineasAux = new DataTree<Line>(); DataTree<Line> estructura = new DataTree<Line>(); Rectangle3d rec = recInic; for (int i = 0; i < nIt; i++) { //almacenamos cada paso del bucle en una rama diferente GH_Path ruta = new GH_Path(i); List<Line> ln = FabricarDivisiones(rec); List<Line> est = LineasEstructura(recInic, ln); lineasAux.AddRange(ln, ruta); estructura.AddRange(est, ruta); // rectangulo que se va a ir sobreescribiendo en cada paso del bucle rec = RectanguloAPartirDeAuxiliares(ln); } // salida de datos rec_inic = recInic; lineas_auxiliares = lineasAux; lineas_estructura = estructura; }
p038
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
FUNCIÓN PARA CONSTRUIR LAS LÍNEAS AUXILIARES List<Line> LineasAuxiliares(Rectangle3d recInic) { // lista contenedora de puntos List<Point3d> ptosMedios = new List<Point3d>(); List<Point3d> ptosTercios = new List<Point3d>(); //lista contenedora de lineas List<Line> lineas = new List<Line>(); for(int s = 0; s < recInic.ToPolyline().SegmentCount; s++) { //variables que se sobreescriben en cada pasada del bucle Point3d ptoMedio = new Point3d(); Point3d ptoTercio = new Point3d(); Line lPmPt = new Line(); //excepción en primer lugar para no caer en error con los índices de listas if(s == recInic.ToPolyline().SegmentCount - 1) { ptoMedio = recInic.ToPolyline().SegmentAt(s).PointAt(0.5); ptoTercio = recInic.ToPolyline().SegmentAt(0).PointAt(0.333); lPmPt = new Line(ptoMedio, ptoTercio); } else { ptoMedio = recInic.ToPolyline().SegmentAt(s).PointAt(0.5); ptoTercio = recInic.ToPolyline().SegmentAt(s + 1).PointAt(0.333); lPmPt = new Line(ptoMedio, ptoTercio); } //añadimos a las listas ptosMedios.Add(ptoMedio); ptosTercios.Add(ptoTercio); p039
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
lineas.Add(lPmPt); } //devolvemos un valor de la función return lineas; }
FUNCIÓN PARA CONSTRUIR LAS LÍNEAS AUXILIARES List<Line> LineasEstructura (Rectangle3d recInic, List<Line> div) { // declaramos e inicializamos la lista de líneas que vamos a querer devolver List<Line> lineas = new List<Line>(); for(int i = 0; i < div.Count; i++) { // fabricamos el plano Plane plano = new Plane(div[i].From, Vector2Points(div[i].From, div[i]. To), Vector3d.ZAxis); // declaramos la lista de intersecciones List<Point3d> pi = new List<Point3d>(); //fabricamos la intersección con todos los segmentos del rectangulo for(int s = 0; s < recInic.ToPolyline().SegmentCount; s++) { Rhino.Geometry.Intersect.CurveIntersections ci = Rhino.Geometry. Intersect.Intersection.CurvePlane(recInic.ToPolyline().SegmentAt(s). ToNurbsCurve(), plano, 0.0); //para no caer en error cuando no hay intersecciones, añadimos la excepción de que sólo añadimos los puntos cuando haya intersección if(ci != null) p040
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
{ //añadimos los puntos for (int p = 0; p < ci.Count; p++) { pi.Add(ci[p].PointA); } } } //fabricamos la línea y la añadimos a la lista lineas.Add(new Line(pi[0], pi[1])); } return lineas; }
FUNCIÓN PARA CONSTRUIR UN RECTÁNGULO A PARTIR DE LAS LÍNEAS AUXILIARES Rectangle3d RectanguloAPartirDeAuxiliares(List<Line> lineasAux) { Rectangle3d rec; //variable que vamos a devolver List<Point3d> verRec = new List<Point3d>(); //vertices del plano del rectangulo Plane pl; //plano del rectángulo // este bucle nos sirve para encontrar los vertices del rectangulo for (int j = 0; j < lineasAux.Count - 1; j++) { bool hayInterseccion; double paramLinea1, paramLinea2; hayInterseccion = Rhino.Geometry.Intersect.Intersection. LineLine(lineasAux[j], lineasAux[j + 1], out paramLinea1, out paramLinea2, 0, false); p041
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
if(hayInterseccion && (paramLinea2 <= 1)) { //añadimos a la lista de intersecciones en el rectangulo verRec.Add(lineasAux[j + 1].PointAt(paramLinea2)); } } pl = new Plane(verRec[0], verRec[1], verRec[2]);//plano del rectangulo
// construimos el nuevo rectangulo return rec = new Rectangle3d(pl, verRec[0].DistanceTo(verRec[1]), verRec[1]. DistanceTo(verRec[2])); }
FUNCIÓN PARA CONSTRUIR UN VECTOR A PARTIR DE DOS PUNTOS Vector3d Vector2Points(Point3d ptoA, Point3d ptoB) { Vector3d vec = new Vector3d(ptoB.X - ptoA.X, ptoB.Y - ptoA.Y, ptoB.Z ptoA.Z); return vec; }
p042
manual de scripting con grasshopper Miguel Vidal Guillermo RamĂrez
p043
ANEXOS
ANEXO 1 Estructura de RhinocCommon
RHINOCOMMON RHINO Rhino Rhino.ApplicationSettings Rhino.Collections CurveList Rhino.Commands Rhino. Display CustomDisplay Text3d Rhino.DocObjects RhinoObject Rhino.DocObjects.Custom Rhino.DocObjects.Tables Rhino.FileIO Rhino. Geometry Point3d Vector3d Box Brep Curve Polyline Rectangle3d Surface Rhino. Geometry.Collections BrepFace BrepEdge Rhino. Geometry.Intersect CurveIntersection Intersection IntersectionEvent Rhino.Input Rhino.Input.Custom Rhino.Plugins Rhino.Render Rhino.Render.Custom Rhino.Runtime Rhino.Runtime.InteropWrapper Rhino.UI
GRASHOPPER GRASHOPPER_IO GH_ISerializable Interface GH_IO.Serialization GH_IO.Types GH_IO.UserInterface GRASHOPPER GH_InstanceServer Grasshopper.GUI Grasshopper.Kernel GH_Path GH_Document
NOTA: Se resaltan en negrita los NameSpace que utilizamos en los ejercicios del manual. Se muestran s贸lo las clases con las que vamos a trabajar.
RHINO PYTHON
RHINO FOR MAC
ANEXO 2 Processing 01. Estructura bรกsica de un programa de Processing 02. El lienzo y la consola 03. Algunas funciones de dibujo bรกsico 04. Algunas funciones de interacciรณn bรกsicas 05. Ejemplos de aplicaciรณn
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
01. Estructura básica de un programa de Processing
02. El lienzo y la consola
// Esta primera parte es la que se ejecuta primero cuando el programa corre. así que declararemos las variables globales al principio del código, que podrán ser llamadas en cualquier apartado del programa int y = 0;
El lienzo (canvas)
// a continuación, vienen las funciones setup y draw. cada programa tiene una sola de cada una de estas funciones. Los corchetes de cada una de ellas definen un bloque independiente
Ambas propiedades se definen en la parte de setup de Processing.
// el bloque de la función setup se ejecuta una única vez por programa y en ella colocamos, fundamentalmente, las propiedades del dibujo de processing void setup() { size(300, 300); //tamaño del lienzo }
Es el espacio de pantalla en el que vamos a hacer nuestro dibujo de Processing. Tiene dos propiedades. - tamaño o size - color de fondo o background
int ancho = 10; int alto = 10; void setup() { size(ancho, alto); //tamaño del lienzo } x y
// el bloque de la función draw se ejecuta continuamente hasta que el programa para void draw() { line(0, y, 300, y); //dibujo de una línea y = y + 4; } La consola Es la ventana en la que imprimimos textodesde el codigo de Processing. Utilizamos dos funciones: - print: escribe cadenas de caracteres de un modo continuo - println: escribe cadenas de caracteres añadiendo un salto de carro Fuente: BEN FRY, CASEY REAS. “Processing. A programming handbook for visual designers and artists”, The MIT Press. p048
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
02. Algunas funciones básicas de dibujo en Processing Dibujar un punto
beginShape(); curveVertex(x, y); endShape(); x entero o decimal: coordenada X del vértice de la curva y entero o decimal: coordenada Y del vértice de la curva
point (x, y); x entero o decimal: coordenada x del punto y entero o decimal: coordenada y del punto Dibujar una línea line (x1, y1, x1, y1); x1 entero o decimal: y1 entero o decimal: x2 entero o decimal: y2 entero o decimal:
coordenada coordenada coordenada coordenada
x y x y
del del del del
punto punto punto punto
origen origen destino destino
Dibujar un rectángulo rect(x, y, ancho, alto); x entero o decimal: coordenada X del vértice superior izquierdo y entero o decimal: coordenada Y del vértice superior izquierdo ancho entero o decimal: anchura del rectángulo alto entero o decimal: altura del rectángulo Dibujar una elipse ellipse(x, y, ancho, alto); x entero o decimal: coordenada X de la elipse y entero o decimal: coordenada Y de la elipse width entero o decimal: anchura de la elipse height entero o decimal: altura de la elipse
Dibujar texto PFont miFuente; miFuente = createFont(“FFScala”, 32); // crea automáticamente una fuente y la guarda en la carpeta “data” de nuestro dibujo de Processing textFont(miFuente);// esta función asigna el tipo de fuente con la que se va a dibujar a continuación text(“hola cocacola”, x, y); texto caracter o cadena de caracteres x entero o decimal: coordenada X del texto y entero o decimal: coordenada Y del texto Colocar una imagen PImage p; p = loadImage(nombre); image(p, x, y); nombre cadena de caracteres: nombre de la imagen, si está en la carpeta “data”, si no, ruta de la misma x entero o decimal: coordenada X de la imagen y entero o decimal: coordenada Y de la imagen
Dibujar una curva p049
manual de scripting con grasshopper Miguel Vidal Guillermo RamĂrez
03. Propiedades del dibujo de Processing Las propiedades fundamentales de lo que dibujamos en processing son las siguientes:
noSmooth();
Color Color de trazo stroke(gray); stroke(gray, alpha); stroke(value1, value2, value3); stroke(value1, value2, value3, alpha); stroke(color); stroke(color, alpha); Grosor de trazo strokeWeight (); Color de relleno fill(); No dibujar trazo noStroke(); No dibujar relleno noFill(); Suavizar bordes smooth(); No suavizar bordes p050
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
04. Algunas funciones básicas de interacción en Processing Posición del ratón mouseX mouseY pmouseX pmouseY Eventos de ratón mousePressed() mouseReleased() mouseMoved() mouseDragged()
p051
manual de scripting con grasshopper Miguel Vidal Guillermo Ramírez
05. Ejemplos de aplicación Dibujar una curva a partir de las coordenadas del ratón
Dibujar una interfaz de interacción con botones
void setup() { size(640, 200); background(102); }
// tamaño visor int ancho = 450; int alto = 200; //tamaño botones int lado = 30; //posicion botones int posX = 50; int posY = 50; // colores color cBotInicial = color(80); color cBotEncima = color(20, 20, 180); color cBotPulsado = color(255); color colorRect;
void draw() { stroke(255); if(mousePressed) { line(mouseX, mouseY, pmouseX, pmouseY); } }
void setup() { size(ancho, alto); background(0); noStroke(); rectMode(CORNER); } void draw() { colorRect = cBotInicial; if ((mouseX (mouseY { colorRect } if(((mouseX (mouseY mousePressed)
>= posX && mouseX <= posX+lado) && >= posY && mouseY <= posY+lado)) = cBotEncima; >= posX && mouseX <= posX+lado) && >= posY && mouseY <= posY+lado)) && p052
manual de scripting con grasshopper Miguel Vidal Guillermo RamĂrez
{ colorRect = cBotPulsado; } fill(colorRect); rect(posX, posY, lado, lado); }
p053
ANEXO 3 Glosario de tĂŠrminos
programación Proceso por el cual se escribe, se prueba, se depura, se compila y se mantiene el código fuente de un programa informático.
lenguaje de programación Idioma artificial diseñado para expresar instrucciones que pueden ser llevadas a cabo por máquinas, como una computadora. Como tal idioma está formado por un conjunto de símbolos y reglas sintácticas que definen su estructura y el significado de sus expresiones.
C# Lenguaje de programación orientado a objetos desarrollado y estandarizado por Microsoft como parte de su plataforma .NET. Su sintaxis básica deriva de C y C++ y utiliza el modelo de objetos similar al de Java.
programación orientada a objetos Paradigma de programación que usa objetos y sus interacciones para diseñar aplicaciones y programas informáticos. Está basado en varias técnicas, entre las que se incluyen la herencia, la abstracción, el polimorfismo y el encapsulamiento.
plataforma .NET Plataforma de software, que corre principalmente en Microsoft Windows, que incluye una extensa biblioteca de clases soportada por diversos lenguajes de programación, como C# o Visual Basic.NET, y un entorno de software en el cual se ejecutan las aplicaciones (Common Language Runtime), similar a una máquina virtual de aplicaciones
script (Se traduce literalmente del inglés como “guión”, “archivo de órdenes”, sería la traducción adecuada). Se trata de un programa simple. Los scripts son casi siempre interpretados, es decir, que son ejecutados por un intérprete.
intérprete Programa infrormático capaz de analizar y ejecutar otros programas. Los intérpretes realizan la traducción a código máquina (unos y ceros) a medida que ésta es necesaria, típicamente instrucción por instrucción y sin guardar el resultado de dicha traducción. Esto hace que los programas interpretados sean más lentos, pero a cambio más flexibles para reemplazar o añadir partes del programa y, además, ofrecen al programa un entorno no dependiente de la máquina donde se ejecuta el intérprete (lo que se conoce comúnmente como máquina virtual).
RhinoCommon Es una SDK (Software Developement Kit) construída bajo la plataforma .NET para el desarrollo de plug-ins para todas las plataformas de Rhinoceros, esto es, Rhino 5 (32 y 64 bits), Rhino para Macintosh, Grasshopper y Phyton scripting para Rhino.
SDK (Software Developement Kit) Conjunto de Herramientas de desarrollo que permiten la creación de aplicaciones para un determinado paquete o plataforma de software, hardware o plataformas similares.
Plug-in En computación, se trata de un conjunto de componentes de software que añaden capacidades especificas a una aplicación mñas grande.
máquina virtual Software que emula a una computadora y puede ejecutar programas como si fuese una computadora real.
Common Language Runtime (”entorno en tiempo de ejecución de lenguje común”) Es el entorno de ejecución para los códigos de los programas de la plataforma .NET, como C# o Visual Basic.NET. Se encarga de compilar un código intermedio al código máquina nativo. Se ejecuta sólo en Microsoft Windows. No es exactamente una máquina virtual, pero su objetivo es el mismo.
Fuente: wikipedia.org
www.frikearq.com