Exemple #1
0
// Position returns observed equatorial coordinates of a planet at a given time.
//
// Argument p must be a valid V87Planet object for the observed planet.
// Argument earth must be a valid V87Planet object for Earth.
//
// Results are right ascension and declination, α and δ in radians.
func Position(p, earth *pp.V87Planet, jde float64) (α, δ float64) {
	L0, B0, R0 := earth.Position(jde)
	L, B, R := p.Position(jde)
	sB0, cB0 := math.Sincos(B0)
	sL0, cL0 := math.Sincos(L0)
	sB, cB := math.Sincos(B)
	sL, cL := math.Sincos(L)
	x := R*cB*cL - R0*cB0*cL0
	y := R*cB*sL - R0*cB0*sL0
	z := R*sB - R0*sB0
	{
		Δ := math.Sqrt(x*x + y*y + z*z) // (33.4) p. 224
		τ := base.LightTime(Δ)
		// repeating with jde-τ
		L, B, R = p.Position(jde - τ)
		sB, cB = math.Sincos(B)
		sL, cL = math.Sincos(L)
		x = R*cB*cL - R0*cB0*cL0
		y = R*cB*sL - R0*cB0*sL0
		z = R*sB - R0*sB0
	}
	λ := math.Atan2(y, x)                // (33.1) p. 223
	β := math.Atan2(z, math.Hypot(x, y)) // (33.2) p. 223
	Δλ, Δβ := apparent.EclipticAberration(λ, β, jde)
	λ, β = pp.ToFK5(λ+Δλ, β+Δβ, jde)
	Δψ, Δε := nutation.Nutation(jde)
	λ += Δψ
	sε, cε := math.Sincos(nutation.MeanObliquity(jde) + Δε)
	return coord.EclToEq(λ, β, sε, cε)
	// Meeus gives a formula for elongation but doesn't spell out how to
	// obtaion term λ0 and doesn't give an example solution.
}
Exemple #2
0
// TrueEquatorial returns the true geometric position of the Sun as equatorial coordinates.
func TrueEquatorial(jde float64) (α, δ float64) {
	s, _ := True(base.J2000Century(jde))
	ε := nutation.MeanObliquity(jde)
	ss, cs := math.Sincos(s)
	sε, cε := math.Sincos(ε)
	// (25.6, 25.7) p. 165
	return math.Atan2(cε*ss, cs), sε * ss
}
Exemple #3
0
// ApparentEquatorial returns the apparent position of the Sun as equatorial coordinates.
//
//	α: right ascension in radians
//	δ: declination in radians
func ApparentEquatorial(jde float64) (α, δ float64) {
	T := base.J2000Century(jde)
	λ := ApparentLongitude(T)
	ε := nutation.MeanObliquity(jde)
	sλ, cλ := math.Sincos(λ)
	// (25.8) p. 165
	sε, cε := math.Sincos(ε + .00256*math.Pi/180*math.Cos(node(T)))
	return math.Atan2(cε*sλ, cλ), math.Asin(sε * sλ)
}
Exemple #4
0
func TestIAUvsLaskar(t *testing.T) {
	for _, y := range []int{1000, 2000, 3000} {
		jd := julian.CalendarGregorianToJD(y, 0, 0)
		i := nutation.MeanObliquity(jd)
		l := nutation.MeanObliquityLaskar(jd)
		if math.Abs((i - l).Sec()) > 1 {
			t.Fatal(y)
		}
	}
	for _, y := range []int{0, 4000} {
		jd := julian.CalendarGregorianToJD(y, 0, 0)
		i := nutation.MeanObliquity(jd)
		l := nutation.MeanObliquityLaskar(jd)
		if math.Abs((i - l).Sec()) > 10 {
			t.Fatal(y)
		}
	}
}
Exemple #5
0
// TrueEquatorial returns the true geometric position of the Sun as equatorial coordinates.
func TrueEquatorial(jde float64) (α unit.RA, δ unit.Angle) {
	s, _ := True(base.J2000Century(jde))
	ε := nutation.MeanObliquity(jde)
	ss, cs := s.Sincos()
	sε, cε := ε.Sincos()
	// (25.6, 25.7) p. 165
	α = unit.RAFromRad(math.Atan2(cε*ss, cs))
	δ = unit.Angle(math.Asin(sε * ss))
	return
}
Exemple #6
0
// Position returns rectangular coordinates referenced to the mean equinox of date.
func Position(e *pp.V87Planet, jde float64) (x, y, z float64) {
	// (26.1) p. 171
	s, β, R := solar.TrueVSOP87(e, jde)
	sε, cε := math.Sincos(nutation.MeanObliquity(jde))
	ss, cs := math.Sincos(s)
	sβ := math.Sin(β)
	x = R * cs
	y = R * (ss*cε - sβ*sε)
	z = R * (ss*sε + sβ*cε)
	return
}
Exemple #7
0
func eqProperMotionToEcl(mα unit.HourAngle, mδ unit.Angle, epoch float64, pos *coord.Ecliptic) (mλ, mβ unit.Angle) {
	ε := nutation.MeanObliquity(base.JulianYearToJDE(epoch))
	sε, cε := ε.Sincos()
	α, δ := coord.EclToEq(pos.Lon, pos.Lat, sε, cε)
	sα, cα := α.Sincos()
	sδ, cδ := δ.Sincos()
	cβ := pos.Lat.Cos()
	mλ = (mδ.Mul(sε*cα) + unit.Angle(mα).Mul(cδ*(cε*cδ+sε*sδ*sα))).Div(cβ * cβ)
	mβ = (mδ.Mul(cε*cδ+sε*sδ*sα) - unit.Angle(mα).Mul(sε*cα*cδ)).Div(cβ)
	return
}
Exemple #8
0
// Nutation returns corrections due to nutation for equatorial coordinates
// of an object.
//
// Results are invalid for objects very near the celestial poles.
func Nutation(α, δ, jd float64) (Δα1, Δδ1 float64) {
	ε := nutation.MeanObliquity(jd)
	sε, cε := math.Sincos(ε)
	Δψ, Δε := nutation.Nutation(jd)
	sα, cα := math.Sincos(α)
	tδ := math.Tan(δ)
	// (23.1) p. 151
	Δα1 = (cε+sε*sα*tδ)*Δψ - cα*tδ*Δε
	Δδ1 = sε*cα*Δψ + sα*Δε
	return
}
Exemple #9
0
func eqProperMotionToEcl(mα, mδ, epoch float64, pos *coord.Ecliptic) (mλ, mβ float64) {
	ε := nutation.MeanObliquity(base.JulianYearToJDE(epoch))
	sε, cε := math.Sincos(ε)
	α, δ := coord.EclToEq(pos.Lon, pos.Lat, sε, cε)
	sα, cα := math.Sincos(α)
	sδ, cδ := math.Sincos(δ)
	cβ := math.Cos(pos.Lat)
	mλ = (mδ*sε*cα + mα*cδ*(cε*cδ+sε*sδ*sα)) / (cβ * cβ)
	mβ = (mδ*(cε*cδ+sε*sδ*sα) - mα*sε*cα*cδ) / cβ
	return
}
Exemple #10
0
// Nutation returns corrections due to nutation for equatorial coordinates
// of an object.
//
// Results are invalid for objects very near the celestial poles.
func Nutation(α unit.RA, δ unit.Angle, jd float64) (Δα1 unit.HourAngle, Δδ1 unit.Angle) {
	ε := nutation.MeanObliquity(jd)
	sε, cε := ε.Sincos()
	Δψ, Δε := nutation.Nutation(jd)
	sα, cα := α.Sincos()
	tδ := δ.Tan()
	// (23.1) p. 151
	Δα1 = unit.HourAngle((cε+sε*sα*tδ)*Δψ.Rad() - cα*tδ*Δε.Rad())
	Δδ1 = Δψ.Mul(sε*cα) + Δε.Mul(sα)
	return
}
Exemple #11
0
// ApparentEquatorialVSOP87 returns the apparent position of the sun as equatorial coordinates.
//
// Result computed by VSOP87, at equator and equinox of date in the FK5 frame,
// and includes effects of nutation and aberration.
//
//	α: right ascension in radians
//	δ: declination in radians
//	R: range in AU
func ApparentEquatorialVSOP87(e *pp.V87Planet, jde float64) (α, δ, R float64) {
	// note: duplicate code from ApparentVSOP87 so we can keep Δε.
	// see also duplicate code in time.E().
	s, β, R := TrueVSOP87(e, jde)
	Δψ, Δε := nutation.Nutation(jde)
	a := aberration(R)
	λ := s + Δψ + a
	ε := nutation.MeanObliquity(jde) + Δε
	sε, cε := math.Sincos(ε)
	α, δ = coord.EclToEq(λ, β, sε, cε)
	return
}
Exemple #12
0
// ApparentEquatorial returns the apparent position of the Sun as equatorial coordinates.
//
//	α: right ascension in radians
//	δ: declination in radians
func ApparentEquatorial(jde float64) (α unit.RA, δ unit.Angle) {
	T := base.J2000Century(jde)
	λ := ApparentLongitude(T)
	ε := nutation.MeanObliquity(jde)
	sλ, cλ := λ.Sincos()
	// (25.8) p. 165
	ε += unit.AngleFromDeg(.00256).Mul(node(T).Cos())
	sε, cε := ε.Sincos()
	α = unit.RAFromRad(math.Atan2(cε*sλ, cλ))
	δ = unit.Angle(math.Asin(sε * sλ))
	return
}
Exemple #13
0
// ESmart computes the "equation of time" for the given JDE.
//
// Result is equation of time as an hour angle.
//
// Result is less accurate that E() but the function has the advantage
// of not requiring the V87Planet object.
func ESmart(jde float64) unit.HourAngle {
	ε := nutation.MeanObliquity(jde)
	t := ε.Mul(.5).Tan()
	y := t * t
	T := base.J2000Century(jde)
	L0 := l0(T * .1)
	e := solar.Eccentricity(T)
	M := solar.MeanAnomaly(T)
	s2L0, c2L0 := L0.Mul(2).Sincos()
	sM := M.Sin()
	// (28.3) p. 185, with double angle identity
	return unit.HourAngle(y*s2L0 - 2*e*sM + 4*e*y*sM*c2L0 -
		y*y*s2L0*c2L0 - 1.25*e*e*M.Mul(2).Sin())
}
Exemple #14
0
// ESmart computes the "equation of time" for the given JDE.
//
// Result is equation of time as an hour angle in radians.
//
// Result is less accurate that E() but the function has the advantage
// of not requiring the V87Planet object.
func ESmart(jde float64) float64 {
	ε := nutation.MeanObliquity(jde)
	t := math.Tan(ε * .5)
	y := t * t
	T := base.J2000Century(jde)
	L0 := l0(T * .1)
	e := solar.Eccentricity(T)
	M := solar.MeanAnomaly(T)
	s2L0, c2L0 := math.Sincos(2 * L0)
	sM := math.Sin(M)
	// (28.3) p. 185
	return y*s2L0 - 2*e*sM + 4*e*y*sM*c2L0 -
		y*y*s2L0*c2L0 - 1.25*e*e*math.Sin(2*M)
}
Exemple #15
0
func ExampleNutation() {
	// Example 22.a, p. 148.
	jd := julian.CalendarGregorianToJD(1987, 4, 10)
	Δψ, Δε := nutation.Nutation(jd)
	ε0 := nutation.MeanObliquity(jd)
	ε := ε0 + Δε
	fmt.Printf("%+.3d\n", sexa.FmtAngle(Δψ))
	fmt.Printf("%+.3d\n", sexa.FmtAngle(Δε))
	fmt.Printf("%.3d\n", sexa.FmtAngle(ε0))
	fmt.Printf("%.3d\n", sexa.FmtAngle(ε))
	// Output:
	// -3″.788
	// +9″.443
	// 23°26′27″.407
	// 23°26′36″.850
}
Exemple #16
0
// E computes the "equation of time" for the given JDE.
//
// Parameter e must be a planetposition.V87Planet object for Earth obtained
// with planetposition.LoadPlanet.
//
// Result is equation of time as an hour angle in radians.
func E(jde float64, e *pp.V87Planet) float64 {
	τ := base.J2000Century(jde) * .1
	L0 := l0(τ)
	// code duplicated from solar.ApparentEquatorialVSOP87 so that
	// we can keep Δψ and cε
	s, β, R := solar.TrueVSOP87(e, jde)
	Δψ, Δε := nutation.Nutation(jde)
	a := -20.4898 / 3600 * math.Pi / 180 / R
	λ := s + Δψ + a
	ε := nutation.MeanObliquity(jde) + Δε
	sε, cε := math.Sincos(ε)
	α, _ := coord.EclToEq(λ, β, sε, cε)
	// (28.1) p. 183
	E := L0 - .0057183*math.Pi/180 - α + Δψ*cε
	return base.PMod(E+math.Pi, 2*math.Pi) - math.Pi
}
Exemple #17
0
// E computes the "equation of time" for the given JDE.
//
// Parameter e must be a planetposition.V87Planet object for Earth obtained
// with planetposition.LoadPlanet.
//
// Result is equation of time as an hour angle.
func E(jde float64, e *pp.V87Planet) unit.HourAngle {
	τ := base.J2000Century(jde) * .1
	L0 := l0(τ)
	// code duplicated from solar.ApparentEquatorialVSOP87 so that
	// we can keep Δψ and cε
	s, β, R := solar.TrueVSOP87(e, jde)
	Δψ, Δε := nutation.Nutation(jde)
	a := unit.AngleFromSec(-20.4898).Div(R)
	λ := s + Δψ + a
	ε := nutation.MeanObliquity(jde) + Δε
	sε, cε := ε.Sincos()
	α, _ := coord.EclToEq(λ, β, sε, cε)
	// (28.1) p. 183
	E := L0 - unit.AngleFromDeg(.0057183) - unit.Angle(α) + Δψ.Mul(cε)
	return unit.HourAngle((E + math.Pi).Mod1() - math.Pi)
}
Exemple #18
0
// Aberration returns corrections due to aberration for equatorial
// coordinates of an object.
func Aberration(α, δ, jd float64) (Δα2, Δδ2 float64) {
	ε := nutation.MeanObliquity(jd)
	T := base.J2000Century(jd)
	s, _ := solar.True(T)
	e := solar.Eccentricity(T)
	π := perihelion(T)
	sα, cα := math.Sincos(α)
	sδ, cδ := math.Sincos(δ)
	ss, cs := math.Sincos(s)
	sπ, cπ := math.Sincos(π)
	cε := math.Cos(ε)
	tε := math.Tan(ε)
	q1 := cα * cε
	// (23.3) p. 152
	Δα2 = κ * (e*(q1*cπ+sα*sπ) - (q1*cs + sα*ss)) / cδ
	q2 := cε * (tε*cδ - sα*sδ)
	q3 := cα * sδ
	Δδ2 = κ * (e*(cπ*q2+sπ*q3) - (cs*q2 + ss*q3))
	return
}
Exemple #19
0
// Aberration returns corrections due to aberration for equatorial
// coordinates of an object.
func Aberration(α unit.RA, δ unit.Angle, jd float64) (Δα2 unit.HourAngle, Δδ2 unit.Angle) {
	ε := nutation.MeanObliquity(jd)
	T := base.J2000Century(jd)
	s, _ := solar.True(T)
	e := solar.Eccentricity(T)
	π := perihelion(T)
	sα, cα := α.Sincos()
	sδ, cδ := δ.Sincos()
	ss, cs := s.Sincos()
	sπ, cπ := π.Sincos()
	cε := ε.Cos()
	tε := ε.Tan()
	q1 := cα * cε
	// (23.3) p. 152
	Δα2 = unit.HourAngle(κ.Rad() * (e*(q1*cπ+sα*sπ) - (q1*cs + sα*ss)) / cδ)
	q2 := cε * (tε*cδ - sα*sδ)
	q3 := cα * sδ
	Δδ2 = κ.Mul(e*(cπ*q2+sπ*q3) - (cs*q2 + ss*q3))
	return
}
Exemple #20
0
// Test with proper motion of Regulus, with equatorial motions given
// in Example 21.a, p. 132, and ecliptic motions given in table 21.A,
// p. 138.
func TestEqProperMotionToEcl(t *testing.T) {
	ε := coord.NewObliquity(nutation.MeanObliquity(base.J2000))
	mλ, mβ := eqProperMotionToEcl(
		// eq motions from p. 132.
		unit.NewHourAngle('-', 0, 0, 0.0169),
		unit.NewAngle(' ', 0, 0, 0.006),
		2000.0,
		// eq coordinates from p. 132.
		new(coord.Ecliptic).EqToEcl(&coord.Equatorial{
			RA:  unit.NewRA(10, 8, 22.3),
			Dec: unit.NewAngle(' ', 11, 58, 2),
		}, ε))
	d := math.Abs((mλ - unit.AngleFromSec(-.2348)).Rad() / mλ.Rad())
	if d*169 > 1 { // 169 = significant digits of given lon
		t.Fatal("mλ")
	}
	d = math.Abs((mβ - unit.AngleFromSec(-.0813)).Rad() / mβ.Rad())
	if d*6 > 1 { // 6 = significant digit of given lat
		t.Fatal("mβ")
	}
}
Exemple #21
0
// Test with proper motion of Regulus, with equatorial motions given
// in Example 21.a, p. 132, and ecliptic motions given in table 21.A,
// p. 138.
func TestEqProperMotionToEcl(t *testing.T) {
	ε := coord.NewObliquity(nutation.MeanObliquity(base.J2000))
	mλ, mβ := eqProperMotionToEcl(
		// eq motions from p. 132.
		sexa.NewHourAngle(true, 0, 0, 0.0169).Rad(),
		sexa.NewAngle(false, 0, 0, 0.006).Rad(),
		2000.0,
		// eq coordinates from p. 132.
		new(coord.Ecliptic).EqToEcl(&coord.Equatorial{
			RA:  sexa.NewRA(10, 8, 22.3).Rad(),
			Dec: sexa.NewAngle(false, 11, 58, 2).Rad(),
		}, ε))
	d := math.Abs((mλ - sexa.NewAngle(true, 0, 0, .2348).Rad()) / mλ)
	if d*169 > 1 { // 169 = significant digits of given lon
		t.Fatal("mλ")
	}
	d = math.Abs((mβ - sexa.NewAngle(true, 0, 0, 0.0813).Rad()) / mβ)
	if d*6 > 1 { // 6 = significant digit of given lat
		t.Fatal("mβ")
	}
}
Exemple #22
0
// Ephemeris returns the apparent orientation of the sun at the given jd.
//
// Results:
//	P:  Position angle of the solar north pole.
//	B0: Heliographic latitude of the center of the solar disk.
//	L0: Heliographic longitude of the center of the solar disk.
//
// All results in radians.
func Ephemeris(jd float64, e *pp.V87Planet) (P, B0, L0 float64) {
	θ := (jd - 2398220) * 2 * math.Pi / 25.38
	I := 7.25 * math.Pi / 180
	K := 73.6667*math.Pi/180 +
		1.3958333*math.Pi/180*(jd-2396758)/base.JulianCentury

	L, _, R := solar.TrueVSOP87(e, jd)
	Δψ, Δε := nutation.Nutation(jd)
	ε0 := nutation.MeanObliquity(jd)
	ε := ε0 + Δε
	λ := L - 20.4898/3600*math.Pi/180/R
	λp := λ + Δψ

	sλK, cλK := math.Sincos(λ - K)
	sI, cI := math.Sincos(I)

	tx := -math.Cos(λp) * math.Tan(ε)
	ty := -cλK * math.Tan(I)
	P = math.Atan(tx) + math.Atan(ty)
	B0 = math.Asin(sλK * sI)
	η := math.Atan2(-sλK*cI, -cλK)
	L0 = base.PMod(η-θ, 2*math.Pi)
	return
}
Exemple #23
0
// Ephemeris returns the apparent orientation of the sun at the given jd.
//
// Results:
//	P:  Position angle of the solar north pole.
//	B0: Heliographic latitude of the center of the solar disk.
//	L0: Heliographic longitude of the center of the solar disk.
func Ephemeris(jd float64, e *pp.V87Planet) (P, B0, L0 unit.Angle) {
	θ := unit.Angle((jd - 2398220) * 2 * math.Pi / 25.38)
	I := unit.AngleFromDeg(7.25)
	K := unit.AngleFromDeg(73.6667) +
		unit.AngleFromDeg(1.3958333).Mul((jd-2396758)/base.JulianCentury)

	L, _, R := solar.TrueVSOP87(e, jd)
	Δψ, Δε := nutation.Nutation(jd)
	ε0 := nutation.MeanObliquity(jd)
	ε := ε0 + Δε
	λ := L - unit.AngleFromSec(20.4898).Div(R)
	λp := λ + Δψ

	sλK, cλK := (λ - K).Sincos()
	sI, cI := I.Sincos()

	tx := -(λp.Cos() * ε.Tan())
	ty := -(cλK * I.Tan())
	P = unit.Angle(math.Atan(tx) + math.Atan(ty))
	B0 = unit.Angle(math.Asin(sλK * sI))
	η := unit.Angle(math.Atan2(-sλK*cI, -cλK))
	L0 = (η - θ).Mod1()
	return
}
Exemple #24
0
func newMoon(jde float64) *moon {
	m := &moon{jde: jde}
	// Δψ, F, Ω, p. 372.
	var Δε float64
	m.Δψ, Δε = nutation.Nutation(jde)
	T := base.J2000Century(jde)
	F := base.Horner(T, 93.272095*p, 483202.0175233*p,
		-.0036539*p, -p/3526000, p/863310000)
	m.F = F
	m.Ω = base.Horner(T, 125.0445479*p, -1934.1362891*p, .0020754*p,
		p/467441, -p/60616000)
	// true ecliptic
	m.sε, m.cε = math.Sincos(nutation.MeanObliquity(jde) + Δε)
	// ρ, σ, τ, p. 372,373
	D := base.Horner(T, 297.8501921*p, 445267.1114034*p,
		-.0018819*p, p/545868, -p/113065000)
	M := base.Horner(T, 357.5291092*p, 35999.0502909*p,
		-.0001535*p, p/24490000)
	Mʹ := base.Horner(T, 134.9633964*p, 477198.8675055*p,
		.0087414*p, p/69699, -p/14712000)
	E := base.Horner(T, 1, -.002516, -.0000074)
	K1 := 119.75*p + 131.849*p*T
	K2 := 72.56*p + 20.186*p*T
	m.ρ = -.02752*p*math.Cos(Mʹ) +
		-.02245*p*math.Sin(F) +
		.00684*p*math.Cos(Mʹ-2*F) +
		-.00293*p*math.Cos(2*F) +
		-.00085*p*math.Cos(2*(F-D)) +
		-.00054*p*math.Cos(Mʹ-2*D) +
		-.0002*p*math.Sin(Mʹ+F) +
		-.0002*p*math.Cos(Mʹ+2*F) +
		-.0002*p*math.Cos(Mʹ-F) +
		.00014*p*math.Cos(Mʹ+2*(F-D))
	m.σ = -.02816*p*math.Sin(Mʹ) +
		.02244*p*math.Cos(F) +
		-.00682*p*math.Sin(Mʹ-2*F) +
		-.00279*p*math.Sin(2*F) +
		-.00083*p*math.Sin(2*(F-D)) +
		.00069*p*math.Sin(Mʹ-2*D) +
		.0004*p*math.Cos(Mʹ+F) +
		-.00025*p*math.Sin(2*Mʹ) +
		-.00023*p*math.Sin(Mʹ+2*F) +
		.0002*p*math.Cos(Mʹ-F) +
		.00019*p*math.Sin(Mʹ-F) +
		.00013*p*math.Sin(Mʹ+2*(F-D)) +
		-.0001*p*math.Cos(Mʹ-3*F)
	m.τ = .0252*p*math.Sin(M)*E +
		.00473*p*math.Sin(2*(Mʹ-F)) +
		-.00467*p*math.Sin(Mʹ) +
		.00396*p*math.Sin(K1) +
		.00276*p*math.Sin(2*(Mʹ-D)) +
		.00196*p*math.Sin(m.Ω) +
		-.00183*p*math.Cos(Mʹ-F) +
		.00115*p*math.Sin(Mʹ-2*D) +
		-.00096*p*math.Sin(Mʹ-D) +
		.00046*p*math.Sin(2*(F-D)) +
		-.00039*p*math.Sin(Mʹ-F) +
		-.00032*p*math.Sin(Mʹ-M-D) +
		.00027*p*math.Sin(2*(Mʹ-D)-M) +
		.00023*p*math.Sin(K2) +
		-.00014*p*math.Sin(2*D) +
		.00014*p*math.Cos(2*(Mʹ-F)) +
		-.00012*p*math.Sin(Mʹ-2*F) +
		-.00012*p*math.Sin(2*Mʹ) +
		.00011*p*math.Sin(2*(Mʹ-M-D))
	return m
}
Exemple #25
0
// Physical computes quantities for physical observations of Mars.
//
// Results:
//	DE  planetocentric declination of the Earth.
//	DS  planetocentric declination of the Sun.
//	ω   Areographic longitude of the central meridian, as seen from Earth.
//	P   Geocentric position angle of Mars' northern rotation pole.
//	Q   Position angle of greatest defect of illumination.
//	d   Apparent diameter of Mars.
//	q   Greatest defect of illumination.
//	k   Illuminated fraction of the disk.
func Physical(jde float64, earth, mars *pp.V87Planet) (DE, DS, ω, P, Q, d, q unit.Angle, k float64) {
	// Step 1.
	T := base.J2000Century(jde)
	const p = math.Pi / 180
	// (42.1) p. 288
	λ0 := 352.9065*p + 1.1733*p*T
	β0 := 63.2818*p - .00394*p*T
	// Step 2.
	l0, b0, R := earth.Position(jde)
	l0, b0 = pp.ToFK5(l0, b0, jde)
	// Steps 3, 4.
	sl0, cl0 := l0.Sincos()
	sb0 := b0.Sin()
	Δ := .5 // surely better than 0.
	τ := base.LightTime(Δ)
	var l, b unit.Angle
	var r, x, y, z float64
	f := func() {
		l, b, r = mars.Position(jde - τ)
		l, b = pp.ToFK5(l, b, jde)
		sb, cb := b.Sincos()
		sl, cl := l.Sincos()
		// (42.2) p. 289
		x = r*cb*cl - R*cl0
		y = r*cb*sl - R*sl0
		z = r*sb - R*sb0
		// (42.3) p. 289
		Δ = math.Sqrt(x*x + y*y + z*z)
		τ = base.LightTime(Δ)
	}
	f()
	f()
	// Step 5.
	λ := math.Atan2(y, x)
	β := math.Atan(z / math.Hypot(x, y))
	// Step 6.
	sβ0, cβ0 := math.Sincos(β0)
	sβ, cβ := math.Sincos(β)
	DE = unit.Angle(math.Asin(-sβ0*sβ - cβ0*cβ*math.Cos(λ0-λ)))
	// Step 7.
	N := 49.5581*p + .7721*p*T
	lʹ := l.Rad() - .00697*p/r
	bʹ := b.Rad() - .000225*p*math.Cos(l.Rad()-N)/r
	// Step 8.
	sbʹ, cbʹ := math.Sincos(bʹ)
	DS = unit.Angle(math.Asin(-sβ0*sbʹ - cβ0*cbʹ*math.Cos(λ0-lʹ)))
	// Step 9.
	W := 11.504*p + 350.89200025*p*(jde-τ-2433282.5)
	// Step 10.
	ε0 := nutation.MeanObliquity(jde)
	sε0, cε0 := ε0.Sincos()
	α0, δ0 := coord.EclToEq(unit.Angle(λ0), unit.Angle(β0), sε0, cε0)
	// Step 11.
	u := y*cε0 - z*sε0
	v := y*sε0 + z*cε0
	α := math.Atan2(u, x)
	δ := math.Atan(v / math.Hypot(x, u))
	sδ, cδ := math.Sincos(δ)
	sδ0, cδ0 := δ0.Sincos()
	sα0α, cα0α := math.Sincos(α0.Rad() - α)
	ζ := math.Atan2(sδ0*cδ*cα0α-sδ*cδ0, cδ*sα0α)
	// Step 12.
	ω = unit.Angle(W - ζ).Mod1()
	// Step 13.
	Δψ, Δε := nutation.Nutation(jde)
	// Step 14.
	sl0λ, cl0λ := math.Sincos(l0.Rad() - λ)
	λ += .005693 * p * cl0λ / cβ
	β += .005693 * p * sl0λ * sβ
	// Step 15.
	λ0 += Δψ.Rad()
	λ += Δψ.Rad()
	ε := ε0 + Δε
	// Step 16.
	sε, cε := ε.Sincos()
	α0ʹ, δ0ʹ := coord.EclToEq(unit.Angle(λ0), unit.Angle(β0), sε, cε)
	αʹ, δʹ := coord.EclToEq(unit.Angle(λ), unit.Angle(β), sε, cε)
	// Step 17.
	sδ0ʹ, cδ0ʹ := δ0ʹ.Sincos()
	sδʹ, cδʹ := δʹ.Sincos()
	sα0ʹαʹ, cα0ʹαʹ := (α0ʹ - αʹ).Sincos()
	// (42.4) p. 290
	P = unit.Angle(math.Atan2(cδ0ʹ*sα0ʹαʹ, sδ0ʹ*cδʹ-cδ0ʹ*sδʹ*cα0ʹαʹ))
	if P < 0 {
		P += 2 * math.Pi
	}
	// Step 18.
	s := l0 + math.Pi
	ss, cs := s.Sincos()
	αs := math.Atan2(cε*ss, cs)
	δs := math.Asin(sε * ss)
	sδs, cδs := math.Sincos(δs)
	sαsα, cαsα := math.Sincos(αs - α)
	χ := math.Atan2(cδs*sαsα, sδs*cδ-cδs*sδ*cαsα)
	Q = unit.Angle(χ) + math.Pi
	// Step 19.
	d = unit.AngleFromSec(9.36) / unit.Angle(Δ)
	k = illum.Fraction(r, Δ, R)
	q = d.Mul(1 - k)
	return
}
Exemple #26
0
// Physical computes quantities for physical observations of Jupiter.
//
// Results:
//	DS  Planetocentric declination of the Sun.
//	DE  Planetocentric declination of the Earth.
//	ω1  Longitude of the System I central meridian of the illuminated disk,
//	    as seen from Earth.
//	ω2  Longitude of the System II central meridian of the illuminated disk,
//	    as seen from Earth.
//	P   Geocentric position angle of Jupiter's northern rotation pole.
func Physical(jde float64, earth, jupiter *pp.V87Planet) (DS, DE, ω1, ω2, P unit.Angle) {
	// Step 1.
	d := jde - 2433282.5
	T1 := d / base.JulianCentury
	const p = math.Pi / 180
	α0 := 268*p + .1061*p*T1
	δ0 := 64.5*p - .0164*p*T1
	// Step 2.
	W1 := 17.71*p + 877.90003539*p*d
	W2 := 16.838*p + 870.27003539*p*d
	// Step 3.
	l0, b0, R := earth.Position(jde)
	l0, b0 = pp.ToFK5(l0, b0, jde)
	// Steps 4-7.
	sl0, cl0 := l0.Sincos()
	sb0 := b0.Sin()
	Δ := 4. // surely better than 0.
	var l, b unit.Angle
	var r, x, y, z float64
	f := func() {
		τ := base.LightTime(Δ)
		l, b, r = jupiter.Position(jde - τ)
		l, b = pp.ToFK5(l, b, jde)
		sb, cb := b.Sincos()
		sl, cl := l.Sincos()
		// (42.2) p. 289
		x = r*cb*cl - R*cl0
		y = r*cb*sl - R*sl0
		z = r*sb - R*sb0
		// (42.3) p. 289
		Δ = math.Sqrt(x*x + y*y + z*z)
	}
	f()
	f()
	// Step 8.
	ε0 := nutation.MeanObliquity(jde)
	// Step 9.
	sε0, cε0 := ε0.Sincos()
	sl, cl := l.Sincos()
	sb, cb := b.Sincos()
	αs := math.Atan2(cε0*sl-sε0*sb/cb, cl)
	δs := math.Asin(cε0*sb + sε0*cb*sl)
	// Step 10.
	sδs, cδs := math.Sincos(δs)
	sδ0, cδ0 := math.Sincos(δ0)
	DS = unit.Angle(math.Asin(-sδ0*sδs - cδ0*cδs*math.Cos(α0-αs)))
	// Step 11.
	u := y*cε0 - z*sε0
	v := y*sε0 + z*cε0
	α := math.Atan2(u, x)
	δ := math.Atan(v / math.Hypot(x, u))
	sδ, cδ := math.Sincos(δ)
	sα0α, cα0α := math.Sincos(α0 - α)
	ζ := math.Atan2(sδ0*cδ*cα0α-sδ*cδ0, cδ*sα0α)
	// Step 12.
	DE = unit.Angle(math.Asin(-sδ0*sδ - cδ0*cδ*math.Cos(α0-α)))
	// Step 13.
	ω1 = unit.Angle(W1 - ζ - 5.07033*p*Δ)
	ω2 = unit.Angle(W2 - ζ - 5.02626*p*Δ)
	// Step 14.
	C := unit.Angle((2*r*Δ + R*R - r*r - Δ*Δ) / (4 * r * Δ))
	if (l - l0).Sin() < 0 {
		C = -C
	}
	ω1 = (ω1 + C).Mod1()
	ω2 = (ω2 + C).Mod1()
	// Step 15.
	Δψ, Δε := nutation.Nutation(jde)
	ε := ε0 + Δε
	// Step 16.
	sε, cε := ε.Sincos()
	sα, cα := math.Sincos(α)
	α += .005693 * p * (cα*cl0*cε + sα*sl0) / cδ
	δ += .005693 * p * (cl0*cε*(sε/cε*cδ-sα*sδ) + cα*sδ*sl0)
	// Step 17.
	tδ := sδ / cδ
	Δα := (cε+sε*sα*tδ)*Δψ.Rad() - cα*tδ*Δε.Rad()
	Δδ := sε*cα*Δψ.Rad() + sα*Δε.Rad()
	αʹ := α + Δα
	δʹ := δ + Δδ
	sα0, cα0 := math.Sincos(α0)
	tδ0 := sδ0 / cδ0
	Δα0 := (cε+sε*sα0*tδ0)*Δψ.Rad() - cα0*tδ0*Δε.Rad()
	Δδ0 := sε*cα0*Δψ.Rad() + sα0*Δε.Rad()
	α0ʹ := α0 + Δα0
	δ0ʹ := δ0 + Δδ0
	// Step 18.
	sδʹ, cδʹ := math.Sincos(δʹ)
	sδ0ʹ, cδ0ʹ := math.Sincos(δ0ʹ)
	sα0ʹαʹ, cα0ʹαʹ := math.Sincos(α0ʹ - αʹ)
	// (42.4) p. 290
	P = unit.Angle(math.Atan2(cδ0ʹ*sα0ʹαʹ, sδ0ʹ*cδʹ-cδ0ʹ*sδʹ*cα0ʹαʹ))
	if P < 0 {
		P += 2 * math.Pi
	}
	return
}
Exemple #27
0
func newMoon(jde float64) *moon {
	m := &moon{jde: jde}
	// Δψ, F, Ω, p. 372.
	var Δε unit.Angle
	m.Δψ, Δε = nutation.Nutation(jde)
	T := base.J2000Century(jde)
	m.F = unit.AngleFromDeg(base.Horner(T,
		93.272095, 483202.0175233, -.0036539, -1/3526000, 1/863310000))
	F := m.F.Rad()
	m.Ω = unit.AngleFromDeg(base.Horner(T,
		125.0445479, -1934.1362891, .0020754, 1/467441, -1/60616000))
	// true ecliptic
	m.sε, m.cε = math.Sincos((nutation.MeanObliquity(jde) + Δε).Rad())
	// ρ, σ, τ, p. 372,373
	D := unit.AngleFromDeg(base.Horner(T,
		297.8501921, 445267.1114034, -.0018819, 1/545868, -1/113065000)).Rad()
	M := unit.AngleFromDeg(base.Horner(T,
		357.5291092, 35999.0502909, -.0001535, 1/24490000)).Rad()
	Mʹ := unit.AngleFromDeg(base.Horner(T,
		134.9633964, 477198.8675055, .0087414, 1/69699, -1/14712000)).Rad()
	E := base.Horner(T, 1, -.002516, -.0000074)
	K1 := unit.AngleFromDeg(119.75 + 131.849*T).Rad()
	K2 := unit.AngleFromDeg(72.56 + 20.186*T).Rad()
	m.ρ = unit.AngleFromDeg(-.02752*math.Cos(Mʹ) +
		-.02245*math.Sin(F) +
		.00684*math.Cos(Mʹ-2*F) +
		-.00293*math.Cos(2*F) +
		-.00085*math.Cos(2*(F-D)) +
		-.00054*math.Cos(Mʹ-2*D) +
		-.0002*math.Sin(Mʹ+F) +
		-.0002*math.Cos(Mʹ+2*F) +
		-.0002*math.Cos(Mʹ-F) +
		.00014*math.Cos(Mʹ+2*(F-D)))
	m.σ = unit.AngleFromDeg(-.02816*math.Sin(Mʹ) +
		.02244*math.Cos(F) +
		-.00682*math.Sin(Mʹ-2*F) +
		-.00279*math.Sin(2*F) +
		-.00083*math.Sin(2*(F-D)) +
		.00069*math.Sin(Mʹ-2*D) +
		.0004*math.Cos(Mʹ+F) +
		-.00025*math.Sin(2*Mʹ) +
		-.00023*math.Sin(Mʹ+2*F) +
		.0002*math.Cos(Mʹ-F) +
		.00019*math.Sin(Mʹ-F) +
		.00013*math.Sin(Mʹ+2*(F-D)) +
		-.0001*math.Cos(Mʹ-3*F))
	m.τ = unit.AngleFromDeg(.0252*math.Sin(M)*E +
		.00473*math.Sin(2*(Mʹ-F)) +
		-.00467*math.Sin(Mʹ) +
		.00396*math.Sin(K1) +
		.00276*math.Sin(2*(Mʹ-D)) +
		.00196*math.Sin(m.Ω.Rad()) +
		-.00183*math.Cos(Mʹ-F) +
		.00115*math.Sin(Mʹ-2*D) +
		-.00096*math.Sin(Mʹ-D) +
		.00046*math.Sin(2*(F-D)) +
		-.00039*math.Sin(Mʹ-F) +
		-.00032*math.Sin(Mʹ-M-D) +
		.00027*math.Sin(2*(Mʹ-D)-M) +
		.00023*math.Sin(K2) +
		-.00014*math.Sin(2*D) +
		.00014*math.Cos(2*(Mʹ-F)) +
		-.00012*math.Sin(Mʹ-2*F) +
		-.00012*math.Sin(2*Mʹ) +
		.00011*math.Sin(2*(Mʹ-M-D)))
	return m
}