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
//
// GENERATED FILE
//
use super::*;
use crate::SpiceContext;
use f2rust_std::*;
/// Build a right handed coordinate frame
///
/// Build a right handed orthonormal frame (x,y,z) from a
/// 3-dimensional input vector, where the X-axis of the resulting
/// frame is parallel to the original input vector.
///
/// # Brief I/O
///
/// ```text
/// VARIABLE I/O DESCRIPTION
/// -------- --- ------------------------------------------------
/// X I-O Input vector. A parallel unit vector on output.
/// Y O Unit vector in the plane orthogonal to X.
/// Z O Unit vector given by the cross product <X,Y>.
/// ```
///
/// # Detailed Input
///
/// ```text
/// X is a 3-dimensional vector used to form the first vector
/// of a right-handed orthonormal triple.
/// ```
///
/// # Detailed Output
///
/// ```text
/// X,
/// Y,
/// Z are the 3-dimensional unit vectors that form a right
/// handed orthonormal frame, where X is now a unit vector
/// parallel to the original input vector in X. There are no
/// special geometric properties connected to Y and Z (other
/// than that they complete the right handed frame).
/// ```
///
/// # Exceptions
///
/// ```text
/// Error free.
///
/// 1) If X on input is the zero vector the "standard" frame (ijk)
/// is returned.
/// ```
///
/// # Particulars
///
/// ```text
/// Given an input vector X, this routine returns unit vectors X,
/// Y, and Z such that XYZ forms a right-handed orthonormal frame
/// where the output X is parallel to the input X.
///
/// This routine is intended primarily to provide a basis for
/// the plane orthogonal to X. There are no special properties
/// associated with Y and Z other than that the resulting XYZ frame
/// is right handed and orthonormal. There are an infinite
/// collection of pairs (Y,Z) that could be used to this end.
/// Even though for a given X, Y and Z are uniquely
/// determined, users
/// should regard the pair (Y,Z) as a random selection from this
/// infinite collection.
///
/// For instance, when attempting to determine the locus of points
/// that make up the limb of a triaxial body, it is a straightforward
/// matter to determine the normal to the limb plane. To find
/// the actual parametric equation of the limb one needs to have
/// a basis of the plane. This routine can be used to get a basis
/// in which one can describe the curve and from which one can
/// then determine the principal axes of the limb ellipse.
/// ```
///
/// # Examples
///
/// ```text
/// In addition to using a vector to construct a right handed frame
/// with the x-axis aligned with the input vector, one can construct
/// right handed frames with any of the axes aligned with the input
/// vector.
///
/// For example suppose we want a right hand frame XYZ with the
/// Z-axis aligned with some vector V. Assign V to Z
///
/// Z(1) = V(1)
/// Z(2) = V(2)
/// Z(3) = V(3)
///
/// Then call FRAME with the arguments X,Y,Z cycled so that Z
/// appears first.
///
/// CALL FRAME (Z, X, Y)
///
/// The resulting XYZ frame will be orthonormal with Z parallel
/// to the vector V.
///
/// To get an XYZ frame with Y parallel to V perform the following
///
/// Y(1) = V(1)
/// Y(2) = V(2)
/// Y(3) = V(3)
///
/// CALL FRAME (Y, Z, X)
/// ```
///
/// # Author and Institution
///
/// ```text
/// N.J. Bachman (JPL)
/// J. Diaz del Rio (ODC Space)
/// W.L. Taber (JPL)
/// I.M. Underwood (JPL)
/// ```
///
/// # Version
///
/// ```text
/// - SPICELIB Version 1.3.0, 03-JUL-2021 (JDR)
///
/// Added IMPLICIT NONE statement.
///
/// Edited the header to comply with NAIF standard. Improved
/// argument descriptions.
///
/// - SPICELIB Version 1.2.0, 02-SEP-2005 (NJB)
///
/// Updated to remove non-standard use of duplicate arguments
/// in VHAT call.
///
/// - 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, 31-JAN-1990 (WLT) (IMU)
/// ```
///
/// # Revisions
///
/// ```text
/// - Beta Version 2.0.0, 29-DEC-1988 (WLT) (IMU)
///
/// The routine was modified so that it now accepts any input
/// vector in the X slot (it originally was assumed to be a unit
/// vector). Moreover, the original algorithm has been streamlined
/// a great deal to take advantage of our knowledge of the
/// internal structure of the orthonormal triple.
/// ```
pub fn frame(x: &mut [f64; 3], y: &mut [f64; 3], z: &mut [f64; 3]) {
FRAME(x, y, z);
}
//$Procedure FRAME ( Build a right handed coordinate frame )
pub fn FRAME(X: &mut [f64], Y: &mut [f64], Z: &mut [f64]) {
let mut X = DummyArrayMut::new(X, 1..=3);
let mut Y = DummyArrayMut::new(Y, 1..=3);
let mut Z = DummyArrayMut::new(Z, 1..=3);
let mut A: f64 = 0.0;
let mut B: f64 = 0.0;
let mut C: f64 = 0.0;
let mut F: f64 = 0.0;
let mut S1: i32 = 0;
let mut S2: i32 = 0;
let mut S3: i32 = 0;
//
//
// Local variables
//
//
// First make X into a unit vector.
//
VHATIP(X.as_slice_mut());
//
// We'll need the squares of the components of X in a bit.
//
A = (X[1] * X[1]);
B = (X[2] * X[2]);
C = (X[3] * X[3]);
//
// If X is zero, then just return the ijk frame.
//
if (((A + B) + C) == 0.0) {
X[1] = 1.0;
X[2] = 0.0;
X[3] = 0.0;
Y[1] = 0.0;
Y[2] = 1.0;
Y[3] = 0.0;
Z[1] = 0.0;
Z[2] = 0.0;
Z[3] = 1.0;
return;
}
//
// If we make it this far, determine which component of X has the
// smallest magnitude. This component will be zero in Y. The other
// two components of X will put into Y swapped with the sign of
// the first changed. From there, Z can have only one possible
// set of values which it gets from the smallest component
// of X, the non-zero components of Y and the length of Y.
//
if ((A <= B) && (A <= C)) {
F = f64::sqrt((B + C));
S1 = 1;
S2 = 2;
S3 = 3;
} else if ((B <= A) && (B <= C)) {
F = f64::sqrt((A + C));
S1 = 2;
S2 = 3;
S3 = 1;
} else {
F = f64::sqrt((A + B));
S1 = 3;
S2 = 1;
S3 = 2;
}
//
// Note: by construction, F is the magnitude of the large components
// of X. With this in mind, one can verify by inspection that X, Y
// and Z yield an orthonormal frame. The right handedness follows
// from the assignment of values to S1, S2 and S3 (they are merely
// cycled from one case to the next).
//
Y[S1] = 0.0;
Y[S2] = -(X[S3] / F);
Y[S3] = (X[S2] / F);
Z[S1] = F;
Z[S2] = -(X[S1] * Y[S3]);
Z[S3] = (X[S1] * Y[S2]);
}