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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//
// GENERATED FILE
//
use super::*;
use crate::SpiceContext;
use f2rust_std::*;
/// Spherical surface distance
///
/// Return the distance between two points on a sphere, measured
/// along the shortest great circle arc connecting them.
///
/// # Brief I/O
///
/// ```text
/// VARIABLE I/O DESCRIPTION
/// -------- --- --------------------------------------------------
/// RADIUS I Radius of sphere.
/// LON1,
/// LAT1 I Longitude and latitude of first point in radians.
/// LON2,
/// LAT2 I Longitude and latitude of second point in radians.
///
/// The function returns the distance between the two input points,
/// measured along the shortest great circle arc connecting them.
/// ```
///
/// # Detailed Input
///
/// ```text
/// RADIUS is the radius of the sphere on which the points are
/// located.
///
/// LON1,
/// LAT1 are, respectively, the longitude and latitude of the
/// first point. The units are radians.
///
/// LON2,
/// LAT2 are, respectively, the longitude and latitude of the
/// second point. The units are radians.
/// ```
///
/// # Detailed Output
///
/// ```text
/// The function returns the distance between the two input points,
/// measured along the shortest great circle arc connecting them.
/// ```
///
/// # Exceptions
///
/// ```text
/// 1) If RADIUS is negative, the error SPICE(INPUTOUTOFRANGE)
/// is signaled. SPHSD is set to zero. RADIUS may be zero;
/// this case is not treated as an exception.
///
/// 2) Latitudes out of the range [-pi/2, pi/2] are NOT treated
/// as errors, although they are not valid in the latitudinal
/// coordinate system and so may be considered to be exceptional
/// inputs. All latitude values are used in the same way in the
/// computation, regardless of whether or not they are in range.
/// See the code for the equation used.
///
/// 3) Longitudes out of the range (-pi, pi] are NOT treated
/// as errors, although they are not valid in the latitudinal
/// coordinate system and so may be considered to be exceptional
/// inputs. All longitude values are used in the same way in the
/// computation, regardless of whether or not they are in range.
/// See the code for the equation used.
/// ```
///
/// # Particulars
///
/// ```text
/// You may need to consider whether a spherical model is adequate
/// for your application; some bodies may be more accurately modeled
/// by an oblate or prolate spheroid, or by a triaxial ellipsoid.
/// ```
///
/// # Examples
///
/// ```text
/// The numerical results shown for this example may differ across
/// platforms. The results depend on the SPICE kernels used as
/// input, the compiler and supporting libraries, and the machine
/// specific arithmetic implementation.
///
/// 1) Find the distance along a sphere of radius 1000 km between
/// the points at
///
/// longitude = pi/2 radians,
/// latitude = pi/4 radians
///
/// and
///
/// longitude = 0 radians,
/// latitude = pi/4 radians
///
///
/// Example code begins here.
///
///
/// PROGRAM SPHSD_EX1
/// IMPLICIT NONE
///
/// C
/// C SPICELIB functions
/// C
/// DOUBLE PRECISION SPHSD
/// DOUBLE PRECISION PI
///
/// C
/// C Local variables.
/// C
/// DOUBLE PRECISION DIST
///
///
/// DIST = SPHSD ( 1.D3, PI()/2.D0, PI()/4.D0,
/// . 0.D0, PI()/4.D0 )
///
/// WRITE(*,*) 'Spherical surface distance:', DIST
///
/// END
///
///
/// When this program was executed on a Mac/Intel/gfortran/64-bit
/// platform, the output was:
///
///
/// Spherical surface distance: 1047.1975511965979
/// ```
///
/// # Author and Institution
///
/// ```text
/// N.J. Bachman (JPL)
/// J. Diaz del Rio (ODC Space)
/// H.A. Neilan (JPL)
/// W.L. Taber (JPL)
/// ```
///
/// # Version
///
/// ```text
/// - SPICELIB Version 1.2.0, 13-AUG-2021 (JDR)
///
/// Changed the input argument names LONG1 and LONG2 to LON1 and
/// LON2 for consistency with other routines.
///
/// Added IMPLICIT NONE statement.
///
/// Edited the header to comply with NAIF standard. Removed
/// unnecessary $Revisions section.
///
/// Added complete code example from existing fragment.
///
/// - SPICELIB Version 1.1.0, 17-MAY-1994 (HAN)
///
/// If the value of the function RETURN is .TRUE. upon execution of
/// this module, this function is assigned a default value of
/// either 0, 0.0D0, .FALSE., or blank depending on the type of
/// the function.
///
/// - SPICELIB Version 1.0.1, 10-MAR-1992 (WLT)
///
/// Comment section for permuted index source lines was added
/// following the header.
///
/// - SPICELIB Version 1.0.0, 01-NOV-1990 (NJB)
/// ```
pub fn sphsd(
ctx: &mut SpiceContext,
radius: f64,
lon1: f64,
lat1: f64,
lon2: f64,
lat2: f64,
) -> crate::Result<f64> {
let ret = SPHSD(radius, lon1, lat1, lon2, lat2, ctx.raw_context())?;
ctx.handle_errors()?;
Ok(ret)
}
//$Procedure SPHSD ( Spherical surface distance )
pub fn SPHSD(
RADIUS: f64,
LON1: f64,
LAT1: f64,
LON2: f64,
LAT2: f64,
ctx: &mut Context,
) -> f2rust_std::Result<f64> {
let mut SPHSD: f64 = 0.0;
let mut SL1SL2: f64 = 0.0;
let mut COSANG: f64 = 0.0;
//
// SPICELIB functions
//
//
// Local variables
//
//
// Check RETURN but do not check in unless an error is detected.
//
if RETURN(ctx) {
SPHSD = 0.0;
return Ok(SPHSD);
}
//
// Make sure that RADIUS is ok; check in only if it isn't.
//
if (RADIUS < 0 as f64) {
SPHSD = 0.0;
CHKIN(b"SPHSD", ctx)?;
SETMSG(b"Radius was #.", ctx);
ERRDP(b"#", RADIUS, ctx);
SIGERR(b"SPICE(VALUEOUTOFRANGE)", ctx)?;
CHKOUT(b"SPHSD", ctx)?;
return Ok(SPHSD);
}
//
// The usual equation for the distance between points, measured
// along a great circle, is:
//
// -1
// DIST = COS ( ( COS(LON1-LON2) * COS(LAT1) * COS(LAT2) )
// + ( SIN(LAT1) * SIN(LAT2) ) )
//
// * RADIUS
//
// To arrive at this equation, we find the cartesian coordinates of
// the input surface points and take the dot product of the two
// points.
//
// To save a trig function reference, however, we implement this
// calculation slightly differently.
//
//
// COSANG is the cosine of the angle between the two position
// vectors. We bracket COSANG 'tween -1 and 1 to make sure
// round-off error doesn't take it out of the domain of arc
// cosine...
//
SL1SL2 = (f64::sin(LAT1) * f64::sin(LAT2));
COSANG = ((f64::cos((LON1 - LON2)) * (f64::cos((LAT1 - LAT2)) - SL1SL2)) + SL1SL2);
SPHSD = (RADIUS * f64::acos(BRCKTD(COSANG, -1.0, 1.0)));
Ok(SPHSD)
}