feat: 完善日月食与月掩几何链路并扩展历法接口
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
This commit is contained in:
+43
-11
@@ -54,8 +54,24 @@ func MoonCalcNew(coordIndex int, jd float64) float64 {
|
||||
}
|
||||
|
||||
func MoonCalcNewN(coordIndex int, jd float64, n int) float64 {
|
||||
rad := 180.0 * 3600.0 / math.Pi
|
||||
t := (jd - 2451545.0) / 36525.0
|
||||
return moonCalcNewN(coordIndex, jd, n)
|
||||
}
|
||||
|
||||
// moonPhaseCompensationThreshold 是启用线性相位补偿的最小 |t|(世纪数)倒数尺度:
|
||||
// 更小的项本身已低于纳角秒级相位舍入,无需补偿。
|
||||
const moonPhaseCompensationThreshold = 1e6
|
||||
|
||||
func moonCalcNewN(coordIndex int, jd float64, n int) float64 {
|
||||
arcsecPerRadian := 180.0 * 3600.0 / math.Pi
|
||||
// Preserve the low parts of both the epoch subtraction and century division.
|
||||
days := jd - 2451545.0
|
||||
origin := days - jd
|
||||
daysLow := (jd - (days - origin)) - (2451545 + origin)
|
||||
t := days / 36525.0
|
||||
tLow := (math.FMA(-t, 36525, days) + daysLow) / 36525
|
||||
// Small angular terms have sub-nanoarcsecond phase roundoff already.
|
||||
// Compensate only the larger terms; distance needs no angular precision.
|
||||
phaseThreshold := moonPhaseCompensationThreshold / math.Abs(t)
|
||||
ob := moonCir[coordIndex]
|
||||
var v float64
|
||||
var tn float64 = 1
|
||||
@@ -65,8 +81,11 @@ func MoonCalcNewN(coordIndex int, jd float64, n int) float64 {
|
||||
t5 := t4 * t
|
||||
tx := t - 10
|
||||
if coordIndex == 0 {
|
||||
v += (3.81034409 + 8399.684730072*t - 3.319e-05*t2 + 3.11e-08*t3 - 2.033e-10*t4) * rad //月球平黄经(弧度)
|
||||
v += 5028.792262*t + 1.1124406*t2 + 0.00007699*t3 - 0.000023479*t4 - 0.0000000178*t5 //岁差(角秒)
|
||||
// 黄经线性项必须始终走补偿版本:MoonCalcNew 与 HMoonTrueLo 是同一个物理量的两个入口,
|
||||
// 只在其中一个入口补偿会让两者差约 1e-9 度。
|
||||
longitude := moonReducedLinearPhase(3.81034409, 8399.684730072, t, tLow)
|
||||
v += (longitude - 3.319e-05*t2 + 3.11e-08*t3 - 2.033e-10*t4) * arcsecPerRadian
|
||||
v += 5028.792262*t + 1.1124406*t2 + 0.00007699*t3 - 0.000023479*t4 - 0.0000000178*t5 //岁差(角秒)
|
||||
if tx > 0 {
|
||||
v += -0.866 + 1.43*tx + 0.054*tx*tx //对公元3000年至公元5000年的拟合,最大误差小于10角秒
|
||||
}
|
||||
@@ -80,6 +99,7 @@ func MoonCalcNewN(coordIndex int, jd float64, n int) float64 {
|
||||
}
|
||||
for i := 0; i < len(ob); i++ {
|
||||
F := ob[i]
|
||||
seriesPhaseThreshold := phaseThreshold / math.Abs(tn)
|
||||
N := math.Floor(float64(nScalars*len(F))/float64(len(ob[0])) + 0.5)
|
||||
if i != 0 {
|
||||
N += 6
|
||||
@@ -89,23 +109,37 @@ func MoonCalcNewN(coordIndex int, jd float64, n int) float64 {
|
||||
}
|
||||
var c float64 = 0
|
||||
for j := 0; float64(j) < N; j += 6 {
|
||||
c += F[j] * math.Cos(F[j+1]+t*F[j+2]+t2*F[j+3]+t3*F[j+4]+t4*F[j+5])
|
||||
phase := F[j+1] + t*F[j+2]
|
||||
if coordIndex != 2 && math.Abs(F[j]*F[j+2]) > seriesPhaseThreshold {
|
||||
phase = moonReducedLinearPhase(F[j+1], F[j+2], t, tLow)
|
||||
}
|
||||
c += F[j] * math.Cos(phase+t2*F[j+3]+t3*F[j+4]+t4*F[j+5])
|
||||
}
|
||||
v += c * tn
|
||||
tn *= t
|
||||
}
|
||||
if coordIndex != 2 {
|
||||
v /= rad
|
||||
v /= arcsecPerRadian
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Keep the small phase increment out of the rounded secular product. The
|
||||
// low part of 2*pi also prevents a range-reduction jump at full revolutions.
|
||||
func moonReducedLinearPhase(offset, rate, t, tLow float64) float64 {
|
||||
const twoPiLow = 2.4492935982947064e-16
|
||||
product := rate * t
|
||||
roundoff := math.FMA(rate, t, -product) + rate*tLow
|
||||
turns := math.Round(product / (2 * math.Pi))
|
||||
return math.FMA(-turns, 2*math.Pi, product) + (roundoff - turns*twoPiLow) + offset
|
||||
}
|
||||
|
||||
func HMoonTrueLo(jd float64) float64 { //计算月亮
|
||||
return HMoonTrueLoN(jd, -1)
|
||||
}
|
||||
|
||||
func HMoonTrueLoN(jd float64, n int) float64 { //计算月亮
|
||||
v := MoonCalcNewN(0, jd, n) * 180 / math.Pi
|
||||
v := moonCalcNewN(0, jd, n) * 180 / math.Pi
|
||||
return Limit360(v)
|
||||
}
|
||||
|
||||
@@ -234,10 +268,8 @@ func HMoonTrueRaN(jd float64, n int) float64 {
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
传入世界时
|
||||
*/
|
||||
* HMoonApparentRaDec 本地民用时下的月球视赤道坐标;jd 是本地民用时(内部按 jd-tz/24 换算 UT),不是世界时
|
||||
*/
|
||||
func HMoonApparentRaDec(jd, lon, lat, tz float64) (float64, float64) {
|
||||
return HMoonApparentRaDecN(jd, lon, lat, tz, -1)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user