开发者

How can I convert these VB calculations to Objective-c?

开发者 https://www.devze.com 2023-03-20 04:48 出处:网络
I have an older program that I wrote some time ago in VB then late updated for VB.Net. The program calculates the ephemerides of comets based on orbital elements downloaded from the Minor Planet Cente

I have an older program that I wrote some time ago in VB then late updated for VB.Net. The program calculates the ephemerides of comets based on orbital elements downloaded from the Minor Planet Center website. I am now trying to make an iPhone/iPad application using the same idea and the same calculations. Unfortunately I am too new at objective-c that trying to convert the extensive calculations is proving quite difficult for me. I am hoping that someone can help me out and at least give me some pointers.

In particular, I have no idea how to accomplish this in objective-c:

    Dim d1 As Date = DateSerial(yr_peri%, mo_peri%, dy_peri%)
    dateser# = d1.ToOADate()
    dateser# = dateser# + frac_day_peri#
    jdperi# = 2415018.5 + dateser#

and this:

    ' Find Julian Day Number of start date & time
    Dim d2 As Date = DateSerial(yr%, mo%, dd%)
    Dim inputdate# = d2.ToOADate()
    jdp# = inputdate + 2415018.5 ' use this day for phenom (rise/set) calcs
    jd# = jdp# + fd# ' add fractional days

Here is the full VB version of the calculations in case it helps to understand the context:

Public Sub calc(ByVal cname$, ByVal qq#, ByVal e#, ByVal w#, ByVal om#, ByVal I#, ByVal yr_peri%, ByVal mo_peri%, ByVal day_peri#, ByVal abs_mag#, ByVal mag_n#)
    Dim ep#
    Dim dy_peri%, frac_day_peri#, dateser#, jdperi#
    Dim yr%, mo%, dd%, fd#
    Dim jdp#, jd#, interval#
    Dim twi%, p_date#, ut#, er%
    Dim t#, tt#, f#, p#, g#, q#, h#, r#
    Dim a1#, a2#, b1#, b2#, c1#, c2#
    Dim sdt#, a#, n#, period#, m#, e0#
    Dim mrs#, frs%, ers0#, drs#, jrs%, mrs1#, e2#
    Dim tv#, v#, r1#, r2#, w0#, s#, s0#
    Dim x#, y#, z#, ls#, ms#, es#, th#, vs#, c#, th2000#
    Dim rs#, xs#, ys#, zs#, xx#, yy#, radeg#, rad#, ra#, ras$
    Dim dl#, dlm#, sd#, dec#, ds$
    Dim cospsi#, psi#, elong#, cosbeta#, beta#, phase#
    Dim ha#, ang#, az#, sinalt#, alt#, m1#, vl#
    Dim Lati$, Longi$
    Dim outpt$

    '----------------------------------------------
    '** AA=ASTRONOMICAL ALGORITHMS BY JEAN MEEUS **
    '----------------------------------------------
    counter% = 0
    ep# = 23.439291  ' year 2000, AA page 214

    cname$ = Trim(cname$)

    'Get orbital elements
    MainForm.grpEphemerides.Text = "Comet: " & cname$ & " - " + when$ ' Name
    'qq# = Val(comet$(ind%, 1))       ' perihelion dist
    'e# = Val(comet$(ind%, 2))        ' eccentricity (1=parabola)
    'w# = Val(comet$(ind%, 3))        ' arg of perihelion - little omega
    'om# = Val(comet$(ind%, 4))       ' long of ascending node - big omega
    'I# = Val(comet$(ind%, 5))        ' inclination
    'yr_peri% = Val(comet$(ind%, 6))  ' year
    'mo_peri% = Val(comet$(ind%, 7))  ' month
    'day_peri# = Val(comet$(ind%, 8)) ' day
    'abs_mag# = Val(comet$(ind%, 9))  ' magnitude coef #1
    'mag_n# = Val(comet$(ind%, 10))   ' magnitude coef #2

    ' Find JD of perihelion
    dy_peri% = Int(day_peri#) ' day
    frac_day_peri# = day_peri# - dy_peri% ' fractional day
    Dim d1 As Date = DateSerial(yr_peri%, mo_peri%, dy_peri%)
    dateser# = d1.ToOADate()
    dateser# = dateser# + frac_day_peri#
    jdperi# = 2415018.5 + dateser#

    ' Start date/time
    yr% = Val(MainForm.txtYear.Text)
    mo% = Val(MainForm.txtMonth.Text)
    dd% = Val(MainForm.txtDay.Text)
    fd# = Val(MainForm.txtHour.Text) / 24 + Val(MainForm.txtMin.Text) / 1440 + Val(MainForm.txtSec.Text) / 86400
    lat# = Val(MainForm.txtLat.Text)
    lon# = Val(MainForm.txtLon.Text)

    ' Find Julian Day Number of start date & time
    Dim d2 As Date = DateSerial(yr%, mo%, dd%)
    Dim inputdate# = d2.ToOADate()
    jdp# = inputdate + 2415018.5 ' use this day for phenom (rise/set) calcs
    jd# = jdp# + fd# ' add fractional days

    interval# = Val(MainForm.txtInterval.Text)


    ' Determine if fixed times or rise/set phenomena
    If MainForm.rdbFixedTimes.Checked = True Then
        twi% = 0 ' use fixed times
    Else
        twi% = 1 ' use twilight times
        interval# = Int(interval#) ' Set integer days (fraction doesn't make sense)
        If interval# < 1 Then interval# = 1 ' make sure interval is at least one day
    End If

    '-----------
    ' Loop here
    '-----------
    While counter% <= Val(MainForm.txtNumSteps.Text)

        If twi% = 1 Then
            'Serial date of this calculation
            p_date# = jdp# - 2415018.5
            Call phenom(p_date#, ut#, er%) ' calcs for rise/set, returns er% (among other stuff)
            jd# = Int(p_date#) + 2415018.5 + ut# / 24 + 1 / 2880

            If er% = 1 Then ' er%=1 means no phenom (ex: sunrise) that day
                ser_date# = jd# - 2415018.5
                outpt$ = Format$(ser_date#, "mm/dd/yy") + "           " + "No Rise/Set Phenomena on this Date"
                GoTo No_phenom
            End If

        End If

        ' Days from perihelion of comet
        t# = jd# - jdperi#

        ' Time (in Julian Centuries (36525 days)) since 1900 Jan 0.5 ET
        ' AA page 151

        tt# = (jd# - 2451545.0#) / 36525.0!

        '--------------  CALC F,G,H,P,Q,R (PP214 IN AA)  ---------------
        f# = Cos(dr# * om#)
        p# = -Sin(dr# * om#) * Cos(dr# * I#)
        g# = Sin(dr# * om#) * Cos(dr# * ep#)
        q# = Cos(dr# * om#) * Cos(dr# * I#) * Cos(dr# * ep#) - Sin(dr# * I#) * Sin(dr# * ep#)
        h# = Sin(dr# * om#) * Sin(dr# * ep#)
        r# = Cos(dr# * om#) * Cos(dr# * I#) * Sin(dr# * ep#) + Sin(dr# * I#) * Cos(dr# * ep#)

        '----------------  CALC A1,A2,B1,B2,C1,C2 (PP214 AA)  -----------------
        Call rec2pol(p#, f#, a1#, a2#)
        Call rec2pol(q#, g#, b1#, b2#)
        Call rec2pol(r#, h#, c1#, c2#)

        '---------------  SIDEREAL TIME AT GREENWICH (PP84 AA) ----------------
        ' In degrees
        sdt# = 280.46061837 + 360.98564736629 * (jd# - 2451545) + 0.000387933 * tt# * tt# - tt# * tt# * tt# / 38710000
        sdt# = sdt# - 360 * Int(sdt# / 360)
        '-------------------  CALC ECCENTRIC & TRUE ANOMALY  --------------------
        If e# < 1 Then ' elliptical motion (pp214 AA)
            a# = qq# / (1 - e#) ' semi major axis (AU)
            n# = 0.9856076686 / a# / Sqrt(a#) ' mean motion (deg/day)
            period# = 360 / n# / 365.25
            MainForm.lblOrbitInf.Text = "Semimajor axis: " + Format$(a#, "#.000") + " AU    Period: " + Format$(period#, "#.00") + " Years"
            m# = n# * t# ' mean anomaly
            e0# = rd# * e# ' "modified" eccentricity, page 187)

            'ecc anomaly (page 195)
            mrs# = m# * dr#
            frs% = Sign(mrs#)
            mrs# = Abs(mrs#) / (2 * pi#)
            mrs# = (mrs# - Int(mrs#)) * 2 * pi# * frs%
            If mrs# < 0 Then mrs# = mrs# + 2 * pi#
            frs% = 1
            If mrs# > pi# Then frs% = -1
            If mrs# > pi# Then mrs# = 2 * pi# - mrs#
            ers0# = pi# / 2
            drs# = pi# / 4
            For jrs% = 1 To 53
                mrs1# = ers0# - e# * Sin(ers0#)
                ers0# = ers0# + drs# * Sign(mrs# - mrs1#)
                drs# = drs# / 2
            Next jrs%
            ers0# = ers0# * frs%
            e2# = ers0# * rd#

            'alpha# = (1 - e#) / (4 * e# + .5)
            'beta# = m# / (8 * e# + 1)
            'signbeta% = Sgn(beta#)
            'cube# = beta# + signbeta% * Sqr(beta# ^ 2 + alpha# ^ 3)
            'signz% = Sgn(cube#)
            'zz# = signz% * (Abs(cube#)) ^ (1 / 3)
            'ss0# = zz# - alpha# / 2
            'ss# = ss0# - .078 * ss0# ^ 5 / (1 + e#)
            'e1# = m# + e# * (3 * ss# - 4 * ss# ^ 3)

            'loop1% = 0 ' counter
1040:
            'e2# = e1# + (m# + e0# * Sin(dr# * e1#) - e1#) / (1 - e# * Cos(dr# * e1#))

            'If Abs(e2# - e1#) < .0000000001 Or loop1% > 1000 Then  ' e2#:ecc anom found
            tv# = Sqrt((1 + e#) / (1 - e#)) * Tan(dr# * e2# / 2)
            v# = 2 * rd# * Atan(tv#) ' true anomaly
            r1# = a# * (1 - e# * Cos(dr# * e2#)) ' dist from sun AU
            GoTo 2120
            'Else
            '    e1# = e2# ' new ecc anomaly
            '    loop1% = loop1% + 1
            '    GoTo 1040
            'End If

        Else ' parabolic motion (pp225 AA)
            MainForm.lblOrbitInf.Text = "This comet has a parabolic orbit-semimajor axis and period not determined"
            w0# = 0.0364911624 * t# / qq# / Sqrt(qq#)
            s# = 0
2110:
            s0# = (2 * s# * s# * s# + w0#) / 3 / (s# * s# + 1)

            If Abs(s# - s0#) > 0.0000000001 Then
                s# = s0#
                GoTo 2110
            End If

            s# = s0#
            v# = 2 * rd# * Atan(s#) ' true anomaly
            r1# = qq# * (1 + s# * s#) ' distance from sun (AU)
        End If

2120:
        v# = v# - 360 * Int(v# / 360) ' true anomaly
        'r1#= dist from sun in au (above)
        r2# = r1# * 92955807.0# ' Dist from sun (miles)

        '--------  CALC HELIOCENTRIC RECT COORD OF COMET (PP215 AA)  ----------
        x# = r1# * a2# * Sin(dr# * (a1# + w# + v#))
        y# = r1# * b2# * Sin(dr# * (b1# + w# + v#))
        z# = r1# * c2# * Sin(dr# * (c1# + w# + v#))

        '--------  CALC GEOCENTRIC RECT COORD OF SUN (PP151,152 AA)  ---------
        ls# = 280.46645 + 36000.76983 * tt# + 0.0003032 * tt# * tt#
        ls# = ls# - 360 * Int(ls# / 360)

        ms# = 357.5291 + 35999.0503 * tt# - 0.0001559 * tt# * tt# - 0.00000048 * tt# * tt# * tt#
        ms# = ms# - 360 * Int(ms# / 360)

        es# = 0.016708617 - 0.000042037 * tt# - 0.0000001236 * tt# * tt#

        c# = (1.9146 - 0.004817 * tt# - 0.000014 * tt# * tt#) * Sin(dr# * ms#) + (0.019993 - 0.000101 * tt#) * Sin(2 * dr# * ms#) + 0.00029 * Sin(3 * dr# * ms#)

        th# = ls# + c# ' TH is Sun's true longitude
        vs# = ms# + c# ' VS is Sun's true anomaly

        ' pp152 AA
        th2000# = th# - 0.01397 * (yr% + mo% / 12 + dd% / 365 - 2000) ' Sun true long referred to 2000

        ' sun's radius vector
        rs# = (1.000001018 * (1 - es# * es#)) / (1 + es# * Cos(dr# * vs#))

        ' rectangular coord of sun (pp159 AA)
        xs# = rs# * Cos(dr# * th2000#)                  ' Xsun
        ys# = rs# * Sin(dr# * th2000#) * Cos(dr# * ep#) ' Ysun
        zs# = rs# * Sin(dr# * th2000#) * Sin(dr# * ep#) ' Zsun

        '-------------  CALC GEOCEN开发者_JAVA技巧TRIC RA & DEC (PP 119 IN AFFC)  --------------
        xx# = xs# + x#
        yy# = ys# + y#
        Call rec2pol(xx#, yy#, radeg#, rad#)
        ra# = radeg# / 15 ' RA of comet (2000) in hours
        ' 0 means time
        ras$ = dec2ddmm(ra#, 0) ' ra in string form

        'dist from comet to earth (au)
        dl# = Sqrt((xs# + x#) ^ 2 + (ys# + y#) ^ 2 + (zs# + z#) ^ 2)
        dlm# = dl# * 92955807.0# ' distance from earth in miles

        sd# = (zs# + z#) / dl#

        'DEC of comet (2000)
        dec# = rd# * Atan(sd# / Sqrt(-sd# * sd# + 1))
        ' 1 means angle
        ds$ = dec2ddmm(dec#, 1) ' dec in string form

        ' Calc elongation
        cospsi# = (rs# * rs# + dl# * dl# - r1# * r1#) / (2 * rs# * dl#)
        psi# = -Atan(cospsi# / Sqrt(-cospsi# * cospsi# + 1)) + pi# / 2
        elong# = psi# * rd#
        elong# = elong# - 360 * Int(elong# / 360)

        ' Calc phase
        cosbeta# = (r1# * r1# + dl# * dl# - rs# * rs#) / (2 * r1# * dl#)
        beta# = -Atan(cosbeta# / Sqrt(-cosbeta# * cosbeta# + 1)) + pi# / 2
        phase# = beta# * rd#
        phase# = phase# - 360 * Int(phase# / 360)


        '------------  CALCULATE ALTITUDE & AZIMUTH (AA PP89)  --------------
        ha# = sdt# - lon# - radeg#
        yy# = Sin(dr# * ha#)
        xx# = (Cos(dr# * ha#) * Sin(dr# * lat#) - Tan(dr# * dec#) * Cos(dr# * lat#))
        ' rectangular to polar
        Call rec2pol(xx#, yy#, ang#, rad#)
        az# = ang# + 180
        az# = az# - 360 * Int(az# / 360)
        sinalt# = Sin(dr# * lat#) * Sin(dr# * dec#) + Cos(dr# * lat#) * Cos(dr# * dec#) * Cos(dr# * ha#)
        alt# = rd# * Atan(sinalt# / Sqrt(1 - sinalt# * sinalt#))

        '--------------  CALC EST MAGNITUDES & ORBITAL VELOCITY (AA PP 216)  ---------------
        m1# = abs_mag# + 5 * Log(dl#) / Log(10) + 2.5 * mag_n# * Log(r1#) / Log(10)

        If e# < 1 Then
            vl# = 42.1219 * Sqrt((1 / r1#) - (1 / (2 * a#))) ' elliptical orbital velocity, page 223
        Else
            vl# = 42.1219 * Sqrt(1 / r1#) ' parabolic orital velocity (my approximation)
        End If

        '-------------  Stuff for output form  -------------
        Dim dt As DateTime = DateTime.FromOADate(dateser#)
        MainForm.lblJDperi.Text = "Date of perihelion: " + dt.ToString("dd MMM yyyy hh:mm:ss") + " UTC  JD: " + Format$(jdperi#, "#.00000")
        Lati$ = "   "
        Longi$ = " "
        If lat# > 0 Then Lati$ = "N  " Else Lati$ = "S  "
        If lon# > 0 Then Longi$ = "W" Else Longi$ = "E"
        MainForm.lblLoc.Text = "Observing Location: " + Format$(lat#, "+00.0000;-00.0000") + Chr(176) + Lati$ + Format$(lon#, "+000.0000;-000.0000") + Chr(176) + Longi$

        'Serial date of this calculation
        ser_date# = jd# - 2415018.5

        ' put the main info into a string
        dt = DateTime.FromOADate(ser_date#)
        outpt = dt.ToString("MM/dd/yy   HH:mm:ss") & "   " & ras$ & "   " & ds$ & "  " & Format$(alt#, "+00.0;-00.0") & Chr(176) & "  " & Format$(az#, "000.0") & Chr(176)
        outpt = outpt & "   " & Format$(r1#, "00.0000") & "   " & Format$(dl#, "00.0000") & "  " & Format$(m1#, "+00.0;-00.0") + "   " & Format$(elong#, "000.0") & Chr(176)

No_phenom:

        ' put the string into the list box
        MainForm.lstPosition.Items.Add(outpt)

        ' put the "extra" data into the array
        extra#(counter%, 0) = t#     ' time to perih
        extra#(counter%, 1) = vl#    ' speed
        extra#(counter%, 2) = phase# ' phase
        extra#(counter%, 3) = v#     ' true anomaly

        ' Increment counter
        counter% = counter% + 1

        ' New JD
        jd# = jd# + interval# 
        jdp# = jdp# + interval#

    End While ' do again until done

End Sub

I appreciate any help or direction anyone can give on converting this function to objective-c.

Regards, Keith


When working with dates in Objective-C you will often need to work with more than 1 class unlike other languages such as C#, Java and VB.NET. For creating a date from a string or getting a string from a date you will want to use the NSDateFormatter. Now when attempting to modify or create a date with "components" (year,month,day etc.) you will want to use NSDateComponents along with the correct NSCalendar. The component solution looks like it will assist you with the DateSerial part. The line jdp# = inputdate + 2415018.5 should be convertible (if it is seconds) to

jdp = [NSDate dateWithTimeInterval:2415018.5 sinceDate:inputdate];
0

精彩评论

暂无评论...
验证码 换一张
取 消