ui more or less done, testing things in progress

This commit is contained in:
Technoduck 2024-11-04 01:13:39 -05:00
parent 583b24274c
commit 2956f6bd78
2 changed files with 124 additions and 98 deletions

124
app.py
View file

@ -43,17 +43,23 @@ class renderedImageZoom:
command=self.get_altitude,
pass_coords=True)
#self.map_widget.add_right_click_menu_command(label="open_window",
# command=self.show_image,
# pass_coords=True)
self.image_window = image_window
self.image_window.title("Simulated Sunset")
self.image_window.config(width=256,height=256)
#image = skydome.renderFromCamera(coords)
self.canvas = tkinter.Canvas(self.image_window,bg="white")
self.canvas.pack(fill=tkinter.BOTH,expand=True)
self.environment_window_filler()
def environment_window_filler(self):
self.aerosol_window.title("options selector")
environemnt_info_text = tkinter.Label(self.aerosol_window, text="Please choose in which environment the sunset is occuring")
environemnt_info_text.pack(side='top',pady=20,padx=10)
environemnt_info_text.grid(column=0,row=0,columnspan=2,pady=20,padx=10)
#Continental Clean - 26e-6 g = 0.709
@ -73,43 +79,84 @@ class renderedImageZoom:
#Antarctic - 11e-6 g = 0.784
buton_cont_clean = tkinter.Button(self.aerosol_window,text="Continental Clean",command=lambda: self.env_setter(26e-6,0.709));
buton_cont_clean.pack(side='top',padx=10,pady=5)
buton_cont_clean.grid(column=0,row=1,padx=10,pady=5)
buton_cont_avr = tkinter.Button(self.aerosol_window,text="Continental Average ",command=lambda: self.env_setter(75e-6,0.793));
buton_cont_avr.pack(side='top',padx=10,pady=5)
buton_cont_avr.grid(column=0,row=2,padx=10,pady=5)
buton_cont_poll = tkinter.Button(self.aerosol_window,text="Continental Polluted ",command=lambda: self.env_setter(175e-6,0.698));
buton_cont_poll.pack(side='top',padx=10,pady=5)
buton_cont_poll.grid(column=0,row=3,padx=10,pady=5)
buton_urban = tkinter.Button(self.aerosol_window,text="Urban ",command=lambda: self.env_setter(353e-6,0.689));
buton_urban.pack(side='top',padx=10,pady=5)
buton_urban.grid(column=0,row=4,padx=10,pady=5)
buton_desert = tkinter.Button(self.aerosol_window,text="Desert ",command=lambda: self.env_setter(145e-6,0.729));
buton_desert.pack(side='top',padx=10,pady=5)
buton_desert.grid(column=0,row=5,padx=10,pady=5)
buton_mar_clean = tkinter.Button(self.aerosol_window,text="Maritime Clean ",command=lambda: self.env_setter(90e-6,0.772));
buton_mar_clean.pack(side='top',padx=10,pady=5)
buton_mar_clean.grid(column=1,row=1,padx=10,pady=5)
buton_mar_poll = tkinter.Button(self.aerosol_window,text="Maritime Polluted ",command=lambda: self.env_setter(115e-6,0.756));
buton_mar_poll.pack(side='top',padx=10,pady=5)
buton_mar_poll.grid(column=1,row=2,padx=10,pady=5)
buton_mar_tro = tkinter.Button(self.aerosol_window,text="Maritime Tropic ",command=lambda: self.env_setter(43e-6,0.774));
buton_mar_tro.pack(side='top',padx=10,pady=5)
buton_mar_tro.grid(column=1,row=3,padx=10,pady=5)
buton_arctic = tkinter.Button(self.aerosol_window,text="Arctic ",command=lambda: self.env_setter(23e-6,0.721));
buton_arctic.pack(side='top',padx=10,pady=5)
buton_arctic.grid(column=1,row=4,padx=10,pady=5)
buton_antarctic = tkinter.Button(self.aerosol_window,text="Antarctic ",command=lambda: self.env_setter(11e-6,0.784));
buton_antarctic.pack(side='top',padx=10,pady=5)
buton_antarctic.grid(column=1,row=5,padx=10,pady=5)
environemnt_info_text = tkinter.Label(self.aerosol_window, text="Please enter the temperature and pressure (in C, and mmHg)")
environemnt_info_text.grid(column=0,row=6,columnspan=2,pady=20,padx=10)
self.image_window = image_window
t_frame = tkinter.Frame(self.aerosol_window)
text_t = tkinter.Text(t_frame,height=1,width=10)
submit_t_button = tkinter.Button(t_frame,text="set temperature",command=lambda: self.set_temp(text_t.get("1.0","end-1c")))
text_t.pack(side=tkinter.LEFT)
submit_t_button.pack(side=tkinter.RIGHT)
t_frame.grid(column=0,row=7,columnspan=2,padx=20)
p_frame = tkinter.Frame(self.aerosol_window)
text_p = tkinter.Text(p_frame,height=1,width=10)
submit_p_button = tkinter.Button(p_frame,text="set pressure",command=lambda: self.set_press(text_p.get("1.0","end-1c")))
text_p.pack(side=tkinter.LEFT)
submit_p_button.pack(side=tkinter.RIGHT)
p_frame.grid(column=0,row=8,columnspan=2,padx=20)
testing_info_text = tkinter.Label(self.aerosol_window, text="Change y heights between which average redness and blueness will be calculated")
testing_info_text.grid(column=0,row=9,columnspan=2,pady=20,padx=10)
r_frame = tkinter.Frame(self.aerosol_window)
text_r_l = tkinter.Text(r_frame,height=1,width=10)
text_r_u = tkinter.Text(r_frame,height=1,width=10)
submit_r_button = tkinter.Button(r_frame,text="calculate_average_red",command=lambda: average_r_label.config(
text=self.get_image_average("red",int(text_r_l.get("1.0","end-1c")),int(text_r_u.get("1.0","end-1c")))))
average_r_label = tkinter.Label(r_frame,text="no average yet")
text_r_l.pack(side=tkinter.LEFT)
text_r_u.pack(side=tkinter.LEFT)
average_r_label.pack(side=tkinter.RIGHT)
submit_r_button.pack(side=tkinter.RIGHT)
r_frame.grid(column=0,row=10,columnspan=2,padx=20)
b_frame = tkinter.Frame(self.aerosol_window)
text_b_l = tkinter.Text(b_frame,height=1,width=10)
text_b_u = tkinter.Text(b_frame,height=1,width=10)
submit_b_button = tkinter.Button(b_frame,text="calculate_average_blue",command=lambda: average_b_label.config(
text=self.get_image_average("blue",int(text_b_l.get("1.0","end-1c")),int(text_b_u.get("1.0","end-1c")))))
average_b_label = tkinter.Label(b_frame,text="no average yet")
text_b_l.pack(side=tkinter.LEFT)
text_b_u.pack(side=tkinter.LEFT)
average_b_label.pack(side=tkinter.RIGHT)
submit_b_button.pack(side=tkinter.RIGHT)
b_frame.grid(column=0,row=11,columnspan=2,padx=20)
self.image_window.title("Simulated Sunset")
self.image_window.config(width=256,height=256)
#image = skydome.renderFromCamera(coords)
self.canvas = tkinter.Canvas(self.image_window,bg="white")
self.canvas.pack(fill=tkinter.BOTH,expand=True)
#self.img = Image.fromarray(image,mode="RGB")
#self.tk_image = ImageTk.PhotoImage(width=256,height=256,image=self.img)
#img = ImageTk.PhotoImage(Image.open("highpress_camera.png"))
@ -125,13 +172,42 @@ class renderedImageZoom:
self.canvas.bind("<Button-4>",self.zoom_in)
self.canvas.bind("<Button-5>", self.zoom_out)
def set_temp(self,temp):
if temp is None:
self.temperature = 0
elif int(temp) < -270 or int(temp) > 100:
print("temperature unrealistic, resetting to 0 degrees")
self.temperature = 0
else:
self.temperature = int(temp)
def set_press(self,press):
if press is None:
self.pressure = 720
elif int(press) < 100 or int(press) > 1300:
print("pressure unrealistic, resetting to 720 mmHg")
self.pressure = 720
else:
self.pressure = int(press)
def get_image_average(self,color,low, high):
if color == "blue":
slice = self.image[:][low:high]
print(slice.size)
print(slice)
return "{} + {}".format(low,high)
else:
return "red".format(low,high)
def env_setter(self,environment_constant,g):
self.betaM = skydome.Vec3(environment_constant,environment_constant,environment_constant)
self.g = g
def render(self):
image = skydome.renderFromCamera(self.coords,self.betaM,self.g,self.altitude)
self.img = Image.fromarray(image,mode="RGB")
self.image = skydome.renderFromCamera(self.coords,self.betaM,self.g,self.altitude,self.temperature,self.pressure)
self.img = Image.fromarray(self.image,mode="RGB")
self.tk_image = ImageTk.PhotoImage(width=256,height=256,image=self.img)
#img = ImageTk.PhotoImage(Image.open("highpress_camera.png"))

View file

@ -1,61 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
# https://journals.ametsoc.org/view/journals/bams/79/5/1520-0477_1998_079_0831_opoaac_2_0_co_2.xml?tab_body=pdf - for aerosols and clouds
#
# https://iopscience.iop.org/article/10.1088/1757-899X/1269/1/012011/pdf - for Rayleigh extinction
#
# https://sci-hub.se/10.1364/josa.48.1018_1 - temperature dependance Rayleigh scattering
#
# https://sci-hub.se/https://doi.org/10.1364/JOSA.47.000176 - Rayleigh coefficients (index of refraction) - Penndorf
#
# We are going to use the real rayleigh scattering coefficient:
#
# $\beta_R(h, \lambda) = \frac{8\pi(n^2 - 1)^2}{2N\lambda^4} e^{-\frac{h}{H_R}}$
#
# n = index of refraction, these are calculated in the 4th paper, temperature dependance
#
# N = molecular density, dependent on humidity
#
# $\lambda$ = wavelength, but we only care for RGB (440, 550, 680 nm)
#
# From Penndorf, the dispersion equation is:
#
# $(n_s - 1) \times 10^{-8} = 6432.8 + \frac{2949810}{146 - v^2} + \frac{25540}{41 - v^2}$
#
# It is important to note that $v=1/f$ which is measured in um
#
# Once we have calculated our dispersion index of refraction, we can see what our new value for n will be (it is dependant on temperature and pressure)
#
# $$
# (n - 1) = (n_s - 1) \left( \frac{(1 + \alpha t_s)}{(1 + \alpha t)} \right) \frac{p}{p_s}
# $$
#
# Here, we are using $n_s$ from the dispersion equation, $t_s$ is 15 degrees Celsius, and $p_s$ is 760 mmHg. $t$ represents the actual temperature, and $p$ represents the actual pressure. $\alpha$ is the coefficient of linear expansion of air = 0.00367 in units of inverse celcius. We see that the influence of air pressure really is critical
#
#
# We also need to find N, the molecular density (depends on temperature, humidity, pressure): We are going to use the value at the altitude where our person is standing and then we scale it using the scale factor. Penndorf uses N_s = 2.54743e19, but i am not sure if it is applicable to our scenario.
#
#
#
#
# Ok, so things work... but they are not super realistic. I think we should be updating the dispersion equation because Penndorf's paper is super old. We want the value of the index of refraction at the location of the observer - this is going to depend on the users inputs.
#
# https://refractiveindex.info/?shelf=other&book=air&page=Ciddor (1996)
#
# New calculation for refractive index (where lambda is in microns)
#
# This applies for : Standard air: dry air at 15 °C, 101.325 kPa and with 450 ppm CO2 content.
#
# $n - 1 = \frac{0.05792105}{238.0185 - \lambda^{-2}} + \frac{0.00167917}{57.362 - \lambda^{-2}}$
#
#
#
# Something really cool here is that we can use the color of the sunset to predict the weather: "Red at night, sailors delight. Red in morning, sailors take warning"
# When there is a bright red sunset at night, it means there is likely a high pressure cell off to the west. With west to east weather patterns, this means a high pressure cell is about to move in, high pressure = pleasant weather, "sailors delight". When there is a red sunrise in the east, it means the high pressure cell has already passed and a low pressure cell is likely to replace it. Low pressure = poor weather, "sailors take warning".
#
# Low pressure: 720mmHg
# High pressure: 780 mmHg
@ -131,8 +76,8 @@ wavelengths = Vec3(0.68, 0.55, 0.44) # These are the wavelengths in um
@cython.cfunc
def refraction_calculator(T:cython.int, P:cython.int) -> tuple[Vec3, Vec3]:
alpha:cython.float = 0.00367 # in inverse Celsius
t_s:cython.int = 15 # degrees Celsius
p_s:cython.int = 760 # mmHg
t_s:cython.int = T # degrees Celsius
p_s:cython.int = P # mmHg
n_s_values = [] # for debugging / comparing to the internet values
n_values = []
@ -304,6 +249,7 @@ def computeIncidentLight(direction:Vec3,betaM,g,observerEarthRadius) -> tuple[fl
# Changing the * 20 number just changes the intensity os the light, it does not much change the colors themselves
# Well the colors kinda change, but more they just get super pale or super not pale. 20 should be fine I guess
#print("sumR: {}, betaR: {}, phaseR {}\n, sumM {},betaM {}, phaseM {}\n".format(sumR,betaR,phaseR,sumM,betaM,phaseM))
final_color = (sumR * betaR * phaseR + sumM * betaM * phaseM) * 20
return final_color.to_tuple()
@ -343,12 +289,13 @@ def solveQuadratic(a:cython.float, b:cython.float, c:cython.float) -> tuple[cyth
@cython.cfunc
def renderSkydome(filename):
def renderSkydome(filename,betaM,g,altitude):
width:cython.int
height:cython.int
width, height = 256,256
image = np.zeros((height, width, 3), dtype=float)
observerEarthRadius = earthRadius + altitude
start_time = time.time() # Start timing
j:cython.int
@ -369,7 +316,7 @@ def renderSkydome(filename):
theta = math.acos(1 - z2)
# This changes for each pixel
direction = Vec3(math.sin(theta) * math.cos(phi), math.cos(theta), math.sin(theta) * math.sin(phi))
color = computeIncidentLight(direction)
color = computeIncidentLight(direction,betaM,g,observerEarthRadius)
#color = computeIncidentLight(direction)
@ -389,7 +336,12 @@ def renderSkydome(filename):
def renderFromCamera(filename,betaM,g,altitude):
def renderFromCamera(filename,betaM,g,altitude,T,P):
print(wavelengths)
n_s_values, n_values = refraction_calculator(T, P)
beta_values = beta(n_values)
betaR = Vec3(*beta_values.v) # Keeps it as a Vec3
observerEarthRadius = earthRadius + altitude
width:cython.int
@ -411,10 +363,11 @@ def renderFromCamera(filename,betaM,g,altitude):
numPixelSamples:cython.int = 4
for y in range(height):
for x in range(width):
# for m in range(numPixelSamples):
# for n in range(numPixelSamples):
# rayx = (2 * (x + (m + random.uniform(0, 1)) / numPixelSamples) / float(width) - 1) * aspectRatio * angle
# rayy = (1 - (y + (n + random.uniform(0, 1)) / numPixelSamples) / float(height) * 2) * angle
if y > 70:
# horrible horrible hack, mainly because below the horizon its dark amnyway?
color = (np.nan,np.nan,np.nan)
image[y][x] = color
else:
rayx = (2 * x / float(width) - 1) * aspectRatio * angle
rayy = (1 - y / float(height) * 2) * angle
@ -425,10 +378,7 @@ def renderFromCamera(filename,betaM,g,altitude):
#image[y, x] = np.array(color)
image[y][x] = np.clip(color, 0, 1)
#image[y, x] /= numPixelSamples * numPixelSamples # Average color
elapsed_time = time.time() - start_time
print("what")
print(f"Renderinggg row {y + 1}/{height}, elapsed time: {elapsed_time:.2f} seconds")
image = np.clip(image, 0, 1) * 255