# The actual program starts in line 150. # The code up to there is just a copy of # the kantigrafik library in order to # have everything in one file. # Space key or mouse click to stop/resume animation. # Escape key to stop program. # begin of kantigrafik library # # kantigrafik-Bibliothek # Version vom 13.12.2022 import pygame import time import math # Farben per Rot-, Grün- und Blauwert # (jeweils auf Skala von 0 bis 255). # rot grün blau ROT = (255, 0, 0) GRUEN = ( 0, 255, 0) BLAU = ( 0, 0, 255) GELB = (255, 255, 0) MAGENTA = (255, 0, 255) CYAN = ( 0, 255, 255) WEISS = (255, 255, 255) SCHWARZ = ( 0, 0, 0) GRAU = (100, 100, 100) HINTERGRUND_FARBE = SCHWARZ ZEICHENFARBE = WEISS def zeichenfenster(min_x, min_y, max_x, max_y, pixel_pro_einheit, titel): global leinwand global ecke_links_unten global ecke_rechts_oben global faktor ecke_links_unten = (min_x, min_y) ecke_rechts_oben = (max_x, max_y) faktor = pixel_pro_einheit pygame.init() leinwand = pygame.display.set_mode(((max_x - min_x) * pixel_pro_einheit + 1, (max_y - min_y) * pixel_pro_einheit + 1)) pygame.display.set_caption(titel) leinwand.fill(HINTERGRUND_FARBE) def neue_zeichnung(): leinwand.fill(HINTERGRUND_FARBE) def leinwandpunkt(x, y): return ((x - ecke_links_unten[0]) * faktor, (ecke_rechts_oben[1] - y) * faktor) def linie(x1, y1, x2, y2): pygame.draw.line(leinwand, ZEICHENFARBE, leinwandpunkt(x1, y1), leinwandpunkt(x2, y2)) def linie_breit(x1, y1, x2, y2, breite): pygame.draw.line(leinwand, ZEICHENFARBE, leinwandpunkt(x1, y1), leinwandpunkt(x2, y2), width=round(breite * faktor)) def raster(): for i in range(ecke_links_unten[0], ecke_rechts_oben[0] + 1): linie(i, ecke_links_unten[1], i, ecke_rechts_oben[1]) for i in range(ecke_links_unten[1], ecke_rechts_oben[1] + 1): linie(ecke_links_unten[0], i, ecke_rechts_oben[0], i) def x_achse(): linie(ecke_links_unten[0], 0, ecke_rechts_oben[0], 0) for i in range(ecke_links_unten[0], ecke_rechts_oben[0]): linie(i, -0.2, i, 0.2) linie(ecke_rechts_oben[0], 0, ecke_rechts_oben[0] - 0.2, 0.2) linie(ecke_rechts_oben[0], 0, ecke_rechts_oben[0] - 0.2, -0.2) def y_achse(): linie(0, ecke_links_unten[1], 0, ecke_rechts_oben[1]) for i in range(ecke_links_unten[1], ecke_rechts_oben[1]): linie(-0.2, i, 0.2, i) linie(0, ecke_rechts_oben[1], 0.2, ecke_rechts_oben[1] - 0.2) linie(0, ecke_rechts_oben[1], -0.2, ecke_rechts_oben[1] - 0.2) def kreis(x, y, r): pygame.draw.circle(leinwand, ZEICHENFARBE, leinwandpunkt(x, y), faktor * r, width=1) def gefuellter_kreis(x, y, r): pygame.draw.circle(leinwand, ZEICHENFARBE, leinwandpunkt(x, y), faktor * r, width=0) def punkt(x, y): # draw.line(leinwand, ZEICHENFARBE, leinwandpunkt(x, y), leinwandpunkt(x, y)) if ecke_links_unten[0] <= x <= ecke_rechts_oben[0] and ecke_links_unten[1] <= y <= ecke_rechts_oben[1]: a, b = leinwandpunkt(x, y) a = round(a) b = round(b) leinwand.set_at((a, b), ZEICHENFARBE) def farbe(c): global ZEICHENFARBE ZEICHENFARBE = c def zeige(): pygame.display.update() def warte_auf_klick(): beenden = False while not beenden: pygame.display.update() for ereignis in pygame.event.get(): if ereignis.type == pygame.QUIT: beenden = True elif ereignis.type == pygame.KEYDOWN: if ereignis.key in {pygame.K_ESCAPE, pygame.K_q}: beenden = True elif ereignis.type == pygame.MOUSEBUTTONDOWN: beenden = True quit() def speichere(dateiname): pygame.image.save(leinwand, dateiname) def pause(sekunden): time.sleep(sekunden) def schreibe(x, y, text, groesse): # schrift = pygame.font.Font('freesansbold.ttf', round(groesse * faktor)) # Mit pygame.font.SysFont kann man wohl jede der Fonts aus der Liste # pygame.font.get_fonts() # verwenden. schrift = pygame.font.SysFont('freemono', round(groesse * faktor)) formatierter_text = schrift.render(text, True, WEISS, SCHWARZ) # formatierter_text.set_alpha(127) rechteck = formatierter_text.get_rect() # rechteck.center = leinwandpunkt(x, y) rechteck.bottomleft = leinwandpunkt(x, y) # print(dir(rechteck)) leinwand.blit(formatierter_text, rechteck) def bogenmass(alpha): return(alpha * math.pi / 180) def grad_cos(alpha): return math.cos(bogenmass(alpha)) def grad_sin(alpha): return math.sin(bogenmass(alpha)) def grad_tan(alpha): return math.tan(bogenmass(alpha)) # end of kantigrafik library # start of the animation program from time import * from math import * STARTWINKEL = -360 - 30 ENDWINKEL = 720 - 30 WINKELVERAENDERUNG = 0.3 MINY = -6 MAXY = 6 KREISZENTRUM_Y = 0 FADE_OUT = (ENDWINKEL - STARTWINKEL) / WINKELVERAENDERUNG print(FADE_OUT) FRAMES_PER_SECOND = 200 ZU_ZEICHNEN = [ 'tan', 'cos', 'sin', 'kreis', ] FARBWAHL = { 'sin': ROT, 'cos': GRUEN, 'tan': GELB, 'kreis': ROT, } # DICKE_GRAPH = 0.03 DICKE_GRAPH = 0.1 DICKE_WANDERNDE_PUNKTE = 1.5 * DICKE_GRAPH DICKE_LINIEN = 1 / 3 * DICKE_GRAPH def verbinde(A, B): linie_breit(A['x'], A['y'], B['x'], B['y'], DICKE_LINIEN) def zeichne_zustand(bogenmass): global punkte_liste neue_zeichnung() farbe(GRAU) raster() # kreis(KREISZENTRUM_Y, 0, 1) farbe(ROT) for name in ZU_ZEICHNEN: for index, (x, y) in enumerate(punkte_liste[name]): # if name != 'kreis': (r, g, b) = (round((index/FADE_OUT) * FARBWAHL[name][0]), round((index/FADE_OUT) * FARBWAHL[name][1]), round((index/ FADE_OUT) * FARBWAHL[name][2])) farbe((r, g, b)) # else: # farbe(FARBWAHL['kreis']) # punkt(x, y) gefuellter_kreis(x, y, DICKE_GRAPH / 2) P = { 'sin': {'x': bogenmass, 'y': math.sin(bogenmass)}, 'cos': {'x': bogenmass, 'y': math.cos(bogenmass)}, 'tan': {'x': bogenmass, 'y': math.tan(bogenmass)}, 'kreis': {'x': KREISZENTRUM_Y + math.cos(bogenmass), 'y': math.sin(bogenmass)} } for name in ZU_ZEICHNEN: farbe(FARBWAHL[name]) x, y = P[name]['x'], P[name]['y'] gefuellter_kreis(x, y, DICKE_WANDERNDE_PUNKTE / 2) punkte_liste[name].append((x, y)) if len(punkte_liste[name]) > FADE_OUT: punkte_liste[name].pop(0) farbe(FARBWAHL['sin']) verbinde(P['kreis'], P['sin']) farbe(FARBWAHL['cos']) WP = {'x': KREISZENTRUM_Y + math.cos(bogenmass), 'y': math.cos(bogenmass)} verbinde(P['kreis'], WP) verbinde(WP, P['cos']) farbe(FARBWAHL['tan']) OP = {'x': KREISZENTRUM_Y, 'y': 0} SP = {'x': KREISZENTRUM_Y + 1, 'y': math.tan(bogenmass)} verbinde(P['kreis'], OP) verbinde(P['kreis'], SP) verbinde(SP, P['tan']) farbe(WEISS) x_achse() y_achse() ######## Main program starts here. ######## zeichenfenster(min(KREISZENTRUM_Y - 1, floor(bogenmass(STARTWINKEL))), MINY, max(KREISZENTRUM_Y + 1, ceil(bogenmass(ENDWINKEL))), MAXY, 100, "Animation der trigonometrischen Funktionen Sinus, Cosinus und Tangens") uhr = pygame.time.Clock() punkte_liste = {'sin': [], "cos": [], "tan": [], "kreis": []} weitermachen = True winkelveraenderung = WINKELVERAENDERUNG while weitermachen: alpha = STARTWINKEL while alpha < ENDWINKEL: if winkelveraenderung > 0: zeichne_zustand(bogenmass(alpha)) zeige() alpha += winkelveraenderung uhr.tick(FRAMES_PER_SECOND) # sleep(0.01) for ereignis in pygame.event.get(): if ereignis.type == pygame.QUIT: weitermachen = False elif ereignis.type == pygame.KEYDOWN: if ereignis.key in {pygame.K_ESCAPE, pygame.K_q}: weitermachen = False elif ereignis.key == pygame.K_SPACE: winkelveraenderung = WINKELVERAENDERUNG - winkelveraenderung elif ereignis.type == pygame.MOUSEBUTTONDOWN: winkelveraenderung = WINKELVERAENDERUNG - winkelveraenderung if not weitermachen: break # speichere("bildchen.jpeg") # Leider werden die Punkte nicht gut abgespeichert. # warte_auf_klick()