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
//
// GENERATED FILE
//
use super::*;
use crate::SpiceContext;
use f2rust_std::*;
/// Nearest point on line segment
///
/// Find the nearest point on a line segment to a given point.
///
/// # Brief I/O
///
/// ```text
/// VARIABLE I/O DESCRIPTION
/// -------- --- --------------------------------------------------
/// EP1,
/// EP2 I Endpoints of a line segment.
/// POINT I A point in 3-dimensional space.
/// PNEAR O Nearest point on the line segment to POINT.
/// DIST O Distance between PNEAR and POINT.
/// ```
///
/// # Detailed Input
///
/// ```text
/// EP1,
/// EP2 are the endpoints of a line segment in 3-dimensional
/// space. EP1 and EP2 need not be distinct.
///
/// POINT is an arbitrary point in 3-dimensional space.
/// ```
///
/// # Detailed Output
///
/// ```text
/// PNEAR is the closest point on the line segment to POINT.
///
/// DIST is the distance between POINT and PNEAR.
/// ```
///
/// # Exceptions
///
/// ```text
/// 1) The input segment is allowed to be degenerate: it may be
/// a single point.
/// ```
///
/// # Examples
///
/// ```text
/// The numerical results shown for this example may differ across
/// platforms. The results depend on the SPICE kernels used as input
/// (if any), the compiler and supporting libraries, and the machine
/// specific arithmetic implementation.
///
/// 1) Compute the nearest point on a line segment to a given
/// point in a simple case for which the results can easily be
/// checked.
///
///
/// Example code begins here.
///
///
/// PROGRAM NPSGPT_EX1
/// IMPLICIT NONE
/// C
/// C Local parameters
/// C
/// CHARACTER*(*) FMT1
/// PARAMETER ( FMT1 = '(A,3F13.8)' )
/// C
/// C Local variables
/// C
/// DOUBLE PRECISION DIST
/// DOUBLE PRECISION ENDPT1 ( 3 )
/// DOUBLE PRECISION ENDPT2 ( 3 )
/// DOUBLE PRECISION PNEAR ( 3 )
/// DOUBLE PRECISION POINT ( 3 )
///
/// C
/// C Initialize the line segment's endpoints.
/// C
/// CALL VPACK ( 1.D0, -2.D0, 3.D0, ENDPT1 )
/// CALL VPACK ( 1.D0, 2.D0, 3.D0, ENDPT2 )
/// C
/// C Set the input point.
/// C
/// CALL VPACK ( 1.D0, 0.D0, 0.D0, POINT )
/// C
/// C Find the near point on the segment.
/// C
/// CALL NPSGPT ( ENDPT1, ENDPT2, POINT, PNEAR, DIST )
///
/// WRITE (*,*) ' '
/// WRITE (*,FMT1) 'Endpoint 1: ', ENDPT1
/// WRITE (*,FMT1) 'Endpoint 2: ', ENDPT2
/// WRITE (*,FMT1) 'Point: ', POINT
/// WRITE (*,*) ' '
/// WRITE (*,FMT1) 'Near point: ', PNEAR
/// WRITE (*,FMT1) 'Distance: ', DIST
/// WRITE (*,*) ' '
///
/// END
///
///
/// When this program was executed on a Mac/Intel/gfortran/64-bit
/// platform, the output was:
///
///
/// Endpoint 1: 1.00000000 -2.00000000 3.00000000
/// Endpoint 2: 1.00000000 2.00000000 3.00000000
/// Point: 1.00000000 0.00000000 0.00000000
///
/// Near point: 1.00000000 0.00000000 3.00000000
/// Distance: 3.00000000
/// ```
///
/// # Author and Institution
///
/// ```text
/// N.J. Bachman (JPL)
/// J. Diaz del Rio (ODC Space)
/// ```
///
/// # Version
///
/// ```text
/// - SPICELIB Version 1.0.1, 06-JUL-2021 (JDR)
///
/// Edited the header to comply with NAIF standard.
///
/// - SPICELIB Version 1.0.0, 02-FEB-2016 (NJB)
///
/// Updated from DSKLIB Version 1.0.0, 20-MAR-2015 (NJB)
/// ```
pub fn npsgpt(
ctx: &mut SpiceContext,
ep1: &[f64; 3],
ep2: &[f64; 3],
point: &[f64; 3],
pnear: &mut [f64; 3],
dist: &mut f64,
) -> crate::Result<()> {
NPSGPT(ep1, ep2, point, pnear, dist, ctx.raw_context())?;
ctx.handle_errors()?;
Ok(())
}
//$Procedure NPSGPT ( Nearest point on line segment )
pub fn NPSGPT(
EP1: &[f64],
EP2: &[f64],
POINT: &[f64],
PNEAR: &mut [f64],
DIST: &mut f64,
ctx: &mut Context,
) -> f2rust_std::Result<()> {
let EP1 = DummyArray::new(EP1, 1..=3);
let EP2 = DummyArray::new(EP2, 1..=3);
let POINT = DummyArray::new(POINT, 1..=3);
let mut PNEAR = DummyArrayMut::new(PNEAR, 1..=3);
let mut SEG = StackArray::<f64, 3>::new(1..=3);
let mut SEGDOT: f64 = 0.0;
let mut LNEAR = StackArray::<f64, 3>::new(1..=3);
let mut OFFSET = StackArray::<f64, 3>::new(1..=3);
let mut OFFDOT: f64 = 0.0;
//
// SPICELIB functions
//
//
// Local variables
//
//
// Use discovery check-in.
//
if RETURN(ctx) {
return Ok(());
}
//
// Find a direction vector defined by the endpoints.
//
VSUB(EP2.as_slice(), EP1.as_slice(), SEG.as_slice_mut());
if VZERO(SEG.as_slice()) {
//
// The endpoints coincide, and both coincide with the
// near point.
//
VEQU(EP1.as_slice(), PNEAR.as_slice_mut());
*DIST = VDIST(EP1.as_slice(), POINT.as_slice());
return Ok(());
}
//
// Find the nearest point to POINT on the line defined by
// EP1 and SEG.
//
NPLNPT(
EP1.as_slice(),
SEG.as_slice(),
POINT.as_slice(),
LNEAR.as_slice_mut(),
DIST,
ctx,
)?;
if FAILED(ctx) {
return Ok(());
}
//
// Determine whether LNEAR is on the segment, "before" EP1, or
// "after" EP2, where SEG points in the "increasing" direction.
//
VSUB(LNEAR.as_slice(), EP1.as_slice(), OFFSET.as_slice_mut());
OFFDOT = VDOT(OFFSET.as_slice(), SEG.as_slice());
if (OFFDOT < 0.0) {
//
// The nearest point on the line precedes the first endpoint.
// The closest point on the segment is the first endpoint.
//
VEQU(EP1.as_slice(), PNEAR.as_slice_mut());
*DIST = VDIST(EP1.as_slice(), POINT.as_slice());
} else {
//
// See whether OFFSET is past the second endpoint. Compare
// the dot product of OFFSET with SEG to that of SEG with
// itself, since SEG is the offset of EP2 from EP1.
//
SEGDOT = VDOT(SEG.as_slice(), SEG.as_slice());
if (OFFDOT > SEGDOT) {
//
// The nearest point on the line follows the last endpoint.
// The closest point on the segment is the last endpoint.
//
VEQU(EP2.as_slice(), PNEAR.as_slice_mut());
*DIST = VDIST(EP2.as_slice(), POINT.as_slice());
} else {
//
// The near point is on the segment. LNEAR is actually the
// solution.
//
VEQU(LNEAR.as_slice(), PNEAR.as_slice_mut());
//
// DIST was correctly set by the call to NPLNPT.
//
}
}
Ok(())
}