Определение восхода и захода солнца и луны
01.01.2007
program sunproject; uses Forms, main in 'main.pas' {Sun}; {$R *.RES} begin Application.Initialize; Application.Title := 'Sun'; Application.CreateForm(TSun, Sun); Application.Run; end.
object Sun: TSun Left = 210 Top = 106 BorderIcons = [biSystemMenu, biMinimize] BorderStyle = bsSingle Caption = 'Sun' ClientHeight = 257 ClientWidth = 299 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Position = poDesktopCenter OnCreate = CreateForm PixelsPerInch = 96 TextHeight = 13 object GroupBoxInput: TGroupBox Left = 4 Top = 4 Width = 173 Height = 93 Caption = ' Ввод ' TabOrder = 0 object LabelLongitude: TLabel Left = 35 Top = 44 Width = 78 Height = 13 Alignment = taRightJustify Caption = 'Долгота (град):' end object LabelTimeZone: TLabel Left = 13 Top = 68 Width = 100 Height = 13 Alignment = taRightJustify Caption = 'Часовая зона (час):' end object LabelAtitude: TLabel Left = 40 Top = 20 Width = 73 Height = 13 Alignment = taRightJustify Caption = 'Широта (град):' end object EditB5: TEdit Tag = 1 Left = 120 Top = 16 Width = 37 Height = 21 TabOrder = 0 Text = '0' end object EditL5: TEdit Tag = 2 Left = 120 Top = 40 Width = 37 Height = 21 TabOrder = 1 Text = '0' end object EditH: TEdit Tag = 3 Left = 120 Top = 64 Width = 37 Height = 21 TabOrder = 2 Text = '0' end end object GroupBoxCalendar: TGroupBox Left = 184 Top = 4 Width = 109 Height = 93 Caption = ' Календарь ' TabOrder = 1 object LabelD: TLabel Left = 19 Top = 20 Width = 30 Height = 13 Alignment = taRightJustify Caption = 'День:' end object LabelM: TLabel Left = 13 Top = 44 Width = 36 Height = 13 Alignment = taRightJustify Caption = 'Месяц:' end object LabelY: TLabel Left = 28 Top = 68 Width = 21 Height = 13 Alignment = taRightJustify Caption = 'Год:' end object EditD: TEdit Tag = 1 Left = 56 Top = 16 Width = 37 Height = 21 TabOrder = 0 Text = '0' end object EditM: TEdit Tag = 2 Left = 56 Top = 40 Width = 37 Height = 21 TabOrder = 1 Text = '0' end object EditY: TEdit Tag = 3 Left = 56 Top = 64 Width = 37 Height = 21 TabOrder = 2 Text = '0' end end object ButtonCalc: TButton Left = 12 Top = 227 Width = 169 Height = 25 Caption = '&Вычислить' TabOrder = 2 OnClick = ButtonCalcClick end object ListBox: TListBox Left = 4 Top = 104 Width = 289 Height = 117 ItemHeight = 13 TabOrder = 3 end object ButtonClear: TButton Left = 192 Top = 227 Width = 91 Height = 25 Caption = '&Очистить' TabOrder = 4 OnClick = ButtonClearClick end end
{ Программа вычисляет время восхода и захода солнца по дате (с точностью до минуты) в пределах нескольких текущих столетий. Производит корректировку, если географическая точка находится в арктическом или антарктическом регионе, где заход или восход солнца на текущую дату может не состояться. Вводимые данные: положительная северная широта и отрицательная западная долгота. Часовой пояс указывается относительно Гринвича (например, 5 для EST и 4 для EDT). Алгоритм обсуждался в "Sky & Telescope" за август 1994, страница 84. } unit main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TSun = class(TForm) GroupBoxInput: TGroupBox; LabelLongitude: TLabel; EditB5: TEdit; EditL5: TEdit; LabelTimeZone: TLabel; EditH: TEdit; GroupBoxCalendar: TGroupBox; LabelD: TLabel; LabelM: TLabel; LabelY: TLabel; EditD: TEdit; EditM: TEdit; EditY: TEdit; ButtonCalc: TButton; ListBox: TListBox; ButtonClear: TButton; LabelAtitude: TLabel; procedure Calendar; // Календарь procedure GetTimeZone; // Получение часового пояса procedure PosOfSun; // Получаем положение солнца procedure OutInform; // Процедура вывода информации procedure PossibleEvents(Hour: integer); // Возможные события на полученный час procedure GetDate; //Получить значения даты procedure GetInput; //Получить значения широты,... procedure ButtonCalcClick(Sender: TObject); procedure CreateForm(Sender: TObject); procedure ButtonClearClick(Sender: TObject); private function Sgn(Value: Double): integer; // Сигнум public { Public declarations } end; var Sun: TSun; st: string; aA, aD: array[1..2] of double; B5: integer; L5: double; H: integer; Z, Z0, Z1: double; D: double; M, Y: integer; A5, D5, R5: double; J3: integer; T, T0, TT, T3: double; L0, L2: double; H0, H1, H2, H7, N7, D7: double; H3, M3: integer; M8, W8: double; A, B, A0, D0, A2, D1, D2, DA, DD: double; E, F, J, S, C, P, L, G, V, U, W: double; V0, V1, V2: double; C0: integer; AZ: double; const P2 = Pi * 2; // 2 * Pi DR = Pi / 180; // Радиан на градус K1 = 15 * DR * 1.0027379; implementation {$R *.DFM} function TSun.Sgn(Value: Double): integer; begin {if Value = 0 then} Result := 0; if Value > 0 then Result := 1; if Value < 0 then Result := -1; end; procedure TSun.Calendar; begin G := 1; if Y < 1583 then G := 0; D1 := Trunc(D); F := D - D1 - 0.5; J := -Trunc(7 * (Trunc((M + 9) / 12) + Y) / 4); if G = 1 then begin S := Sgn(M - 9); A := Abs(M - 9); J3 := Trunc(Y + S * Trunc(A / 7)); J3 := -Trunc((Trunc(J3 / 100) + 1) * 3 / 4); end; J := J + Trunc(275 * M / 9) + D1 + G * J3; J := J + 1721027 + 2 * G + 367 * Y; if F >= 0 then Exit; F := F + 1; J := J - 1; end; procedure TSun.GetTimeZone; begin T0 := T / 36525; S := 24110.5 + 8640184.813 * T0; S := S + 86636.6 * Z0 + 86400 * L5; S := S / 86400; S := S - Trunc(S); T0 := S * 360 * DR; end; procedure TSun.PosOfSun; begin // Фундаментальные константы // (Van Flandern & Pulkkinen, 1979) L := 0.779072 + 0.00273790931 * T; G := 0.993126 + 0.0027377785 * T; L := L - Trunc(L); G := G - Trunc(G); L := L * P2; G := G * P2; V := 0.39785 * Sin(L); V := V - 0.01000 * Sin(L - G); V := V + 0.00333 * Sin(L + G); V := V - 0.00021 * TT * Sin(L); U := 1 - 0.03349 * Cos(G); U := U - 0.00014 * Cos(2 * L); U := U + 0.00008 * Cos(L); W := -0.00010 - 0.04129 * Sin(2 * L); W := W + 0.03211 * Sin(G); W := W + 0.00104 * Sin(2 * L - G); W := W - 0.00035 * Sin(2 * L + G); W := W - 0.00008 * TT * Sin(G); // Вычисление солнечных координат S := W / Sqrt(U - V * V); A5 := L + ArcTan(S / Sqrt(1 - S * S)); S := V / Sqrt(U); D5 := ArcTan(S / Sqrt(1 - S * S)); R5 := 1.00021 * Sqrt(U); end; procedure TSun.PossibleEvents(Hour: integer); var num: string; begin st := ''; L0 := T0 + Hour * K1; L2 := L0 + K1; H0 := L0 - A0; H2 := L2 - A2; H1 := (H2 + H0) / 2; // Часовой угол, D1 := (D2 + D0) / 2; // наклон в получасе if Hour <= 0 then V0 := S * Sin(D0) + C * Cos(D0) * Cos(H0) - Z; V2 := S * Sin(D2) + C * Cos(D2) * Cos(H2) - Z; if Sgn(V0) = Sgn(V2) then Exit; V1 := S * Sin(D1) + C * Cos(D1) * Cos(H1) - Z; A := 2 * V2 - 4 * V1 + 2 * V0; B := 4 * V1 - 3 * V0 - V2; D := B * B - 4 * A * V0; if D < 0 then Exit; D := Sqrt(D); if (V0 < 0) and (V2 > 0) then st := st + 'Восход солнца в '; if (V0 < 0) and (V2 > 0) then M8 := 1; if (V0 > 0) and (V2 < 0) then st := st + 'Заход солнца в '; if (V0 > 0) and (V2 < 0) then W8 := 1; E := (-B + D) / (2 * A); if (E > 1) or (E < 0) then E := (-B - D) / (2 * A); T3 := Hour + E + 1 / 120; // Округление H3 := Trunc(T3); M3 := Trunc((T3 - H3) * 60); Str(H3: 2, num); st := st + num + ':'; Str(M3: 2, num); st := st + num; H7 := H0 + E * (H2 - H0); N7 := -Cos(D1) * Sin(H7); D7 := C * Sin(D1) - S * Cos(D1) * COS(H7); AZ := ArcTan(N7 / D7) / DR; if (D7 < 0) then AZ := AZ + 180; if (AZ < 0) then AZ := AZ + 360; if (AZ > 360) then AZ := AZ - 360; Str(AZ: 4: 1, num); st := st + ', азимут ' + num; end; procedure TSun.OutInform; begin if (M8 = 0) and (W8 = 0) then begin if V2 < 0 then ListBox.Items.Add('Солнце заходит весь день '); if V2 > 0 then ListBox.Items.Add('Солнце восходит весь день '); end else begin if M8 = 0 then ListBox.Items.Add('В этот день солнце не восходит '); if W8 = 0 then ListBox.Items.Add('В этот день солнце не заходит '); end; end; procedure TSun.GetDate; begin D := StrToInt(EditD.text); M := StrToInt(EditM.text); Y := StrToInt(EditY.text); end; procedure TSun.GetInput; begin B5 := StrToInt(EditB5.Text); L5 := StrToInt(EditL5.Text); H := StrToInt(EditH.Text); end; procedure TSun.ButtonCalcClick(Sender: TObject); var C0: integer; begin GetDate; GetInput; ListBox.Items.Add('Широта: ' + EditB5.Text + ' Долгота: ' + EditL5.Text + ' Зона: ' + EditH.Text + ' Дата: ' + EditD.Text + '/' + EditM.Text + '/' + EditY.Text); L5 := L5 / 360; Z0 := H / 24; Calendar; T := (J - 2451545) + F; TT := T / 36525 + 1; // TT - столетия, начиная с 1900.0 GetTimeZone; // Получение часового пояса T := T + Z0; PosOfSun; // Получаем положение солнца aA[1] := A5; aD[1] := D5; T := T + 1; PosOfSun; aA[2] := A5; aD[2] := D5; if aA[2] < aA[1] then aA[2] := aA[2] + P2; Z1 := DR * 90.833; // Вычисление зенита S := Sin(B5 * DR); C := Cos(B5 * DR); Z := Cos(Z1); M8 := 0; W8 := 0; A0 := aA[1]; D0 := aD[1]; DA := aA[2] - aA[1]; DD := aD[2] - aD[1]; for C0 := 0 to 23 do begin P := (C0 + 1) / 24; A2 := aA[1] + P * DA; D2 := aD[1] + P * DD; PossibleEvents(C0); if st <> '' then ListBox.Items.Add(st); A0 := A2; D0 := D2; V0 := V2; end; OutInform; ListBox.Items.Add(''); // Разделяем данные end; procedure TSun.CreateForm(Sender: TObject); begin EditD.Text := FormatDateTime('d', Date); EditM.Text := FormatDateTime('m', Date); EditY.Text := FormatDateTime('yyyy', Date); end; procedure TSun.ButtonClearClick(Sender: TObject); begin ListBox.Clear; end; end.
DelphiWorld 6.0