You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
astro/basic/star.go

173 lines
5.1 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package basic
import (
. "b612.me/astro/tools"
"math"
)
// StarHeight 星体的高度角
// 传入 jde时间、瞬时赤经、瞬时赤纬、经度、纬度、时区jde时间应为时区时间
// 返回高度角,单位为度
func StarHeight(jde, ra, dec, lon, lat, timezone float64) float64 {
// 转换为世界时
utcJde := jde - timezone/24.0
// 计算视恒星时
st := Limit360(ApparentSiderealTime(utcJde)*15 + lon)
// 计算时角
H := Limit360(st - ra)
// 高度角、时角与天球座标三角转换公式
// sin(h)=sin(lat)*sin(dec)+cos(dec)*cos(lat)*cos(H)
sinHeight := Sin(lat)*Sin(dec) + Cos(dec)*Cos(lat)*Cos(H)
return ArcSin(sinHeight)
}
//StarAzimuth 星体的方位角
// 传入 jde时间、瞬时赤经、瞬时赤纬、经度、纬度、时区jde时间应为时区时间
// 返回方位角单位为度正北为0度数顺时针增加取值范围[0-360)
func StarAzimuth(jde, ra, dec, lon, lat, timezone float64) float64 {
// 转换为世界时
utcJde := jde - timezone/24.0
// 计算视恒星时
st := Limit360(ApparentSiderealTime(utcJde)*15 + lon)
// 计算时角
H := Limit360(st - ra)
// 三角转换公式
tanAzimuth := Sin(H) / (Cos(H)*Sin(lat) - Tan(dec)*Cos(lat))
Azimuth := ArcTan(tanAzimuth)
if Azimuth < 0 {
if H/15 < 12 {
return Azimuth + 360
}
return Azimuth + 180
}
if H/15 < 12 {
return Azimuth + 180
}
return Azimuth
}
//StarHourAngle 星体的时角
// 传入 jde时间、瞬时赤经、瞬时赤纬、经度、时区jde时间应为时区时间
// 返回时角
func StarHourAngle(jde, ra, lon, timezone float64) float64 {
// 转换为世界时
utcJde := jde - timezone/24.0
// 计算视恒星时
st := Limit360(ApparentSiderealTime(utcJde)*15 + lon)
// 计算时角
return Limit360(st - ra)
}
// MeanSiderealTime 不含章动下的恒星时
func MeanSiderealTime(JD float64) float64 {
T := (JD - 2451545) / 36525
return (Limit360(280.46061837+360.98564736629*(JD-2451545.0)+0.000387933*T*T-T*T*T/38710000) / 15)
}
// ApparentSiderealTime 视恒星时,计算章动
func ApparentSiderealTime(JD float64) float64 {
tmp := MeanSiderealTime(JD)
return tmp + HJZD(JD)*Cos(Sita(JD))/15
}
func StarAngle(RA, DEC, JD, Lon, Lat, TZ float64) float64 {
//JD=JD-8/24+TZ/24;
calcjd := JD - TZ/24
st := Limit360(ApparentSiderealTime(calcjd)*15 + Lon)
H := Limit360(st - RA)
tmp2 := Sin(H) / (Cos(H)*Sin(Lat) - Tan(DEC)*Cos(Lat))
Angle := ArcTan(tmp2)
if Angle < 0 {
if H/15 < 12 {
return Angle + 360
} else {
return Angle + 180
}
} else {
if H/15 < 12 {
return Angle + 180
} else {
return Angle
}
}
}
func StarRiseTime(jde, ra, dec, lon, lat, height, timezone float64, aero bool) float64 {
return StarRiseDownTime(jde, ra, dec, lon, lat, height, timezone, aero, true)
}
func StarDownTime(jde, ra, dec, lon, lat, height, timezone float64, aero bool) float64 {
return StarRiseDownTime(jde, ra, dec, lon, lat, height, timezone, aero, false)
}
func StarRiseDownTime(jde, ra, dec, lon, lat, height, timezone float64, aero, isRise bool) float64 {
//jde 世界时,非力学时,当地时区 0时无需转换力学时
//ra,dec 瞬时天球座标非J2000等时间天球坐标
jde = math.Floor(jde) + 0.5
var An float64 = 0
if aero {
An = -0.566667
}
An = An - HeightDegreeByLat(height, lat)
sct := StarCulminationTime(jde, ra, lon, timezone)
tmp := (Sin(An) - Sin(dec)*Sin(lat)) / (Cos(dec) * Cos(lat))
if math.Abs(tmp) > 1 {
if StarHeight(sct, ra, dec, lon, lat, timezone) < 0 {
return -2 //极夜
} else {
return -1 //极昼
}
}
var JD1 float64
if isRise {
JD1 = sct - ArcCos(tmp)/15.0/24.0
} else {
JD1 = sct + ArcCos(tmp)/15.0/24.0
}
for {
JD0 := JD1
stDegree := StarHeight(JD0, ra, dec, lon, lat, timezone) - An
stDegreep := (StarHeight(JD0+0.000005, ra, dec, lon, lat, timezone) - StarHeight(JD0-0.000005, ra, dec, lon, lat, timezone)) / 0.00001
JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00001 {
break
}
}
return JD1
}
func StarCulminationTime(jde, ra, lon, timezone float64) float64 {
//jde 世界时,非力学时,当地时区 0时无需转换力学时
//ra,dec 瞬时天球座标非J2000等时间天球坐标
jde = math.Floor(jde) + 0.5
JD1 := jde + Limit360(360-StarHourAngle(jde, ra, lon, timezone))/15.0/24.0*0.99726851851851851851
limitStarHA := func(jde, ra, lon, timezone float64) float64 {
ha := StarHourAngle(jde, ra, lon, timezone)
if ha < 180 {
ha += 360
}
return ha
}
for {
JD0 := JD1
stDegree := limitStarHA(JD0, ra, lon, timezone) - 360
stDegreep := (limitStarHA(JD0+0.000005, ra, lon, timezone) - limitStarHA(JD0-0.000005, ra, lon, timezone)) / 0.00001
JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00001 {
break
}
}
return JD1
}
func StarAngularSeparation(ra1, dec1, ra2, dec2 float64) float64 {
//cos(d)=sinδ1 sinδ2 + cosδ1 cosδ2 cos(α1-α2)
d := Sin(dec1)*Sin(dec2) + Cos(dec1)*Cos(dec2)*Cos(ra1-ra2)
if math.Abs(d) >= 0.999999997 {
//d = √(Δα*cosδ)2+(Δδ)2
tmp1 := ((ra1 - ra2) * Cos((dec1+dec2)/2))
tmp2 := (dec1 - dec2)
return math.Sqrt(tmp1*tmp1 + tmp2*tmp2)
}
return ArcCos(d)
}