Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
ws1718:programmcode [2018/03/26 04:32] m.hansemann angelegt |
ws1718:programmcode [2018/03/26 04:33] (aktuell) m.hansemann |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | <code>[Python] | + | <code Python> |
+ | |||
+ | import pygame | ||
+ | from random import uniform | ||
+ | import numpy as np | ||
+ | from numpy import sign | ||
+ | from scipy.spatial import cKDTree | ||
+ | |||
+ | def board(screen,xsc,sizey,bloblist,struc): #Funktion die das Board in jeder Iteration neu zeichnet | ||
+ | i=0 | ||
+ | k=0 | ||
+ | pinc=0 | ||
+ | while (i<struc): | ||
+ | pygame.draw.line(screen,0,((xsc/2)+(xsc*i), sizey),(((xsc/2)+(xsc)*i), (sizey-50))) #Zeichnet die Linien der Faecher | ||
+ | |||
+ | while (k<=i): #Zeichnet einen Punkt an jeder Koordinate in der "bloblist"-Liste | ||
+ | pygame.draw.line(screen,0,bloblist[pinc],bloblist[pinc]) | ||
+ | pinc=pinc+1 | ||
+ | k=k+2 | ||
+ | i=i+1 | ||
+ | k=i*(-1) | ||
+ | |||
+ | |||
+ | |||
+ | def main(sizex, sizey, struc, radi, nball, mode,filos): #Hauptfunktion | ||
+ | |||
+ | pygame.init() #erzeugung der pygame instanz | ||
+ | screen = pygame.display.set_mode((int(sizex), int(sizey))) #Setzt die Fenstergroesse anhand der Uebergeben Groessen fest | ||
+ | pygame.display.set_caption("Galton") #Name des Fensters | ||
+ | screen.fill((255,255,255)) #hintergurndfarbe | ||
+ | |||
+ | pygame.draw.line(screen,0,(50.0,50),(50,150)) #Massstab um groessen zu Vergleichen | ||
+ | pygame.draw.circle(screen,0,(int(50),int(50.0)),5,0) | ||
+ | |||
+ | #-------------------VARIABLEN-------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | |||
+ | i=0 | ||
+ | k=0 | ||
+ | j=0 | ||
+ | |||
+ | by=0.0 #Y-Impuls der Kugel | ||
+ | bx=0.0 #X-Impuls der Kugel | ||
+ | |||
+ | t=0.0 #Zeitparameter | ||
+ | s=9000000.0 #Maxmimale Zeit, Abruchkriterium | ||
+ | |||
+ | colisionY=0.0 #Y-Koordinate des Abstands zwichen 2 Punkten | ||
+ | colisionX=0.0 #X-Koordinate des Abstands zwichen 2 Punkten | ||
+ | |||
+ | bloblist= [] #Liste aller Pins (Enthaelt je ein Orts-Tupel) | ||
+ | loballs=[] #Liste aller Kugel und ihrer Eigenschaften | ||
+ | poballs=[] #Liste aller Kugelpositionen (Enthaelt je ein Orts-Tupel) | ||
+ | |||
+ | pinc=0 #Zaehler der die Pins zaehlt, wird zur erzeugung der Pinstruktur benoetigt | ||
+ | |||
+ | bacou=0 #Beschreibt die Farbe der Kugel | ||
+ | |||
+ | |||
+ | grav=0.00981 #Gravitationskontante, Bestimmt die zuname der Geschwindigkeit in Y-richtung | ||
+ | |||
+ | #radi=5 #Radius der Kugel, Bestimmt auch Kollisionsradius | ||
+ | |||
+ | zahlen='' #String in dem jedesmal wenn eine Kugel in ein Fach faellt die Nummer des Fachs geschrieben wird | ||
+ | a=0 #Anzahl der Kugel in einem Fach | ||
+ | w=(struc*(-0.5)) #das am weitesten Linke Fach | ||
+ | dati="" #String der in die Datei geschrieben wird | ||
+ | |||
+ | coliimpx=0.0 #Variablen die zur Berechnung der dezentralen Kollision verwendet werden | ||
+ | coliimpy=0.0 | ||
+ | coliswapx=0.0 | ||
+ | coliswapy=0.0 | ||
+ | impimpx=0.0 | ||
+ | impimpy=0.0 | ||
+ | |||
+ | xsc=(sizex/(struc)) #Struktur Einteilung in X-Richtung | ||
+ | ysc=(sizey/(struc+1)) #Struktur Einteilung in Y-Richtung | ||
+ | |||
+ | #-------------------ERZEUGUNG------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ||
+ | |||
+ | if mode >1: # Verhindert Modi groesser 1 | ||
+ | mode=1 | ||
+ | |||
+ | |||
+ | while i<nball: # Erzeugung der Kugeln | ||
+ | loballs.append([(sizex/2)+(np.random.rand()-0.5)*5, (np.random.rand()-0.5)*5 + (sizey/2 *mode), (bx+(np.random.rand()-0.5)*0.02+(np.random.rand()-0.5)*0.5*mode), (by+(np.random.rand()-0.5)*0.02*mode), bacou]) # (X-Position,Y-Position,X-Impuls,Y-Impuls,Farbe) | ||
+ | loballs[i][4]=((np.random.randint(0,255)),(np.random.randint(0,255)),(np.random.randint(0,255))) #Erzeugung der Farbe durch RNG | ||
+ | i=i+1 | ||
+ | i=0 | ||
+ | |||
+ | if mode==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | while (i<struc): #Erzeugung des Boards | ||
+ | pygame.draw.line(screen,0,((xsc/2)+(xsc*i), sizey),(((xsc/2)+(xsc)*i), (sizey-50))) #Zeichnen der Linien der Faecher | ||
+ | |||
+ | while (k<=i): #Erzeugung der Pins | ||
+ | bloblist.append(((((sizex/2)+(xsc/2)*(k))), ((ysc)*i)+50)) | ||
+ | pygame.draw.line(screen,0,bloblist[pinc],bloblist[pinc]) | ||
+ | |||
+ | pinc=pinc+1 | ||
+ | k=k+2 | ||
+ | i=i+1 | ||
+ | k=i*(-1) | ||
+ | i=0 | ||
+ | |||
+ | tree = cKDTree(bloblist,leafsize=1) #Erzeugung des Pin-Tree in dem alle Orte der Pins gespeichert werden | ||
+ | |||
+ | |||
+ | #-------------------Bewegung und Kollision--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | while t!=s: #Grosse Schleife, bricht ab sobald Zeitparameter t den Abruchparameter s erreicht | ||
+ | if t!=s: | ||
+ | |||
+ | t=t+1 #Iteriert den Zeitparameter | ||
+ | screen.fill((255,255,255)) #setzt das Fenster auf Weiss zurueck | ||
+ | |||
+ | |||
+ | poballs=[] #Leert die Liste | ||
+ | for ball in loballs: #Fuegt die aktuellen Positionen aller Kugeln hinzu | ||
+ | poballs.append((ball[0],ball[1])) | ||
+ | |||
+ | tree2 = cKDTree(poballs, leafsize=1) #Erzeugt den Kugel-Tree | ||
+ | |||
+ | |||
+ | #-------------------Bewegung------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ||
+ | for ball in loballs: | ||
+ | |||
+ | if mode==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | ball[3]=ball[3]+grav #Fuegt der Y-Impulskoordinate die Gravitation hinzu (in Testbench nicht noetig) | ||
+ | ball[0]=ball[0]+ball[2] #Addiert die X-Impulskoordinate auf den X-Ort der Kugel (Bewegung) | ||
+ | ball[1]=ball[1]+ball[3] #Addiert die Y-Impulskoordinate auf den Y-Ort der Kugel (Bewegung) | ||
+ | |||
+ | pygame.draw.circle(screen,ball[4],(int(ball[0]),int(ball[1])),radi,0) #Zeichnet die Kugel am neuen Ort in ihrer Farbe | ||
+ | pygame.draw.circle(screen,(0,0,0),(int(ball[0]),int(ball[1])),radi,1) #Zeichnet schwarzen Rand um die Kugel | ||
+ | |||
+ | #-------------------Kollision------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | #----------------------Wand--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | if ball[0]>=(sizex-5): #rechtsseitiger Rand | ||
+ | ball[2]=ball[2]*(-1) | ||
+ | |||
+ | if ball[0]<=5: #linksseitiger Rand | ||
+ | ball[2]=ball[2]*(-1) | ||
+ | |||
+ | |||
+ | if mode!=0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | if ball[1]>=(sizey-5): #unterer Rand (nur in Testbench) | ||
+ | ball[3]=ball[3]*(-1) | ||
+ | if ball[1]<=(5): #oberer Rand (nur in Testbench) | ||
+ | ball[3]=ball[3]*(-1) | ||
+ | |||
+ | #----------------------Pin--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | d,j= tree.query([ball[0],ball[1]]) #dursucht den Pin-Tree nach naechstem Pin | ||
+ | if d <radi: | ||
+ | |||
+ | colisionY = ball[1]-bloblist[j][1] #Bestimmung des Abstandsvektors | ||
+ | colisionX = ball[0]-bloblist[j][0] | ||
+ | |||
+ | ball[3]=0.5*ball[3]*sign(ball[3])*sign(colisionY) #Reversion des Kugel-Impulses, wenn dieser auf den Pin zeigt | ||
+ | ball[2]=ball[2]*sign(ball[2])*sign(colisionX) | ||
+ | |||
+ | if abs(ball[3])<grav: #Verhindert das der Impuls zu klein wird und die Kugel am Pin 'klebt' | ||
+ | ball[3]=ball[3]+(sign(ball[3])*0.8*grav) | ||
+ | if abs(ball[2])<0.002: | ||
+ | ball[2]=ball[2]+((np.random.rand()-0.5)*0.05) | ||
+ | |||
+ | #----------------------Kugel-Kugel--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | h,g= tree2.query(([ball[0],ball[1]]),2) #durchsucht den Kugel-Tree nach naechste Kugel die nicht sie selbst ist | ||
+ | if h[1]<(2*radi): | ||
+ | if g[1]<len(loballs): | ||
+ | colisionY = ball[1]-loballs[g[1]][1]+0.000001 #Bestimmung des Abstandsvektors der Beiden Kugeln | ||
+ | colisionX = ball[0]-loballs[g[1]][0]+0.000001 #+0.0000001 damit der Abstand nicht 0 wird [WORKAROUND] | ||
+ | |||
+ | coliimpx = colisionX*ball[2] #multiplikation mit den Impulskoordinaten der Kugel mit dem Abstandsvektor | ||
+ | coliimpy = colisionY*ball[3] | ||
+ | impimpx = ball[2]*loballs[g[1]][2] #multiplikation der Impulskoordinaten beider Kugeln | ||
+ | impimpy = ball[3]*loballs[g[1]][3] | ||
+ | |||
+ | if sign(coliimpx)*sign(impimpx) >=0: #check ob beide Impulse aufeinander zu zeigen | ||
+ | if sign(coliimpy)*sign(impimpy) >=0: | ||
+ | |||
+ | coliimpx = (((ball[2]-loballs[g[1]][2])*colisionX + (ball[3]-loballs[g[1]][3])*colisionY)*colisionX)/(colisionX**2+colisionY**2) # dezentrale Kollision | ||
+ | coliimpy = (((ball[2]-loballs[g[1]][2])*colisionX + (ball[3]-loballs[g[1]][3])*colisionY)*colisionY)/(colisionX**2+colisionY**2) | ||
+ | |||
+ | loballs[g[1]][2]=loballs[g[1]][2]+0.5*coliimpx #Impuls neu zuweisung | ||
+ | loballs[g[1]][3]=loballs[g[1]][3]+0.5*coliimpy | ||
+ | |||
+ | ball[2]=ball[2]-coliimpx #Impuls neu zuweisung | ||
+ | ball[3]=ball[3]-coliimpy | ||
+ | #----------------------Fach-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | if ball[1]>=(sizey-40): #Zaehlung der Kugel im Fach | ||
+ | c=int(ball[0]/(sizex/(struc+1)))-((struc)/2) | ||
+ | zahlen=zahlen + " " + str(c) + " " | ||
+ | #----------------------Endkriterien---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | loballs = [ ball for ball in loballs if ball[1]<sizey-40] #Ausschluss aller in Faecher gefallenen Kugeln | ||
+ | |||
+ | if not loballs: #Abruch sobald alle Kugel in Faechern sind | ||
+ | t=s | ||
+ | if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | board(screen,xsc,sizey,bloblist,struc) #neuzeichnen des Bretts | ||
+ | pygame.display.flip() | ||
+ | #----------------------Auswertung-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) | ||
+ | f=open(filos+".txt", "w") | ||
+ | while w<=(struc/2): #Zaehlung der Kugeln in den Faechern und schreiben der AAnzahlen in die Datei | ||
+ | dt=" "+str(w) + " " | ||
+ | a=zahlen.count(dt) | ||
+ | dati= dati + str(w) + "\t" + str(a) +"\t" + "\n" | ||
+ | w=w+1 | ||
+ | f.write(dati) | ||
+ | f.close() | ||
+ | print "fin" | ||
+ | |||
+ | filos="pygg_data3" #Dateiname | ||
+ | |||
+ | main(500.0, 500.0, 12.0, 5, 200, 0, filos) | ||
</code> | </code> |