B4A Library Astro library

The library provides the times of Sunrise, Sunset, Moon rise and Moon set, according to place and date.
It also provides the phase of the moon (equivalent to the day of the moon month).
The Sunrise and Sunset times vary according to the value of Zenith angle.
The following conventions are in use:
Official – 90.8333 (90° 50’)
Civil - 96°
Nautical - 102°
Astronomical - 108°
The values can be used by their names.
The library use the Official value as default, and it can be changed using the method Zenith.

No demo program as it is very simple to use.
Please report problems.

Edit: Version 1.1 corrected the following as per alfcen comments:
- no_rise or no_set time are returned as "--:--"
- sun rise and set times are within the 24 hours.

Edit: the files are updated to ver. 1.2 with additional methods which provide data about the sun and the moon, all by our astronomy expert alfcen:sign0188:
Edit: Ver 1.21 correction of rounding problem.
Edit: Ver 1.22 bug correction in sun + format change.
Edit: ver 1.23 bug correction in moon phase.
Edit: ver 1.4 added a method to calculate sun's position (azimuth and elevation).
 

Attachments

  • Astro 1.4.zip
    17.5 KB · Views: 627
Last edited:

derez

Expert
Licensed User
Longtime User
Hi, derez! it's very usefull library!
I have seen in you post a fragment of code for calculating SunPosition. And Celectial coordinates was used inside him.
How i Can get celestial coordinates ( right ascension And declination ) for Sun and for Moon?
I have created the library in 2012 based on algorithms that I have found googling. I didn't do much with it since then...
The expert that helped me after first publishing is alfcen (see post #3) and since Astronomy is his hobby, he may help you much better then me.
 

sn_nn

Member
Licensed User
Longtime User
Thank you, derez! For the first attemption, i will try to rewrite untAstro code from my Delphi project...
 

sn_nn

Member
Licensed User
Longtime User
Hi, derez! For now untAstro-code is working in Android! untAstro can calculate Rise and Set times without limitations for 65deg Latitude (it's very important for me). Can i take one or two procedures from Your library (Astrolib) and insert them into my library? (Some procedures from You code are more compact then my... ) :)
 

BlueVision

Active Member
Licensed User
Longtime User
Great library derez! Integrated the lib into my new project and I am really satisfied with the accuracy of the data. Only trouble is the "circumpolar" mode of the sun during summertime in the far north or south of the globe (and this happens already in the north of sweden and norway here in europe). So if the sun is not sinking below the horizon, this should be visible somehow. A "--:--" is not enough (when travelling virtually). So this is also valid for the times of dusk and dawn. Is there a way to indicate that somehow? Maybe the elevation value of sun could be used if the library can calculate it. So then you could replace the "--:--" from the sample simply with an "UP" or "PD" for polar day and a "DOWN" or "PN" for polar night. Same for the south pole, think it's the same there 6 months later.
A little bit more tricky, when it comes to dusk & dawn. So, in St. Peterburg in Russia you have "white nights", where sun is down but it is not dark. Is that dusk or already dawn? Probably not a big change in code, just a nice finetuning.
What if the Moon simply had no rise, like today here in Berlin? Also a "--:--" for the Moon's rise. When there is no rise-time, is the Moon visible? In this case it was easy to answer because Moon had a set-time, so Moon must be visible (it was not, it was cloudy). Just an idea... Maybe you can change that somehow? Would be perfect then.
 

derez

Expert
Licensed User
Longtime User
I have not done any work with eclipse and writing libraries in java and I don't have intention to restart it all over.
I attach the java code that was used, feel free to modify to your likes.
Sorry !
 

Attachments

  • Astro.java.zip
    9.9 KB · Views: 141

BlueVision

Active Member
Licensed User
Longtime User
I see, what a pity. That's a perfect match then, because I have no knowledge about java. So I have to work around with the data I have or calculate what I am missing within B4A. Thanks for the response, derez.
 

derez

Expert
Licensed User
Longtime User
I can translate the code for sun but I don't know how to solve the problem of "no result = --:--"
The case is when there is no solution because cosh > 1 :
part of sun:
...
    double sinDec = 0.39782 * Math.sin(DtoR*L); //' this is in radians
    double cosDec = Math.cos(Math.asin(sinDec))   ;
    double cosH = (Math.cos(DtoR*zenith) - (sinDec * Math.sin(DtoR*latit))) / (cosDec * Math.cos(DtoR*latit));
    if (cosH >  1)
    { RiseSet[order]= "--:--" ;}
    else
        ...

In b4x code this code is:
B4X:
...
dim sinDec as double  = 0.39782 *sinD(L)
dim cosDec as double = cos(asin(sinDec))  
dim cosH as double = (cosD(zenith) - (sinDec * sinD(latit))) / (cosDec * cosD(latit))
    if  cosH >  1 then
        RiseSet(order)= "--:--"
    else
        ...
 
Last edited:

derez

Expert
Licensed User
Longtime User
Here is the code translation for sun and tsun:
sun & tsun:
'    /**
'     * Returns the Sunrise And Sunset times in an Array of two strings.
'     * At Latitudes greater Then 65 Or smaller Then -65 there are cases that
'     * there Is no sunrise And sunset. The result in this Case Is "--:--"
'     */
    Public Sub  Sun( day As Int, month As Int ,  year As Int, latitude As Double , longitude As Double,  deltahour As Double) As String()
           Dim RiseSet(2) As String
 
        ' test the input
        If ((day < 1 ) Or ( day > 31) Or (month<1) Or (month>12) Or(year <100)) Then
            RiseSet(0) = "Date error"
            RiseSet(1) = "Date error"
        else if ((year = 1582) And (month = 10) And ( day > 4) And (day < 15)) Then
            RiseSet(0) = "Date error"
            RiseSet(1) = "Date error"
        Else
            Dim N1 As Int =  275 * month / 9
            Dim N2 As Int = Floor((month + 9) / 12)
            Dim N3 As Int = (1 + Floor((year - 4 *Floor(year / 4) + 2) / 3))
            Dim N As Int = N1 - N2 * N3 + day - 30
        
            RiseSet(0) = tsun( 0, N, latitude, longitude, deltahour) ' rise time
            RiseSet(1) = tsun( 1, N, latitude, longitude, deltahour) ' set time
        End If
        Return RiseSet
    End Sub
 
    ' use the library to get the value of zenith
    Private Sub tsun(order As Int, N As Int,  latit As Double, longit As Double,  deltahour As Double) As String
        Dim RiseSet(2) As String
        Dim  RtoD As Double= 180/cPI
'       double DtoR = Math.PI/180 ;
        Dim lngHour As Double = longit / 15
        Dim  H , TT , UT, localT , ht , mint As Double
    
        Dim st1,st2 As String
        Dim t As Double = N + (6 + 12 * order - lngHour) / 24
        Dim M As Double= (0.9856 * t) - 3.289
        Dim L As Double = M + (1.916 * SinD(M)) + (0.020 * SinD( 2 * M)) + 282.634
        L = (L + 720 ) Mod 360
        Dim RA As Double = RtoD * ATan(0.91764 * TanD(L))
        RA = (RA + 720 ) Mod 360
        Dim Lquadrant As Double = Floor( L/90) * 90
        Dim RAquadrant As Double = Floor(RA/90) * 90
        RA = RA + Lquadrant - RAquadrant
        RA = (RA + 720 ) Mod 360
        RA = RA / 15
        Dim sinDec As Double  = 0.39782 *SinD(L)
        Dim cosDec As Double = Cos(ASin(sinDec))
        Dim cosH As Double = (CosD(zenith) - (sinDec * SinD(latit))) / (cosDec * CosD(latit))
        If  Abs(cosH) > 1  Then
            RiseSet(order)= "--:--"
        Else
    
            If order = 0 Then
                H = 360 - RtoD * ACos(cosH)
            Else
                H = RtoD * ACos(cosH)
            End If
            H = H / 15
            TT = H + RA - 0.06571 * t - 6.622
            UT = TT - lngHour
            localT = (UT + deltahour + 48) Mod 24
            ht = Floor (localT)
                    
            mint = Floor((localT - Floor (localT)) *60 + 0.5 )
            If (mint = 60) Then
                ht = ht + 1
                mint = 0
            End If   
            If (ht < 10) Then
                st1 = "0" & ht
            Else
                st1 = ht
            End If
            If (mint < 10.0 ) Then
                st2 = "0" & Floor(mint)
            Else
                st2 = Floor(mint)
            End If
            RiseSet(order) = st1 & ":" & st2
            If (st2.length = 1) Then  RiseSet(order) = "--:--"    ' Case that mint Is Null

        End If
        Return RiseSet(order)
    End Sub

I compared the results to the library and the results are the same.
 
Last edited:

BlueVision

Active Member
Licensed User
Longtime User
Well Derez, I am close to solve my "Moon"-problem within my current app-development. Spent hours with reading books about spherical trigonometrics. It's a mess. Forget one transition from rad to deg and you are lost. Currently I am working on a huge Excel-sheet putting all the formulas together to bring it into a "system". This is better done with Excel then with B4A. If that works, I will do the transition to B4A for my app.

To solve the problem with the "--:--" I have an idea in mind. It's so far only a workaround outside the library. It's an addition of B4A-code to your AstroLib-example. Don't know if I can realize it, but it looks promising. So stay tuned, this will take a while. As said above, calculating with spherical trigonometrics is not easy, I forget most of it since study-times. It's mostly a long chain of additions of sin, cos, tan and their opposites. Often you calculate with the same value, but you have to convert to deg or rad, for making the formula's work.
Calculations for the Moon in opposite to Sun are very complicated. NASA is doing that very exactly with uncounted variables with their highend-computers. It is good enough for us to calculate position and other things with the formulas developod by Jean Meeus (a belgian mathematic-astronomic genius). The result of these simplified calculations are up to 0.5 to 1 degree close to the real value. So gravitational influences from other objects in space for instance are playing no role.

Short: If that works as expected, somebody with excellent knowledge of Java could eventually enhance the library itself later, adding some new functions if there is public interest to it. We will see...
 

freedom2000

Well-Known Member
Licensed User
Longtime User
Hi,

Thank you for this nice library 👍

I have tried it and got a "shift" of one hour for the sun position.

I mean that to get the correct values I must call the method with "1" hour delay. And I am currently at Universal Time +2 here in France.

I have tried also the sub provided here : https://www.b4x.com/android/forum/threads/astro-library.15975/post-481866
And this sub gives perfect results
B4X:
    AzimuthAstro = SunPosition(43.5156,1.4996,DateTime.Now)
        Log("Sun Azimuth: " & AzimuthAstro(0) & " Sun Elevation : " & AzimuthAstro(1) & " " & DateTime.GetHour(DateTime.Now)& ":" & DateTime.GetMinute(DateTime.Now))

result is consistant : Sun Azimuth: 237.16063521081998 Sun Elevation : 54.57340827034812 16:4
Which is the right value for 16:04 local time
 

BlueVision

Active Member
Licensed User
Longtime User
This could be tricky...
A year ago I had also problems while using the lib. But...

In my understanding, you should try to fix all your calculations based on UTC in general. Given this, France is more or less located on the Greenwich meridian from astronomical point of view. But France is using Middle European Time politically, so this is already one hour difference to Greenwich. On top comes during summertime one hour for DST. So this gives you a two hours offset compared to the "real astronomical time". All you have to do is to calculate this "real astronomical time", based on your offset to Greenwich Mean Time or Universal Time.
Try to use your own "timezone" definition, depending on astronomical point of view. So based on Greenwich meridian, you have to add every 15 degrees to the east 1 hour, subtracting it to the west for getting a correct result, after determining your GPS-Position. If you are using the "time-zone-declaration" of your mobile provider, it may fail, because it is astronomically wrong for France, even more when DST is in effect because it is already included in your local time.

As far as I remember there is something about that written within the explanation of the astro-library.

Honestly I fixed it somehow within my COMPASS-APP, but have no idea what I did exactly in the past. Within this app I am calculating the actual position of the sun and (MUCH MUCH MORE COMPLICATED) the actual position and phase of the moon for plotting two symbols on the compass rose. And the moon gave me real headache for some weeks, finally I made it... But then never released the app nor the code, it was more or less a project "for fun". I don't like the playstore, because of it's "useful" developer-regulations, renewed every day. I am not willing to follow all this developer-regulations and to fill out every day a formular for "better security". This is driving me nuts.
 
Last edited:

freedom2000

Well-Known Member
Licensed User
Longtime User
Thank you fo this clear explaination.

I do use UTC for all my computations, and especially for my solar tracker

I expected the lib to do all the tricky stuff and to be consistant with the sub
The sub gives good results without any correction.
I can see that the code takes into account the timezone
B4X:
' Calculate time of the day in UT decimal hours
            Dim offsetTicks As Long = DateTime.TimeZoneOffset * DateTime.TicksPerHour
            Dim UTCTimenow As Long = Timenow - offsetTicks
            dDecimalHours = DateTime.GetHour(UTCTimenow ) + DateTime.GetMinute(UTCTimenow )/60 + DateTime.GetSecond(UTCTimenow )/3600.0

But the lib doesn't...

Well I will use the sub 👍
 

BlueVision

Active Member
Licensed User
Longtime User
Well, yes and no, depending on needed accuracy. For a given date and time you can calculate the moon phase based on a known date of new moon or full moon. The cycle is about 29,53059 days (synodic period). This is a "rounded" value. The true cycle varies above and below that value, because of gravitation effects of other objects in space (constellation of other planets and moons).
Try the ASTROLIB DEMO for better understanding. It calculates the moon phase exactly enough for your personal needs. Use the value "moon age" to determine the moon phase.
 
Top