feat: 扩展天文计算能力
- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息 - 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算 - 新增木星伽利略卫星位置、现象与接触事件计算 - 新增恒星星表、星座判定、自行修正与观测辅助能力 - 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包 - 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算 - 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试 - 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试 - 更新中文和英文 README,补充示例、精度说明、SVG 配图
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
. "b612.me/astro/tools"
|
||||
)
|
||||
|
||||
const (
|
||||
VENUS_S_PERIOD = 1 / ((1 / 224.701) - (1 / 365.256363004))
|
||||
venusEventSearchN = 16
|
||||
)
|
||||
|
||||
func venusSunLongitudeDelta(jde float64) float64 {
|
||||
sub := Limit360(VenusApparentLo(jde) - HSunApparentLo(jde))
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub
|
||||
}
|
||||
|
||||
func venusSunLongitudeDeltaN(jde float64, n int) float64 {
|
||||
sub := Limit360(VenusApparentLoN(jde, n) - HSunApparentLoN(jde, n))
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub
|
||||
}
|
||||
|
||||
func venusSunRADelta(jde float64) float64 {
|
||||
sub := Limit360(VenusApparentRa(jde) - SunApparentRa(jde))
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub
|
||||
}
|
||||
|
||||
func venusRADerivative(jde, val float64) float64 {
|
||||
sub := VenusApparentRa(jde+val) - VenusApparentRa(jde-val)
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub / (2 * val)
|
||||
}
|
||||
|
||||
func venusRADerivativeN(jde, val float64, n int) float64 {
|
||||
sub := VenusApparentRaN(jde+val, n) - VenusApparentRaN(jde-val, n)
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub / (2 * val)
|
||||
}
|
||||
|
||||
func venusSunElongationN(jde float64, n int) float64 {
|
||||
lo1, bo1 := VenusApparentLoBoN(jde, n)
|
||||
lo2 := SunApparentLo(jde)
|
||||
bo2 := HSunTrueBoN(jde, n)
|
||||
return StarAngularSeparation(lo1, bo1, lo2, bo2)
|
||||
}
|
||||
|
||||
func venusElongationDerivative(jde, val float64) float64 {
|
||||
sub := VenusSunElongation(jde+val) - VenusSunElongation(jde-val)
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub / (2 * val)
|
||||
}
|
||||
|
||||
func venusElongationDerivativeN(jde, val float64, n int) float64 {
|
||||
sub := venusSunElongationN(jde+val, n) - venusSunElongationN(jde-val, n)
|
||||
if sub > 180 {
|
||||
sub -= 360
|
||||
}
|
||||
if sub < -180 {
|
||||
sub += 360
|
||||
}
|
||||
return sub / (2 * val)
|
||||
}
|
||||
|
||||
func venusConjunction(jde float64, next uint8) float64 {
|
||||
//0=last 1=next
|
||||
nowSub := venusSunLongitudeDeltaN(jde, venusEventSearchN)
|
||||
pos := math.Abs(venusSunLongitudeDeltaN(jde+1/86400.0, venusEventSearchN)) - math.Abs(nowSub)
|
||||
if pos >= 0 && next == 1 && nowSub > 0 {
|
||||
jde += VENUS_S_PERIOD/8.0 + 2
|
||||
}
|
||||
if pos >= 0 && next == 1 && nowSub < 0 {
|
||||
jde += VENUS_S_PERIOD/6.0 + 2
|
||||
}
|
||||
if pos <= 0 && next == 0 && nowSub < 0 {
|
||||
jde -= VENUS_S_PERIOD/8.0 + 2
|
||||
}
|
||||
if pos <= 0 && next == 0 && nowSub > 0 {
|
||||
jde -= VENUS_S_PERIOD/6.0 + 2
|
||||
}
|
||||
for {
|
||||
nowSub := venusSunLongitudeDeltaN(jde, venusEventSearchN)
|
||||
pos := math.Abs(venusSunLongitudeDeltaN(jde+1/86400.0, venusEventSearchN)) - math.Abs(nowSub)
|
||||
if math.Abs(nowSub) > 24 || (pos > 0 && next == 1) || (pos < 0 && next == 0) {
|
||||
if next == 1 {
|
||||
jde += 8
|
||||
} else {
|
||||
jde -= 8
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
JD1 := jde
|
||||
for {
|
||||
JD0 := JD1
|
||||
stDegree := venusSunLongitudeDelta(JD0)
|
||||
stDegreep := (venusSunLongitudeDelta(JD0+0.000005) - venusSunLongitudeDelta(JD0-0.000005)) / 0.00001
|
||||
JD1 = JD0 - stDegree/stDegreep
|
||||
if math.Abs(JD1-JD0) <= 0.00001 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return TD2UT(JD1, false)
|
||||
}
|
||||
|
||||
func LastVenusConjunction(jde float64) float64 {
|
||||
return venusConjunction(jde, 0)
|
||||
}
|
||||
|
||||
func NextVenusConjunction(jde float64) float64 {
|
||||
return venusConjunction(jde, 1)
|
||||
}
|
||||
|
||||
func NextVenusInferiorConjunction(jde float64) float64 {
|
||||
date := NextVenusConjunction(jde)
|
||||
if EarthVenusAway(date) > EarthAway(date) {
|
||||
return NextVenusConjunction(date + 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func NextVenusSuperiorConjunction(jde float64) float64 {
|
||||
date := NextVenusConjunction(jde)
|
||||
if EarthVenusAway(date) < EarthAway(date) {
|
||||
return NextVenusConjunction(date + 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusInferiorConjunction(jde float64) float64 {
|
||||
date := LastVenusConjunction(jde)
|
||||
if EarthVenusAway(date) > EarthAway(date) {
|
||||
return LastVenusConjunction(date - 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusSuperiorConjunction(jde float64) float64 {
|
||||
date := LastVenusConjunction(jde)
|
||||
if EarthVenusAway(date) < EarthAway(date) {
|
||||
return LastVenusConjunction(date - 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func venusRetrograde(jde float64) float64 {
|
||||
//0=last 1=next
|
||||
lastHe := LastVenusConjunction(jde)
|
||||
nextHe := NextVenusConjunction(jde)
|
||||
nowSub := venusSunRADelta(jde)
|
||||
if nowSub > 0 {
|
||||
jde = lastHe + ((nextHe - lastHe) / 5.0 * 3.5)
|
||||
} else {
|
||||
jde = lastHe + 10
|
||||
}
|
||||
for {
|
||||
nowSub := venusRADerivativeN(jde, 1.0/86400.0, venusEventSearchN)
|
||||
if math.Abs(nowSub) > 0.5 {
|
||||
jde += 5
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
JD1 := jde
|
||||
for {
|
||||
JD0 := JD1
|
||||
stDegree := venusRADerivative(JD0, 0.5/86400.0)
|
||||
stDegreep := (venusRADerivative(JD0+10.0/86400.0, 0.5/86400.0) - venusRADerivative(JD0-10.0/86400.0, 0.5/86400.0)) / (20.0 / 86400.0)
|
||||
JD1 = JD0 - stDegree/stDegreep
|
||||
if math.Abs(JD1-JD0) <= 20.0/86400.0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
min := eventZeroRefine(JD1, 10.0/86400.0, 0.5/86400.0, func(jd float64) float64 {
|
||||
return venusRADerivative(jd, 0.5/86400.0)
|
||||
})
|
||||
//fmt.Println((min - lastHe) / (nextHe - lastHe))
|
||||
return TD2UT(min, false)
|
||||
}
|
||||
|
||||
func NextVenusRetrograde(jde float64) float64 {
|
||||
date := venusRetrograde(jde)
|
||||
if date < jde {
|
||||
nextHe := NextVenusConjunction(jde)
|
||||
return venusRetrograde(nextHe + 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusRetrograde(jde float64) float64 {
|
||||
lastHe := LastVenusConjunction(jde)
|
||||
date := venusRetrograde(lastHe + 2)
|
||||
if date > jde {
|
||||
lastLastHe := LastVenusConjunction(lastHe - 2)
|
||||
return venusRetrograde(lastLastHe + 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func NextVenusProgradeToRetrograde(jde float64) float64 {
|
||||
date := NextVenusRetrograde(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub > 180 {
|
||||
return NextVenusRetrograde(date + VENUS_S_PERIOD/2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func NextVenusRetrogradeToPrograde(jde float64) float64 {
|
||||
date := NextVenusRetrograde(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub < 180 {
|
||||
return NextVenusRetrograde(date + 12)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusProgradeToRetrograde(jde float64) float64 {
|
||||
date := LastVenusRetrograde(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub > 180 {
|
||||
return LastVenusRetrograde(date - 12)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusRetrogradeToPrograde(jde float64) float64 {
|
||||
date := LastVenusRetrograde(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub < 180 {
|
||||
return LastVenusRetrograde(date - VENUS_S_PERIOD/2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func VenusSunElongation(jde float64) float64 {
|
||||
lo1, bo1 := VenusApparentLoBo(jde)
|
||||
lo2 := SunApparentLo(jde)
|
||||
bo2 := HSunTrueBo(jde)
|
||||
return StarAngularSeparation(lo1, bo1, lo2, bo2)
|
||||
}
|
||||
|
||||
func venusGreatestElongation(jde float64) float64 {
|
||||
lastHe := LastVenusConjunction(jde)
|
||||
nextHe := NextVenusConjunction(jde)
|
||||
nowSub := venusSunRADelta(jde)
|
||||
if nowSub > 0 {
|
||||
jde = lastHe + ((nextHe - lastHe) / 5.0 * 2.5)
|
||||
} else {
|
||||
jde = lastHe + ((nextHe - lastHe) / 5.0)
|
||||
}
|
||||
for {
|
||||
nowSub := venusElongationDerivativeN(jde, 1.0/86400.0, venusEventSearchN)
|
||||
if math.Abs(nowSub) > 0.15 {
|
||||
jde += 5
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
JD1 := jde
|
||||
for {
|
||||
JD0 := JD1
|
||||
stDegree := venusElongationDerivative(JD0, 2.0/86400.0)
|
||||
stDegreep := (venusElongationDerivative(JD0+15.0/86400.0, 2.0/86400.0) - venusElongationDerivative(JD0-15.0/86400.0, 2.0/86400.0)) / (30.0 / 86400.0)
|
||||
JD1 = JD0 - stDegree/stDegreep
|
||||
if math.Abs(JD1-JD0) <= 30.0/86400.0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
min := eventZeroRefine(JD1, 15.0/86400.0, 0.5/86400.0, func(jd float64) float64 {
|
||||
return venusElongationDerivative(jd, 0.5/86400.0)
|
||||
})
|
||||
//fmt.Println((min - lastHe) / (nextHe - lastHe))
|
||||
return TD2UT(min, false)
|
||||
}
|
||||
|
||||
func NextVenusGreatestElongation(jde float64) float64 {
|
||||
date := venusGreatestElongation(jde)
|
||||
if date < jde {
|
||||
nextHe := NextVenusConjunction(jde)
|
||||
return venusGreatestElongation(nextHe + 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusGreatestElongation(jde float64) float64 {
|
||||
lastHe := LastVenusConjunction(jde)
|
||||
date := venusGreatestElongation(lastHe + 2)
|
||||
if date > jde {
|
||||
lastLastHe := LastVenusConjunction(lastHe - 2)
|
||||
return venusGreatestElongation(lastLastHe + 2)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func NextVenusGreatestElongationEast(jde float64) float64 {
|
||||
date := NextVenusGreatestElongation(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub > 180 {
|
||||
return NextVenusGreatestElongation(date + 1)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func NextVenusGreatestElongationWest(jde float64) float64 {
|
||||
date := NextVenusGreatestElongation(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub < 180 {
|
||||
return NextVenusGreatestElongation(date + 1)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusGreatestElongationEast(jde float64) float64 {
|
||||
date := LastVenusGreatestElongation(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub > 180 {
|
||||
return LastVenusGreatestElongation(date - 1)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func LastVenusGreatestElongationWest(jde float64) float64 {
|
||||
date := LastVenusGreatestElongation(jde)
|
||||
sub := Limit360(VenusApparentRa(date) - SunApparentRa(date))
|
||||
if sub < 180 {
|
||||
return LastVenusGreatestElongation(date - 1)
|
||||
}
|
||||
return date
|
||||
}
|
||||
Reference in New Issue
Block a user