-
Notifications
You must be signed in to change notification settings - Fork 4
/
tools_body.go
162 lines (147 loc) · 3.59 KB
/
tools_body.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package novas
import (
"errors"
"time"
)
// Compute the time of rise of a body above the dip angle.
// Returns an error if the body doesn't rise above dip within 24 hours from the time given.
func (p *Body) Rise(t Time, geo *Place, dip float64, precision time.Duration, refr RefractType) (Time, BodyTopoData, error) {
alt1 := p.Topo(t, geo, refr).Alt
t1 := t
t2 := t
found := false
for i := 0; i < 48; i++ {
t2.Time = t1.Add(30 * time.Minute)
alt2 := p.Topo(t2, geo, refr).Alt
if alt1 < dip && alt2 > dip {
found = true
break
}
t1 = t2
alt1 = alt2
}
if !found {
return Time{}, BodyTopoData{}, errors.New("No rise above dip in the next 24 hours")
}
var topo BodyTopoData
tt := t1
for t2.Sub(t1.Time) > precision {
tt.Time = t1.Add(t2.Sub(t1.Time) / 2)
topo = p.Topo(tt, geo, refr)
if topo.Alt > dip {
t2 = tt
} else {
t1 = tt
}
}
return tt, topo, nil
}
// Compute the time of set of a body below the dip angle.
// Returns an error if the body doesn't set below dip within 24 hours from the time given.
func (p *Body) Set(t Time, geo *Place, dip float64, precision time.Duration, refr RefractType) (Time, BodyTopoData, error) {
alt1 := p.Topo(t, geo, refr).Alt
t1 := t
t2 := t
found := false
for i := 0; i < 48; i++ {
t2.Time = t1.Add(30 * time.Minute)
alt2 := p.Topo(t2, geo, refr).Alt
if alt1 > dip && alt2 < dip {
found = true
break
}
t1 = t2
alt1 = alt2
}
if !found {
return Time{}, BodyTopoData{}, errors.New("No set below dip in the next 24 hours")
}
var topo BodyTopoData
tt := t1
for t2.Sub(t1.Time) > precision {
tt.Time = t1.Add(t2.Sub(t1.Time) / 2)
topo = p.Topo(tt, geo, refr)
if topo.Alt < dip {
t2 = tt
} else {
t1 = tt
}
}
return tt, topo, nil
}
// Compute the time of highest position in the sky of a body.
// Returns an error if the body doesn't goes up then down within 24 hours from the time given.
func (p *Body) High(t Time, geo *Place, precision time.Duration, refr RefractType) (Time, BodyTopoData, error) {
alt1 := p.Topo(t, geo, refr).Alt
alt2 := alt1
alt3 := alt1
t1 := t
t2 := t
t3 := t
found := false
for i := 0; i < 48; i++ {
t3.Time = t2.Add(30 * time.Minute)
alt3 = p.Topo(t3, geo, refr).Alt
if i > 1 && alt2 > alt3 && alt2 > alt1 {
found = true
break
}
t1, t2 = t2, t3
alt1, alt2 = alt2, alt3
}
if !found {
return Time{}, BodyTopoData{}, errors.New("No high point in the next 24 hours")
}
var topo BodyTopoData
tt := t1
for t3.Sub(t1.Time) > precision {
tt.Time = t1.Add(t3.Sub(t1.Time) / 2)
topo = p.Topo(tt, geo, refr)
if alt1 < alt3 {
t1 = tt
alt1 = topo.Alt
} else {
t3 = tt
alt3 = topo.Alt
}
}
return tt, topo, nil
}
// Compute the time of lowest position in the sky of a body.
// Returns an error if the body doesn't goes down then up within 24 hours from the time given.
func (p *Body) Low(t Time, geo *Place, precision time.Duration, refr RefractType) (Time, BodyTopoData, error) {
alt1 := p.Topo(t, geo, refr).Alt
alt2 := alt1
alt3 := alt1
t1 := t
t2 := t
t3 := t
found := false
for i := 0; i < 48; i++ {
t3.Time = t2.Add(30 * time.Minute)
alt3 = p.Topo(t3, geo, refr).Alt
if i > 1 && alt2 < alt3 && alt2 < alt1 {
found = true
break
}
t1, t2 = t2, t3
alt1, alt2 = alt2, alt3
}
if !found {
return Time{}, BodyTopoData{}, errors.New("No low point in the next 24 hours")
}
var topo BodyTopoData
tt := t1
for t3.Sub(t1.Time) > precision {
tt.Time = t1.Add(t3.Sub(t1.Time) / 2)
topo = p.Topo(tt, geo, refr)
if alt1 > alt3 {
t1 = tt
alt1 = topo.Alt
} else {
t3 = tt
alt3 = topo.Alt
}
}
return tt, topo, nil
}