steclpse.pas
来自「条码控件: 一维条码控件 二维条码控件 PDF417Barcode Ma」· PAS 代码 · 共 732 行 · 第 1/2 页
PAS
732 行
non-central Axis of moon's umbral shadow does not touch earth's surface
Eclipse is usually partial but can be one of possibilities
for central eclipse if very near one of the earth's poles
Partial eclipses
----------------
partial None of the moon's umbral shadow touches the earth's surface
}
if (abs(Gamma) <= (0.9972 + abs(Mu))) then
NonPartialSolarEclipse(CentralJD, Mu, Gamma)
else begin
if (abs(Gamma) < 1.5433 + Mu) then
PartialSolarEclipse(CentralJD, Mu, Gamma);
end;
end;
end;
procedure TStEclipses.TotalLunarEclipse(CentralJD, MoonAnom, Mu,
PMag, UMag, Gamma : Double);
var
TLE : PStEclipseRecord;
PartialSemiDur,
TotalSemiDur,
Dbl1 : Double;
begin
New(TLE);
TLE^.Magnitude := UMag;
TLE^.Hemisphere := htNone;
TLE^.EType := etLunarTotal;
TLE^.Path := nil;
CentralJD := AJDToDateTime(CentralJD);
PartialSemiDur := 1.0128 - Mu;
TotalSemiDur := 0.4678 - Mu;
Dbl1 := 0.5458 + 0.0400 * cos(MoonAnom);
PartialSemiDur := 60/Dbl1 * sqrt(sqr(PartialSemiDur) - sqr(Gamma)) / 1440;
TotalSemiDur := 60/Dbl1 * sqrt(sqr(TotalSemiDur) - sqr(Gamma)) / 1440;
TLE^.LContacts.FirstContact := CentralJD - PartialSemiDur;
TLE^.LContacts.SecondContact := CentralJD - TotalSemiDur;
TLE^.LContacts.MidEclipse := CentralJD;
TLE^.LContacts.ThirdContact := CentralJD + TotalSemiDur;
TLE^.LContacts.FourthContact := CentralJD + PartialSemiDur;
PartialSemiDur := 60/Dbl1 * sqrt(sqr(1.5573 + Mu) - sqr(Gamma)) / 1440;
TLE^.LContacts.UT1 := CentralJD - PartialSemiDur;
TLE^.LContacts.UT2 := CentralJD + PartialSemiDur;
Self.Append(TLE);
end;
procedure TStEclipses.PartialLunarEclipse(CentralJD, MoonAnom, Mu,
PMag, UMag, Gamma : Double);
var
TLE : PStEclipseRecord;
PartialSemiDur,
Dbl1 : Double;
begin
New(TLE);
TLE^.Magnitude := UMag;
TLE^.Hemisphere := htNone;
TLE^.EType := etLunarPartial;
TLE^.Path := nil;
CentralJD := AJDToDateTime(CentralJD);
PartialSemiDur := 1.0128 - Mu;
Dbl1 := 0.5458 + 0.0400 * cos(MoonAnom);
PartialSemiDur := 60/Dbl1 * sqrt(sqr(PartialSemiDur) - sqr(Gamma)) / 1440;
TLE^.LContacts.FirstContact := CentralJD - PartialSemiDur;
TLE^.LContacts.SecondContact := 0;
TLE^.LContacts.MidEclipse := CentralJD;
TLE^.LContacts.ThirdContact := 0;
TLE^.LContacts.FourthContact := CentralJD + PartialSemiDur;
PartialSemiDur := 60/Dbl1 * sqrt(sqr(1.5573 + Mu) - sqr(Gamma)) / 1440;
TLE^.LContacts.UT1 := CentralJD - PartialSemiDur;
TLE^.LContacts.UT2 := CentralJD + PartialSemiDur;
Self.Append(TLE);
end;
procedure TStEclipses.PenumbralLunarEclipse(CentralJD, MoonAnom, Mu,
PMag, UMag, Gamma : Double);
var
TLE : PStEclipseRecord;
PartialSemiDur,
Dbl1 : Double;
begin
New(TLE);
TLE^.Magnitude := PMag;
TLE^.Hemisphere := htNone;
TLE^.EType := etLunarPenumbral;
TLE^.Path := nil;
CentralJD := AJDToDateTime(CentralJD);
TLE^.LContacts.FirstContact := 0;
TLE^.LContacts.SecondContact := 0;
TLE^.LContacts.MidEclipse := CentralJD;
TLE^.LContacts.ThirdContact := 0;
TLE^.LContacts.FourthContact := 0;
Dbl1 := 0.5458 + 0.0400 * cos(MoonAnom);
PartialSemiDur := 60/Dbl1 * sqrt(sqr(1.5573 + Mu) - sqr(Gamma)) / 1440;
TLE^.LContacts.UT1 := CentralJD - PartialSemiDur;
TLE^.LContacts.UT2 := CentralJD + PartialSemiDur;
Self.Append(TLE);
end;
procedure TStEclipses.GetBesselianElements(CentralJD : Double);
var
I,
Mins : LongInt;
CurJD,
SidTime,
SunDist,
MoonDist,
DistRatio,
Alpha,
Theta,
Sun1,
Sun2,
Moon1,
Moon2,
Dbl3,
F1, F2 : Double;
DTRec : TStDateTimeRec;
SunXYZ : TStSunXYZRec;
Sun : TStPosRec;
Moon : TStMoonPosRec;
begin
{compute BesselianElements every 10 minutes starting 2 hours prior to CentralJD}
{but forcing positions to be at multiple of ten minutes}
for I := 1 to 25 do begin
CurJD := CentralJD + ((I-13) * (10/1440));
DTRec.D := AstJulianDateToStDate(CurJD, True);
if ((Frac(CurJD) + 0.5) >= 1) then
Mins := Trunc(((Frac(CurJD) + 0.5)-1) * 1440)
else
Mins := Trunc((Frac(CurJD) + 0.5) * 1440);
{changed because, for example, both 25 and 35 rounded to 30}
Mins := ((Mins + 5) div 10) * 10;
if (Mins = 1440) then
Mins := 0;
DTRec.T := Mins * 60;
SidTime := SiderealTime(DTRec) / radcor;
SunXYZ := SunPosPrim(DTRec);
Sun := SunPos(DTRec);
Moon := MoonPos(DTRec);
Sun1 := Sun.RA/radcor;
Sun2 := Sun.DC/radcor;
Moon1 := Moon.RA/radcor;
Moon2 := Moon.DC/radcor;
FBesselianElements[I].JD := StDateToDateTime(DTRec.D)
+ StTimeToDateTime(DTRec.T);
SunDist := 1.0 / sin(8.794/SunXYZ.RV/3600.0/radcor);
MoonDist := 1.0 / sin(Moon.Plx/radcor);
DistRatio := MoonDist / SunDist;
Theta := DistRatio/cos(Sun2) * cos(Moon2) * (Moon1 - Sun1);
Theta := Theta/(1.0-DistRatio);
Alpha := Sun1 - Theta;
Theta := DistRatio/(1.0 - DistRatio) * (Moon2 - Sun2);
FBesselianElements[I].Delta := Sun2 - Theta;
FBesselianElements[I].Angle := SidTime - Alpha;
FBesselianElements[I].XAxis := MoonDist * cos(Moon2) * (sin(Moon1 - Alpha));
Dbl3 := FBesselianElements[I].Delta;
FBesselianElements[I].YAxis := MoonDist * (sin(Moon2) * cos(Dbl3)
- cos(Moon2) * sin(Dbl3) * cos(Moon1 - Alpha));
Theta := DistRatio * SunXYZ.RV;
Theta := SunXYZ.RV - Theta;
F1 := StInvSin(0.004664012/Theta);
F2 := StInvSin(0.004640787/Theta);
Theta := MoonDist * (sin(Moon2) * sin(Dbl3) + cos(Moon2)
* cos(Dbl3) * cos(Moon1 - Alpha));
FBesselianElements[I].L1 := (Theta + 0.272453/sin(F1)) * StTan(F1);
FBesselianElements[I].L2 := (Theta - 0.272453/sin(F2)) * StTan(F2);
if (I = 13) then
F0 := StTan(F2);
if (I = 16) then begin
FUPrime := FBesselianElements[16].Angle - FBesselianElements[10].Angle;
FDPrime := FBesselianElements[16].Delta - FBesselianElements[10].Delta;
end;
end;
end;
procedure TStEclipses.GetShadowPath(I1, I2 : Integer; Path : TStList);
var
J,
I3, I4,
I5, I6 : integer;
Delta,
Dbl1,
Dbl2,
P1,
XAxis,
YAxis,
Eta,
R1, R2,
D1, D2,
D3, D4,
V3, V4,
V5, V6, V7,
XPrime,
YPrime : Double;
Position : PStLongLat;
begin
for J := I1 to I2 do begin
Eta := 0.00669454;
Delta := FBesselianElements[J].Delta;
XAxis := FBesselianElements[J].XAxis;
YAxis := FBesselianElements[J].YAxis;
R1 := sqrt(1.0 - Eta * sqr(cos(Delta)));
R2 := sqrt(1.0 - Eta * sqr(sin(Delta)));
D1 := sin(Delta) / R1;
D2 := sqrt(1.0 - Eta) * cos(Delta) / R1;
D3 := Eta * sin(Delta) * cos(Delta) / R1 / R2;
D4 := sqrt(1.0 - Eta) / R1 / R2;
V3 := YAxis / R1;
V4 := sqrt(1.0 - sqr(XAxis) - sqr(V3));
V5 := R2 * (V4 * D4 - V3 * D3);
V6 := FUPrime * (-YAxis * sin(Delta) + V5 * cos(Delta));
V7 := FUPrime * XAxis * sin(Delta) - FDPrime * V5;
if ((I2-I1) div 2) >= 4 then begin
I3 := (I2-I1) div 2;
I4 := I1 + I3;
I5 := I4 - 3;
I6 := I4 + 3;
XPrime := FBesselianElements[I6].XAxis
- FBesselianElements[I5].XAxis;
YPrime := FBesselianElements[I6].YAxis
- FBesselianElements[I5].YAxis;
end else begin
XPrime := (FBesselianElements[J+1].XAxis -
FBesselianElements[J-1].XAxis) * 3;
YPrime := (FBesselianElements[J+1].YAxis -
FBesselianElements[J-1].YAxis) * 3;
end;
New(Position);
Dbl1 := sqrt(sqr(XPrime - V6) + sqr(YPrime - V7));
Position^.JD := FBesselianElements[J].JD;
Dbl2 := (FBesselianElements[J].L2 - V5 * F0) / Dbl1;
Dbl2 := abs(Dbl2 * 120);
Position^.Duration := int(Dbl2) + frac(Dbl2) * 0.6;
Dbl1 := -V3 * D1 + V4 * D2;
P1 := StInvTan2(Dbl1, XAxis);
Dbl2 := (FBesselianElements[J].Angle - P1) * radcor;
Dbl2 := frac(Dbl2 / 360.0) * 360;
if (Dbl2 < 0) then
Dbl2 := Dbl2 + 360.0;
if (Dbl2 > 180.0) and (Dbl2 < 360.0) then
Dbl2 := Dbl2 - 360.0;
Position^.Longitude := Dbl2;
Dbl1 := StInvSin(V3 * D2 + V4 * D1);
Dbl2 := ArcTan(1.003364 * StTan(Dbl1)) * radcor;
Position^.Latitude := Dbl2;
Path.Append(Position);
end;
end;
procedure TStEclipses.NonPartialSolarEclipse(CentralJD, Mu, Gamma : Double);
var
SolEc : PStEclipseRecord;
I1, I2 : Integer;
begin
New(SolEc);
if (Mu < 0) then
SolEc^.EType := etSolarTotal
else if (Mu > 0.0047) then
SolEc^.EType := etSolarAnnular
else begin
if (Mu < (0.00464 * sqrt(1 - sqr(Gamma)))) then
SolEc^.EType := etSolarAnnularTotal
else
SolEc^.EType := etSolarTotal;
end;
SolEc^.Magnitude := -1;
if (Gamma > 0) then
SolEc^.Hemisphere := htNorthern
else
SolEc^.Hemisphere := htSouthern;
FillChar(SolEc^.LContacts, SizeOf(TStContactTimes), #0);
SolEc^.LContacts.MidEclipse := AJDtoDateTime(CentralJD);
GetBesselianElements(CentralJD);
{find limits - then go one step inside at each end}
I1 := 1;
while (sqr(FBesselianElements[I1].XAxis) +
sqr(FBesselianElements[I1].YAxis) >= 1.0) and (I1 < 25) do
Inc(I1);
Inc(I1);
I2 := I1;
repeat
if (I2 < 25) then begin
if (sqr(FBesselianElements[I2+1].XAxis) +
sqr(FBesselianElements[I2+1].YAxis) < 1) then
Inc(I2)
else
break;
end;
until (sqr(FBesselianElements[I2].XAxis) +
sqr(FBesselianElements[I2].YAxis) >= 1) or (I2 >= 25);
Dec(I2);
{this test accounts for non-central eclipses, i.e., those that are total}
{and/or annular but the axis of the moon's shadow does not touch the earth}
if (I1 <> I2) and (I1 < 26) and (I2 < 26) then begin
SolEc^.Path := TStList.Create(TStListNode);
SolEc^.Path.DisposeData := DisposePathData;
GetShadowPath(I1, I2, SolEc^.Path);
end else
SolEc^.Path := nil;
Self.Append(SolEc);
end;
procedure TStEclipses.PartialSolarEclipse(CentralJD, Mu, Gamma : Double);
var
SolEc : PStEclipseRecord;
begin
New(SolEc);
SolEc^.EType := etSolarPartial;
SolEc^.Magnitude := (1.5433 + Mu - abs(Gamma)) / (0.5461 + 2*Mu);
if (Gamma > 0) then
SolEc^.Hemisphere := htNorthern
else
SolEc^.Hemisphere := htSouthern;
FillChar(SolEc^.LContacts, SizeOf(TStContactTimes), #0);
SolEc^.LContacts.MidEclipse := AJDToDateTime(CentralJD);
SolEc^.Path := nil;
Self.Append(SolEc);
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?