044f2f4381
- 新增半解析、旧模型、自定义与多源堆叠星历实例,提供 Context、Instance、SPK 读取及状态与视位置计算 - 统一太阳、月球和行星实例接口,扩展黄经穿越、留、相位、最近角距、偕日可见、任意高度升落、轨道节点及凌日等天象查询 - 完善日月食、月掩与凌日的月缘剖面、有限盘面接触、站心修正、局地可见性、全球路径和地图输出 - 新增 SVG、GeoJSON、KML 天象输出及凌日、月掩和月缘地形相关缓存与几何求解 - 新增恒星星表导入与查询,支持 CSV、Hipparcos、BSC5、Stellarium 等格式及名称、交叉标识、锥面检索和星等过滤 - 补充 IAU 2006、地球定向、折射消光、大气观测、轨道传播及半解析行星/月球数据支持 - 将默认未来民用时标切换为 TimeScaleLeapHour,更新 2027–2400 农历速查表、中文日期解析和时区边界处理 - 增加事件基线、跨模型回归、几何边界、月缘地形和输出契约测试,完善中英文手册、示例资源、NOTICE 与忽略规则
158 lines
5.1 KiB
Go
158 lines
5.1 KiB
Go
package basic
|
||
|
||
import (
|
||
"math"
|
||
|
||
. "b612.me/astro/tools"
|
||
)
|
||
|
||
/*
|
||
* 坐标变换,黄道转赤道
|
||
*/
|
||
func LoToRa(jde, lo, bo float64) float64 {
|
||
eps := TrueObliquity(jde)
|
||
ra := math.Atan2(Sin(lo)*Cos(eps)-Tan(bo)*Sin(eps), Cos(lo))
|
||
ra = ra * 180 / math.Pi
|
||
if ra < 0 {
|
||
ra += 360
|
||
}
|
||
return ra
|
||
}
|
||
|
||
func BoToDec(jde, lo, bo float64) float64 {
|
||
eps := TrueObliquity(jde)
|
||
dec := ArcSin(Sin(bo)*Cos(eps) + Cos(bo)*Sin(eps)*Sin(lo))
|
||
return dec
|
||
}
|
||
|
||
func LoBoToRaDec(jde, lo, bo float64) (float64, float64) {
|
||
eps := TrueObliquity(jde)
|
||
sinEps := Sin(eps)
|
||
cosEps := Cos(eps)
|
||
dec := ArcSin(Sin(bo)*cosEps + Cos(bo)*sinEps*Sin(lo))
|
||
ra := math.Atan2(Sin(lo)*cosEps-Tan(bo)*sinEps, Cos(lo))
|
||
ra = ra * 180 / math.Pi
|
||
if ra < 0 {
|
||
ra += 360
|
||
}
|
||
return ra, dec
|
||
}
|
||
|
||
func RaDecToLoBo(jde, ra, dec float64) (float64, float64) {
|
||
//tan(λ) = (sin(α)*cos(ε) + tan(δ)*sin(ε)) / cos(α)
|
||
//sin(β)=sin(δ)*cos(ε)-cos(δ)*sin(ε)*sin(α)
|
||
eps := TrueObliquity(jde)
|
||
sinBo := Sin(dec)*Cos(eps) - Cos(dec)*Sin(eps)*Sin(ra)
|
||
lo := math.Atan2((Sin(ra)*Cos(eps) + Tan(dec)*Sin(eps)), Cos(ra))
|
||
lo = Limit360(lo * 180 / math.Pi)
|
||
return lo, ArcSin(sinBo)
|
||
}
|
||
|
||
func RaToLo(jde, ra, dec float64) float64 {
|
||
//tan(λ) = (sin(α)*cos(ε) + tan(δ)*sin(ε)) / cos(α)
|
||
//sin(β)=sin(δ)*cos(ε)-cos(δ)*sin(ε)*sin(α)
|
||
eps := TrueObliquity(jde)
|
||
lo := math.Atan2((Sin(ra)*Cos(eps) + Tan(dec)*Sin(eps)), Cos(ra))
|
||
lo = Limit360(lo * 180 / math.Pi)
|
||
return lo
|
||
}
|
||
|
||
func DecToBo(jde, ra, dec float64) float64 {
|
||
//tan(λ) = (sin(α)*cos(ε) + tan(δ)*sin(ε)) / cos(α)
|
||
//sin(β)=sin(δ)*cos(ε)-cos(δ)*sin(ε)*sin(α)
|
||
eps := TrueObliquity(jde)
|
||
sinBo := Sin(dec)*Cos(eps) - Cos(dec)*Sin(eps)*Sin(ra)
|
||
return ArcSin(sinBo)
|
||
}
|
||
|
||
/*
|
||
* 地心坐标转站心坐标,参数分别为,地心赤经赤纬 纬度经度,jde,离地心位置au
|
||
*/
|
||
// 站心视差沿用的旧地球椭球,与 geodata 的赤道半径不同,不可混用。
|
||
const (
|
||
topocentricEarthRadiusKM = 6378.14
|
||
topocentricEarthPolarRadiusKM = 6356.755
|
||
)
|
||
|
||
func pcosi(lat, h float64) float64 {
|
||
b := topocentricEarthPolarRadiusKM
|
||
a := topocentricEarthRadiusKM
|
||
u := ArcTan(b / a * Tan(lat))
|
||
//psin=b/a*Sin(u)+h/(topocentricEarthRadiusKM*1000)*Sin(lat);
|
||
pcos := Cos(u) + h/(topocentricEarthRadiusKM*1000)*Cos(lat)
|
||
return pcos
|
||
}
|
||
func psini(lat, h float64) float64 {
|
||
b := topocentricEarthPolarRadiusKM
|
||
a := topocentricEarthRadiusKM
|
||
u := ArcTan(b / a * Tan(lat))
|
||
psin := b/a*Sin(u) + h/(topocentricEarthRadiusKM*1000)*Sin(lat)
|
||
//pcos=Cos(u)+h/(topocentricEarthRadiusKM*1000)*Cos(lat);
|
||
return psin
|
||
}
|
||
|
||
func TopocentricRaDec(ra, dec, lat, lon, jd, au, h float64) (float64, float64) {
|
||
return topocentricRaDecWithSidereal(ra, dec, lat, lon, ApparentSiderealTime(UTC2UT1(jd))*15, au, h)
|
||
}
|
||
|
||
func topocentricRaDecWithSidereal(ra, dec, lat, lon, siderealDegrees, au, h float64) (float64, float64) {
|
||
sinpi := Sin(0.0024427777777) / au
|
||
pcosi := pcosi(lat, h)
|
||
psini := psini(lat, h)
|
||
tH := Limit360(siderealDegrees + lon - ra)
|
||
nra := math.Atan2(-pcosi*sinpi*Sin(tH), (Cos(dec)-pcosi*sinpi*Cos(tH))) * 180 / math.Pi
|
||
|
||
ndec := math.Atan2((Sin(dec)-psini*sinpi)*Cos(nra), (Cos(dec)-pcosi*sinpi*Cos(tH))) * 180 / math.Pi
|
||
return ra + nra, ndec
|
||
}
|
||
|
||
func TopocentricRa(ra, dec, lat, lon, jd, au, h float64) float64 { //jd为格林尼治标准时
|
||
topocentricRA, _ := TopocentricRaDec(ra, dec, lat, lon, jd, au, h)
|
||
return topocentricRA
|
||
}
|
||
func TopocentricDec(ra, dec, lat, lon, jd, au, h float64) float64 { //jd为格林尼治标准时
|
||
_, topocentricDec := TopocentricRaDec(ra, dec, lat, lon, jd, au, h)
|
||
return topocentricDec
|
||
}
|
||
|
||
// TopocentricLoBo 一次求值给出站心黄经与黄纬 / topocentric ecliptic longitude and latitude in one solve.
|
||
//
|
||
// 先解站心赤道坐标再转黄道:黄道版公式的分母在黄经 90°–270° 时变号,直接 atan2 会切到对顶象限。
|
||
func TopocentricLoBo(lo, bo, lat, lon, jde, au, h float64) (float64, float64) {
|
||
ra, dec := LoBoToRaDec(jde, lo, bo)
|
||
topRA, topDec := TopocentricRaDec(ra, dec, lat, lon, jde, au, h)
|
||
return RaDecToLoBo(jde, topRA, topDec)
|
||
}
|
||
|
||
// TopocentricLo 站心黄经 / topocentric ecliptic longitude.
|
||
func TopocentricLo(lo, bo, lat, lon, jde, au, h float64) float64 {
|
||
nlo, _ := TopocentricLoBo(lo, bo, lat, lon, jde, au, h)
|
||
return nlo
|
||
}
|
||
|
||
// TopocentricBo 站心黄纬 / topocentric ecliptic latitude.
|
||
func TopocentricBo(lo, bo, lat, lon, jde, au, h float64) float64 {
|
||
_, nbo := TopocentricLoBo(lo, bo, lat, lon, jde, au, h)
|
||
return nbo
|
||
}
|
||
|
||
// GXCLoWithInstance 用指定星历实例求值;inst 为 nil 时用进程当前模型 / evaluation with an explicit instance; nil uses the process model.
|
||
func GXCLoWithInstance(lo, bo, jde float64, inst *Instance) float64 { //光行差修正
|
||
k := 20.49552
|
||
sunlo := SunTrueLoWithInstance(jde, inst)
|
||
e := Earthe(jde)
|
||
epi := EarthPI(jde)
|
||
tmp := (-k*Cos(sunlo-lo) + e*k*Cos(epi-lo)) / Cos(bo)
|
||
return tmp
|
||
}
|
||
|
||
// GXCBoWithInstance 用指定星历实例求值;inst 为 nil 时用进程当前模型 / evaluation with an explicit instance; nil uses the process model.
|
||
func GXCBoWithInstance(lo, bo, jde float64, inst *Instance) float64 {
|
||
k := 20.49552
|
||
sunlo := SunTrueLoWithInstance(jde, inst)
|
||
e := Earthe(jde)
|
||
epi := EarthPI(jde)
|
||
tmp := -k * Sin(bo) * (Sin(sunlo-lo) - e*Sin(epi-lo))
|
||
return tmp
|
||
}
|