Search code examples
javascriptgoogle-mapsmathastronomy

Direction from current location on Google Maps to the Sun


I currently am able to calculate the Altitude and Azimuth of the Sun on a given Datetime, now I would like to be able to point an arrow from any current position on Google Map towards the direction of the Sun (based on Altitude coordinates and Azimuth).

I am working on a app which is suppose to show a user the direction to the sun from users current location.

Any ideas very welcome.


Solution

  • Given geo-coordinates lat (positive for north) and long (positive for east), the 3D-coordinates on the globe are (one possibility):

        / x \   / cos(lat) * sin(long) \
    p = | y | = | cos(lat) * cos(long) |
        \ z /   \ sin(lat)             /
    

    The north direction is then:

            / -sin(lat) * sin(long) \
    north = | -sin(lat) * cos(long) |
            \  cos(lat)             /
    

    And the east direction is:

           /  cos(lat) * cos(long) \
    east = | -cos(lat) * sin(long) |
           \  0                    /
    

    Given azimuth and altitude, you can get the 3D direction as:

    dir = (-cos(azimuth) * north -sin(azimuth) * east) * cos(altitude) + sin(altitude) * p
    

    Hence, for any positive scalar t, you can calculate a point between your position on the globe and the object:

    pos(t) = p + t * dir
    

    You can project the position back onto the globe by normalization:

    pos_normalized(t) = pos(t) / ||pos(t)||
    

    , where ||pos(t)|| is the length of pos(t).

    And given this, you can calculate latitude and longitude:

    lat2 = asin(pos_normalized(t).z)
    long2 = atan2(pos_normalized(t).x, pos_normalized(t).y)
    

    This is one point that lies in the direction of the sun. Choose some sufficiently small t to calculate it (it should be much smaller than 1; the unit is basically multiples of earth radius). For certain maps, all these positions may lie on a line. However, this is not guaranteed for arbitrary maps. So you might want to sample a few points and generate a polyline instead.