Page 1

RHINO USER MEETING DAY RHINOSCRIPT - PYTHON | DISEÑO ALGORÍTMICO

PROFESOR ADOLFO NADAL SERRANO


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

TOPOLOGÍA DE LA GEOMETRÍA NURBS [Non-Uniform Rational Bezier Splines]

[ 2 ]


[ 3 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

I. NOCIONES BÁSICAS DE PROGRAMACIÓN Aproximarse a la topología NURBS implica un conocimiento amplio de la descripción geométrica de los objetos a partir de fórmulas matemáticas y, de manera implícita, del comportamiento y descripción de las mismas en los entresijos del ordenador. Es, por tanto, imprescindible, iniciarse en el apasionante mundo de la programación, y, si bien no llegaremos a ser programadores profesionales, sí podremos entender y crear geometrías complejas a través de rutinas y “scripts”, pequeños programas hechos a medida que nos dan acceso directo al núcleo de Rhino, así como sus funciones y métodos. 1. Scripts, ejecución secuencial y programación orientada a objetos Generalmente, la manera más sencilla de comenzar un código es mediante la utilización de “comandos” u “órdenes” dadas en una secuencia determinada. Podríamos decir que el modo más primitivo de escribir código es mediante macros, secuencias de órdenes ordenadas de una manera determinada y que siempre llevan a cabo la misma labor. Las macros no permiten interacción con el usuario y son bastante limitadas, si bien son muy útiles a la hora de abordar problemas que requieren mucho esfuerzo o tiempo y que pueden automatizarse (por ejemplo, una secuencia de acciones que abre una imagen, cambia su brillo y su opacidad, la recorta, y la vuelve a guardar). Todos los parámetros implicados en una macro deben estar predefinidos de antemano, no pudiendo dejar ni una sola variable sin determinar. En el ejemplo anterior, si quisiéramos cambiar el brillo de una imagen, debemos especificar exactamente el nuevo valor de brillo, así como, a la hora de recortarla, cuáles son los píxeles que definen el cuadro delimitador del corte. Un script, en cambio, permite cierta interacción con el ususario, así como el uso de variables. Esto implica mayor flexibilidad, pero también mayor riesgo de error. Los scripts son, en lo que a nosotros nos concierne, el siguiente paso en la “inteligencia” de la programación. Dedicaremos a continuación una buena parte de tiempo a describir y cualificar cómo escribir scripts y sus diferentes funcionalidades, desde la creación de geometrías complejas hasta la automatización de procesos de creación de planos para la fabricación, exportación de archivos y otras utilidades varias. Tanto las macros como los scripts, sin embargo, comparten una propiedad fundamental: ambos se basan en una secuencia de órdenes que el ordenador interpreta linealmente. La programación orientada a objetos permite la descripción de objetos [instancias de clases] mediante una serie de “características” [propiedades] y “comportamientos” [métodos], que son capaces de interactuar entre sí mediante una serie de reglas compartidas definidas a través de dichos comportamientos. Dicho paradigma excede el nivel que queremos alcanzar con el presente manual, por lo que lo dejaremos para ediciones posteriores. 2. Macros Aunque no es el tema principal que nos ocupa, una leve introducción a las macros no hace mal, y nos ayudará a entender los conceptos básicos que hemos descrito anteriormente. Valga de ejemplo una escalera de caracol: para dibujar una escalera de caracol necesitaríamos repetir un objeto (escalón), copiarlo en altura, y rotarlo una serie de grados. Después, tendríamos que tomar el último elemento u objeto creado (es decir, el escalón que acabamos de copiar) y repetir la operación una serie de veces hasta que terminemos de rellenar el espacio necesario. Hacer esto a mano podría suponernos un buen rato de modelado, aburrido y tedioso. Podemos evitar innecesarias horas delante del monitor si somos capaces de describir [y posteriormente transcribir] las órdenes necesarias en una secuencia que el ordenador pueda entender. A saber: 1. Selecciona el escalón que quieras repetir 2. Copia dicho escalón 3. Mueve el escalón verticalmente una distancia establecida para la huella, por ejemplo: 15cm. 4. Rota el escalón un cierto ángulo (por ejemplo: 10º) alrededor de un eje (por ejemplo uno vertical en 0,0) Podríamos, además, implementar un último paso que repitiera el proceso una serie de veces, como por ejemplo 15, pero de momento vamos a dejarlo aquí para facilitar la simplicidad del código. En todo caso, una macro es una lista o secuencia de órdenes predeterminadas que el programa ejecuta.

[ 4 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

Una vez tenemos claro lo que necesitamos hacer, debemos poder transcribir todo en un lenguaje que pueda entender e interpretar el ordenador. Usaremos el término macro para describir un conjunto de órdenes ordinarias de Rhino escritas de manera secuencial para crear una función automatizada. Así pues, es “scripting” en su nivel más bajo, y veremos que es accesible a cualquier usuario de Rhino, incluso si no tiene conocimientos de programación. Todo lo que necesitamos, como hemos dicho, es un conocimiento aceptable de Rhino, algo de experiencia en modelado, y cierto gusto por la experimentación. Para escribir una macro precisamos: - Nuestro propio interés - Los archivos de ayuda de Rhino, que describen todos los comandos así como sus opciones - Posiblemente el editor “MacroEditor”, que permite ejecutar y analizar nuestras macros. Aquí exponemos algunas de las claves que nos permiten comunicarnos con nuestra herramienta en forma de normas sencillas de sintaxis [puedes ver un listado completo en ingés en http://www.rhino3d.com/4/help/information/rhino_scripting. htm]:

Símbolo Nombre

Explicación

-

Guión

_

Guión Bajo

! ; \

Signo exclamación Punto y coma Barra invertida

Pause w r <

Pause

Cancela la aparición de ventanas asociadas a comandos. Todos los comandos pueden, además, escribirse o llamarse mediante scripts, por lo que es una opción destacada a la hora de escribir los literales o “strings” [ya veremos lo que es ésto más adelante]. Ejecuta el comando en inglés. Necesario para que las macros sean ejecutables independientemente del idioma en el que estemos usando Rhino actualmente. Cancela los comandos en ejecución. Permite introducir un comentario, que no será leido por rhino Si el comando no comienza por “!” y termina con la barra invertida “\”, la macro se ejecutará en la línea de comandos sin pulsar enter, de manera que se puede introducir más información. Esto es útil para construir un comando a partir de dígitos, decimales, ángulos [tal como “<45”] y que se encuentran en botones, creando un “teclado numérico” en la pantalla. Para una macro para input de usuario. Usar coordenadas “World Coordinates” en vez de coordenadas del plano de trabajo. Las coordenadas relativas son relativas a la posición actual del cursor. Input de ángulo en grados.

Menor que

Y aquí podemos analizar nuestra pequeña macro: Linea

Código

Explicación

1 2 3 4 5 6 7 8 9 10 11

! _Copy _pause 0,0,0 0,0,1 _enter

Comando copia con espera para intervención de usuario [selección] Punto inicio [copia] Punto final [copia] Finalizar comando

_selLast

Seleccionar último objeto creado

_rotate _pause 0,0,0 10 _enter

Comando rotar con espera para intervención de usuario Punto para el eje de rotación Ángulo de rotación Finalizar Comando

[Fig 1. Escalera creada con macro]

[ 5 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

3. ¿Dónde escribimos las macros? Perfecto, sabemos escribir un ejemplo de macro, pero, ¿dónde la guardamos? La respuesta es muy sencilla: dado que una macro equivale, a efectos prácticos, a un comando, no hay mejor manera que asociarla a un botón. Aunque hay diferentes maneras de hacer esto, aquí explicaremos las más sencilla y directa. Manteniendo pulsada la tecla Shift mientras ponemos el cursor sobre cualquier botón nos permite Mover o Editar los botones [figura 2]. Edita el botón y aparecerá un menú como el de la figura 3. Menu Emergente

Mover/Editar (Shift+hover) Copiar/Vincular (Ctrl+hover)

[Fig 2. Menú Editar/Mover]

[Fig 3 Menú de edición de botones]

En el espacio reservado para el comando del botón izquierdo del ratón pega el conjunto de órdenes que hemos descrito para nuestra macro. Puedes cambiar la leyenda del mismo. Para guardar los cambios, acepta. Cuando cliques sobre el icono del botón, se ejecutará la macro. Puedes también editar el aspecto del botón, pero eso lo dejaremos para después, cuando tratemos la personalización de la interfaz. Puedes probar tus macros en el editor de macros. Dicho editor es, además, una herramienta útil para excribir macros y detectar posibles errores. Usa el comando “ejecutar” de la ventana de edición para probar tu código. 4. Variables y scripts Una vez nos hemos familiarizado con el comportamiento básico de las macros, podemos empezar a pensar en sistemas más complejos que requieran interacción usuario-ordenador y la introducción de variables para dicha interacción, es decir, sistemas dinámicos que son capaces de manejar distintas situaciones. El funcionamiento de los scripts es similar, si bien se requieren conocimientos de lenguajes de programación [es decir, no vale solamente con copiar y pegar nombres de coman-

[ 6 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

dos] y de modelado. Las limitaciones de las macros han dado lugar, por tanto, a los scripts, una suerte de lugar indefinido entre simples secuencias de órdenes y programas compilados. Así pues, las macros pueden realizar operaciones matemáticas, evaluar condicionantes, responder al entorno y comunicarse con el ususario. Rhinoceros, en su versión 4, implementa VBScript, lo que significa que aquello que es válido para VBScript, lo es también para RhinoScript. Rhinoceros v5 implementa además python, por lo que habrá que ir incorporando lentamente este lenguaje a nuestro día a día. “Traducir” RhinoScript en lenguaje natural [con el que nos comunicamos tú y yo] no debe ser muy complicado a este nivel. Inicialmente, los lenguajes de programación eran un conjunto de ceros y unos, que con el tiempo [el paso de generaciones de lenguajes en su sentido más estricto] se han conseguido hacer fácilmente entendibles para seres humanos. Las primeras generaciones de lenguaje “código máquina” son muy difíciles de entender, y no tienen cabida entre la mayoría de nosotros. Afortunadamente, se ha evolucionado en los sucesivos desarrollos generacionales hacia una mayor encapsulación que abriese el marco de la programación a gente no necesariamente iniciada. Por ejemplo, es posible que queramos guardar unas curvas de nuestro modelo en 3D para modificarlas o borrarlas posteriormente, o tal vez necesitemos conocer la fecha para saber si el software ha expirado; ninguno de estos datos está disponible cuando se ha escrito el script y serán sólamente accesibles a través de variables. Pero volviendo a lo que nos ocupa, sabemos que a menudo necesitamos almacenar información para realizar los cálculos que nos lleven, poco a poco, a la resolución de problemas complejos. Dichos cálculos forman parte de un todo que podemos denominar algoritmo: una secuencia de órdenes determinada, que en un tiempo finito, da un resultado concreto y correcto. El almacenamiento de información para su uso en los algoritmos se puede [y debe] llevar a cabo mediante variables, contenedores de información que constan básicamente de: - Nombre: El nombre es un dato simbólico que se refiere a información almacenada en memoria. Dicho nombre puede ser cualquiera en rVB, con las siguientes salvedades: · Comenzará por carácter alfabético · Contendrá menos de 255 caracteres · No se permiten espacios en blanco, puntos, ni caracteres especiales (!,”, : ; , ...) · No pueden emplearse palabras reservadas del lenguaje - Tipo: indica el tipo de información que almacena una variable. Por ejemplo, y sin entrar en mas detalles, las variables Single y Double pueden ocupar números reales muy grandes. Además, hay otro tipo de variables, las denominadas variant, que son como una variable estándar que “admite cualquier tipo de dato.” - Alcance [“tiempo de vida”]: · Global: para variables declaradas fuera de funciones y subrutinas y accesibles desde cualquier parte del código. · Local: variables declaradas dentro de funciones y subrutinas, no se podrá tener acceso a ellas desde otra parte del código. Esto es, si declaro una variable dentro de una función, solamente podré acceder a ella mientras me encuentre en la función. Si quiero, posteriormente, usar el valor de la misma, deberé pasarla como referencia bien como valor. algunNumero = RhinoScriptSyntax.GetInteger(“Introduce un número”,0,50,100) En este ejemplo, “algunNumero” es sencillamente un “placeholder” para un valor determinado, que obtendremos cuando se ejecute el script [en tiempo de ejecución]. Está claro que, cuando estamos escribiendo el script no conocemos el valor de la variable. Fíjate además que el nombre de la variable algunNumero no tiene tilde, ya que sería considerado un carácter especial, cuyo uso está prohibido para la nomenglatura en código [visita de nuevo las características de los nombres si tienes alguna duda]. Recuerda que el lenguaje de código por excelencia es el inglés.

[ 7 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

El uso de las variables debe incluir tres pasos: - Declarar y comentar la variable [esto puede hacerse o no, en función del alcance de la misma]. - Inicializar la variable [asignar un valor inicial] - Programar las debidas instrucciones. Tipo Tamaño Rango Boolean 1 Bit True/False Byte Entero Corto: 1 Byte De -128 a 127 Integer Entero: 2 Bytes De -32768 a 32767 Long Entero: 4 Bytes De -232/2 a (232/2-1) Single Real Simple Precisión: 4 bytes Real Double Real Doble Precisión Real Carácter 1 Byte De -128 a 127 String Cadena de caracteres Texto Date Fecha Fecha

Es posible que en ocasiones [y de hecho, la mayoría de las veces sucede] deseemos agrupar variables, tales como “Nombre”, “Empresa”, “Cargo”, “Sueldo”, o cualquier otro. Python, al contrario que vbScript, nos dota de un sistema potente y bastante útil para lidiar con este asunto. Tanto los “tuples” como las “listas” son estructuras de información capaces de agrupar variables; puedes pensar en ellas como “contenedores” de información, una especie de bandeja donde podemos colocar los platos de una buena comida.

[Fig 4. Ejemplos cotidianos de arrays: una granja solar, un contenedor]

5. Declaración e inicialización de variables en rVB y Python De igual manera que tu interlocutor te preguntará quién es Pepe a tu afirmación “ayer fui al cine con Pepe”, si no le conoce, RhinoScript solicita saber con quién está tratando, es decir, requiere saber qué variables vas a utilizar durante la ejecución del script. Si bien esto es cierto para scripts escritos con VB, python es más directo y admite la declaración e inicicalización simultánea de variables. Generalmente es necesario y suficiente “presentar” [declarar] una variable antes de usarla, es decir, valdría con afirmar “Pepe es un amigo”. En rVB se declaran las variables utilizando la palabra reservada Dim, de la siguiente manera: Dim nombreVar Dim algunNumero Esto es todo lo que necesitamos hacer para hacer saber a Rhino que vamos a utilizar una variable cuyo nombre es algunNumero. Para arrays, esto funciona exactamente igual, ya que se comportan como una variable: Dim nombreArr Dim conjuntoNumeros En python, sin embargo, podemos declarar las variables al mismo tiempo que las usamos, según asignamos valores (es decir según inicializamos las variables). Python, además, distingue entre listas, tuples, y variables. Tanto las listas como los tuples son conjuntos de variables; las listas, para mayor complejidad, son dinámicas [lo que significa que se pueden añadir elementos a la lista, modificarlos, o eliminarlos].

[ 8 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

De este modo, el equivalente a lo visto anteriormente en Python sería: nombreVar = valorVar algunNumero = 25 Queda patente que la declaración e inicialización de la variable se hacen de manera simultánea. Asimismo, veremos que se puede comenzar por el valor None, una especie de “Ninguno”, una manera de decir que la variable no tiene contenido. De este modo podemos declarar una variable sin valor, y asignarle un valor posteriormente. Además, este “no valor” None es el que devuelven las funciones de RhinoScript cuando fallan. Es la manera que tiene Rhino de decirnos “no lo sé”. algunNumero = None ... algunNumero = 25 La asignación del valor se hace mediante el símbolo “=”, que asigna el valor de la derecha al elemento que se encuentre a su izquierda. Así pues a=1, asigna el valor 1 a la variable de nombre “a”. El tipo de valor que asignemos a la variable determinará el tipo de la variable, de manera que si asignamos un número la variable tendrá carácter numérico, y si asignamos, por ejemplo, una cadena de caracteres, tendrá tipo “String”. El nombre de la variable hace que podamos entender lo que ésta contiene. Podríamos asignar algunNumero = “Presidente”, y RhinoScript lo entendería perfectamente. Sin embargo, nos llevaría a error con absoluta seguridad. Esta asignación se vuelve ligeramente más compleja cuando tratamos con listas. Las listas, como hemos dicho anteriormente, son conjuntos de elementos, por lo que habrá que asignar un conjunto como valor inicial:

conjuntoNumeros = [ ] #esto indica que el conjunto está vacío conjuntoNumeros = [val1,val2,val3,val4,val5]

Una vez más, el nombre es independiente de los valores que contiene la variable [esto es, es para “uso humano” solamente], por lo que es más que recomendable tener un nombre descriptivo, sencillo de recordar, y corto, para evitar errores de tipografía. 6. Asignación de valores Al igual que para inicializar variables, la asignación de valores hace uso del símbolo “=”, y funciona de la misma manera. Durante la ejecución del script podemos cambiar el tipo de valor que almacena la variable, pero esto no es recomendable por coherencia y claridad. además, los seres humanos tenemos muy mala memoria, está casi garanztizado que no seremos capaces de recordar la razón por la que hicimos esto o lo otro dos días después de haberlo hecho, así que es una buena práctica mantener una coherencia en todo el código. 7. Obtención/acceso de valores; cambio de los mismos. Necesariamente, si almacenamos información, necesitaremos acceder a ella, tal vez únicamente para conocer su estado, tal vez para modificarla o hacer algún tipo de tarea. La manera de acceder a la inormación es tan sencilla como escribir lo siguiente:

queNumero = algunNumero

O, por ejemplo, imprimir su valor en la pantalla (línea de comandos)

print algunNumero

En el primer caso hemos asignado el valor de la variable “algunNumero” a la variable “queNumero”. En el segundo caso, hemos dicho a Rhino que imprima en la línea comandos el valor de algunNumero. Evidentemente, podemos también modificar el valor de la variable o usarlo en alguna operación matemática.

[ 9 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

otroNumero = math.sin(algunNumero)

otroNumero = otroNumero + 10

De nuevo, hemos usado la función “sin” [seno] para calcular el valor del seno de algunNumero, y asignar dicho valor a la variable otroNumero. Después, hemos modificado el valor de otroNumero incrementandolo en 10. Recomiendo que pruebes este conjunto de operaciones en un sencillo script, que se podría transcribir como sigue: import rhinoscriptsyntax as rss def simpleOperation(): algunNumero = None otroNumero = None algunNumero = 90 otroNumero = math.sin(algunNumero) print algunNumero print otroNumero otroNumero = otroNumero +10 print otroNumero return call simpleOperation()

8. Estructura del código Acabas de ver [¡y escribir!] posiblemente tu primer script, ¡enhorabuna! Verás que la estructura del código es muy simple, y consta esencialmente, de las siguientes partes reconocibles a simple vista: · importación de rhinoscriptsyntax · declaración de variables globales [ya lo veremos en un futuro...] · declaración de funciones mediante la palabra reservada def ····bloques de código de función [indentado] · llamadas a dichas funciones con la palabra “call” Puede parecer que la estructura es algo compleja, sin embargo, cuando comencemos a escribir, veremos que es mucho más sencilla de lo que aparenta. En este caso, más es menos. La importación, por ejemplo, nos permite acceder a funciones nativas de Rhinoscript de manera sencilla. Estas funciones son preexistentes y se denominan métodos. 9. Funciones y subrutinas Todo lo que debes saber de funciones y subrutinas es que son bloques de código con un nombre asignado [de manera que puedas “llamarlas” o usarlas cuando lo necesites], una serie de “argumentos” [datos que necesitan para ejecutar correctamente] y un resultado, que puedes decidir pasar o no.Ya ahondaremos en este tema al tiempo que comencemos a escribir scripts más complejos. Recuerda: - Las subrutinas son bloques de código que expresan la secuencia de ejecución del programa. Deben ser llamadas desde fuera y tienen la capacidad de llamar asimismo a otras subrutinas y funciones. - Las funciones bloques de código, grupos de órdenes en secuencia que se agrupan por su lógica. Cada función debe tener una única finalidad. Las funciones, si están debidamente escritas, podrán reutilizarse para varios códigos. - Métodos: los métodos son funciones ya escritas que pertenecen a librerías preexistentes. En el caso de Rhinoceros, se accede a ellos mediante el prefijo “rhinoscriptsyntax.”, lo que indica que la función está en un paquete con ese nombre.

[ 10 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

10. Ejemplo de código: Puedes comenzar a escribir el siguiente script en el editor de scripts de Rhino, que puedes ejecutar mediante el comando _EditScript. Por defecto, a partir de la versión 5.0 de Rhino, el editor de Scripts será Monkey. El script crea una serie de puntos en el modelo tridimensional de Rhino que tengas abierto. Verás que, una vez terminado el script, estos objetos son una parte más del mismo, y que podrás transformarlos, editarlos, o borrarlos a tu antojo. Procura copiar el script exactamente como se escribe; de otro modo podrías tener problemas de sintaxis con los que es más que probable que no estés familiarizado, por lo que podrías bloquearte. Recuerda, es mala idea generalmente tratar de resolver problemas relacionados con estos asuntos durante más de 30-60 minutos sin consultar la ayuda de una persona más experta. Se trata de aprender, no de desesperar. Verás que al copiar el código en tu editor de scripts, algunas palabras cambian de color, son palabras reservadas de python. Aquellas líneas precedidas de # [almohadilla] son comentarios, y no serán leidas por Rhino. Son para uso humano. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

#example 1: create a series of points/spheres import rhinoscriptsyntax as rss def createPoints(): print “This definition (function) creates points using 3 loops” maxX = 10 maxY = 10 maxZ = 10 for i in range (maxX): for j in range (maxY): for k in range (maxZ): ptarr = [i,k,j] pt = rss.AddPoint(ptarr) sp = rss.AddSphere(pt,0.25) rss.ObjectColor(pt,(i*255/maxX,j*255/maxY,k*255/maxZ)) rss.ObjectColor(sp,(i*255/maxX,j*255/maxY,k*255/maxZ)) createPoints()

Fíjate en la descripción del script línea por línea para entender exactamente qué ocurre. 1 3 5 6-20 6 8-10 12 13 14 15 16

17 18-19 21

[ 11 ]

Comentario para el ususario o lector del script que comenta lo que éste hace Importación de Rhinoscriptsyntax para poder acceder a los métodos nativos del mismo Comienzo de la función “createPoints”, o signatura de la misma mediante la palabra reservada def, nombre, y argumentos o parámetros (paréntesis), seguido de dos puntos (“:”) para indicar que viene a continuación.. Cuerpo de la función. Observa que está indentado Llamada a la función de python print, que imprime un mensaje en la ventana de comando. El mensaje se escribe entre comillas para indicar a python que se trata de una cadena de caracteres. Declaración e inicialización de las variables maxX, maxY, y maxZ, todas con el mismo valor. Iniciación de un bucle o loop que se ejecutará 10 veces (0,1,2,3,4,5,6,7,8,9) Iniciación de un bucle o loop que se ejecutará 10 veces (0,1,2,3,4,5,6,7,8,9) para cada una de las 10 anteriores. Iniciación de un bucle o loop que se ejecutará 10 veces (0,1,2,3,4,5,6,7,8,9) para cada una de las 100 anteriores. En total, el bloque de código que se encuentra entre las líneas 15 y 20 se ejecutará 10*10*10 = 1000 veces (en sólo 3 líneas!). Declaración e inicialización de una lista con 3 valores (un punto!!) Añadimos el punto al modelo. Observa que el método AddPoint (que ya está definido por Rhino) viene precedido de “rss.”, el nombre que hemos puesto a nuestra importación de rhinoscriptsyntax. Asimismo, para que python pueda añadir el punto al modelo deberemos darle la información de x, y, z (es decir, las coordenadas en el espacio). Nosotros guardamos estas coordenadas en la variable (lista) ptarr que hemos definido previamente en la línea 15. Añadir una esfera al modelo de manera análoga. Se necesita un centro (punto tridimensional) y un radio. Cambiar el color de los objetos Llamada a la ejecución de la función


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

[Fig 5 Resultado del script]

[ 12 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

[ 13 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

II. PROGRAMACIÓN Y TOPOLOGÍA 1. Editor de rhinopython El editor, además de espacio para el texto del scrit, incluye el compilador y “debugger”, una herramienta que permite localizar y corregir errores en el código. En realidad, todo lo necesario para escribir scripts es un editor de texto (notePad, wordPad, o cualquier otro). Este texto es después interpretado, compilado y ejecutado por los “intérpretes”, compilador y motor correspondientes. Rhinoceros incorpora su propio editor de texto, accesible mediante el comando “_editscript”. Para editar un script de python, usa el comando “_EditPythonScript”. El debugger es un programa que ayuda a encontrar errores en el script, especialmente de sintaxis, por lo que te será sencillo corregir tus scripts durante su ejecución, mediante la visualización de variables en tiempo real y la detección de errores de sintaxis. El “highlighter”, o reconocimiento automático de palabras reservadas, permite que éstas aparezcan automáticamente en colores que identificarán varios tipos: generalmente azul para palabras de Python, verde para los comentarios, rojo para cadenas de caracteres, y negro para el resto en general. 1.1. Opciones principales del editor Las principales operaciones que se pueden realizar son: - Editar scripts: en la ventana de edición, donde debes copiar los scripts que hemos escrito anteriormente. - Consultar la librería, en la ventana de métodos nativos de Rhinoceros. - Consultar la ayuda, haciendo doble click sobre el método que se quiere consultar. La ayuda es muy sencilla y explicativa, e incluye lo siguiente: · Nombre del comando, con una breve descripción de su funcionamiento · Sintaxis y uso: atributos [input] y valores de retorno [output] · Ejemplo, que puedes copiar y pegar directamente en la ventana del editor de scripts. Título de script

Menú

Pestañas de edición Librería general y rhino Canvas de edición de código

Diálogo de creación Depurar (debug) Ejecutar

Printed output Variable state monitor Call stack monitor

[Fig 6. Elementos principales de la interfaz del editor]

[ 14 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

- Para ejecutar un script usa el botón de play; esto ejecutará el script actual [la pestaña activa]. - “Debug” los scripts consite en encontrar fallos en el script. Como hemos dicho, esto se realiza visualizando los calores de las variables en líneas seleccionadas y el estado del script en cada momento. De esta manera podemos encontrar errores comunes tales como: · Confusión entre tipos de datos; por ejemplo, una variable debería tener valor numérico y contiene una cadena de caracteres o alfabéticos. · Errores en la definición de variables, y sus nombres. · Errores de sintaxis; por ejemplo, en símbolos, “(),=.” y otros · Errores en el paso de variables en las funciones. 1.2. Instalando el editor. Interfaz. No es necesario que instales ningún software o extensión adicional, el editor viene ya de serie con la instalación de Rhino v5. Como ves en la figura 6, la interfaz es muy clara. Es probable que únicamente necesites usar los botones principales, que dan acceso a las funciones de edición, corrección y ejecución de scripts. Para abrir Monkey, ve a la pestaña que aparece en la barra de menún, “Monkey”, y haz click sobre “Monkey Editor”. 2. Vectores y puntos: una sencilla base de geometrías complejas 2.1. Puntos En Rhinoceros, los puntos son las entidades geométricas más sencillas que hay. Tienen tres componentes, que corresponden a su localización x,y,z respecto del plano de trabajo universal. Un punto se describe, por tanto de la siguiente manera:

[ 15 ]

[Fig 8 Punto en espacio cartesiano R3: A(a1,a2,a3)]

[Fig 9. Vector v en espacio cartesiano R3: v(v1, v2,v3). El punto de apli-

[Fig 10 Punto en espacio cartesiano R3: A(a1,a2,a3)]

[Fig 11. Vector v en espacio cartesiano R3: v(v1, v2,v3). El punto de aplicación (base) del vector es (0,0,0) por defecto.]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

aPoint = [x,y,z]

Si quisiéramos definir un punto en 10,3,7, por ejemplo, lo podríamos hacer de la siguiente manera creando una lista o tuple con las coordenadas del mismo: import rhinoscriptsyntax as rss

x = 10 y= 3 z = 7 aPoint = [x,y,z] rss.AddPoint (aPoint)

2.2. Vectores Los vectores también se describen por conjuntos de coordenadas, listas que contienen [x,y,z]. En este sentido, son exactamente iguales que los puntos, y tienen el mismo comportamiento. La única diferencia estriba en que, por defecto, todos los vectores están basados en [0,0,0]. Las operaciones más sencillas con vectores incluyen suma, diferencia, y escalado, que responden a los siguientes métodos: - Suma: VectorAdd (vec1,vec2) - Sustracción: VectorSubtract (vec1,vec2) - Escalado: VectorScale (vec1,vec2) Donde vec1 y vec2 son arrays de 3 componentes, exactamente igual que en el caso de puntos. 3. Curvas Podemos entender las curvas como entidades controlables a partir de puntos. Las líneas, polilíneas y curvas están basadas en puntos de control, que definen su geometría, continuidad, y tangencias. Los conceptos básicos que debemos conocer en curvas son los siguientes: - Dominio de una curva: es el conjunto de valores reales que resultan que hace que se cumpla la ecuación de la misma. En f(x) = axn+bx(n-1)+(...)+g, por ejemplo, el dominio es el conjunto de valores de x que hacen que f(x) tenga un valor real. Esto mismo aplica a las curvas NURBS, si bien hemos de ser conscientes que las curvas tienen un principio y un final determinado, y que sus ecuaciones, a las que no podemos acceder, son más complejas. Sin embargo, existe una clara correspondencia entre dichos valores y la curva, que podemos ver en la figura 12. La ecuación paramétrica de una recta es como sigue:

(x,y) = (x1,y1) + k(v1,v2)

Como recordarás de álgebra, puedes hallar culquier punto de la recta con un vector director y un valor de k, el parámetro. Esto aplica exactamente a las curvas NURBs, si bien su topología es algo más compleja. Es suficiente con que recuerdes que a cada valor de k le corresponde un punto en la recta, y por tanto, en el espacio. - Puntos de control: puntos que definen el polígono de control, a partir del cual se define, en función del tipo de continuidad [es decir, el grado], la curva final. Con RhinoScript es relativamente sencillo obtener este tipo de información, de la misma manera que somos capaces de acceder a los datos de X,Y,Z, de un punto y modificarlo. Las operaciones más comunes son las siguientes: · Evaluar el dominio de una curva. · Crear puntos sobre curvas con RhinoScript. · Crear curvas a través de puntos o usando los puntos como puntos de control de la curva. De todos modos, este tipo de operaciones los veremos a continuación en el siguiente apartado, “Topología de la Geometría NURBS II, Geometría computacional básica 2”. En los scripts que siguen verás que cada una de las funciones incluye a la anterior, de modo que puedes “activar” y “desactivar” los sucesivos pasos a medida que vas avanzando. Te recomiendo que borres los objetos creados en cada uno antes de ejecutar el siguiente, para que puedas comparar los resultados sin miedo a esquivocarte.

[ 16 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

P0

P6

P1 P5

P2

P7

P4 P8 P3

dom(0)+ dom(0)+ dom(0)+ dom(0)+ dom(0)+ dom(0)+ dom(0)+ 1*step 2*step 3*step 4*step 5*step 6*step 7*step

dom(0) valor mínimo dominio

dom(1) valor máximo dominio

[Fig 12. Concepto de dominio de una curva. Los valores Dom(0) [min] y Dom(1) [max] no son necesariamente 0 y 1 y son asignados por Rhino.

El código está comentado, de manera que puedes entender cada paso una vez lo vayas copiando en el editor de scripts. III. SCRIPTS RELACIONADOS En este punto, presentamos dos scripts. El primero incluye funciones de creación de puntos. El segundo, análisis de curvas, dominios y puntos de control. Ambos comienzan por “Option Explicit”. 1. Puntos Como verás, la creación de puntos es muy sencilla, y se realiza mediante el método [función nativa] de Rhino “Rhino. AddPoint”. Esta función requiere de una matriz de componentes (x,y,z), como hemos visto anteriormente. La subrutina Main tiene una serie de funciones, crecientes en complejidad. doSinglePoint añade un punto al modelo en las coordenadas dadas. Prueba a cambiarlas y ejecutar el script. Para ejecutar una única función descoméntala, y comenta el resto. Haz esto con cada una de las funciones cambiando los valores. doPointGrid utiliza dos “loops” [estructuras do...] para crear una malla de puntos, lo que hace por medio de filas y columnas [crea una columna con j puntos, luego otra... hasta que hace i columnas con j puntos cada una, en total n = j*i puntos]. El siguiente paso es crear una malla tridimensional, para lo cual createPoints (en la página11) añade un valor distinto de cero para la componente Z del punto. La fórmula utilizada para crear Z puede cambiar. Prueba a cambiarla para ver los distintos resultados. Una vez que hemos manejado puntos en 3D, podemos proceder a crear líneas. Para ello, examina doLine, una función que crea una línea a partir de dos puntos definidos explícitamente por su punto origen y punto final [cada uno de ellos por sus coordenadas X,Y,Z agrupadas en una array]. doLines crea líneas a partir de los puntos en una recta, de la misma manera que creábamos los puntos en la función doPointGrid. Fíjate en que hay que esperar a tener al menos dos puntos creados para proceder a una línea [para tener en cuenta esta condición usamos el código condicional if [condición] ... end if. Intenta crear una malla de líneas, siguiendo el mismo procedimiento que para doLines, pero en ambas direcciones (esto es, en X y en Y). doSimpleComponentGrid podría aprovechar los mismos puntos para crear una polilínea [la única diferencia estriba en que tenemos ahora un único conjunto de puntos]. Recuerda que para cerrar una polilínea debemos hacer coincidir el primer punto con el último; es decir, para un cuadrado tendremos 5 puntos [ya que el último será igual que el primero si queremos cerrar el polígono].

[ 17 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

doComplexComponentGrid podría crear, además del perímetro, una curva con los mismos puntos. Esta curva estaría contenida dentro del perímetro. import rhinoscriptsyntax as rss #Script written by <Adolfo Nadal [archiologics.com]> #Script NOT copyrighted #Script versión martes, 29 de junio de 2010 18:21:34 #A series of VERY SIMPLE functions to demonstrate the VERY BASICS of NURBS geometry #In later sessions we will explore how to enhance our lofting capabilities import rhinoscriptsyntax as rss def doSinglePoint(): #This adds a single point in 0,0,0 #We need to enter the 3D coordinates defining the point in an array (collection of objects) rss.AddPoint(20,20,0) def doSinglePointWithAnnotation(): rss.AddPoint(20,20,0) rss.AddTextDot(“A point here”,[20,20,0]) def doPointGrid(): for i in range (10): for j in range (10): rss.AddPoint(i,j,0) rss.AddTextDot(“Pt at: “ + str(i) + “ “ + str(j),[i,j,0]) def doLine(): rss.AddLine([0,0,0],[0,20,0]) def doLines(): maxX = 10 maxY = 10 for i in range(1,maxX): for j in range(1,maxY): rss.AddLine([i,j,0],[i-1,j-1,0]) rss.EnableRedraw(False) #doSinglePoint() #doSinglePointWithAnnotation() #doPointGrid() #doLine() #doLines() rss.EnableRedraw(True)

2. Curvas La función ShowDomain muestra el concepto de dominio de una curva. Para ello, crea un punto en la curva y muestra, mediante un “textDot” o anotación, el valor del dominio en ese punto. El script requiere una curva, que deberá ser seleccionada por el usuario. Veremos más sobre curvas en el siguiente apartado. import rhinoscriptsyntax as rss def showDomain(): crv = rss.GetObject (“Get curve to evaluate”,4) dom = rss.CurveDomain(crv) rss.AddPoint(rss.EvaluateCurve(crv,dom[0])) rss.AddPoint(rss.EvaluateCurve(crv,dom[1])) rss.AddTextDot(“Dom[0] is: “ + str(dom[0]),rss.EvaluateCurve(crv,dom[0])) rss.AddTextDot(“Dom[1] is: “ + str(dom[1]),rss.EvaluateCurve(crv,dom[1])) showDomain()

[ 18 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

[ 19 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

TOPOLOGÍA DE LA GEOMETRÍA NURBS II [Non-Uniform Rational Bezier Splines]

[ 20 ]


[ 21 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

I. GEOMETRÍA COMPUTACIONAL BÁSICA 2 - RECTAS Y CURVAS NURBS 1. El dominio de curvas en Rhino y Rhinoscript: La representación del dominio de curvas en Rhinoceros responde a una serie de características y conceptos que debemos conocer si pretendemos crear scripts o rutinas que incluyan trabajo con líneas, polilíneas, curvas o curvas mixtas, sea cual sea su creación. Es importante resaltar asimismo que los conceptos que siguen aplican a todas las curvas por igual, con independencia de su grado o manera de creación. · En álgebra, el dominio de una curva se refiere al conjunto de valores de la variable independiente (normalmente “x” para los cuales existe un valor real de la variable dependiente (normalmente “y”). Para más información, vuelve a ver la figura 12 del apartado anterior. · En geometría computacional, sea cual sea la representación de la curva, el dominio responde a la definición interna de la misma en R1 (es decir, en el espacio de la curva). Así pues, en Rhino 4 oscila entre 0 y 1, mientras que en Rhino 5 entre 0 y la longitud de la curva. En cualquier caso, 0 representa el origen de la curva, y 1 (o su longitud) el final de la misma. · El dominio responde a la curvatura de la curva, por lo que una división del dominio en n partes iguales no se traduce necesariamente en n segmentos de la misma longitud. · Debemos saber, a la hora de usar curvas para superficies, cuál es el origen y el final de la curva, porque esto influirá en comandos como “loft”, por ejemplo. El comando “_flip”, invierte el sentido de una curva. CRV DOMAIN (0)

CURVE OBJECT MAIN PROPERTIES: ID, DOMAIN, DEGREE - ID: UNIQUE IDENTIFIER ASSIGNED BY RHINO AT THE TIME OF CREATION - DOMAIN: INTERNAL DEFINITION OF A CURVE. IT IS A VALUE BETWEEN 0 & 1, WHERE 0 REPRESENTS THE START OF THE CURVE AND 1 THE END. IT DOES NOT REFER TO ITS LENGTH, RATHER TO ITS CURVATURE

CRV DOMAIN (X)

CRV DOMAIN (0)<CRV DOMAIN (X)<...<CRV DOMAIN (Z)<CRV DOMAIN (1)

CRV DOMAIN (Y)

CRV DOMAIN (Z)

[Fig 1. Dominio de una curva]

CRV DOMAIN (1)

2. Espacio R1 (curva) y espacio R3 (cartesiano): Así pues, parece obvio que podemos referirnos a los puntos de una curva aproximándonos a ellos de dos maneras distintas: por un lado, mediante su localización en el espacio, es decir, por sus coordenadas (X,Y,Z); por otro, por su posición en la curva, es decir, por su domino (d). Esto responde claramente a la diferencia entre R3 [espacio cartesiano] y R1 [espacio unidimensional de la curva]: · R1 es el espacio unidimensional de la curva, definido por un único valor [dominio] · R3 es el espacio tridimensional cartesiano, definido por tres valores [array(x,y,z)]

[ 22 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

import rhinoscriptsyntax as rss def showDomain(): crv = rss.GetObject (“Get curve to evaluate”,4) dom = rss.CurveDomain(crv) rss.AddPoint(rss.EvaluateCurve(crv,dom[0])) rss.AddPoint(rss.EvaluateCurve(crv,dom[1])) rss.AddTextDot(“Dom[0] is: “ + str(dom[0]),rss.EvaluateCurve(crv,dom[0])) rss.AddTextDot(“Dom[1] is: “ + str(dom[1]),rss.EvaluateCurve(crv,dom[1])) showDomain()

Por lo tanto, recuerda que cualquier punto de una curva puede expresarse de dos modos: (i) en referencia al espacio cartesiano [su posición x,y,z en el espacio], y (ii) en referencia a la curva a la que pertenece, mediante su dominio [que tomará un valor entre 0 y 1 en Rhino v4, o entre 0 y su longitud en Rhino v5]. 3. Curvas a partir de puntos Rhinoceros permite la generación de una gran variedad de curvas, entre las que se encuentran: - Por puntos de control - Interpoladas [a través de puntos] - Interpoladas en superficie [la curva estará contenida en ella] - Por manejadores [define un punto y su tangencia] - Trazar [bosquejar] curvas: boceto - Trazar en malla poligonal/superficie - Cónicas - Promedios Todas estas curvas pueden modificarse una vez terminadas. La modificación se hace generalmente a partir de los puntos de control, bien por adición y substracción, bien por su modificación. Los puntos de control se comportan como objetos del dibujo, e incluyen una serie de propiedades., que siguen: - Posición - Peso: grado de influencia sobre la curvatura de la curva [a mayor peso, más cerca estará la curva de pasar por el punto de control]. Existen otras técnicas avanzadas de creación de curvas, tales como: - Fluir a lo largo de una superficie - Curvas UVN [aplicadas sobre superficies] Curva por puntos de control Curva por interpolación Curva por interpolación en superficies Curva por manejadores Trazar Trazar sobre malla Cónicas y parábolas Hélice y espiral Curvas promedio Activar puntos de control Activar puntos de edición/ desactivar seleccionados Ocultar caras posteriores de polígono de control Mover UVN, toque ligero UVN Insertar nodo/ punto de edición

Extender/Empalmar /Achaflanar línea Simplificar Insertar/Eliminar puntos de control Cambiar modo de arrastre Editar con manejadores Añadir nodo Eliminar nodo Definir peso de puntos de control

Subcurva Insertar línea en curva Booleana de curvas

Cerrar curvas abiertas Eliminar subcurva Extraer subcurva

[Fig 2. Herramientas de creación y edición de curvas - II]

[ 23 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

Dichas técnica interpolan de una u otra manera la curva original sobre la superficie seleccionada. La primera admite guardado de historial, por lo que es muy útil a la hora de crear curvas sobre superficies complejas, como por ejemplo fachadas estructurales. La edición de las curvas se realiza, como hemos dicho, a partir de sus puntos de control, fácilmente accesibles tanto explícitamente [modelando] como implícitamente [a partir de RhinoScript]. II. SUPERFICIES Y POLISUPERFICIES EN RHINOCEROS 1. Direcciones en superficies - Direcciones U y V: · Las superficies son más o menos rectangulares. Las superficies tienen tres direcciones, U, V y normal. Las direcciones U, V y normal se pueden visualizar con el comando Dir. Las direcciones U y V son como el tejido de ropa o de una tela. La dirección U se indica con la flecha roja y la dirección V con la flecha verde. La dirección normal se indica con flechas blancas. Las direcciones U, V y normal se corresponderían a las direcciones X, Y y Z de la superficie. · Estas direcciones se utilizan para el mapeado de texturas y la inserción de puntos de control. - Dirección normal: · En las superficies, la normal es una dirección que señala hacia la parte “exterior” o “superior” de la superficie, y es perpendicular a la superficie en el punto de cálculo. Para polisuperficies cerradas (cono, cilindro, caja, etc.) o sólidos de una superficie (esfera, toroide), la normal siempre está orientada “hacia fuera”. Sin embargo, en una superficie o polisuperficie abierta la dirección de la normal depende de cómo se creó y puede ser arbitraria. · El comando Dir muestra la dirección de la normal de un objeto.

[Fig 3. Dirección en una superficie]

2. Concepto y manejo de dominios de superficies en Rhinoscript · Al igual que en curvas, el dominio en superficies es la representación geométrica interna que nos permite obtener puntos sobre la superficie en R2 (es decir, sobre el “espacio binario” de la superficie). · Toda superficie tiene dos dominios, uno en la dirección “u” y otro en la dirección “v”, de manera que, mediante la combinación de dos parámetros “i” (correspondiente a u) y “j” (correspondiente a v), se puede hallar y calcular la posición de un punto en la superficie (que, de nuevo, puede expresarse en términos de R2 o R3). Coloquialmente podríamos decir que u y v corresponden a las componentes ”X” e “Y” sobre un plano [en el que sabemos, por ejemplo, que la componente Z es 0], pero sobre la superficie. · Para una polisuperficie, el dominio se calcula para cada una de las superficies componente, por lo que es muy conveniente modelar con superficies.

3. R2 y R3 [“espacio superficie” y espacio cartesiano] · R2 es el espacio bidimensional de la superficie [coordenadas implícitas a la geometría]. · R3 es el espacio tridimensional cartesiano, eso ya lo sabíamos. de anteriores descripciones. · Como sabemos, cualquier punto de una superficie puede expresarse de dos modos: (i) en referencia al espacio cartesiano (su posición x,y,z en el espacio en las coordenadas de dibujo y coordenadas globales), y (ii) en referencia

[ 24 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

a la superficie a la que pertenece, mediante su dominio [mediante dos valores entre DomMin y DomMax, si dichos valores no se han normalizado para que sean DomMin = 0 y DomMax = 1]. · Normalizado: con la opción Sí, los intervalos de los parámetros U y V se escalan para que los valores resultantes estén entre cero y uno (en lugar de usar el valor del parámetro real). Esta opción es útil cuando desea saber el porcentaje del espacio de los parámetros del punto designado sin tener que calcularlo según el dominio de la superficie. Con la opción No, se proporcionan los valores de los parámetros U y V no escalados. Véase también Dominio. · Nota: Cuando se selecciona una polisuperficie, Rhino calcula el resultado de la superficie componente en la posición designada. Si la superficie es recortada, Rhino usará la superficie no recortada.

[Fig 4. Expresión de superficies y puntos sobre superficies. Dominio]

4. Creación de superficies, puntos y nubes de puntos, curvas - Los métodos más comunes de creación de superficies son: · Superficies a partir de puntos: rectangulares, por 3 ó 4 puntos, ajustar plano a través de puntos. · Superficies a partir de curvas: loft, sweep extrusión, patchwork, revolución, a partir de una red de curvas. · De la misma manera pueden crearse polisuperficies y sólidos. Dejaremos la edición de sólidos por el moment, ya que éstos requieren de un conocimiento propio de modelado con caras que no incluimos en este manual. Si eres un usuario habitual de programas de modelado 3D para animación [como por ejemplo Autodesk Maya o Autodesk 3DMax] entonces es probable que te interesen, pero los encontrarás limitados con respecto a las limitaciones de dichos programas. - Precauciones usando el comando “loft”: · Como norma general, las curvas deben tener el mismo número de puntos de control · Asimismo, hemos de ser cuidadosos con el sentido de las mismas, así como su alineación.

[ 25 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

FILA 1 Superficie por 3 ó 4 puntos Superficie por curvas de borde Superficie a partir de curvas planas Superficie rectangular Extruir curva FILA 2 Loft - transición Superficie por network de curvas Superficie parche Sweep 1/2 railes

FILA 3 Superficie de revolución Cubrir objetos con superficie Mapa de alturas desde imagen Superficie desde rejilla de puntos

[Fig 5. Principales herramientas relativas a generación y ectracción de información de superficies]

[ 26 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

[ 27 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

DISEテ前 CON PYTHONSCRIPT [Cubierta de un estadio]

[ 28 ]


[ 29 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

I. UN EJEMPLO SENCILLO DE APLICACIÓN DE RHINOSCRIPT 1. Objetivo: El objetivo del script es practicar los métodos más usuales en rhinoscript, tales como la selección de objetos existentes, y el trabajo con puntos. Además, crearemos superficies automáticamente mediante la interacción directa con el usuario. Aplicaremos el script inicialmente a un conjunto de curvas indiferenciado para comprobar y entender su funcionamiento. Posteriormente entenderemos cómo utilizar el mismo sobre una superficie diseñada para albergar una cubierta de un estadio. Para ello, intentaremos seguir una estrategia en complejidad ascendente, comenzando por los métodos más sencillos hasta conseguir tener un script complejo. RhinoPython es perfectamente compatible con grasshopper, por lo que será nuestro lenguaje de programación preferido. 2. Comenzando: los “babystepts”: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

#example: get a curve, a number of divisions, and divide curve import rhinoscriptsyntax as rss def getCurves(): print “This definition (function) gets curves in series of three” crv = rss.GetObject(“Select curve”,4) if not crv: return divNr = rss.GetInteger(“Nr of divisions”,4,6,20) if not divNr: return divPts = rss.DivideCurve(crv,divNr) rss.AddPoints(divPts) getCurves()

12 13

Comentario para el ususario o lector del script que comenta lo que éste hace Importación de Rhinoscriptsyntax para poder acceder a los métodos nativos del mismo Comienzo de la función “getCurves”, o signatura de la misma mediante la palabra reservada def, nombre, y argumentos o parámetros (paréntesis), seguido de dos puntos (“:”) para indicar que viene a continuación.. Cuerpo de la función. Observa que está indentado Llamada a la función de python print, que imprime un mensaje en la ventana de comando. El mensaje se escribe entre comillas para indicar a python que se trata de una cadena de caracteres. Declaración e inicialización de la variable crv, que albergará la curva que seleccione el usuario por medio delmétodo nativo de Rhino GetObject. Para seleccionar curvas, utiliza el filtro de tipo 4. Si tienes dificultades entendiendo lo que esto significa, puedes usar la ayuda de RhinoScript. Nos aseguramos que el usuario ha seleccionado una curva, de manera que, si no es así, salimos de la función Solicitud de un número de divisiones determinado por parte del usuario Una vez más, no aseguramos el éxito de la función mediante la comprobación de la correcta introducción de datos por el ususario. Llamada al método nativo de Rhino para dividir la curva Añadir puntos en cada una de las divisiones

15

Llamada a la ejecución de la función

1 3 5 6-13 6 8

9 10 11

Como ves, este sencillo script divide una curva del modelo y añade una serie de puntos sobre cada una de las divisiones. Esta es la base de nuestro pequeño programa, ya que dividiremos las curvas en una serie de segmentos sobre los cuales crearemos las superficies que van a constituir la cubierta. Como puedes entrever, el número de divisiones producirá un efecto diferente, tal y como puedes ver en la figura a continuación. Como es evidente, podrías usar el número de divisiones para optiizar el grado de asoleo de un estadio, por ejemplo, o para crear efectos de vistas concretos, o incluso simular una estructura arquitectónica completa, en función de determinados factores de diseño que puedas decidir.

[ 30 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

[Fig 1.Ejemplo de cubierta de estadio]

Como puedes imaginar, lo que se puede hacer con una curva se puede hacer con 3 curvas. En este caso, y al tratarse de un número pequeño de inputs por parte del usuario, no deberíamos tener demasiado problema en repetir el proceso tres veces. Sin embargo, para un mayor número de inputs, deberíamos considerar trabajar con bucles que nos permitan hacer una única selección. Iremos viendo esto en pasos sucesivos, pero de momento vamos a conformarnos con conseguir que cada paso aumente la complejidad del script. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

1-9 10-15 20-25 27

[ 31 ]

#example 1: get a curve, a number of divisions, and divide curve #imports import rhinoscriptsyntax as rss #define functions def getCurves(): print “This definition (function) gets curves in series of three” crv = rss.GetObject(“Select first curve”,4) if not crv: return crv1 = rss.GetObject(“Select second curve”,4) if not crv1: return crv2 = rss.GetObject(“Select third curve”,4) if not crv2: return divNr = rss.GetInteger(“Nr of divisions or segments”,4,4,20) if not divNr: return divPts = rss.DivideCurve(crv,divNr) rss.AddPoints(divPts) divPts1 = rss.DivideCurve(crv1,divNr) rss.AddPoints(divPts1) divPts2 = rss.DivideCurve(crv2,divNr) rss.AddPoints(divPts2) #call function = tell rhino to execute the function getCurves()

Estas líneas deben ser conocidas a estas alturas Selección de 3 curvas y correspondientes comprobaciones División de cada una de las curvas y añadir puntos. Llamada a la ejecución de la función


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

Para desarrollar el progama, calcularemos el punto medio entre dos dados, y así formaremos una estructura con forma de diamante, tal como ves en la figura 2. No existe una función para hallar el punto medio dados dos puntos por coordenadas, pero nosotros podemos escribir un algoritmo que funcione para nuestros propósitos. 1 2 3 4 5

1 2 3 4 5

#function to calculate mid pt between 2 given points def MidPt(pt1,pt2): midPt = None midPt = [(pt1[0]+pt2[0])/2,(pt1[1]+pt2[1])/2,(pt1[2]+pt2[2])/2] return midPt

Comentario que describe el uso de la función Declaración de la función con la palabra reservada def, argumentos entre paréntesis, y dos puntos. Los argumentos son los inputs que precisa la función, en este caso dos puntos (definidos por sus coordenadas). Declaración de la variable midPt, o punto medio. Este punto medio deberá contener el resultado de nuestros cálculos, es decir, el punto medio de dos dados. Cálculo del punto medio Retorno de la función: punto medio

[Fig 2. Puntos medios en la curva intermedia]

Como se ve, podemos llamar la función desde cualquier otro punto del código. Evidentemente, esto nos permite reusar bloques de código tantas veces como nos sea necesario. Puedes copiar y pegar dichos bloques de código tantas veces como sea necesario. Puedes incluso crear bibliotecas de código para reusarlas, del mismo modo que funcionan los métodos nativos de rhino. 3. Crea curvas a partir de los puntos: Para crear curvas debes disponer primero de un conjunto de puntos, que has de agrupar en listas. Prueba, por ejemplo, el siguiente código: 1 2

#generate base curves basecrv1 = rss.AddCurve([divPts[0],midPts[0],divPts2[0],divPts[0]],1)

[ 32 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI[O]LOGICS

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

28 29-31 29

30 31 34-37

Con estos dos bloques de código, el script queda del siguiente modo: #example 1: get a curve, a number of divisions, and divide curve #imports import rhinoscriptsyntax as rss #define functions def getCurves(): print “This definition (function) gets curves in series of three” crv = rss.GetObject(“Select first curve”,4) if not crv: return crv1 = rss.GetObject(“Select second curve”,4) if not crv1: return crv2 = rss.GetObject(“Select third curve”,4) if not crv2: return divNr = rss.GetInteger(“Nr of divisions or segments”,4,4,20) if not divNr: return divPts = rss.DivideCurve(crv,divNr) rss.AddPoints(divPts) divPts1 = rss.DivideCurve(crv1,divNr) rss.AddPoints(divPts1) divPts2 = rss.DivideCurve(crv2,divNr) rss.AddPoints(divPts2) #loop to generate mid pts midPts = [] for i in range (len(divPts1)-1): midPts.append(MidPt(divPts1[i],divPts1[i+1])) rss.AddPoints (midPts) #generate base curves basecrv1 = rss.AddCurve([divPts[0],midPts[0],divPts2[0],divPts[0]],1) basecrv2 = rss.AddCurve([divPts[1],midPts[0],divPts2[1]],divPts[1],1) basecrv3 = rss.AddCurve([divPts[0],midPts[0],divPts[1]],divPts[0],1) basecrv4 = rss.AddCurve([divPts2[0],midPts[0],divPts2[1]],divPts2[0],1) #function to calculate mid pt between 2 given points def MidPt(pt1,pt2): midPt = None midPt = [(pt1[0]+pt2[0])/2,(pt1[1]+pt2[1])/2,(pt1[2]+pt2[2])/2] return midPt #call function = tell rhino to execute the function getCurves()

Declaración de la lista que va a contenter a los puntos como una lista vacía. Iremos llenando la lista dentro del bucle Bucle para generar los puntos medios en la curva intermedia Esta línea es fundamental. Decimos a Rhinoscript que, para cada uno de los puntos en los que hemos dividido la curva intermedia, repita la línea 30. Es decir, para cada punto (desde el 0 hasta el penúltimo para ser más exactos), cogeremos el punto actual y el siguiente, y llamaremos a la función Midt(punto actual, punto siguiente), obteniendo de esta manera el punto medio correspondiente. Llamada a la función punto medio y guardado de su valor en la variable midPts. “Append” añade cada uno de los puntos obtenidos a la lista de puntos medios. Añadir puntos al modelo. Añadimos las curvas correspondientes como base para las superficies del modelo. En total son 4 curvas.

Finalmente, podemos crear superficies planas a partir de las curvas que hemos creado. Verás que las curvas son de grado 1, por lo que se asemejarán a polilíneas. Además, tienen 4 puntos, pero al coincidir el primero y el último sabemos que es una curva cerrada, por lo que en realidad se trata de un triángulo. Todo triángulo define un plano.

[ 33 ]


RHINO USER MEETING DAY RHINOSCRIPT - PYTHON

ADOLFO NADAL SERRANO MAS. ARCHITECT - ARCHI [O] LOGICS

4. Finaliza el script e intenta ampliar su funcionalidad: El script queda de la siguiente manera. Puedes probar a unir las superficies, cambiarlas de color, borrar alguna superficie, o cambiar su material, por ejemplo. Haz eso entre las lineas 45 y 47, una vez hayas creado todas las superficies. Verás que hemos incluido llamadas a EnableRedraw. Esto acelera el proceso sustancialmente, ya que evita que la pantalla de rhinoceros se actualice con cada cración de objetos. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

#example 1: get a curve, a number of divisions, and divide curve #imports import rhinoscriptsyntax as rss #define functions def getCurves(): print “This definition (function) gets curves in series of three” crv = rss.GetObject(“Select first curve”,4) if not crv: return crv1 = rss.GetObject(“Select second curve”,4) if not crv1: return crv2 = rss.GetObject(“Select third curve”,4) if not crv2: return divNr = rss.GetInteger(“Nr of divisions or segments”,4,4,100) if not divNr: return divPts = rss.DivideCurve(crv,divNr) rss.AddPoints(divPts) divPts1 = rss.DivideCurve(crv1,divNr) rss.AddPoints(divPts1) divPts2 = rss.DivideCurve(crv2,divNr) rss.AddPoints(divPts2) #loop to generate mid pts midPts = [] for i in range (len(divPts1)-1): midPts.append(MidPt(divPts1[i],divPts1[i+1])) #rss.AddPoints (midPts) rss.EnableRedraw (False) #generate base curves for i in range (divNr): #baseCrv1 = rss.AddCurve([midPts[i],divPts[i+1],divPts2[i+1],midPts[i]],1) baseCrv2 = rss.AddCurve([midPts[i],divPts2[i+1],divPts2[i],midPts[i]],1) baseCrv3 = rss.AddCurve([midPts[i],divPts2[i],divPts[i],midPts[i]],1) baseCrv4 = rss.AddCurve([midPts[i],divPts[i],divPts[i+1],midPts[i]],1) #generate surfaces #srf1 = rss.AddPlanarSrf(baseCrv1) srf2 = rss.AddPlanarSrf(baseCrv2) srf3 = rss.AddPlanarSrf(baseCrv3) srf4 = rss.AddPlanarSrf(baseCrv4) rss.EnableRedraw(True) #function to calculate mid pt between 2 given points def MidPt(pt1,pt2): midPt = None midPt = [(pt1[0]+pt2[0])/2,(pt1[1]+pt2[1])/2,(pt1[2]+pt2[2])/2] return midPt #call function = tell rhino to execute the function getCurves()

[ 34 ]

RhinoPython Manual for beginners  

RhinoPython manual for beginners: basics and geometry

Read more
Read more
Similar to
Popular now
Just for you