(es) Construcción de la Cornoide
(eo) Konstruado de Kornokurbo
http://dx.doi.org/10.13140/RG.2.2.34092.90243
Descripción artística:
Instrucciones visuales para el trazo de la curva Cornoide, descubierta por el Doctor Alberto Sánchez, salvadoreño, en 1895.
La secuencia está en espiral: Comenzando en la esquina superior izquierda, luego a la derecha hasta la esquina superior derecha, luego hacia abajo hasta la esquina inferior derecha, luego a la izquierda y así sucesivamente.
Motivación:
Las instrucciones simples pero poco conocidas para la construcción de la Cornoide.
Descripción técnica:
El trazo de la curva Cornoide, en 16 pasos en espiral de afuera hacia adentro.
El procedimiento geométrico para construirla es el siguiente:
Sea un punto de la circunferencia de diámetro director y sea el punto de intersección de la circunferencia con la paralela por el punto al diámetro . Desde se traza la recta tangente a la circunferencia y desde la recta perpendicular a la recta tangente. Sea el punto intersección de ambas rectas. Cuando el punto describe la circunferencia, el punto 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
"""Este programa genera la secuencia de pasos de la construcción de la Cornoide
"""
import pygame
import math
import escala
#prueba = False
prueba = True
if prueba:
ANCHO = 1000
ALTO = 1000
else:
ANCHO = 2000
ALTO = 2000
INF_IZQ = (-1.05,-1.05)
#INF_IZQ = (-1.45,-1.45)
SUP_DER = (1.45,1.45)
TAMMATRIZ = 4
NUMPASOS = 16
NUMPASOSCURVA = 160*NUMPASOS
TIEMPO_PAUSA = 600
#En pixeles:
GRUESO_CIRCULO = 4 ####2
GRUESO_CORNOIDE = 20 ####4
GRUESO_LINEA = 2
RADIO_PUNTO = 10 ####2
#En unidades virtuales:
RADIO_CIRCULO = 1.0
PROP_ANG = 0.1
ROJO = (255,0,0)
VERDE = (0,255,0)
AZUL = (0,0,255)
BLANCO = (255,255,255)
NEGRO = (0,0,0)
COLOR_CORNOIDE = (84,187,255)
COLOR_CIRCULO = NEGRO
COLOR_RADIO = (0,250,0)
COLOR_TANGENTE = (0,200,0)
COLOR_SECANTE = (0,150,0)
COLOR_FINAL = (0,100,0)
COLOR_ANGULO = (200,200,200)
COLOR_PUNTO = ROJO
matriz = [(0,0),(1,0),(2,0),(3,0),(3,1),(3,2),(3,3),(2,3),(1,3),(0,3),(0,2),(0,1),(1,1),(2,1),(2,2),(1,2),]
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(lienzo,i):
"""Aquí hay que guardar las imágenes"""
global imgfinal
if prueba:
pygame.display.flip()
#Descomentar la siguiente línea para generar los archivos *.png individuales
#pygame.image.save(lienzo, "img-{0:02}.png".format(i))
else:
if NUMPASOS==16:
imgfinal.blit(lienzo, (ANCHO*matriz[i-1][0],ALTO*matriz[i-1][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)
def dibujar(pantalla, e):
i = 0
t = 0.0
i=i+1
while i<=NUMPASOS:
#Limpiar lienzo:
pantalla.fill(BLANCO)
#Dibujar círculo:
circunferencia(pantalla, COLOR_CIRCULO, e.vr((0.0,0.0)), int(e.magnitudvrx(RADIO_CIRCULO)), GRUESO_CIRCULO)
#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
#Calcular punto actual del cornoide:
t = math.pi/2 * i/NUMPASOS
p = cornoide(t, RADIO_CIRCULO)
pr = e.vr(p)
#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:
pendienteRad = math.tan(t)
pendienteTan = -1.0/pendienteRad
ptan1 = e.minxv, pendienteTan * (e.minxv - pcirc[0]) + pcirc[1]
ptan2 = e.maxxv, pendienteTan * (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)
##Marcadores de ángulos rectos:
pe1 = (1.0+PROP_ANG)*p[0] - PROP_ANG*pcirc[0], (1.0+PROP_ANG)*p[1] - PROP_ANG*pcirc[1]
pe2 = p[1]+p[0]-pe1[1], p[1]-p[0]+pe1[0]
pe3 = pe1[0] + pe2[0]-p[0], pe1[1] + pe2[1]-p[1]
pygame.draw.line(pantalla, COLOR_TANGENTE, e.vr(pe1), e.vr(pe3), GRUESO_LINEA)
pygame.draw.line(pantalla, COLOR_TANGENTE, e.vr(pe2), e.vr(pe3), GRUESO_LINEA)
pe1 = (1.0+PROP_ANG)*pcirc[0] - PROP_ANG*p[0], (1.0+PROP_ANG)*pcirc[1] - PROP_ANG*p[1]
pe2 = -pcirc[1]+pcirc[0]+pe1[1], pcirc[1]+pcirc[0]-pe1[0]
pe3 = pe1[0] + pe2[0]-pcirc[0], pe1[1] + pe2[1]-pcirc[1]
pygame.draw.line(pantalla, COLOR_TANGENTE, e.vr(pe1), e.vr(pe3), GRUESO_LINEA)
pygame.draw.line(pantalla, COLOR_TANGENTE, e.vr(pe2), e.vr(pe3), GRUESO_LINEA)
##Puntos:
#Centro del círculo:
pygame.draw.circle(pantalla, COLOR_PUNTO, e.vr((0.0,0.0)), RADIO_PUNTO)
#Punto del círculo:
pygame.draw.circle(pantalla, COLOR_PUNTO, e.vr(pcirc), RADIO_PUNTO)
#Simétrico al anterior (de la secante):
pygame.draw.circle(pantalla, COLOR_PUNTO, e.vr(pcirc2), RADIO_PUNTO)
#Punto guía de la cornoide:
pygame.draw.circle(pantalla, COLOR_PUNTO, pr, RADIO_PUNTO)
#Dibujar y guardar si está habilitado
actualizar(pantalla, i)
if prueba:
pygame.time.delay(TIEMPO_PAUSA)
i = i+1
if __name__ == "__main__":
global imgfinal
pygame.init()
if prueba:
pantalla = pygame.display.set_mode((ANCHO, ALTO))
pygame.display.set_caption("Cornoide")
else:
pantalla = pygame.Surface((ANCHO, ALTO))
imgfinal = pygame.Surface((ANCHO*TAMMATRIZ, ALTO*TAMMATRIZ))
e = escala.Escala((ANCHO, ALTO), INF_IZQ, SUP_DER)
dibujar(pantalla, e)
#Guardar imagen final
if not prueba and NUMPASOS==16:
for x in range(TAMMATRIZ-1):
pygame.draw.line(imgfinal, (0,0,0), (ANCHO*(x+1),0), (ANCHO*(x+1),ALTO*TAMMATRIZ))
for y in range(TAMMATRIZ-1):
pygame.draw.line(imgfinal, (0,0,0), (0,ALTO*(y+1)), (ANCHO*TAMMATRIZ, ALTO*(y+1)))
pygame.image.save(imgfinal, "pasos.png")
raw_input("Presione una tecla para salir")
No hay comentarios:
Publicar un comentario