use crate::assert_slice_eq;
use crate::common;
fn segment() -> (i32, spice::DLADSC) {
let handle = spice::dasopr(&common::kernel("test.bds"));
common::assert_ok("dasopr");
let (dladsc, found) = spice::dlabfs(handle);
assert!(found, "the test DSK should hold one segment");
(handle, dladsc)
}
#[test]
#[serial]
fn das_and_dla() {
common::load();
let (handle, first) = segment();
assert!(handle != 0);
let (last, found) = spice::dlabbs(handle);
assert!(found);
assert_eq!(first.ibase, last.ibase);
assert_eq!(first.dbase, last.dbase);
assert!(!spice::dlafns(handle, first).1);
spice::dascls(handle);
common::assert_ok("dascls");
common::unload();
}
#[test]
#[serial]
fn dskgd() {
common::load();
let (handle, dladsc) = segment();
let descriptor = spice::dskgd(handle, dladsc);
assert_eq!(descriptor.surfce, common::SURFACE);
assert_eq!(descriptor.center, common::TARGET);
assert_eq!(descriptor.dtype, 2, "a type 2, plate model, segment");
assert_eq!(descriptor.dclass, 2, "a general surface");
assert_eq!(descriptor.corsys, 1, "latitudinal coordinates");
assert_relative_eq!(descriptor.co3max, common::SHAPE_RADIUS, epsilon = 1e-9);
assert_relative_eq!(descriptor.start, common::FIRST, epsilon = 1e-9);
assert_relative_eq!(descriptor.stop, common::LAST, epsilon = 1e-9);
spice::dascls(handle);
common::unload();
}
#[test]
#[serial]
fn dskz02() {
common::load();
let (handle, dladsc) = segment();
assert_eq!(spice::dskz02(handle, dladsc), (6, 8), "an octahedron");
spice::dascls(handle);
common::unload();
}
#[test]
#[serial]
fn dskv02() {
common::load();
let (handle, dladsc) = segment();
let vertices = spice::dskv02(handle, dladsc);
assert_eq!(vertices, common::octahedron_vertices());
assert_eq!(
spice::raw::dskv02(handle, dladsc, 2, 2),
vertices[1..3].to_vec()
);
assert_eq!(spice::raw::dskv02(handle, dladsc, 1, 100).len(), 6);
spice::dascls(handle);
common::unload();
}
#[test]
#[serial]
fn dskp02() {
common::load();
let (handle, dladsc) = segment();
let plates = spice::dskp02(handle, dladsc);
assert_eq!(plates, common::octahedron_plates());
assert_eq!(
spice::raw::dskp02(handle, dladsc, 1, 3),
plates[..3].to_vec()
);
spice::dascls(handle);
common::unload();
}
#[test]
#[serial]
fn dskn02() {
common::load();
let (handle, dladsc) = segment();
let normal = spice::dskn02(handle, dladsc, 1);
let third = 1.0 / 3f64.sqrt();
assert_slice_eq(&normal, &[third, third, third], 1e-12);
for plate in 1..=8 {
let normal = spice::dskn02(handle, dladsc, plate);
assert_relative_eq!(spice::vnorm(normal), 1.0, epsilon = 1e-12);
}
spice::dascls(handle);
common::unload();
}
#[test]
#[serial]
fn dskx02() {
common::load();
let (handle, dladsc) = segment();
let vertex = [3.0 * common::SHAPE_RADIUS; 3];
let raydir = spice::vminus(spice::vhat(vertex));
let (plate, point, found) = spice::dskx02(handle, dladsc, vertex, raydir);
assert!(found);
assert_eq!(plate, 1);
assert_slice_eq(&point, &[common::SHAPE_RADIUS / 3.0; 3], 1e-9);
assert!(!spice::dskx02(handle, dladsc, vertex, spice::vhat(vertex)).2);
spice::dascls(handle);
common::unload();
}
#[test]
#[serial]
fn dskobj_and_dsksrf() {
common::load();
let dsk = common::kernel("test.bds");
let bodies = spice::dskobj(&dsk);
assert_eq!(bodies.to_vec(), vec![common::TARGET]);
let surfaces = spice::dsksrf(&dsk, common::TARGET);
assert_eq!(surfaces.to_vec(), vec![common::SURFACE]);
assert!(spice::dsksrf(&dsk, 499).is_empty());
common::unload();
}
#[test]
#[serial]
fn tolerances() {
common::load();
let keyword = spice::raw::DSK_KEYXFR;
let original = spice::dskgtl(keyword);
common::assert_ok("dskgtl");
assert!(
original > 0.0,
"the plate expansion fraction defaults to 1e-10"
);
spice::dskstl(keyword, original * 2.0);
common::assert_ok("dskstl");
assert_relative_eq!(spice::dskgtl(keyword), original * 2.0, epsilon = 1e-15);
spice::dskstl(keyword, original);
assert_relative_eq!(spice::dskgtl(keyword), original, epsilon = 1e-15);
common::unload();
}
#[test]
#[serial]
fn write_and_read_back() {
common::load();
let path = common::kernel("written.bds");
let _ = std::fs::remove_file(&path);
let vertices = vec![[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
let plates = vec![[1, 2, 3]];
let (spaixd, spaixi) = spice::dskmi2(
&vertices, &plates, 0.1, 4, 100_000, 10_000, 10_000, true, 200_000,
);
common::assert_ok("dskmi2");
assert_eq!(spaixd.len(), spice::raw::DSK02_SPADSZ);
assert_eq!(spice::raw::DSK_NSYPAR, 10);
let handle = spice::dskopn(&path, "rust-spice written DSK", 0);
common::assert_ok("dskopn");
spice::dskw02(
handle,
common::TARGET,
2,
2,
"IAU_EARTH",
1,
&[0.0; 10],
-std::f64::consts::PI,
std::f64::consts::PI,
-std::f64::consts::FRAC_PI_2,
std::f64::consts::FRAC_PI_2,
0.0,
2.0,
common::FIRST,
common::LAST,
&vertices,
&plates,
&spaixd,
&spaixi,
);
spice::dskcls(handle, true);
common::assert_ok("dskw02");
let handle = spice::dasopr(&path);
let (dladsc, found) = spice::dlabfs(handle);
assert!(found);
assert_eq!(spice::dskz02(handle, dladsc), (3, 1));
assert_eq!(spice::dskv02(handle, dladsc), vertices);
assert_eq!(spice::dskp02(handle, dladsc), plates);
spice::dascls(handle);
common::assert_ok("reading back the written DSK");
common::unload();
let _ = std::fs::remove_file(&path);
}
#[test]
#[serial]
#[should_panic(expected = "dskw02 needs")]
fn dskw02_rejects_too_few_coordinate_parameters() {
common::load();
spice::dskw02(
1,
common::TARGET,
1,
2,
"IAU_EARTH",
1,
&[0.0; 3],
0.0,
1.0,
0.0,
1.0,
0.0,
1.0,
common::FIRST,
common::LAST,
&[[0.0; 3]; 3],
&[[1, 2, 3]],
&[0.0; 10],
&[0; 10],
);
}
#[test]
#[serial]
fn dskxv() {
common::load();
let vertex = [3.0 * common::SHAPE_RADIUS; 3];
let inward = spice::vminus(spice::vhat(vertex));
let outward = spice::vhat(vertex);
let (points, found) = spice::dskxv(
false,
"EARTH",
&[],
common::EPOCH,
"IAU_EARTH",
&[vertex, vertex],
&[inward, outward],
);
common::assert_ok("dskxv");
assert_eq!(points.len(), 2);
assert_eq!(
found,
vec![true, false],
"one ray hits, the one aimed away misses"
);
assert_slice_eq(&points[0], &[common::SHAPE_RADIUS / 3.0; 3], 1e-9);
common::unload();
}
#[test]
#[serial]
fn dskxsi() {
common::load();
let vertex = [3.0 * common::SHAPE_RADIUS; 3];
let raydir = spice::vminus(spice::vhat(vertex));
let (point, handle, _dladsc, dskdsc, _dc, ic, found) = spice::dskxsi(
false,
"EARTH",
&[],
common::EPOCH,
"IAU_EARTH",
vertex,
raydir,
);
common::assert_ok("dskxsi");
assert!(found);
assert_slice_eq(&point, &[common::SHAPE_RADIUS / 3.0; 3], 1e-9);
assert!(handle != 0);
assert_eq!(dskdsc.center, common::TARGET);
assert_eq!(dskdsc.surfce, common::SURFACE);
assert_eq!(ic[0], 1);
assert_eq!(ic.len(), spice::raw::DSKXSI_ICSIZE);
let (points, _) = spice::dskxv(
false,
"EARTH",
&[],
common::EPOCH,
"IAU_EARTH",
&[vertex],
&[raydir],
);
assert_slice_eq(&point, &points[0], 0.0);
common::unload();
}