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,96 @@
|
||||
package basic
|
||||
|
||||
import "math"
|
||||
|
||||
const (
|
||||
orbitReferenceJD = 2451545.0
|
||||
gaussianGravitationalConstant = 0.01720209895 // rad/day
|
||||
lightTimeDaysPerAU = 0.0057755183
|
||||
orbitParabolicTolerance = 1e-12
|
||||
)
|
||||
|
||||
// OrbitElements 日心二体圆锥曲线根数,参考系为 J2000 平黄道/平春分点。
|
||||
// EpochJD 与 TpJD 使用 TT/TDB 对应的儒略日。
|
||||
//
|
||||
// 两种输入形式:
|
||||
// 1. 椭圆经典根数:A/E/I/Omega/W/M0(原有形式)
|
||||
// 2. 近日点形式:Q/E/I/Omega/W/TpJD,用于高偏心、抛物或双曲轨道
|
||||
//
|
||||
// 线性 rates 仅作用于经典根数形式,单位均为“每天变化量”。
|
||||
type OrbitElements struct {
|
||||
EpochJD float64
|
||||
A float64 // 半长径 / semi-major axis in AU.
|
||||
E float64 // 离心率 / eccentricity.
|
||||
I float64 // 轨道倾角 / inclination in degrees.
|
||||
Omega float64 // 升交点黄经 / longitude of ascending node in degrees.
|
||||
W float64 // 近日点幅角 / argument of perihelion in degrees.
|
||||
M0 float64 // 历元平近点角 / mean anomaly at epoch in degrees.
|
||||
Q float64 // 近日点距离 / perihelion distance in AU.
|
||||
TpJD float64 // 近日点通过时刻 / perihelion passage TT/TDB Julian day.
|
||||
|
||||
ADot float64 // 半长径日变化 / daily rate of A in AU/day.
|
||||
EDot float64 // 离心率日变化 / daily rate of E per day.
|
||||
IDot float64 // 倾角日变化 / daily rate of I in deg/day.
|
||||
OmegaDot float64 // 升交点黄经日变化 / daily rate of Omega in deg/day.
|
||||
WDot float64 // 近日点幅角日变化 / daily rate of W in deg/day.
|
||||
MDot float64 // 平近点角日变化 / daily rate of M in deg/day.
|
||||
}
|
||||
|
||||
func (elements OrbitElements) usesPerihelionForm() bool {
|
||||
return isFinitePositive(elements.Q) && isFinite(elements.TpJD)
|
||||
}
|
||||
|
||||
func (elements OrbitElements) validOrientation() bool {
|
||||
angles := [...]float64{elements.I, elements.Omega, elements.W}
|
||||
for _, angle := range angles {
|
||||
if !isFinite(angle) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (elements OrbitElements) validEllipticClassical() bool {
|
||||
if !isFinite(elements.EpochJD) || !isFinitePositive(elements.A) {
|
||||
return false
|
||||
}
|
||||
if !isFinite(elements.E) || elements.E < 0 || elements.E >= 1 {
|
||||
return false
|
||||
}
|
||||
if !isFinite(elements.M0) {
|
||||
return false
|
||||
}
|
||||
return elements.validOrientation()
|
||||
}
|
||||
|
||||
func (elements OrbitElements) validPerihelionForm() bool {
|
||||
if !elements.usesPerihelionForm() {
|
||||
return false
|
||||
}
|
||||
if !isFinite(elements.E) || elements.E < 0 {
|
||||
return false
|
||||
}
|
||||
return elements.validOrientation()
|
||||
}
|
||||
|
||||
func orbitElementsAt(jd float64, elements OrbitElements) OrbitElements {
|
||||
if elements.usesPerihelionForm() || !isFinite(jd) || !isFinite(elements.EpochJD) {
|
||||
return elements
|
||||
}
|
||||
deltaDays := jd - elements.EpochJD
|
||||
updated := elements
|
||||
updated.A += updated.ADot * deltaDays
|
||||
updated.E += updated.EDot * deltaDays
|
||||
updated.I += updated.IDot * deltaDays
|
||||
updated.Omega += updated.OmegaDot * deltaDays
|
||||
updated.W += updated.WDot * deltaDays
|
||||
return updated
|
||||
}
|
||||
|
||||
func isFinite(value float64) bool {
|
||||
return !(math.IsNaN(value) || math.IsInf(value, 0))
|
||||
}
|
||||
|
||||
func isFinitePositive(value float64) bool {
|
||||
return isFinite(value) && value > 0
|
||||
}
|
||||
Reference in New Issue
Block a user