@@ -70,15 +70,17 @@ function calcs(src: SKPaths): CourseData {
70
70
71
71
const xte = vesselPosition ?. crossTrackDistanceTo ( startPoint , destination )
72
72
const magVar = src [ 'navigation.magneticVariation' ] ?? 0.0
73
+ const vmgValue = vmg ( src )
73
74
74
75
// GreatCircle
75
76
const bearingTrackTrue = toRadians ( startPoint ?. initialBearingTo ( destination ) )
76
77
const bearingTrue = toRadians ( vesselPosition ?. initialBearingTo ( destination ) )
77
78
const bearingTrackMagnetic = compassAngle ( bearingTrackTrue + magVar )
78
79
const bearingMagnetic = compassAngle ( bearingTrue + magVar )
79
80
const gcDistance = vesselPosition ?. distanceTo ( destination )
80
- const gcVmg = vmg ( src , bearingTrue , 'true' ) // prefer 'true' values
81
- const gcTime = timeCalcs ( src , gcDistance , gcVmg as number , false )
81
+ const gcVmg = vmgValue
82
+ const gcVmc = vmc ( src , bearingTrue , 'true' ) // for ETA, TTG - prefer 'true' values
83
+ const gcTime = timeCalcs ( src , gcDistance , gcVmc as number , false )
82
84
83
85
res . gc = {
84
86
calcMethod : 'GreatCircle' ,
@@ -108,8 +110,9 @@ function calcs(src: SKPaths): CourseData {
108
110
const rlBearingTrackMagnetic = compassAngle ( rlBearingTrackTrue + magVar )
109
111
const rlBearingMagnetic = compassAngle ( rlBearingTrue + magVar )
110
112
const rlDistance = vesselPosition ?. rhumbDistanceTo ( destination )
111
- const rlVmg = vmg ( src , rlBearingTrue , 'true' ) // prefer 'true' values
112
- const rlTime = timeCalcs ( src , rlDistance , rlVmg as number , true )
113
+ const rlVmg = vmgValue
114
+ const rlVmc = vmc ( src , rlBearingTrue , 'true' ) // for ETA, TTG - prefer 'true' values
115
+ const rlTime = timeCalcs ( src , rlDistance , rlVmc as number , true )
113
116
114
117
res . rl = {
115
118
calcMethod : 'Rhumbline' ,
@@ -143,24 +146,38 @@ function calcs(src: SKPaths): CourseData {
143
146
return res
144
147
}
145
148
146
- // Velocity Made Good to Course
147
- function vmg (
149
+ // Velocity Made Good
150
+ function vmg ( src : SKPaths ) : number | null {
151
+ if (
152
+ typeof src [ 'environment.wind.angleTrueGround' ] !== 'number' ||
153
+ typeof src [ 'navigation.speedOverGround' ] !== 'number'
154
+ ) {
155
+ return null
156
+ }
157
+ return (
158
+ Math . cos ( src [ 'environment.wind.angleTrueGround' ] ) *
159
+ src [ 'navigation.speedOverGround' ]
160
+ )
161
+ }
162
+
163
+ // Velocity Made Good to Course (used for ETA / TTG calcs)
164
+ function vmc (
148
165
src : SKPaths ,
149
166
bearing : number ,
150
167
bearingType : 'true' | 'magnetic' = 'true'
151
168
) : number | null {
152
- const hdg =
169
+ const cog =
153
170
bearingType === 'true'
154
- ? src [ 'navigation.headingTrue ' ]
155
- : src [ 'navigation.headingMagnetic ' ]
171
+ ? src [ 'navigation.courseOverGroundTrue ' ]
172
+ : src [ 'navigation.courseOverGroundMagnetic ' ]
156
173
if (
157
- typeof hdg !== 'number' ||
174
+ typeof cog !== 'number' ||
158
175
typeof src [ 'navigation.speedOverGround' ] !== 'number'
159
176
) {
160
177
return null
161
178
}
162
179
163
- return Math . cos ( bearing - hdg ) * src [ 'navigation.speedOverGround' ]
180
+ return Math . cos ( bearing - cog ) * src [ 'navigation.speedOverGround' ]
164
181
}
165
182
166
183
interface CourseTimes {
@@ -178,7 +195,7 @@ interface CourseTimes {
178
195
function timeCalcs (
179
196
src : SKPaths ,
180
197
distance : number ,
181
- vmg : number ,
198
+ vmc : number ,
182
199
rhumbLine : boolean
183
200
) : CourseTimes {
184
201
const isRoute =
@@ -190,7 +207,7 @@ function timeCalcs(
190
207
route : { ttg : null , eta : null , dtg : null }
191
208
}
192
209
193
- if ( typeof distance !== 'number' || ! vmg ) {
210
+ if ( typeof distance !== 'number' || ! vmc ) {
194
211
return result
195
212
}
196
213
@@ -200,14 +217,14 @@ function timeCalcs(
200
217
201
218
const dateMsec = date . getTime ( )
202
219
203
- const nextTtgMsec = Math . floor ( ( distance / vmg ) * 1000 )
220
+ const nextTtgMsec = Math . floor ( ( distance / vmc ) * 1000 )
204
221
const nextEtaMsec = dateMsec + nextTtgMsec
205
222
result . nextPoint . ttg = nextTtgMsec / 1000
206
223
result . nextPoint . eta = new Date ( nextEtaMsec ) . toISOString ( )
207
224
208
225
if ( isRoute ) {
209
226
const rteDistance = distance + routeRemaining ( src , rhumbLine )
210
- const routeTtgMsec = Math . floor ( ( rteDistance / vmg ) * 1000 )
227
+ const routeTtgMsec = Math . floor ( ( rteDistance / vmc ) * 1000 )
211
228
const routeEtaMsec = dateMsec + routeTtgMsec
212
229
result . route . ttg = routeTtgMsec / 1000
213
230
result . route . eta = new Date ( routeEtaMsec ) . toISOString ( )
0 commit comments