Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Определение восхода и захода солнца и луны

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.

https://delphiworld.narod.ru/

DelphiWorld 6.0