diff --git a/Ray.py b/Ray.py new file mode 100644 index 0000000..e0f0345 --- /dev/null +++ b/Ray.py @@ -0,0 +1,105 @@ +from scipy.integrate import solve_ivp +import math +import numpy as np +from scipy.constants import pi +from scipy.interpolate import interp1d +from functools import cache +import copy +from PIL import Image + + +class Ray(): + interpolation = None + + def __init__(self, x, y, D, Rs, fov, res, accuracy): + self.x = x + self.y = y + self.D = D + self.Rs = Rs + self.fovX = fov[0] + self.fovY = fov[1] + self.res = res + self.accuracy = accuracy + + if Ray.interpolation is None: + self.interpolate() + + self.interpolation = Ray.interpolation + + def interpolate(self): + maxA = self.fovX + minA = self.apperentSize(0, 180) + + linspace = np.linspace(0, 1, self.accuracy) + angles = minA + (maxA - minA) * linspace**6 + + array = [] + for i in range(self.accuracy): + sol = self.solver(angles[i]) + deviatedAngle = sol[1][len(sol[1]) - 1] + array.append([angles[i], np.degrees(deviatedAngle)]) + + #interpolierung der punkte + points = np.array(array) + Ray.interpolation = interp1d(points[:, 0], points[:, 1], kind='cubic') + + def solver(self, alpha): + if alpha == 0: # skip divided by 0 error + return [0], [0] # r and phi=0 + + if alpha == 180: + return [self.D], [0] # if angle= pi then, tan(pi)=0 so 1/tan=1/0 + + # initial value for position and angular speed + y0 = [1/self.D, 1/(self.D*math.tan(math.radians(alpha)))] + sol = solve_ivp(fun=self._diff_eq, t_span=[0, 10*pi], y0=y0, method='DOP853', events=[self._eventRs]) #, self._eventR])#,t_eval=np.linspace(0, t_max, 10000)) #dense_output=False + + if sol.t[-1] == 10*pi: + raise StopIteration("solver error, alpha reached computation limit (loop number)") + + phi = np.array(sol.t) + r = np.abs(1/sol.y[0, :]) # must use this because solver can't be stop before infinity because negative + + return r, phi + + def _diff_eq(self, phi, u): + """Represent the differential equation : d²u(ɸ)/dɸ²=3/2*Rs*u²(ɸ)-u(ɸ) + """ + v0 = u[1] #correspond to u' + v1 = 3/2*self.Rs*u[0]**2 - u[0] #correspond to u" + return v0, v1 + + def _eventRs(self, phi, u): + """stop solver if radius < black hole radius""" + with np.errstate(all='ignore'): + return 1/u[0] - self.Rs + _eventRs.terminal = True + + def apperentSize(self, a1, a2): + + if a2-a1 <= .01: #!!!!!!!!!!!!MaxDeviation später einfügen maybe + return a2 + + points = np.linspace(a1, a2, 3) + point = self.solver(points[1]) + + test = point[0][len(point[0]) - 1 ] + + if test > self.Rs: + return self.apperentSize(a1, points[1]) + + + elif test <= self.Rs: + return self.apperentSize(points[1], a2) + else: + print("Fehler") + + def angle(self): + x = self.x + y = self.y + + n = None + m = None + + angle = math.degrees(math.atan2(math.sqrt(n**2 + m**2))) + return self.interpolation(angle) diff --git a/black_hole2.py b/black_hole2.py new file mode 100644 index 0000000..155fc3d --- /dev/null +++ b/black_hole2.py @@ -0,0 +1,259 @@ +from scipy.integrate import solve_ivp +import math +import numpy as np +from scipy.constants import pi +from scipy.interpolate import interp1d +import copy +from PIL import Image + +Rs = 8 # in au +D = 50 # -"- +accuracy = 100 # amount of iterations of solver +res = 500 #as pixel on X-Axis +fovX = 180 #in ° ####vorläufig über 180 +fovY = 180 # -"- +maxDeviation = .01 # bei zu kleinem wert, knick in interpolation. ?photonensphäre? später lösen!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +bg = Image.open("old/images/background.jpg") +#test = [] + +def solver(alpha): + if alpha == 0: # skip divided by 0 error + return [0], [0] # r and phi=0 + + if alpha == 180: + return [D], [0] # if angle= pi then, tan(pi)=0 so 1/tan=1/0 + + # initial value for position and angular speed + y0 = [1/D, 1/(D*math.tan(math.radians(alpha)))] + sol = solve_ivp(fun=_diff_eq, t_span=[0, 10*pi], y0=y0, method='DOP853', events=[_eventRs]) #, self._eventR])#,t_eval=np.linspace(0, t_max, 10000)) #dense_output=False + + if sol.t[-1] == 10*pi: + raise StopIteration("solver error, alpha reached computation limit (loop number)") + + phi = np.array(sol.t) + r = np.abs(1/sol.y[0, :]) # must use this because solver can't be stop before infinity because negative + + #print("alpha:", alpha) + #print(phi, r) + + print("I AM DOING SOMETHING!!", alpha) + + return r, phi + +def _diff_eq(phi, u): + """Represent the differential equation : d²u(ɸ)/dɸ²=3/2*Rs*u²(ɸ)-u(ɸ) + """ + v0 = u[1] #correspond to u' + v1 = 3/2*Rs*u[0]**2 - u[0] #correspond to u" + return v0, v1 + + +def _eventRs(phi, u): + """stop solver if radius < black hole radius""" + with np.errstate(all='ignore'): + return 1/u[0] - Rs +_eventRs.terminal = True + + + +def apperentSize(a1, a2): + + if a2-a1 <= maxDeviation: + print(a2) + return a2 + + + points = np.linspace(a1, a2, 3) + point = solver(points[1]) + + test = point[0][len(point[0]) - 1 ] + + if test > Rs: + print("1") + return apperentSize(a1, points[1]) + + + elif test <= Rs: + print("2") + return apperentSize(points[1], a2) + else: + print("Fehler") + +def getAllAngles(): + maxA = 0# 180 - math.degrees( math.acos(math.cos(math.radians(fovX)) * math.cos(math.radians(fovY)))) #math.sqrt(((fovX/2)**2) + ((fovY/2)**2)) + print("MAX_____________________", maxA) + maxA = fovX + #maxA = 90 + + minA = apperentSize(0, 180) + print(minA) + # minA = 24.2086 + + linspace = np.linspace(0, 1, accuracy) + + angles = minA + (maxA - minA) * linspace**6 #beser als **6 finden !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + #angles = np.geomspace(minA, maxA, accuracy) + array = [] + for i in range(accuracy): + sol = solver(angles[i]) + deviatedAngle = sol[1][len(sol[1]) - 1] + array.append([angles[i], np.degrees(deviatedAngle)]) + + #print(array) + + #interpolierung der punkte + + points = np.array(array) + + f = interp1d(points[:, 0], points[:, 1], kind='cubic') + + #x_new = np.linspace(points[:, 0].min(), points[:, 0].max(), 5000) + #y_new = f(x_new) +# + #plt.figure() + #plt.scatter(points[:, 0], points[:, 1]) + #plt.plot(x_new, y_new, '-', label='Kubische Interpolation', color= 'orange') + #plt.xlabel("Seen angle") + #plt.ylabel("deviated angle") + #plt.title("Punkte aus array") + #plt.grid(True) + #plt.show() + + #berechnung der einzelnen Pixel + + resX = res + resY = int(res * fovY / fovX) + + deviationOfPixels = [] + + conversion = maxA / math.degrees( math.acos(math.cos(math.radians(resX) / 2) * math.cos(math.radians(resY) / 2))) ##################################################################### + + for x in range(int(resX / 2)): + deviationOfPixels.append([]) + for y in range(int(resY / 2)): + deviationOfPixels[x].append([]) + + d = math.degrees( math.acos(math.cos(math.radians(x/int(resX / 2) * fovX / 2)) * math.cos(math.radians(y/int(resY / 2) * fovY / 2))))#% maxA #* conversion + + if d >= minA: + + beta = math.atan2(y, x) + + deviation = f(d) % 360 #unnötige umdrehungen durch subtrahieren von auf 360 gerundeten Wert ignorieren + + alpha = x/int(resX / 2) * fovX / 2 + beta = y/int(resY / 2) * fovY / 2 + + phi = math.degrees(math.atan2(math.sin(math.radians(deviation)) * (math.cos(math.radians(beta)) * math.sin(math.radians(alpha))) / math.sqrt((math.cos(math.radians(beta)) * math.sin(math.radians(alpha)))**2 + math.sin(math.radians(beta))**2), math.cos(math.radians(deviation)))) + + theta = 2 * math.degrees(math.asin(math.sin(math.radians(deviation)) * math.sin(math.radians(beta)) / math.sqrt((math.cos(math.radians(beta)) * math.sin(math.radians(alpha)))**2 + math.sin(math.radians(beta))**2))) + + deviationX = theta + deviationY = phi + + deviationOfPixels[x][y] = ([deviationX, deviationY]) + + else: + deviationOfPixels[x][y] = None + + print("ARRAY") + + doc = open("del3.txt", "w") + for i in range(len(deviationOfPixels)): + doc.write(str(deviationOfPixels[i])) + doc.write('\n') + doc.close() + + return deviationOfPixels + +def fullArray(array): + arr = array + arr.reverse() + arr2 = copy.deepcopy(arr) + result =[] + result2 = [] + for i in range(len(arr2)): + arr2[i].reverse() + for j in range(len(arr2[i])): + if arr2[i][j] != None: + + zahl1, zahl2 = arr2[i][j] + + arr2[i][j] = [-zahl1, zahl2] + result.append((arr2[i]) + arr[i]) + + res = copy.deepcopy(result) + + for i in range(len(res)): + for j in range(len(res[i])): + if res[i][j] != None: + zahl1, zahl2 = res[i][j] + + res[i][j] = [zahl1, -zahl2] + + res.reverse() + + result2.append(result + res) + #result2.append(result) + + return result2[0] + +def allPixel(deviations): + Img = [] + + + bgY, bgX = bg.size + + conversionX = bgX / 360 + print("len", len(deviations)) + print("con", conversionX) + conversionY = bgY / 360 + print("len", len(deviations[0])) + print("con", conversionY) + + test = .5 + + print(" max X:", ) + + for x in range(len(deviations)): + Img.append([]) + for y in range(len(deviations[x])): + Img[x].append([]) + + if deviations[x][y] == None: + pixel = (0, 0, 0) + + else: + px = int(deviations[x][y][0] % 360 * conversionX - (bgX / 2)) - 1 + py = int(deviations[x][y][1] % 360 * conversionY) - 1 + + pixel = bg.getpixel((py ,px)) + + Img[x][y] = pixel + #print(Img) + return Img + +def showImage(arrayx): + # Beispiel: array ist dein Pixel-Array + # Achtung: Pillow erwartet (height, width), also [y][x] + height = len(arrayx[0]) + width = len(arrayx) + + # In ein flaches Array umwandeln + pixels = [] + for y in range(height): + for x in range(width): + pixels.append(arrayx[x][y]) + + # Bild erzeugen + img = Image.new("RGB", (width, height)) + img.putdata(pixels) + img.show() + + +deviationOfPixels = getAllAngles() + +array = fullArray(deviationOfPixels) + +showImage(allPixel(array)) \ No newline at end of file diff --git a/test.py b/test.py index 25c8885..1e9cebe 100644 --- a/test.py +++ b/test.py @@ -1,282 +1,5 @@ -import pygame -import random -import time -from kart import Kart, Item +from Ray import Ray +ray = Ray(199, 231, 50, 8, [90, 90], [200, 200], 20) -# ------------------------- -# Einstellungen -# ------------------------- - -WIDTH = 1000 -HEIGHT = 700 -FPS = 60 - -BACKGROUND = (40, 40, 40) - - -# ------------------------- -# Hilfsfunktion zum Zeichnen -# ------------------------- - -def draw_kart(screen, kart): - # Kart als Rechteck - width = 40 - height = 25 - - surface = pygame.Surface((width, height), pygame.SRCALPHA) - pygame.draw.rect(surface, kart.color, (0, 0, width, height)) - - # Richtung des Karts - rotated = pygame.transform.rotate(surface, -kart.rotation) - - rect = rotated.get_rect( - center=(int(kart.position[0]), int(kart.position[1])) - ) - - screen.blit(rotated, rect) - - -# ------------------------- -# Pool zeichnen -# ------------------------- - -def draw_pool(screen, pool): - pygame.draw.ellipse( - screen, - pool.color, - ( - int(pool.position[0] - pool.size), - int(pool.position[1] - pool.size / 2), - int(pool.size * 2), - int(pool.size) - ) - ) - - -# ------------------------- -# Main -# ------------------------- - -def main(): - pygame.init() - - screen = pygame.display.set_mode((WIDTH, HEIGHT)) - pygame.display.set_caption("Kart Game") - - clock = pygame.time.Clock() - - # ------------------------- - # Karts erzeugen - # ------------------------- - - kart1 = Kart( - "Player 1", - (255, 50, 50), - acceleration=0.2, - vMax=5, - handling=4 - ) - - kart2 = Kart( - "Player 2", - (50, 100, 255), - acceleration=0.2, - vMax=5, - handling=4 - ) - - # Startpositionen - kart1.position = [250, 350] - kart1.rotation = 0 - - kart2.position = [750, 350] - kart2.rotation = 180 - - # ------------------------- - # Pool - # ------------------------- - - pool = None - - # Zeitpunkt, wann der nächste Pool erscheint - nextPoolTime = time.time() + random.uniform(3, 8) - - running = True - - while running: - - # ------------------------- - # Events - # ------------------------- - - for event in pygame.event.get(): - if event.type == pygame.QUIT: - running = False - - # ------------------------- - # Pool erzeugen / entfernen - # ------------------------- - - currentTime = time.time() - - # Wenn momentan kein Pool existiert - # und die Wartezeit vorbei ist - if pool is None and currentTime >= nextPoolTime: - - pool = Item("pool") - pool.typ() - - # Zufällige Position - pool.position = [ - random.randint(80, WIDTH - 80), - random.randint(80, HEIGHT - 80) - ] - - # Zufällige Größe - pool.size = random.randint(40, 80) - - # Pool bleibt unterschiedlich lange sichtbar - poolEndTime = currentTime + random.uniform(3, 7) - - # Pool verschwinden lassen - if pool is not None and currentTime >= poolEndTime: - - pool = None - - # Unregelmäßige Zeit bis zum nächsten Pool - nextPoolTime = currentTime + random.uniform(3, 10) - - keys = pygame.key.get_pressed() - - # ------------------------- - # Kart 1 - # WASD + E - # ------------------------- - - # W = Gas - if keys[pygame.K_w]: - kart1.acc(False) - - # S = Rückwärts / Bremsen - elif keys[pygame.K_s]: - kart1.acc(True) - - # Wenn kein Gas/Bremse -> langsam abbremsen - else: - kart1.speed *= 0.98 - - # A = links - if keys[pygame.K_a]: - kart1.turn(-1) - - # D = rechts - if keys[pygame.K_d]: - kart1.turn(1) - - # E = Rammen - if keys[pygame.K_e]: - kart1.ram(kart2) - - # ------------------------- - # Kart 2 - # IJKL + O - # ------------------------- - - # I = Gas - if keys[pygame.K_i]: - kart2.acc(False) - - # K = Rückwärts / Bremsen - elif keys[pygame.K_k]: - kart2.acc(True) - - else: - kart2.speed *= 0.98 - - # J = links - if keys[pygame.K_j]: - kart2.turn(-1) - - # L = rechts - if keys[pygame.K_l]: - kart2.turn(1) - - # O = Rammen - if keys[pygame.K_o]: - kart2.ram(kart1) - - # ------------------------- - # Position aktualisieren - # ------------------------- - - kart1.pos() - kart2.pos() - - # ------------------------- - # Bildschirm verlassen? - # -> auf andere Seite wechseln - # ------------------------- - - # Abstand zum Bildschirmrand - border = 20 - - for kart in [kart1, kart2]: - - # Linker Rand - if kart.position[0] < border: - kart.position[0] = border - - # Rechter Rand - if kart.position[0] > WIDTH - border: - kart.position[0] = WIDTH - border - - # Oberer Rand - if kart.position[1] < border: - kart.position[1] = border - - # Unterer Rand - if kart.position[1] > HEIGHT - border: - kart.position[1] = HEIGHT - border - - # ------------------------- - # Zeichnen - # ------------------------- - - screen.fill(BACKGROUND) - - # Pool zeichnen - if pool is not None: - draw_pool(screen, pool) - - draw_kart(screen, kart1) - draw_kart(screen, kart2) - - # Namen anzeigen - font = pygame.font.Font(None, 28) - - text1 = font.render( - f"{kart1.name}: {kart1.speed:.1f}", - True, - kart1.color - ) - - text2 = font.render( - f"{kart2.name}: {kart2.speed:.1f}", - True, - kart2.color - ) - - screen.blit(text1, (20, 20)) - screen.blit(text2, (20, 50)) - - pygame.display.flip() - - # FPS - clock.tick(FPS) - - pygame.quit() - - -if __name__ == "__main__": - main() +print(ray.angle(90)) \ No newline at end of file