(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