astro/basic/refraction.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

90 lines
3.3 KiB
Go

package basic
import "math"
const (
refractionStandardPressureHPa = 1010.0
refractionStandardTemperatureK = 283.0
refractionAbsoluteZeroC = -273.15
refractionLowerLimitAltitudeDeg = -5.0
refractionUpperLimitAltitudeDeg = 90.0
)
// RefractionFromApparentAltitude 大气折射修正量,单位度;输入为视高度角。
// 返回值应从真高度角加上后得到视高度角。
func RefractionFromApparentAltitude(apparentAltitude, pressureHPa, temperatureC float64) float64 {
if !validRefractionInputs(apparentAltitude, pressureHPa, temperatureC) {
return math.NaN()
}
if apparentAltitude < refractionLowerLimitAltitudeDeg || apparentAltitude > refractionUpperLimitAltitudeDeg {
return 0
}
angle := (apparentAltitude + 10.3/(apparentAltitude+5.11)) * math.Pi / 180
return refractionScale(pressureHPa, temperatureC) * (1.02 / math.Tan(angle)) / 60
}
// TrueAltitude 真高度角,单位度;输入为视高度角。
func TrueAltitude(apparentAltitude, pressureHPa, temperatureC float64) float64 {
refraction := RefractionFromApparentAltitude(apparentAltitude, pressureHPa, temperatureC)
if math.IsNaN(refraction) {
return math.NaN()
}
return apparentAltitude - refraction
}
// ApparentAltitude 视高度角,单位度;输入为真高度角。
func ApparentAltitude(trueAltitude, pressureHPa, temperatureC float64) float64 {
if !validRefractionInputs(trueAltitude, pressureHPa, temperatureC) {
return math.NaN()
}
if trueAltitude < refractionLowerLimitAltitudeDeg || trueAltitude > refractionUpperLimitAltitudeDeg {
return trueAltitude
}
estimate := trueAltitude + RefractionFromApparentAltitude(trueAltitude, pressureHPa, temperatureC)
for i := 0; i < 8; i++ {
refraction := RefractionFromApparentAltitude(estimate, pressureHPa, temperatureC)
if math.IsNaN(refraction) {
return math.NaN()
}
value := estimate - refraction - trueAltitude
if math.Abs(value) < 1e-12 {
break
}
const delta = 1e-6
refractionPlus := RefractionFromApparentAltitude(estimate+delta, pressureHPa, temperatureC)
refractionMinus := RefractionFromApparentAltitude(estimate-delta, pressureHPa, temperatureC)
if math.IsNaN(refractionPlus) || math.IsNaN(refractionMinus) {
return math.NaN()
}
derivative := 1 - (refractionPlus-refractionMinus)/(2*delta)
if derivative == 0 {
break
}
estimate -= value / derivative
}
return estimate
}
// RefractionFromTrueAltitude 大气折射修正量,单位度;输入为真高度角。
// 返回值应从真高度角加上后得到视高度角。
func RefractionFromTrueAltitude(trueAltitude, pressureHPa, temperatureC float64) float64 {
apparentAltitude := ApparentAltitude(trueAltitude, pressureHPa, temperatureC)
if math.IsNaN(apparentAltitude) {
return math.NaN()
}
return apparentAltitude - trueAltitude
}
func validRefractionInputs(altitude, pressureHPa, temperatureC float64) bool {
return !(math.IsNaN(altitude) || math.IsInf(altitude, 0) ||
math.IsNaN(pressureHPa) || math.IsInf(pressureHPa, 0) || pressureHPa <= 0 ||
math.IsNaN(temperatureC) || math.IsInf(temperatureC, 0) || temperatureC <= refractionAbsoluteZeroC)
}
func refractionScale(pressureHPa, temperatureC float64) float64 {
return pressureHPa / refractionStandardPressureHPa * refractionStandardTemperatureK / (273 + temperatureC)
}