improve rise/down calc

master
兔子 3 years ago
parent c5f34d3ab8
commit 7604fabf8f
Signed by: b612
GPG Key ID: 481225A74DEB62A1

@ -1443,19 +1443,36 @@ func GetMoonRiseTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
if math.Abs(now-180) > 0.5 { if math.Abs(now-180) > 0.5 {
JD1 += (180 - now) * 4.0 / 60.0 / 24.0 JD1 += (180 - now) * 4.0 / 60.0 / 24.0
} }
hei := MoonHeight(JD1, Lon, Lat, TZ) hei := HMoonHeight(JD1, Lon, Lat, TZ)
if !(hei < -10 && math.Abs(Lat) < 60) { if !(hei < -10 && math.Abs(Lat) < 60) {
if hei > An { if hei > An {
return -1 //拱 return -1 //拱
} }
if MoonHeight(JD1+12/24+6/15/24, Lon, Lat, TZ) < An { reJde := JD1 + 12.0/24.0 + 6.0/15.0/24.0
mag := MoonTimeAngle(reJde, Lon, Lat, TZ)
if mag < 90 {
mag += 360
}
reJde += (360 - mag) * 4.0 / 60.0 / 24.0
if HMoonHeight(reJde, Lon, Lat, TZ) < An {
return -2 //沉 return -2 //沉
} }
} }
dec := MoonSeeDec(JD1, Lon, Lat, TZ) dec := MoonSeeDec(JD1, Lon, Lat, TZ)
SJ := (180 - ArcCos(-Tan(Lat)*Tan(dec))) / 15 tmp := (Sin(An) - Sin(dec)*Sin(Lat)) / (Cos(dec) * Cos(Lat))
if math.Abs(tmp) <= 1 && Lat < 85 {
SJ := (180 - ArcCos(tmp)) / 15
JD1 += SJ/24.00 + SJ/33.00/15.00 JD1 += SJ/24.00 + SJ/33.00/15.00
} else {
i := 0
for MoonHeight(JD1, Lon, Lat, TZ) < An {
i++
JD1 += 15.0 / 60.0 / 24.0
if i > 48 {
break
}
}
}
for { for {
JD0 := JD1 JD0 := JD1
stDegree := HMoonHeight(JD0, Lon, Lat, TZ) - An stDegree := HMoonHeight(JD0, Lon, Lat, TZ) - An
@ -1487,10 +1504,11 @@ func GetMoonDownTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
} }
An = An - HeightDegreeByLat(HEI, Lat) An = An - HeightDegreeByLat(HEI, Lat)
moonang := MoonTimeAngle(JD, Lon, Lat, TZ) moonang := MoonTimeAngle(JD, Lon, Lat, TZ)
if moonheight < 0 { //月亮在地平线上或在落下与下中天之间 if moonheight < 0 {
tms = (360 - moonang) / 15 tms = (360 - moonang) / 15
JD1 += (tms/24 + (tms/24.0*12.0)/15.0/24.0) JD1 += (tms/24 + (tms/24.0*12.0)/15.0/24.0)
} }
//月亮在地平线上或在落下与下中天之间
if moonheight > 0 && moonang < 180 { if moonheight > 0 && moonang < 180 {
tms = (-moonang) / 15 tms = (-moonang) / 15
JD1 += (tms/24.0 + (tms/24.0*12.0)/15.0/24.0) JD1 += (tms/24.0 + (tms/24.0*12.0)/15.0/24.0)
@ -1505,18 +1523,34 @@ func GetMoonDownTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
if math.Abs(now-360) > 0.5 { if math.Abs(now-360) > 0.5 {
JD1 += (360 - now) * 4.0 / 60.0 / 24.0 JD1 += (360 - now) * 4.0 / 60.0 / 24.0
} }
hei := MoonHeight(JD1, Lon, Lat, TZ) //JD1=月球中天时间
hei := HMoonHeight(JD1, Lon, Lat, TZ)
if !(hei > 10 && math.Abs(Lat) < 60) { if !(hei > 10 && math.Abs(Lat) < 60) {
if hei < An { if hei < An {
return -2 //沉 return -2 //沉
} }
if MoonHeight(JD1+12.0/24.0+6.0/15.0/24.0, Lon, Lat, TZ) > An { reJde := JD1 + 12.0/24.0 + 6.0/15.0/24.0
sub := 180 - MoonTimeAngle(reJde, Lon, Lat, TZ)
reJde += sub * 4.0 / 60.0 / 24.0
if HMoonHeight(reJde, Lon, Lat, TZ) > An {
return -1 //拱 return -1 //拱
} }
} }
dec := MoonSeeDec(JD1, Lon, Lat, TZ) dec := MoonSeeDec(JD1, Lon, Lat, TZ)
SJ := (ArcCos(-Tan(Lat) * Tan(dec))) / 15.0 tmp := (Sin(An) - Sin(dec)*Sin(Lat)) / (Cos(dec) * Cos(Lat))
if math.Abs(tmp) <= 1 && Lat < 85 {
SJ := (ArcCos(tmp)) / 15.0
JD1 += SJ/24 + SJ/33.0/15.0 JD1 += SJ/24 + SJ/33.0/15.0
} else {
i := 0
for MoonHeight(JD1, Lon, Lat, TZ) > An {
i++
JD1 += 15.0 / 60.0 / 24.0
if i > 48 {
break
}
}
}
for { for {
JD0 := JD1 JD0 := JD1
stDegree := HMoonHeight(JD0, Lon, Lat, TZ) - An stDegree := HMoonHeight(JD0, Lon, Lat, TZ) - An

@ -14,6 +14,26 @@ func Benchmark_MoonRiseBench(b *testing.B) {
} }
func Test_MoonDown(t *testing.T) {
jde := GetNowJDE()
for i := 30.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetMoonDownTime(jde, 115, float64(i), 8, 1, 0))
}
}
func Test_MoonRise(t *testing.T) {
//2.459984692085961e+06 113.58880556 87.36833333 8 0 0
//2.459984692085961e+06 113.58880556 87.36833333 8 0 0
//2.4599846948519214e+06 113.58880556 87.36833333 8 0 0
//cst := time.FixedZone("cst", 8*3600)
//jde := Date2JDE(time.Date(2023, 2, 9, 15, 59, 0, 0, cst))
fmt.Println(GetMoonRiseTime(2.4599846948519214e+06, 113.58880556, 87.36833333, 8, 0, 0))
for i := 30.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetMoonRiseTime(2.459984692085961e+06, 113.588, float64(i), 8, 0, 0))
}
}
func Test_MoonS(t *testing.T) { func Test_MoonS(t *testing.T) {
//fmt.Println(Sita(2451547)) //fmt.Println(Sita(2451547))
//fmt.Println(MoonHeight(2451547, 115, 32, 8)) //fmt.Println(MoonHeight(2451547, 115, 32, 8))

@ -2,6 +2,7 @@ package basic
import ( import (
. "b612.me/astro/tools" . "b612.me/astro/tools"
"math"
) )
// StarHeight 星体的高度角 // StarHeight 星体的高度角
@ -90,7 +91,70 @@ func StarAngle(RA, DEC, JD, Lon, Lat, TZ float64) float64 {
} }
} }
func StarRiseTime(jde, ra, dec, lon, lat, height, timezone float64, aero bool) (float64, error) { 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)
}
return 0, nil 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) - SunHeight(JD0-0.000005, ra, lon, timezone)) / 0.00001
JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00001 {
break
}
}
return JD1
} }

@ -8,7 +8,15 @@ import (
func Test_StarHeight(t *testing.T) { func Test_StarHeight(t *testing.T) {
date := GetNowJDE() + 6.0/24.0 date := GetNowJDE() + 6.0/24.0
fmt.Println(JDE2Date(date)) fmt.Println(JDE2Date(date))
fmt.Println("Sirius Height:", StarHeight(date, 101.5, -16.8, 113.5, 22, 8.0)) fmt.Println("Sirius Height:", StarHeight(date, 101.5, -16.8, 115, 40, 8.0))
fmt.Println("Sirius Azimuth:", StarAzimuth(date, 101.5, -16.8, 113.5, 22, 8.0)) fmt.Println("Sirius Azimuth:", StarAzimuth(date, 101.5, -16.8, 115, 40, 8.0))
} }
func Test_Star(t *testing.T) {
date := GetNowJDE() - 20/24.0
fmt.Println(JDE2Date(date))
fmt.Println("Sirius RiseTime:", JDE2Date(StarRiseTime(date, 101.529, -16.8, 113.568, 22.5, 0, 8.0, true)))
fmt.Println("Sirius CulminationTime:", JDE2Date(StarCulminationTime(date, 101.529, 113.568, 8.0)))
fmt.Println("Sirius DownTime:", JDE2Date(StarDownTime(date, 101.529, -16.8, 113.568, 22.5, 0, 8.0, true)))
}

@ -1,19 +1,20 @@
package basic package basic
import ( import (
"fmt"
"io/ioutil"
"testing" "testing"
) )
func Test_ParseStar(t *testing.T) { func Test_ParseStar(t *testing.T) {
//dat := []byte(`2491 9Alp CMaBD-16 1591 48915151881 257I 5423 064044.6-163444064508.9-164258227.22-08.88-1.46 0.00 -0.05 -0.03 A1Vm -0.553-1.205 +.375-008SBO 13 10.3 11.2AB 4*`) //dat := []byte(`2491 9Alp CMaBD-16 1591 48915151881 257I 5423 064044.6-163444064508.9-164258227.22-08.88-1.46 0.00 -0.05 -0.03 A1Vm -0.553-1.205 +.375-008SBO 13 10.3 11.2AB 4*`)
LoadStarData() err := LoadStarData()
out := "" if err != nil {
t.Fatal(err)
}
for _, v := range stardat { for _, v := range stardat {
data, _ := parseStarData(v) _, err = parseStarData(v)
out += fmt.Sprintln(data.HD, ",", data.HR) if err != nil {
t.Fatal(err)
}
} }
ioutil.WriteFile("./index.csv", []byte(out), 0644)
} }

@ -1179,28 +1179,29 @@ func GetBanTime(JD, Lon, Lat, TZ, An float64) float64 {
JD = math.Floor(JD) + 1.5 JD = math.Floor(JD) + 1.5
ntz := math.Round(Lon / 15) ntz := math.Round(Lon / 15)
tztime := GetSunTZTime(JD, Lon, ntz) tztime := GetSunTZTime(JD, Lon, ntz)
dec := HSunSeeDec(tztime)
tmp := -Tan((math.Abs(Lat)+An)*(Lat/math.Abs(Lat))) * Tan(dec)
if math.Abs(tmp) > 1 {
if SunHeight(tztime, Lon, Lat, ntz) < An { if SunHeight(tztime, Lon, Lat, ntz) < An {
return -2 //极夜 return -2 //极夜
} }
if SunHeight(tztime-0.5, Lon, Lat, ntz) > An { if SunHeight(tztime+0.5, Lon, Lat, ntz) > An {
return -1 //极昼 return -1 //极昼
} }
} tmp := (Sin(An) - Sin(HSunSeeDec(tztime))*Sin(Lat)) / (Cos(HSunSeeDec(tztime)) * Cos(Lat))
tmp = -Tan(Lat) * Tan(dec) var sundown float64
if math.Abs(tmp) <= 1 && Lat < 85 {
rzsc := ArcCos(tmp) / 15 rzsc := ArcCos(tmp) / 15
sunrise := tztime + rzsc/24.0 + 35.0/24.0/60.0 sundown = tztime + rzsc/24.0 + 35.0/24.0/60.0
} else {
sundown = tztime
i := 0 i := 0
for LowSunHeight(sunrise, Lon, Lat, ntz) < An { for LowSunHeight(sundown, Lon, Lat, ntz) > An {
i++ i++
sunrise -= 15 / 60 / 24 sundown += 15.0 / 60.0 / 24.0
if i > 12 { if i > 48 {
break break
} }
} }
JD1 := sunrise - 5.00/24.00/60.00 }
JD1 := sundown - 5.00/24.00/60.00
for { for {
JD0 := JD1 JD0 := JD1
stDegree := SunHeight(JD0, Lon, Lat, ntz) - An stDegree := SunHeight(JD0, Lon, Lat, ntz) - An
@ -1217,27 +1218,28 @@ func GetAsaTime(JD, Lon, Lat, TZ, An float64) float64 {
JD = math.Floor(JD) + 1.5 JD = math.Floor(JD) + 1.5
ntz := math.Round(Lon / 15) ntz := math.Round(Lon / 15)
tztime := GetSunTZTime(JD, Lon, ntz) tztime := GetSunTZTime(JD, Lon, ntz)
dec := HSunSeeDec(tztime)
tmp := -Tan((math.Abs(Lat)+An)*(Lat/math.Abs(Lat))) * Tan(dec)
if math.Abs(tmp) > 1 {
if SunHeight(tztime, Lon, Lat, ntz) < An { if SunHeight(tztime, Lon, Lat, ntz) < An {
return -2 //极夜 return -2 //极夜
} }
if SunHeight(tztime-0.5, Lon, Lat, ntz) > An { if SunHeight(tztime-0.5, Lon, Lat, ntz) > An {
return -1 //极昼 return -1 //极昼
} }
} tmp := (Sin(An) - Sin(HSunSeeDec(tztime))*Sin(Lat)) / (Cos(HSunSeeDec(tztime)) * Cos(Lat))
tmp = -Tan(Lat) * Tan(dec) var sunrise float64
if math.Abs(tmp) <= 1 && Lat < 85 {
rzsc := ArcCos(tmp) / 15 rzsc := ArcCos(tmp) / 15
sunrise := tztime - rzsc/24 - 25.0/24.0/60.0 sunrise = tztime - rzsc/24 - 25.0/24.0/60.0
} else {
sunrise = tztime
i := 0 i := 0
for LowSunHeight(sunrise, Lon, Lat, ntz) > An { for LowSunHeight(sunrise, Lon, Lat, ntz) > An {
i++ i++
sunrise -= 15 / 60 / 24 sunrise -= 15.0 / 60.0 / 24.0
if i > 12 { if i > 48 {
break break
} }
} }
}
JD1 := sunrise - 5.00/24.00/60.00 JD1 := sunrise - 5.00/24.00/60.00
for { for {
JD0 := JD1 JD0 := JD1
@ -1275,18 +1277,30 @@ func GetSunRiseTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
} }
An = An - HeightDegreeByLat(HEI, Lat) An = An - HeightDegreeByLat(HEI, Lat)
tztime := GetSunTZTime(JD, Lon, ntz) tztime := GetSunTZTime(JD, Lon, ntz)
dec := HSunSeeDec(tztime) if SunHeight(tztime, Lon, Lat, ntz) < An {
tmp := -Tan(Lat) * Tan(dec)
if math.Abs(tmp) > 1 {
if SunHeight(tztime, Lon, Lat, ntz) < 0 {
return -2 //极夜 return -2 //极夜
} }
if SunHeight(tztime-0.5, Lon, Lat, ntz) > 0 { if SunHeight(tztime-0.5, Lon, Lat, ntz) > An {
return -1 //极昼 return -1 //极昼
} }
} //(sin(ho)-sin(φ)*sin(δ2))/(cos(φ)*cos(δ2))
tmp := (Sin(An) - Sin(HSunSeeDec(tztime))*Sin(Lat)) / (Cos(HSunSeeDec(tztime)) * Cos(Lat))
var sunrise float64
if math.Abs(tmp) <= 1 && Lat < 85 {
rzsc := ArcCos(tmp) / 15 rzsc := ArcCos(tmp) / 15
sunrise := tztime - rzsc/24 - 5.0/24.0/60.0 sunrise = tztime - rzsc/24 - 25.0/24.0/60.0
} else {
sunrise = tztime
i := 0
//TODO:使用二分法计算
for LowSunHeight(sunrise, Lon, Lat, ntz) > An {
i++
sunrise -= 15.0 / 60.0 / 24.0
if i > 48 {
break
}
}
}
JD1 := sunrise JD1 := sunrise
for { for {
JD0 := JD1 JD0 := JD1
@ -1308,19 +1322,29 @@ func GetSunDownTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
} }
An = An - HeightDegreeByLat(HEI, Lat) An = An - HeightDegreeByLat(HEI, Lat)
tztime := GetSunTZTime(JD, Lon, ntz) tztime := GetSunTZTime(JD, Lon, ntz)
dec := HSunSeeDec(tztime) if SunHeight(tztime, Lon, Lat, ntz) < An {
tmp := -Tan(Lat) * Tan(dec)
if math.Abs(tmp) > 1 {
if SunHeight(tztime, Lon, Lat, ntz) < 0 {
return -2 //极夜 return -2 //极夜
} }
if SunHeight(tztime+0.5, Lon, Lat, ntz) > 0 { if SunHeight(tztime+0.5, Lon, Lat, ntz) > An {
return -1 //极昼 return -1 //极昼
} }
tmp := (Sin(An) - Sin(HSunSeeDec(tztime))*Sin(Lat)) / (Cos(HSunSeeDec(tztime)) * Cos(Lat))
var sundown float64
if math.Abs(tmp) <= 1 && Lat < 85 {
rzsc := ArcCos(tmp) / 15
sundown = tztime + rzsc/24.0 + 35.0/24.0/60.0
} else {
sundown = tztime
i := 0
for LowSunHeight(sundown, Lon, Lat, ntz) > An {
i++
sundown += 15.0 / 60.0 / 24.0
if i > 48 {
break
}
} }
rzsc := ArcCos(tmp) / 15.0 }
sunrise := tztime + rzsc/24 - 5.0/24.0/60.0 JD1 := sundown
JD1 := sunrise
for { for {
JD0 := JD1 JD0 := JD1
stDegree := SunHeight(JD0, Lon, Lat, ntz) - An stDegree := SunHeight(JD0, Lon, Lat, ntz) - An

@ -66,3 +66,40 @@ func Test_SunRise(t *testing.T) {
fmt.Println(JDE2Date((b))) fmt.Println(JDE2Date((b)))
fmt.Println(time.Now().UnixNano() - a) fmt.Println(time.Now().UnixNano() - a)
} }
func Test_SunTwilightMo(t *testing.T) {
cst := time.FixedZone("cst", 8*3600)
jde := Date2JDE(time.Date(2023, 10, 3, 15, 59, 0, 0, cst))
fmt.Println(GetAsaTime(jde, 113.58880556, 87.66833333, 8, -6))
for i := 10.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetAsaTime(jde, 113.5880556, float64(i), 8, -6))
}
}
func Test_SunTwilightEv(t *testing.T) {
cst := time.FixedZone("cst", 8*3600)
jde := Date2JDE(time.Date(2023, 10, 3, 15, 59, 0, 0, cst))
for i := 10.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetBanTime(jde, 115, float64(i), 8, -18))
}
}
func Test_SunRiseRound(t *testing.T) {
jde := GetNowJDE()
for i := 10.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetSunRiseTime(jde, 115, float64(i), 8, 0, 0))
}
}
func Test_SunDown(t *testing.T) {
jde := GetNowJDE()
for i := 10.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetSunDownTime(jde, 115, float64(i), 8, 0, 0))
}
}
func Test_SunAz(t *testing.T) {
cst := time.FixedZone("cst", 8*3600)
fmt.Println(SunAngle(Date2JDE(time.Date(2022, 5, 30, 11, 55, 0, 0, cst)),
120, 30, 8.0))
}

@ -86,6 +86,9 @@ func DownTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, e
// angle朦影角度可选-6 -12 -18(民用、航海、天文) // angle朦影角度可选-6 -12 -18(民用、航海、天文)
func MorningTwilight(date time.Time, lon, lat, angle float64) (time.Time, error) { func MorningTwilight(date time.Time, lon, lat, angle float64) (time.Time, error) {
var err error var err error
if date.Hour() > 12 {
date = date.Add(time.Hour * -12)
}
jde := basic.Date2JDE(date) jde := basic.Date2JDE(date)
_, loc := date.Zone() _, loc := date.Zone()
timezone := float64(loc) / 3600.0 timezone := float64(loc) / 3600.0
@ -106,6 +109,9 @@ func MorningTwilight(date time.Time, lon, lat, angle float64) (time.Time, error)
// angle朦影角度可选-6 -12 -18(民用、航海、天文) // angle朦影角度可选-6 -12 -18(民用、航海、天文)
func EveningTwilight(date time.Time, lon, lat, angle float64) (time.Time, error) { func EveningTwilight(date time.Time, lon, lat, angle float64) (time.Time, error) {
var err error var err error
if date.Hour() > 12 {
date = date.Add(time.Hour * -12)
}
jde := basic.Date2JDE(date) jde := basic.Date2JDE(date)
_, loc := date.Zone() _, loc := date.Zone()
timezone := float64(loc) / 3600.0 timezone := float64(loc) / 3600.0

Loading…
Cancel
Save