#!/usr/bin/python3
# ====================================================================
# galactic lat/lon -> convert -> points in a graphics window
# ====================================================================
import sys
import math as m
import graphics as gr
import draw_xy_axes as ax
import user_interface as ui
import coordinate_conversion as cc
description='''
=============================================================
test converting galactic lat/lon to x,y,z coordinates
-------------------------------------------------------------
longitude is measured from the +x axis counter-clockwise
as viewed from the galactic north pole (0 to 360 degrees)
latitude is measured from the galactic plane (the x,y plane)
+90 (north pole) to -90 (south pole)
the right hand rule determines the direction of the +y axes
-------------------------------------------------------------
-x (galactic anti-center)
(galactic north pole) +z /
| /
| /
|/
-y -------+------- +y
/|
/ |
/ |
/ -z (galactic south pole)
(galactic center) +x
-------------------------------------------------------------
At the origin (0,0) looking towards the galactic
center (+x infinity)
+z
|
|
|
+y -------+------- -y
|
|
|
-z
-------------------------------------------------------------
At the galactic center (+x infinity) looking towards
the origin (0,0)
+Z
|
|
|
-y -------+------- +y
|
|
|
-z
-------------------------------------------------------------
Graphics Window Coordinates
(0,0) +-------------- +x
|
|
|
|
|
+y
=============================================================
'''
# --------------------------------------------------------------------
# ---- convert galactic lat/lon (degrees) to x,y,x
# ---- note: the diameter of sphere of stars is 1.0
# ---- viewer is at +x infinity
# --------------------------------------------------------------------
def convert_lat_lon_to_xyz(lat_deg,lon_deg):
lat_rad = m.radians(lat_deg) # radians
lon_rad = m.radians(lon_deg) # radians
x = m.cos(lat_rad) * m.cos(lon_rad)
y = m.cos(lat_rad) * m.sin(lon_rad)
z = m.sin(lat_rad)
return (x,y,z)
# --------------------------------------------------------------------
# ---- draw a point (small circle) using window coordinates
# --------------------------------------------------------------------
def draw_point(win,wx,wy,color='black',size=2):
p = gr.Circle(gr.Point(wx,wy),size)
p.setFill(color)
p.setOutline(color)
p.setWidth(1)
p.draw(win)
return p
# -------------------------------------------------------------------
# ---- convert lat/lon XYZ to window coordinates
# ---- returned coordinates are integers
# ----
# ---- the viewer is at the origin looking towards the
# ---- galactic center (+Z axis)
# -------------------------------------------------------------------
def ll_to_win_coords(llx,lly,llz,win_width,win_height):
wcx = win_width / 2.0 # window center X coordinates
wcy = win_height / 2.0 # window center Y coordinates
wx = int(round(wcx + lly))
wy = int(round(wcy - llz))
return (wx,wy)
# --------------------------------------------------------------------
# ---- test all of the conversions (scale the window coordinates)
# ---- the lat/lon XYZ coordinates map to a unit sphere (raidus 1)
# ---- scale them to fit the graphics window
# --------------------------------------------------------------------
def test_conversions(win,lat,lon,color='black',scale=300):
print('----------------------------------------')
print(f'test lat={lat} lon={lon}')
llx,lly,llz = convert_lat_lon_to_xyz(lat,lon)
print(f'llx={llx:.2f} lly={lly:.2f} llz={llz:.2f}')
llx = scale * llx
lly = scale * lly
llz = scale * llz
print(f'scaled llx={llx:.2f} lly={lly:.2f} llz={llz:.2f}')
wx,wy = ll_to_win_coords(llx,lly,llz,win.width,win.height)
print(f'wx={wx:.2f} wy={wy:.2f}')
p = draw_point(win,wx,wy,color)
return p
# --------------------------------------------------------------------
# ---- interactive lat/lon tests
# --------------------------------------------------------------------
def interactive_lat_lon_tests(win):
viewer = '----------------------------------------------\n' +\
'Viewer is at the galactic center (+x infinity)\n' +\
'looking towards the origin (0,0). (The sun.)\n' +\
'----------------------------------------------'
print(description)
graphics_objs = []
color = 'red'
while True:
print()
print(viewer)
s = ui.get_user_input('Enter star\'s galactic lat/lon: ')
if not s: break
if s == 'clear':
undraw_graphics_objects(graphics_objs)
continue
s = s.replace(',', ' ')
s = s.replace(r'/', ' ')
s = s.replace(':', ' ')
slat,slon = s.split()
tf,lat = ui.is_float(slat)
if not tf:
print('bad latitude entered')
continue
tf,lon = ui.is_float(slon)
if not tf:
print('bad longitude entered')
continue
p = test_conversions(win,lat,lon,color,scale=300)
graphics_objs.append(p)
return graphics_objs
# --------------------------------------------------------------------
# ---- pre defined lat/lon tests
# --------------------------------------------------------------------
def pre_defined_lat_lon_tests(win):
# ---- fixed tests format is (lat,lon,color)
tests = [(0,0,'red'),(0,90,'green'),(0,135,'blue')]
# ---- execute the tests
graphics_obj = []
for test in tests:
p = test_conversions(win,test[0],test[1],test[2],300)
graphics_obj.append(p)
win.getMouse()
# --------------------------------------------------------------------
# ---- undraw graphics objects
# --------------------------------------------------------------------
def undraw_graphics_objects(objlst):
for o in objlst:
o.undraw()
# --------------------------------------------------------------------
# ---- main
# --------------------------------------------------------------------
if __name__ == '__main__':
# ---- setup graphics window
win = gr.GraphWin('Star Catalog',801,801)
win.setBackground('white')
# ---- draw X,Y axes
ax.draw_xy_axes(win)
# ---- pre defined lat/lon test
##objlst = pre_defined_lat_lon_tests(win)
# ---- interactive lat/lon test
objlst = interactive_lat_lon_tests(win)
win.close()