astro/basic/venus.go
starainrt 3ffdbe0034
feat: 扩展天文计算能力
- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息
- 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算
- 新增木星伽利略卫星位置、现象与接触事件计算
- 新增恒星星表、星座判定、自行修正与观测辅助能力
- 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包
- 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算
- 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试
- 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试
- 更新中文和英文 README,补充示例、精度说明、SVG 配图
2026-05-01 22:38:44 +08:00

230 lines
6.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package basic
import (
"math"
"b612.me/astro/planet"
. "b612.me/astro/tools"
)
func VenusL(jd float64) float64 {
return planet.WherePlanet(2, 0, jd)
}
func VenusB(jd float64) float64 {
return planet.WherePlanet(2, 1, jd)
}
func VenusR(jd float64) float64 {
return planet.WherePlanet(2, 2, jd)
}
func AVenusX(jd float64) float64 {
l := VenusL(jd)
b := VenusB(jd)
r := VenusR(jd)
el := planet.WherePlanet(-1, 0, jd)
eb := planet.WherePlanet(-1, 1, jd)
er := planet.WherePlanet(-1, 2, jd)
x := r*Cos(b)*Cos(l) - er*Cos(eb)*Cos(el)
return x
}
func AVenusY(jd float64) float64 {
l := VenusL(jd)
b := VenusB(jd)
r := VenusR(jd)
el := planet.WherePlanet(-1, 0, jd)
eb := planet.WherePlanet(-1, 1, jd)
er := planet.WherePlanet(-1, 2, jd)
y := r*Cos(b)*Sin(l) - er*Cos(eb)*Sin(el)
return y
}
func AVenusZ(jd float64) float64 {
//l := VenusL(jd)
b := VenusB(jd)
r := VenusR(jd)
// el := planet.WherePlanet(-1, 0, jd)
eb := planet.WherePlanet(-1, 1, jd)
er := planet.WherePlanet(-1, 2, jd)
z := r*Sin(b) - er*Sin(eb)
return z
}
func AVenusXYZ(jd float64) (float64, float64, float64) {
l := VenusL(jd)
b := VenusB(jd)
r := VenusR(jd)
el := planet.WherePlanet(-1, 0, jd)
eb := planet.WherePlanet(-1, 1, jd)
er := planet.WherePlanet(-1, 2, jd)
x := r*Cos(b)*Cos(l) - er*Cos(eb)*Cos(el)
y := r*Cos(b)*Sin(l) - er*Cos(eb)*Sin(el)
z := r*Sin(b) - er*Sin(eb)
return x, y, z
}
func VenusApparentRa(jd float64) float64 {
lo, bo := VenusApparentLoBo(jd)
eps := TrueObliquity(jd)
ra := math.Atan2((Sin(lo)*Cos(eps) - Tan(bo)*Sin(eps)), Cos(lo))
ra = ra * 180 / math.Pi
return Limit360(ra)
}
func VenusApparentDec(jd float64) float64 {
lo, bo := VenusApparentLoBo(jd)
eps := TrueObliquity(jd)
dec := ArcSin(Sin(bo)*Cos(eps) + Cos(bo)*Sin(eps)*Sin(lo))
return dec
}
func VenusApparentRaDec(jd float64) (float64, float64) {
lo, bo := VenusApparentLoBo(jd)
eps := TrueObliquity(jd)
ra := math.Atan2((Sin(lo)*Cos(eps) - Tan(bo)*Sin(eps)), Cos(lo))
ra = ra * 180 / math.Pi
dec := ArcSin(Sin(bo)*Cos(eps) + Cos(bo)*Sin(eps)*Sin(lo))
return Limit360(ra), dec
}
func EarthVenusAway(jd float64) float64 {
x, y, z := AVenusXYZ(jd)
to := math.Sqrt(x*x + y*y + z*z)
return to
}
func VenusApparentLo(jd float64) float64 {
x, y, z := AVenusXYZ(jd)
to := 0.0057755183 * math.Sqrt(x*x+y*y+z*z)
x, y, z = AVenusXYZ(jd - to)
lo := math.Atan2(y, x)
bo := math.Atan2(z, math.Sqrt(x*x+y*y))
lo = lo * 180 / math.Pi
bo = bo * 180 / math.Pi
lo = Limit360(lo)
//lo-=GXCLo(lo,bo,jd)/3600;
//bo+=GXCBo(lo,bo,jd);
lo += Nutation2000Bi(jd)
return lo
}
func VenusApparentBo(jd float64) float64 {
x, y, z := AVenusXYZ(jd)
to := 0.0057755183 * math.Sqrt(x*x+y*y+z*z)
x, y, z = AVenusXYZ(jd - to)
//lo := math.Atan2(y, x)
bo := math.Atan2(z, math.Sqrt(x*x+y*y))
//lo = lo * 180 / math.Pi
bo = bo * 180 / math.Pi
//lo+=GXCLo(lo,bo,jd);
//bo+=GXCBo(lo,bo,jd)/3600;
//lo+=Nutation2000Bi(jd);
return bo
}
func VenusApparentLoBo(jd float64) (float64, float64) {
x, y, z := AVenusXYZ(jd)
to := 0.0057755183 * math.Sqrt(x*x+y*y+z*z)
x, y, z = AVenusXYZ(jd - to)
lo := math.Atan2(y, x)
bo := math.Atan2(z, math.Sqrt(x*x+y*y))
lo = lo * 180 / math.Pi
bo = bo * 180 / math.Pi
lo = Limit360(lo)
//lo-=GXCLo(lo,bo,jd)/3600;
//bo+=GXCBo(lo,bo,jd);
lo += Nutation2000Bi(jd)
return lo, bo
}
func VenusMag(jd float64) float64 {
sunDistance := VenusR(jd)
earthDistance := EarthVenusAway(jd)
earthSunDistance := planet.WherePlanet(-1, 2, jd)
i := (sunDistance*sunDistance + earthDistance*earthDistance - earthSunDistance*earthSunDistance) / (2 * sunDistance * earthDistance)
i = ArcCos(i)
mag := -4.40 + 5*math.Log10(sunDistance*earthDistance) + 0.0009*i + 0.000239*i*i - 0.00000065*i*i*i
return FloatRound(mag, 2)
}
func VenusHeight(jde, lon, lat, timezone float64) float64 {
// 转换为世界时
utcJde := jde - timezone/24.0
// 计算视恒星时
ra, dec := VenusApparentRaDec(TD2UT(utcJde, true))
st := Limit360(ApparentSiderealTime(utcJde)*15 + lon)
// 计算时角
hourAngle := Limit360(st - ra)
// 高度角、时角与天球座标三角转换公式
// sin(h)=sin(lat)*sin(dec)+cos(dec)*cos(lat)*cos(hourAngle)
sinHeight := Sin(lat)*Sin(dec) + Cos(dec)*Cos(lat)*Cos(hourAngle)
return ArcSin(sinHeight)
}
func VenusAzimuth(jde, lon, lat, timezone float64) float64 {
// 转换为世界时
utcJde := jde - timezone/24.0
// 计算视恒星时
ra, dec := VenusApparentRaDec(TD2UT(utcJde, true))
st := Limit360(ApparentSiderealTime(utcJde)*15 + lon)
// 计算时角
hourAngle := Limit360(st - ra)
// 三角转换公式
tanAzimuth := Sin(hourAngle) / (Cos(hourAngle)*Sin(lat) - Tan(dec)*Cos(lat))
azimuth := ArcTan(tanAzimuth)
if azimuth < 0 {
if hourAngle/15 < 12 {
return azimuth + 360
}
return azimuth + 180
}
if hourAngle/15 < 12 {
return azimuth + 180
}
return azimuth
}
func VenusHourAngle(jd, lon, tz float64) float64 {
startime := Limit360(ApparentSiderealTime(jd-tz/24)*15 + lon)
timeangle := startime - VenusApparentRa(TD2UT(jd-tz/24.0, true))
if timeangle < 0 {
timeangle += 360
}
return timeangle
}
func VenusCulminationTime(jde, lon, timezone float64) float64 {
//jde 世界时,非力学时,当地时区 0时无需转换力学时
//ra,dec 瞬时天球座标非J2000等时间天球坐标
jde = math.Floor(jde) + 0.5
estimateJD := jde + Limit360(360-VenusHourAngle(jde, lon, timezone))/15.0/24.0*0.99726851851851851851
limitHA := func(jde, lon, timezone float64) float64 {
ha := VenusHourAngle(jde, lon, timezone)
if ha < 180 {
ha += 360
}
return ha
}
for {
prevJD := estimateJD
stDegree := limitHA(prevJD, lon, timezone) - 360
stDegreep := (limitHA(prevJD+0.000005, lon, timezone) - limitHA(prevJD-0.000005, lon, timezone)) / 0.00001
estimateJD = prevJD - stDegree/stDegreep
if math.Abs(estimateJD-prevJD) <= 0.00001 {
break
}
}
return estimateJD
}
func VenusRiseTime(jd, lon, lat, tz, aeroCorrection, observerHeight float64) (float64, error) {
return venusRiseDown(jd, lon, lat, tz, aeroCorrection, observerHeight, true)
}
func VenusSetTime(jd, lon, lat, tz, aeroCorrection, observerHeight float64) (float64, error) {
return venusRiseDown(jd, lon, lat, tz, aeroCorrection, observerHeight, false)
}
func venusRiseDown(jd, lon, lat, tz, aeroCorrection, observerHeight float64, isRise bool) (float64, error) {
return planetRiseDown(jd, lon, lat, tz, aeroCorrection, observerHeight, isRise, VenusCulminationTime, VenusHeight, VenusApparentDec)
}