Horizontal sundial calculations

From Rosetta Code
Revision as of 13:59, 25 June 2010 by rosettacode>Jofur (→‎{{header|PureBasic}}: Added PureBasic)
Task
Horizontal sundial calculations
You are encouraged to solve this task according to the task description, using any language you may know.

A program that calculates the hour, sun hour angle, dial hour line angle from 6am to 6pm for an operator entered location.

As the example the user is prompted for a location and inputs the latitude and longitude 4°57′S 150°30′W (4.95°S 150.5°W) of Jules Verne's Lincoln Island, aka Ernest Legouve Reef). With a legal meridian of 150°W.

Wikipedia: A sundial is a device that measures time by the position of the Sun. In common designs such as the horizontal sundial, the sun casts a shadow from its style (also called its Gnomon, a thin rod or a sharp, straight edge) onto a flat surface marked with lines indicating the hours of the day. As the sun moves across the sky, the shadow-edge progressively aligns with different hour-lines on the plate. Such designs rely on the style being aligned with the axis of the Earth's rotation. Hence, if such a sundial is to tell the correct time, the style must point towards true north (not the north or south magnetic pole) and the style's angle with horizontal must equal the sundial's geographical latitude.

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

Example extracted - with permission for a GPL - from Simon Wheaton-Smith's Illustrating Time's Shadow web page. <lang algol68>BEGIN

 REAL lat, slat, lng, ref;
 print ( "Enter latitude       => " ); read (lat);
 print ( "Enter longitude      => " ); read (lng);
 print ( "Enter legal meridian => " ); read (ref);
 new line(stand out);
 slat := sin(lat*2*pi/360) ;
 print ( ("    sine of latitude:   ", float(slat,8,2,1), new line ) );
 print ( ("    diff longitude:     ", fixed((lng - ref),0,3), new line, new line ) );
 print ( ("Hour, sun hour angle, dial hour line angle from 6am to 6pm", new line ));
 FOR h FROM -6 TO 6
 DO
    REAL hra , hla ;              # define hour angle and hour line angle #
    hra := 15 * h ;               # hour angle is 15 times the hour #
    hra := hra - (lng - ref);     # but correct for longitude difference #
    hla := arc tan ( slat * tan(hra*2*pi/360) ) * 360 / ( 2*pi) ;
    # page 132 of a68gdoc.pdf documentationfile #
    print ("HR="+whole(h,3)+"; HRA="+fixed(hra,8,3)+"; HLA="+fixed(hla,8,3));
    new line(stand out)
 OD

END</lang> Output:

Enter latitude       => -4.95
Enter longitude      => -150.5
Enter legal meridian => -150  

    sine of latitude:   -86.3e-3
    diff longitude:     -.500

Hour, sun hour angle, dial hour line angle from 6am to 6pm
HR= -6; HRA= -89.500; HLA= +84.225
HR= -5; HRA= -74.500; HLA= +17.283
HR= -4; HRA= -59.500; HLA=  +8.334
HR= -3; HRA= -44.500; HLA=  +4.847
HR= -2; HRA= -29.500; HLA=  +2.795
HR= -1; HRA= -14.500; HLA=  +1.278
HR= +0; HRA=  +0.500; HLA=  -0.043
HR= +1; HRA= +15.500; HLA=  -1.371
HR= +2; HRA= +30.500; HLA=  -2.910
HR= +3; HRA= +45.500; HLA=  -5.018
HR= +4; HRA= +60.500; HLA=  -8.671
HR= +5; HRA= +75.500; HLA= -18.451
HR= +6; HRA= +90.500; HLA= +84.225

PicoLisp

Translation of: ALGOL 68

<lang PicoLisp>(load "@lib/math.l")

(de prompt (Str . Arg)

  (prin Str " => ")
  (set (car Arg) (in NIL (read))) )

(use (Lat Lng Ref)

  (prompt "Enter latitude      " Lat)
  (prompt "Enter longitude     " Lng)
  (prompt "Enter legal meridian" Ref)
  (prinl)
  (let Slat (sin (*/ Lat pi 180.0))
     (prinl "    sine of latitude:   " (round Slat 3))
     (prinl "    diff longitude:     " (round (- Lng Ref) 3))
     (prinl)
     (prinl "Hour, sun hour angle, dial hour line angle from 6am to 6pm")
     (for H (range -6 6)
        (let Hra (- (* 15.0 H) (- Lng Ref))
           (let Hla (*/ (atan (*/ Slat (tan (*/ Hra pi 180.0)) 1.0)) 180.0 pi)
              (prinl
                 "HR="
                 (align 3 H)
                 "; HRA="
                 (align 8 (round Hra 3))
                 "; HLA="
                 (align 8 (round Hla 3)) ) ) ) ) ) )</lang>

Output:

Enter latitude       => -4.95
Enter longitude      => -150.5
Enter legal meridian => -150.          # Don't omit the '.' here

    sine of latitude:   -0.086
    diff longitude:     -0.500

Hour, sun hour angle, dial hour line angle from 6am to 6pm
HR= -6; HRA= -89.500; HLA=  84.225
HR= -5; HRA= -74.500; HLA=  17.283
HR= -4; HRA= -59.500; HLA=   8.334
HR= -3; HRA= -44.500; HLA=   4.847
HR= -2; HRA= -29.500; HLA=   2.795
HR= -1; HRA= -14.500; HLA=   1.278
HR=  0; HRA=   0.500; HLA=  -0.043
HR=  1; HRA=  15.500; HLA=  -1.371
HR=  2; HRA=  30.500; HLA=  -2.910
HR=  3; HRA=  45.500; HLA=  -5.018
HR=  4; HRA=  60.500; HLA=  -8.671
HR=  5; HRA=  75.500; HLA= -18.451
HR=  6; HRA=  90.500; HLA=  84.225

PureBasic

Translation of: ALGOL 68

<lang PureBasic>If OpenConsole()

 Define.f lat, slat, lng, ref
 Define.i h
 Print("Enter latitude       => "): lat=ValF(Input())
 Print("Enter longitude      => "): lng=ValF(Input())
 Print("Enter legal meridian => "): ref=ValF(Input())
 PrintN("")
 
 slat=Sin(lat*2*#PI/360)
 PrintN("    sine of latitude:   "+StrF(slat,3))
 PrintN("    diff longitude:     "+StrF((lng-ref),3)+#CRLF$)
 PrintN("Hour, sun hour angle, dial hour line angle from 6am to 6pm")
 
 For h=-6 To 6
   Define.f hra, hla
   hra=15*h
   hra-(lng-ref)
   hla=ATan(slat*Tan(hra*2*#PI/360))*360/(2*#PI)
   PrintN("HR="+RSet(Str(h),3)+"; HRA="+RSet(StrF(hra,3),7)+"; HLA="+RSet(StrF(hla,3),7))
 Next
 

EndIf</lang>

Enter latitude       => -4.95
Enter longitude      => -150.5
Enter legal meridian => -150

    sine of latitude:   -0.086
    diff longitude:     -0.500

Hour, sun hour angle, dial hour line angle from 6am to 6pm
HR= -6; HRA=-89.500; HLA= 84.225
HR= -5; HRA=-74.500; HLA= 17.283
HR= -4; HRA=-59.500; HLA=  8.334
HR= -3; HRA=-44.500; HLA=  4.847
HR= -2; HRA=-29.500; HLA=  2.795
HR= -1; HRA=-14.500; HLA=  1.278
HR=  0; HRA=  0.500; HLA= -0.043
HR=  1; HRA= 15.500; HLA= -1.371
HR=  2; HRA= 30.500; HLA= -2.910
HR=  3; HRA= 45.500; HLA= -5.018
HR=  4; HRA= 60.500; HLA= -8.671
HR=  5; HRA= 75.500; HLA=-18.451
HR=  6; HRA= 90.500; HLA= 84.225