lunes, 2 de marzo de 2015

Cornoide

(es) Coronoide

(eo) Kornokurbo

Cornoide

http://dx.doi.org/10.13140/RG.2.2.34092.90243

Descripción artística:

El trazo de la curva Cornoide, descubierta por el Doctor Alberto Sánchez, salvadoreño, en 1895.

Motivación:

El trabajo de un salvadoreño que aportó la identificación de una curva de construcción relativamente simple que todos los grandes matemáticos de la historia pasaron por alto. La Escuela de Matemática de la Facultad de Ciencias Naturales y Matemática de la Universidad de El Salvador, lleva su nombre en su honor.

Descripción técnica:

El trazo de la curva Cornoide, con ecuación paramétrica:
{ x(t)=R cos t cos 2t y(t)=R sin t( 2+ cos 2t )
El procedimiento geométrico para construirla es el siguiente:
Sea C un punto de la circunferencia de diámetro director AB y sea C' el punto de intersección de la circunferencia con la paralela por el punto C al diámetro AB . Desde C se traza la recta tangente a la circunferencia y desde C' la recta perpendicular a la recta tangente. Sea D el punto intersección de ambas rectas. Cuando el punto C describe la circunferencia, el punto D describe la Cornoide.
Archivos

 Código (Python):

#!/usr/bin/env python
# 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

"""Animación del cornoide.
Gerera archivos con nombre: img-*.png

Este comando genera la animación gif a partir de la secuencia de archivos png:
$ convert -delay 10 -loop 0 img-*.png animacion.gif

Con este otro se puede generar la animación al derecho y al revés:
$ convert -delay 10 -loop 0 img-*.png $(ls img-*.png -r) animacion.gif
"""

import pygame
import math
import escala

prueba = False
#prueba = True

if prueba:
 ANCHO = 1000
 ALTO  = 1000
else:
 ANCHO = 8000
 ALTO  = 8000

INF_IZQ = (-1.03,-0.61)
SUP_DER = (1.03,1.45)

NUMPASOS = 50
NUMPASOSCURVA = 100*NUMPASOS
TIEMPO_PAUSA = 50

#En pixeles:
GRUESO_CIRCULO = 10 ####4
GRUESO_CORNOIDE = 10 ####6
GRUESO_LINEA = 4 ####2 
RADIO_PUNTO = 10 ####2

#En unidades virtuales:
RADIO_CIRCULO = 1.0

ROJO   = (255,0,0)
VERDE  = (0,255,0)
AZUL   = (0,0,255)
BLANCO = (255,255,255)
NEGRO  = (0,0,0)

COLOR_CORNOIDE = (112,121,246)
COLOR_CIRCULO = (100,100,100)
#COLOR_RADIO = (0,0,250)
COLOR_TANGENTE = (0,0,200)
#COLOR_SECANTE = (0,0,150)
COLOR_FINAL = (0,0,150)
COLOR_PUNTO = ROJO

def cornoide(t, r=1.0):
 return r*math.cos(t)*math.cos(2*t), r*math.sin(t)*(2+math.cos(2*t))

def actualizar(t):
 """Aquí hay que guardar las imágenes"""
 global pantalla

 if prueba:
  pygame.display.flip()
  #Descomentar la siguiente línea para generar los archivos *.png que componen la animación
  #pygame.image.save(pantalla, "img-{0:.10}.png".format(t))

def dibujar():
 global pantalla, e

 i = 0
 t = 0.0
 pcirc = RADIO_CIRCULO*math.cos(t), RADIO_CIRCULO * math.sin(t)
 #i=i+1
 pantalla.fill(BLANCO)
 while i<=NUMPASOS:
  #Calcular siguiente punto del cornoide:
  t = math.pi/2 * i/NUMPASOS
  p = cornoide(t, RADIO_CIRCULO)
  pr = e.vr(p)

  #Dibujar círculo:
  circunferencia(pantalla, COLOR_CIRCULO, e.vr((0.0,0.0)), int(e.magnitudvrx(RADIO_CIRCULO)), GRUESO_CIRCULO)

  #Centro del círculo:
  pygame.draw.circle(pantalla, COLOR_PUNTO, e.vr((0.0,0.0)), RADIO_PUNTO)

  #Dibujar el Cornoide hasta este punto:
  ii = 0
  Lii = i*NUMPASOSCURVA/float(NUMPASOS)
  while ii<=Lii:
   ttemp = math.pi/2 * ii/NUMPASOSCURVA
   pA = e.vr(cornoide(ttemp, RADIO_CIRCULO))
   pygame.draw.circle(pantalla, COLOR_CORNOIDE, pA, GRUESO_CORNOIDE/2)
   ii=ii+1

  #Punto del círculo:
  pcirc = RADIO_CIRCULO*math.cos(t), RADIO_CIRCULO * math.sin(t)

  #Radio:
  #pygame.draw.line(pantalla, COLOR_RADIO, e.vr((0.0,0.0)), e.vr(pcirc), GRUESO_LINEA)

  #Recta tangente al círculo:
  pygame.draw.line(pantalla, COLOR_TANGENTE, e.vr(p), e.vr(pcirc), GRUESO_LINEA)
  
  ##con esto se prolonga la tangente
  #pendiente = -1.0/math.tan(t)
  #ptan1 = e.minxv, pendiente * (e.minxv - pcirc[0]) + pcirc[1]
  #ptan2 = e.maxxv, pendiente * (e.maxxv - pcirc[0]) + pcirc[1]
  #pygame.draw.line(pantalla, COLOR_TANGENTE, e.vr(ptan1), e.vr(ptan2), GRUESO_LINEA)

  #Secante al círculo:
  pcirc2 = (-pcirc[0], pcirc[1])
  #pygame.draw.line(pantalla, COLOR_SECANTE, e.vr(pcirc2), e.vr(pcirc), GRUESO_LINEA)

  #Segmento final:
  pygame.draw.line(pantalla, COLOR_FINAL, e.vr(pcirc2), pr, GRUESO_LINEA)

  actualizar(t)
  if prueba:
   pygame.time.delay(TIEMPO_PAUSA)

  i = i+1

def dibujarCircunferencia(xc, yc, re, ri, color,lienzo):
 """Dibuja una circunferencia con centro (xc,yc)
 y radio exterior re e interior ri.
 """
 if re <= ri: return #No funcionaría el algoritmo
 def marcarPixel(x,y):
  lienzo.set_at(( x+xc, y+yc), color)
  lienzo.set_at(( x+xc,-y+yc), color)
  lienzo.set_at((-x+xc, y+yc), color)
  lienzo.set_at((-x+xc,-y+yc), color)
  lienzo.set_at(( y+xc, x+yc), color)
  lienzo.set_at(( y+xc,-x+yc), color)
  lienzo.set_at((-y+xc, x+yc), color)
  lienzo.set_at((-y+xc,-x+yc), color)
 def marcarLineaH(xi,xf,y):
  i = xi
  while i<=xf:
   marcarPixel(i,y)
   i = i+1
 limites = {}
 x = 0
 y = re
 d = 1-re
 while y>x:
  if d<0:
   d += x*2+3
  else:
   d += (x-y)*2+5
   limites[y] = [None, x]
   y = y-1
  x = x+1
 x = 0
 y = ri
 d = 1-ri
 if limites.has_key(y):
  limites[y][0] = x
 else:
  limites[y] = [x, None]
 while y>x:
  if d<0:
   d += x*2+3
   x = x+1
  else:
   d += (x-y)*2+5
   y = y-1
   x = x+1
   if limites.has_key(y):
    limites[y][0] = x
   else:
    limites[y] = [x, None]
 for cada_y, (xi,xf) in limites.iteritems():
  if xi is None:
   marcarLineaH(0,xf,cada_y)
  elif xf is None:
   marcarLineaH(xi,cada_y,cada_y)
  else:
   marcarLineaH(xi,xf,cada_y)


def circunferencia(lienzo, color, (xc,yc), radio, ancho=1):
 dibujarCircunferencia(xc, yc, radio+ancho/2, radio-ancho/2, color, lienzo)



if __name__ == "__main__":
 global pantalla, e

 pygame.init()

 if prueba:
  pantalla = pygame.display.set_mode((ANCHO, ALTO))
  pygame.display.set_caption("Cornoide")
 else:
  pantalla = pygame.Surface((ANCHO, ALTO))

 e = escala.Escala((ANCHO, ALTO), INF_IZQ, SUP_DER)

 dibujar()
 if not prueba:
  print "Imagen generada. Guardando..."
  pygame.image.save(pantalla, "cornoide.png")
 raw_input("Presione una tecla para salir")

No hay comentarios:

Publicar un comentario