(es) Homenaje al gato sin hogar
(eo) Omaĝo al senhejmaj gekatoj
http://dx.doi.org/10.13140/RG.2.2.34092.90243
Descripción artística:
Un gato sentado viendo a lo lejos en dirección del observador.
Motivación:
Hay una gran cantidad de gatos y gatas que son abandonados y/o maltratados por los humanos. En su mayoría porque no tienen los medios económicos para darles el cuido correcto y en otras ocaciones por falta de humanidad.
Si los humanos no desean lidiar con la procreación de sus mascotas, deben esterilizarlos.
Descripción técnica:
Perfil de un gato delineado con curvas cúbicas de Bézier.
Dados cuatro puntos (que pueden ser unidimensionales, bidimensionales, tridimensionales, etc.), llamados puntos de control, se define la curva de Bézier de la siguiente manera:
Las curvas de Bézier son ampliamente usadas para la modelación por computadora por su simplicidad de cálculo frente a cualquier técnica de interpolación polinomial o racional.
Archivos
Archivos
Código (Python):
Este es un segmento del código necesario para la construcción. Se incluye aquí sólo con propósitos ilustrativos.
# coding: utf-8 # Copyright 2015 Eduardo Adam Navas López # Este programa es Software Libre liberado bajo la licencia GNU GPLv3 o su versión más reciente: # http://www.gnu.org/licenses/gpl.html class SecuenciaBezier: """Esta clase representa una secuencia de segmentos de Bézier""" def __init__(self, (x1,y1), (x2,y2), (x3,y3), (x4,y4)): """Esta función recibe los cuatro nodos del primer segmento de Bézier""" self.__lista = [ [x1,y1], [x2,y2], [x3,y3], [x4,y4] ] self.curvaSuave = True def sustituirLista(self, L): '''Para sustituír toda la lista de una sóla vez''' self.__lista = L def segmento(self, n): """Devuelve una lista de cuatro puntos que representan un segmento de Bézier""" return self.__lista[3*n: 3*(n+1)+1] def agregarSegmento(self, i, (x2,y2), (x3,y3), (x4,y4)): '''Agrega un segmento adicional a partir de la posición 'i' ''' self.__lista[i+1:i+1] = [ [x2,y2], [x3,y3], [x4,y4] ] # Garantizar continuidad C1 if self.curvaSuave: self.continuizar() def punto(self, n): """Devuelve el punto representado como una lista de dos elementos.""" return self.__lista[n] def desplazar(self, (dx,dy)): '''Desplaza todos los nodos en una misma cantidad''' for p in self.__lista: p[0] += dx p[1] += dy def actualizarPunto(self, n, (x,y)): '''Permite modificar un punto específico''' if self.curvaSuave and n > 1 and n < len(self.__lista)-2: if n%3 == 0: '''Es un nodo que une dos segmentos, por lo que hay que desplazar el punto anterior y el siguiente''' self.__lista[n-1][0] += x - self.__lista[n][0] self.__lista[n-1][1] += y - self.__lista[n][1] self.__lista[n+1][0] += x - self.__lista[n][0] self.__lista[n+1][1] += y - self.__lista[n][1] elif (n+1)%3 == 0: '''Es un nodo previo a la unión de dos segmentos, por lo que hay que desplazar el primer punto del segmento siguiente''' self.__lista[n+2][0] = self.__lista[n+1][0] - (x-self.__lista[n+1][0]) self.__lista[n+2][1] = self.__lista[n+1][1] - (y-self.__lista[n+1][1]) else: #(n-1)%3 == 0: '''Es un nodo posterior a la unión de dos segmentos, por lo que hay que desplazar el penúltimo punto del segmento anterior''' self.__lista[n-2][0] = self.__lista[n-1][0] - (x-self.__lista[n-1][0]) self.__lista[n-2][1] = self.__lista[n-1][1] - (y-self.__lista[n-1][1]) self.__lista[n] = [x,y] def eliminarPuntos(self, n): '''Se elimina un segmento completo, es decir, tres nodos, tomando como centro a un punto de unión. ''' if n==0: self.__lista[0:3]=[] elif n==len(self.__lista)-1: self.__lista[-3:-1] = [] self.__lista.pop() #esto borra el último else: if n%3==0: self.__lista[n-1:n+2] = [] else: pass #ignorarlo por el momento def numSegmentos(self): """Devuelve el número de segmentos que esta serie contiene""" return int(len(self.__lista)//3) #compatibilidad con Python3 ;) def numPuntos(self): """Devuelve el número de puntos que esta serie contiene""" return len(self.__lista) def calcular(self, t): '''Para la actual secuencia de Segmentos Bézier, calcula el punto (x,y) al cual corresponde el valor 't' ''' #Calcular el índice del segmento de Bézier #con el que debe calcularse este 't': numS = self.numSegmentos() ixSegmento = int(t * numS) if ixSegmento == numS: ixSegmento = ixSegmento-1 s = self.segmento(ixSegmento) t = numS * t - ixSegmento _1_t1 = 1-t _1_t2 = _1_t1 * _1_t1 _1_t3 = _1_t2 * _1_t1 t2 = t*t t3 = t2*t x = _1_t3 * s[0][0] + 3*t*_1_t2 * s[1][0] + 3*t2*_1_t1 * s[2][0] + t3 * s[3][0] y = _1_t3 * s[0][1] + 3*t*_1_t2 * s[1][1] + 3*t2*_1_t1 * s[2][1] + t3 * s[3][1] return x,y def continuizar(self): '''Garantiza continuidad C^1 entre los segmentos''' nodo = 4 #debe haber al menos dos segmentos while len(self.__lista)>nodo: self.__lista[nodo][0] = self.__lista[nodo-1][0]-self.__lista[nodo-2][0]+self.__lista[nodo-1][0] self.__lista[nodo][1] = self.__lista[nodo-1][1]-self.__lista[nodo-2][1]+self.__lista[nodo-1][1] nodo += 3
No hay comentarios:
Publicar un comentario