home *** CD-ROM | disk | FTP | other *** search
- unit Calculate;
-
- interface
-
- uses Globals;
-
- type
-
- SunTime = record Dawn,Dusk:Float; end;
-
- Daytime = record
- Astronomical,
- Nautical,
- Civil,
- Actual:SunTime;
- end;
-
- procedure Phenomina(lat,long,zone:float; y:longint;m,d:integer;
- var Day:DayTime);
-
-
- implementation
-
- const
- Sunup = pi/2;
- Sundown = pi*3/2;
-
-
- function Normalize(z:float):float;
- begin
- z := 2*pi * Frac(z/(2*pi));
- if z<0 then
- z := z + 2*pi;
- Normalize := z;
- end;
-
- procedure CalcSolar(SunAt,lat,long:float; y:longint; m,d:integer;
- var ApproxTime,
- SolarRightAscension, SolarDeclination:float);
- var
- SolarMeanAnomaly,
- SolarTrueLong
- :Float;
- n :integer;
- begin
- ApproxTime := DayOfYear(y,m,d) + (SunAt+long)/(2*pi);
- SolarMeanAnomaly := ApproxTime * 0.017202 - 0.0574039;
- SolarTrueLong := Normalize(
- SolarMeanAnomaly
- + 0.0334405 * sin(SolarMeanAnomaly)
- + 3.49066E-4 * sin(2*SolarMeanAnomaly)
- + 4.93289
- );
- {Quadrant Determination}
- if Frac(SolarTrueLong*2/pi) = 0.0 then
- SolarTrueLong := SolarTrueLong + 4.84814e-6;
- n := 2;
- if SolarTrueLong <= pi/2 then
- n := 0
- else if SolarTrueLong <= pi*3/2 then
- n := 1;
- SolarRightAscension := ArcTan(0.91746 * Tan(SolarTrueLong));
- {Quadrant Adjustment}
- if n = 1 then
- SolarRightAscension := SolarRightAscension + pi
- else if n = 2 then
- SolarRightAscension := SolarRightAscension + 2*pi;
- {Solar Declination}
- SolarDeclination := 0.39782 * Sin(SolarTrueLong);
- SolarDeclination := ArcTan(SolarDeclination
- / Sqrt(1-Sqr(SolarDeclination))
- );
- end;
-
- procedure ConvertCoords(r,q,lat:float; var s:float);
- begin
- s := (r-(sin(q)*sin(lat))) / (cos(q)*cos(lat));
- end;
-
- function SettingAdjustment(var SolarDeclination:float):float;
- begin
- SettingAdjustment := pi/2 - ArcTan( SolarDeclination
- / Sqrt(1-sqr(SolarDeclination))
- );
- end;
-
- function RisingAdjustment(var SolarDeclination:float):float;
- begin
- RisingAdjustment := 2*pi - SettingAdjustment(SolarDeclination);
- end;
-
- procedure GetTime(long,zone:float; y,m,d: integer;
- ApproxTime,SolarRightAscension, SolarDeclination:float;
- var t:float);
- begin
- t := {Loval Apparent Time}
- SolarDeclination + SolarRightAscension
- - ApproxTime * 2*pi/365.2425 - 1.73364
- {Universal Time}
- + long
- {Wall Clock Time}
- - zone;
- t := Normalize(t) * 24{hours}/(2*pi{radians});
- end;
-
-
- procedure Phenomina(lat,long,zone:float; y:longint;m,d:integer;
- var Day:DayTime);
- var time,ascension,declination:float;
- procedure RisingTime(r:float; var t:SunTime);
- var s:float;
- i:integer;
- begin;
- ConvertCoords(r,declination,lat,s);
- if abs(s)>1.0 then
- t.Dawn := 0
- else
- GetTime(long,zone,y,m,d,time,ascension,RisingAdjustment(s),t.Dawn);
- end;
- procedure SettingTime(r:float; var t:SunTime);
- var s:float;
- i:integer;
- begin;
- ConvertCoords(r,declination,lat,s);
- if abs(s)>1.0 then
- t.Dusk := 0
- else
- GetTime(long,zone,y,m,d,time,ascension,SettingAdjustment(s),t.Dusk);
- end;
- const
- Astro = -0.309017;
- Nautic = -0.207912;
- Civil = -0.104528;
- Actual = -0.0145439;
- begin
- lat := Radians(lat);
- long := Radians(long);
- zone := Radians(zone)*15.0; {15 degrees/Time Zone}
-
- CalcSolar(Sunup,lat,long, y,m,d, time,ascension,declination);
- RisingTime(Astro ,Day.Astronomical);
- RisingTime(Nautic ,Day.Nautical);
- RisingTime(Civil ,Day.Civil);
- RisingTime(Actual ,Day.Actual);
-
- CalcSolar(Sundown,lat,long, y,m,d, time,ascension,declination);
- SettingTime(Actual ,Day.Actual);
- SettingTime(Civil ,Day.Civil);
- SettingTime(Nautic ,Day.Nautical);
- SettingTime(Astro ,Day.Astronomical);
- end;
-
- end.