Semiesfera con una tortuga 3D

En el grupo Python Blender Spanish de Google+ se hizo esta pregunta.

Como respuesta comencé plantearme un procedimiento con la tortuga 3D (ver: Construir un cuadrado a partir de una tortuga Logo 3D).

Lo más sencillo es plantearse una variable llamada radio, creamos una tortuga que la llamamos t, este objeto tiene todas las propiedades de la class tortuga.py,

import bpy

from tortuga import Tortuga

t=Tortuga()

El algoritmo usado es avanzar un radio, capturar las coordenadas (andar(radio)), guardarlas en la lista coords, volver al punto de partida.

t.Cabecear(15*j)

andar(radio)

t.Andar(-radio)

t.Cabecear(-15*j)

Se usa la definición andar, que a su vez usa otra definición carga_coords()

def carga_coords():

coordenada=[]

coordenada.append(t.X)

coordenada.append(t.Y)

coordenada.append(t.Z)

coords.append(coordenada)

Aquí se utiliza una lista vacía auxiliar llamada coordenada, se agraga a la lista las coordenadas del punto a través de t.X, t.Y, t.Z que son las coordenadas de la tortuga t, luego esta lista coordenadas, se agrega a la lista coords, en la que se van guardando las coordenadas de los puntos de la esfera.

def andar(paso):

t.Andar(paso)

carga_coords()

Esta definición hace avanzar a la tortuga y a la par agrega la lista de las coordenadas a la lista coords

Si nos decidimos a tener cinco filas de caras, debemos capturar puntos usando estos ángulos 0, 15, 30, 45, 60 y 75

j=0

while j<6:

t.Cabecear(15*j)

andar(radio)

t.Andar(-radio)

t.Cabecear(-15*j)

if j>0 and i>0:

carga_cara(len(coords)-1,len(coords)-2,len(coords)-8,len(coords)-7,faces)

j+=1

La definición carga_cara

def carga_cara(v1,v2,v3,v4,lista):

cara=[]

cara.append(v1)

cara.append(v2)

cara.append(v3)

cara.append(v4)

lista.append(cara)

Se utiliza len(coords)-1 para obtener número del último de punto. En carga_cara(len(coords)-1,len(coords)-2,len(coords)-8,len(coords)-7,faces)

cargamos a la lista faces los cuatro puntos de la última cara posible de cargar, es por eso que usamos if j>0 and i>0: para no tener errores y usar el mismo algoritmo para todas las caras.

Es importante tener en cuenta los casos especiales como el siguiente. Vamos generando tiras que van desde el ecuador hacia el polo, menos los triángulos superiores, pero tenemos un caso especial en la última tira.

if i==24: #completa la última tira de la semiesfera.

j=0

while j<5:

carga_cara(len(coords)-6+j,len(coords)-5+j,1+j,0+j,faces)

j+=1

Solo falta completar la semiesfera con los triángulos que cierren la parte superior.

Primero obtenemos el punto más alto de la semiesfera, que también es común a todos los triángulos, en nuestro caso son 24.

# Se carga el punto superior para cerrar la semiesfera

t.Cabecear(90)

andar(radio)

t.Andar(radio)

t.Cabecear(-90)

Obtenemos el punto superior y v.olvemos al centro de la semiesfera

#Se cargan en la lista "faces" los triángulos que cierran la semiesfera

i=0

while i<138:

carga_caratri(len(coords)-1,len(coords)-(2+i),len(coords)-(8+i),faces)

i+=6

carga_caratri(len(coords)-1,len(coords)-(140),len(coords)-(2 ),faces)

Aqui cargamos los triángulos superiores y tenemos por último un caso especial en el último triángulo.

Para entender este procedimiento de generación de una semiesfera, recomiendo copiar el script python semiesfera_01.py, imprimirlo e ir comprendiéndolo paso a paso.

Cualquier dificultad que tenga, me consulta a mi correo.

Este es el resultado de ejecutar el script semiesfera_01.py