## coords01.coffee | |
---|---|

© 2011, Sean B. Palmer This is a CoffeeScript program used in my Coordinate Conversion page. This converts equatorial coordinates, which give the positions of celestial objects, to horizontal coordinates, which give the positions of things in the local sky relative to an observer. You can get the source and the compiled versions: The Javascript file requires jQuery and the Google Maps API to run. If you're using the CoffeeScript file instead, that also needs coffee-script.js to run. | |

The | ```
greenwichSiderealTime = ->
now = new Date
seconds = (now.getTime() / 1000) - 946728000
D = seconds / (24 * 3600)
GMST = 18.697374558 + 24.06570982441908 * D
GMST % 24
``` |

Takes a longitude in degrees, and gives the Local Sidereal Time. According to the USNO, this is just the observer's longitude in hours added to the Greenwich Mean Sidereal Time. To get hours from degrees, we just divide by fifteen. | ```
localSiderealTime = (longitude) ->
hours = longitude / 15
greenwichSiderealTime() + hours
``` |

| ```
updateLocation = (location) ->
$('#lat').val round(location.lat(), 5)
$('#lon').val round(location.lng(), 5)
updateValues()
``` |

These are just helper functions. | ```
degrees = (n) -> n * 180 / Math.PI
radians = (n) -> n * Math.PI / 180
square = (n) -> n * n
round = (n, x) -> Math.round(n * Math.pow(10, x)) / Math.pow(10, x)
{sin, cos} = Math
``` |

| ```
polar = (x, y) ->
r = Math.sqrt square(x) + square(y)
t = Math.atan2(y, x)
[r, degrees(t)]
``` |

This does the actual mathematical work of converting the equatorial coordinates, expressed as latitude, declination, and hour angle arguments all in degrees, to horizontal coordinates. The algorithm is one described by Montenbruck and Pfleger. | ```
equatorialToHorizontal = (lat, dec, ha) ->
A = (sin(lat) * sin(dec)) + (cos(lat) * cos(dec) * cos(ha))
B = (cos(lat) * sin(dec)) - (sin(lat) * cos(dec) * cos(ha))
C = - (cos(dec) * sin(ha))
``` |

One calculation gives us the azimuth, and the next one gives us the altitude. We add 360 to the angle and modulo 360 because sometimes the angle comes out as a negative value. | ```
[radius1, angle1] = polar(B, C)
direction = (angle1 + 360) % 360
[radius2, angle2] = polar(radius1, A)
[direction, angle2, radius2]
``` |

| `updateValues = ->` |

Update the Local Sidereal Hour from the longitude, and the Hour Angle from the Local Sidereal Hour and RA. | ```
$('#hour').val round(localSiderealTime($('#lon').val()), 5)
$('.ha').text round($('#hour').val() - $('#ra').val(), 3)
``` |

Get the latitude, declination, and Hour Angle from the calculated form field values. We need only these to convert to the horizontal coordinates. | ```
lat = radians($('#lat').val())
dec = radians($('#dec').val())
ha = radians($('.ha').text() * 15)
``` |

The horizontal coordinates are returned along with a radius from the polar conversion, which helps us to check that we did the calculation correctly. The radius should be 1, and if it's not then there's a bug. | ```
[az, alt, radius] = equatorialToHorizontal lat, dec, ha
$('.azimuth').text round(az, 3)
$('.altitude').text round(alt, 3)
``` |

Do the little bugcheck, and scare the user if we messed up. | ```
if round(radius, 3) != 1
then $('.error').text 'There was an error!'
``` |

Create a Google Map. This uses v3 of the API, which is actually quite sensible. It's literally five lines of code in CoffeeScript if you just want to display a map. You have to use the ID map_canvas, by the way, apparently. The marker variable is used to store the only marker that we place down. | ```
createGoogleMap = ->
marker = null
map = new google.maps.Map $('#map_canvas')[0],
center: new google.maps.LatLng(52,0)
mapTypeId: google.maps.MapTypeId.ROADMAP
zoom: 5
``` |

Here we make a listener so that when somebody clicks on the map, we can
draw a marker on there and recentre the map there. When the marker is
drawn, we pass the position to the | ```
google.maps.event.addListener map, 'click', (e) ->
marker?.setMap null
marker = new google.maps.Marker
position: e.latLng
map: map
map.setCenter e.latLng
updateLocation e.latLng
``` |

This is the jQuery initialisation function. When the document loads we just create the Google Map and the event handler that it has, and then make sure that all of the controls have change event callbacks so that everything is kept in sync. | ```
$ ->
createGoogleMap()
``` |

The #update element is just an HTML5 button. I looked at the jQuery Docs to check button support. | ` $('#update').click updateValues` |

These are the form controls. I don't really know what all the events do, for example change seems to work very strangely, so I figured I'd just bind them all. Super programming, I know. | ```
$('input').change updateValues
$('input').focus updateValues
$('input').blur updateValues
``` |

| |