rsspice 0.1.0

Pure Rust port of the SPICE Toolkit for space geometry
Documentation
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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
//
// GENERATED FILE
//

use super::*;
use crate::SpiceContext;
use f2rust_std::*;

const ND: i32 = 2;
const NI: i32 = 5;

/// PCK, read record from type 2 segment
///
/// Read a single PCK data record from a segment of type 2
/// (Chebyshev, 3-vector only).
///
/// # Required Reading
///
/// * [PCK](crate::required_reading::pck)
///
/// # Brief I/O
///
/// ```text
///  VARIABLE  I/O  DESCRIPTION
///  --------  ---  --------------------------------------------------
///  HANDLE     I   File handle.
///  DESCR      I   Segment descriptor.
///  ET         I   Target epoch.
///  RECORD     O   Data record.
/// ```
///
/// # Detailed Input
///
/// ```text
///  HANDLE,
///  DESCR    are the file handle and segment descriptor for
///           a PCK segment of type 2.
///
///  ET       is a target epoch, for which a data record from
///           a specific segment is required.
/// ```
///
/// # Detailed Output
///
/// ```text
///  RECORD   is the record from the specified segment which,
///           when evaluated at epoch ET, will give the Euler
///           angles (orientation) of some body.
/// ```
///
/// # Files
///
/// ```text
///  See argument HANDLE.
/// ```
///
/// # Particulars
///
/// ```text
///  See the PCK Required Reading file for a description of the
///  structure of a data type 2 (Chebyshev polynomials, Euler
///  angles only) segment.
/// ```
///
/// # 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) Dump the record of a type 2 PCK which, when evaluated at
///     a given epoch, will give the Euler angles (orientation) of
///     the Moon body-fixed frame with class ID 31004 with respect
///     to J2000.
///
///     Note that the data returned is in its rawest form, taken
///     directly from the segment. As such, it will be meaningless to
///     a user unless he/she understands the structure of the data
///     type completely. Given that understanding, however, the PCKR02
///     routine might be used to "dump" and check segment data for a
///     particular epoch.
///
///     Use the PCK kernel below to obtain the record.
///
///        moon_pa_de418_1950-2050.bpc
///
///
///     Example code begins here.
///
///
///           PROGRAM PCKR02_EX1
///           IMPLICIT NONE
///
///     C
///     C     Local parameters
///     C
///           INTEGER               BODY
///           PARAMETER           ( BODY   = 31004 )
///
///           INTEGER               DESCSZ
///           PARAMETER           ( DESCSZ = 5     )
///
///           INTEGER               IDSIZE
///           PARAMETER           ( IDSIZE = 40    )
///
///     C
///     C     Set the maximum record size:
///     C
///     C        RSIZE = 2 + 3 * (PDEG +1)
///     C
///     C     Assume a maximum polynomial degree of 25, and
///     C     knowing that PCKR02 returns RSIZE as first element
///     C     of the output record...
///     C
///           INTEGER               RECRSZ
///           PARAMETER           ( RECRSZ = 81    )
///
///     C
///     C     Local variables
///     C
///           CHARACTER*(IDSIZE)    SEGID
///
///           DOUBLE PRECISION      BEGET
///           DOUBLE PRECISION      DESCR  ( DESCSZ )
///           DOUBLE PRECISION      ENDET
///           DOUBLE PRECISION      ET
///           DOUBLE PRECISION      RECORD ( RECRSZ )
///
///           INTEGER               BADDR
///           INTEGER               BODYID
///           INTEGER               EADDR
///           INTEGER               FRAMID
///           INTEGER               HANDLE
///           INTEGER               I
///           INTEGER               INDEX
///           INTEGER               PCKHDL
///           INTEGER               PCKTYP
///           INTEGER               PDEG
///           INTEGER               RSIZE
///
///           LOGICAL               FOUND
///
///     C
///     C     Load the PCK file.
///     C
///           CALL PCKLOF ( 'moon_pa_de418_1950-2050.bpc', PCKHDL )
///
///     C
///     C     Set the epoch. Use ephemeris time of J2000 epoch.
///     C
///           ET = 0.D0
///
///     C
///     C     Get a segment applicable to a specified body and epoch.
///     C
///           CALL PCKSFS ( BODY, ET, HANDLE, DESCR, SEGID, FOUND )
///
///           IF ( FOUND ) THEN
///
///     C
///     C        Unpack the segment.
///     C
///              CALL PCKUDS ( DESCR, BODYID, FRAMID, PCKTYP,
///          .                 BEGET, ENDET,  BADDR,  EADDR  )
///
///
///              IF ( PCKTYP .EQ. 2 ) THEN
///
///                 CALL PCKR02 ( HANDLE, DESCR, ET, RECORD )
///
///                 RSIZE = RECORD(1)
///                 PDEG  = ( RSIZE - 2 ) / 3 - 1
///
///     C
///     C           Output the data.
///     C
///                 WRITE(*,*) 'Record size      : ', RSIZE
///                 WRITE(*,*) 'Polynomial degree: ', PDEG
///
///                 WRITE(*,*) 'Record data      :'
///                 WRITE(*,*) '   Interval midpoint: ', RECORD(2)
///                 WRITE(*,*) '   Interval radius  : ', RECORD(3)
///
///                 INDEX = 4
///                 WRITE(*,*) '   RA coefficients  : '
///                 DO I = 0, PDEG
///                    WRITE(*,*) '      ', RECORD(INDEX+I)
///                 END DO
///
///                 INDEX = 4 + ( PDEG + 1 )
///                 WRITE(*,*) '   DEC coefficients : '
///                 DO I = 0, PDEG
///                    WRITE(*,*) '      ', RECORD(INDEX+I)
///                 END DO
///
///                 INDEX = 4 + 2 * ( PDEG + 1 )
///                 WRITE(*,*) '   W coefficients   : '
///                 DO I = 0, PDEG
///                    WRITE(*,*) '      ', RECORD(INDEX+I)
///                 END DO
///
///              ELSE
///
///                 WRITE(*,*) 'PCK is not type 2'
///
///              END IF
///
///           ELSE
///
///              WRITE(*,*) '   ***** SEGMENT NOT FOUND *****'
///
///           END IF
///
///     C
///     C     Unload the PCK file.
///     C
///           CALL PCKUOF ( PCKHDL )
///
///           END
///
///
///     When this program was executed on a Mac/Intel/gfortran/64-bit
///     platform, the output was:
///
///
///      Record size      :           32
///      Polynomial degree:            9
///      Record data      :
///         Interval midpoint:    302400.00000000000
///         Interval radius  :    345600.00000000000
///         RA coefficients  :
///              -5.4242086033301107E-002
///              -5.2241405162792561E-005
///               8.9751456289930307E-005
///              -1.5288696963234620E-005
///               1.3218870864581395E-006
///               5.9822156790328180E-007
///              -6.5967702052551211E-008
///              -9.9084309118396298E-009
///               4.9276055963541578E-010
///               1.1612267413829385E-010
///         DEC coefficients :
///              0.42498898565916610
///               1.3999219324235620E-004
///              -1.8855140511098865E-005
///              -2.1964684808526649E-006
///               1.4229817868138752E-006
///              -1.6991716166847001E-007
///              -3.4824688140649506E-008
///               2.9208428745895990E-009
///               4.4217757657060300E-010
///              -3.9211207055305402E-012
///         W coefficients   :
///               2565.0633504619473
///              0.92003769451305328
///              -8.0503797901914501E-005
///               1.1960860244433900E-005
///              -1.2237900518372542E-006
///              -5.3651349407824562E-007
///               6.0843372260403005E-008
///               9.0211287487688797E-009
///              -4.6460429330339309E-010
///              -1.0446918704281774E-010
/// ```
///
/// # Author and Institution
///
/// ```text
///  J. Diaz del Rio    (ODC Space)
///  E.D. Wright        (JPL)
///  K.S. Zukor         (JPL)
/// ```
///
/// # Version
///
/// ```text
/// -    SPICELIB Version 1.1.2, 06-JUL-2021 (JDR)
///
///         Edited the header to comply with NAIF standard.
///         Added complete code example from existing fragment.
///
/// -    SPICELIB Version 1.1.1, 03-JAN-2014 (EDW)
///
///         Minor edits to $Procedure; clean trailing whitespace.
///
/// -    SPICELIB Version 1.1.0, 07-SEP-2001 (EDW)
///
///         Replaced DAFRDA call with DAFGDA.
///         Added IMPLICIT NONE.
///
/// -    SPICELIB Version 1.0.0, 11-MAR-1993 (KSZ)
/// ```
///
/// # Revisions
///
/// ```text
/// -    SPICELIB Version 1.1.0, 07-SEP-2001 (EDW)
///
///         Replaced DAFRDA call with DAFGDA.
///         Added IMPLICIT NONE.
/// ```
pub fn pckr02(
    ctx: &mut SpiceContext,
    handle: i32,
    descr: &[f64; 5],
    et: f64,
    record: &mut [f64],
) -> crate::Result<()> {
    PCKR02(handle, descr, et, record, ctx.raw_context())?;
    ctx.handle_errors()?;
    Ok(())
}

//$Procedure PCKR02 ( PCK, read record from type 2 segment )
pub fn PCKR02(
    HANDLE: i32,
    DESCR: &[f64],
    ET: f64,
    RECORD: &mut [f64],
    ctx: &mut Context,
) -> f2rust_std::Result<()> {
    let DESCR = DummyArray::new(DESCR, 1..=5);
    let mut RECORD = DummyArrayMut::new(RECORD, 1..);
    let mut DC = StackArray::<f64, 2>::new(1..=ND);
    let mut INIT: f64 = 0.0;
    let mut INTLEN: f64 = 0.0;
    let mut BEGIN: i32 = 0;
    let mut END: i32 = 0;
    let mut IC = StackArray::<i32, 5>::new(1..=NI);
    let mut NREC: i32 = 0;
    let mut RECADR: i32 = 0;
    let mut RECNO: i32 = 0;
    let mut RECSIZ: i32 = 0;

    //
    // SPICELIB functions
    //

    //
    // Parameters
    //

    //
    // Local variables
    //

    //
    // Standard SPICE error handling.
    //
    if RETURN(ctx) {
        return Ok(());
    } else {
        CHKIN(b"PCKR02", ctx)?;
    }

    //
    // Unpack the segment descriptor.
    //
    DAFUS(
        DESCR.as_slice(),
        ND,
        NI,
        DC.as_slice_mut(),
        IC.as_slice_mut(),
    );

    BEGIN = IC[(NI - 1)];
    END = IC[NI];

    //
    // The segment is made up of a number of logical records, each
    // having the same size, and covering the same length of time.
    //
    // We can determine which record to return by comparing the input
    // epoch with the initial time of the segment and the length of the
    // interval covered by each record.  These final two constants are
    // located at the end of the segment, along with the size of each
    // logical record and the total number of records.
    //
    DAFGDA(HANDLE, (END - 3), END, RECORD.as_slice_mut(), ctx)?;

    INIT = RECORD[1];
    INTLEN = RECORD[2];
    RECSIZ = (RECORD[3] as i32);
    NREC = (RECORD[4] as i32);

    RECNO = ((((ET - INIT) / INTLEN) as i32) + 1);
    RECNO = intrinsics::MIN0(&[RECNO, NREC]);

    //
    // Compute the address of the desired record.
    //
    RECADR = (((RECNO - 1) * RECSIZ) + BEGIN);

    //
    // Along with the record, return the size of the record.
    //
    RECORD[1] = RECORD[3];
    DAFGDA(
        HANDLE,
        RECADR,
        ((RECADR + RECSIZ) - 1),
        RECORD.subarray_mut(2),
        ctx,
    )?;

    CHKOUT(b"PCKR02", ctx)?;
    Ok(())
}