Skip to content

Commit 73aab4a

Browse files
feat: add points iterator
1 parent 8210868 commit 73aab4a

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

capt/src/lib.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,24 @@ pub enum NewCaptError {
414414
InvalidLaneCount,
415415
}
416416

417+
/// An iterator over the points in a `[Capt]`.
418+
/// This structure can only be created by `[Capt::points]`.
419+
/// This iterator also skips non-finite points.
420+
///
421+
/// # Examples
422+
///
423+
/// ```
424+
/// # use capt::{Capt, Points};
425+
///
426+
/// let capt = Capt::<1>::new(&[[0.0]], (0.0, f32::INFINITY), 1);
427+
/// let _points: Points<1> = capt.points();
428+
/// ```
429+
pub struct Points<'a, const K: usize, A = f32, I = usize> {
430+
afforded: [&'a [A]; K],
431+
starts: &'a [I],
432+
i: usize,
433+
}
434+
417435
impl<A, I, const K: usize> Capt<K, A, I>
418436
where
419437
A: Axis,
@@ -849,6 +867,27 @@ where
849867
})
850868
}
851869

870+
/// Get an iterator over the points in this Capt.
871+
/// The iterator skips non-finite points.
872+
/// It makes no guarantee of iteration order.
873+
///
874+
///
875+
/// ```
876+
/// # use capt::{Capt, Points};
877+
///
878+
/// let capt = Capt::<2>::new(&[[0.0, 1.0]], (0.0, f32::INFINITY), 1);
879+
/// for point in capt.points() {
880+
/// println!("{point:?}");
881+
/// }
882+
/// ```
883+
pub fn points(&self) -> Points<'_, K, A, I> {
884+
Points {
885+
afforded: self.afforded.each_ref().map(|x| &**x),
886+
starts: &self.starts,
887+
i: 0,
888+
}
889+
}
890+
852891
#[must_use]
853892
#[doc(hidden)]
854893
/// Get the total memory used (stack + heap) by this structure, measured in bytes.
@@ -984,6 +1023,45 @@ where
9841023
}
9851024
}
9861025

1026+
impl<const K: usize, A: Axis, I: Index> Iterator for Points<'_, K, A, I> {
1027+
type Item = [A; K];
1028+
1029+
fn next(&mut self) -> Option<Self::Item> {
1030+
while self.i + 1 < self.starts.len() {
1031+
let j = self.starts[self.i]
1032+
.try_into()
1033+
.map_err(|_| ())
1034+
.expect("must be able to convert index into usize");
1035+
let j2 = self.starts[self.i + 1]
1036+
.try_into()
1037+
.map_err(|_| ())
1038+
.expect("must be able to convert index into usize");
1039+
self.i += 1;
1040+
1041+
if j == j2 {
1042+
// zero points in the afforded set
1043+
continue;
1044+
}
1045+
let ret = self.afforded.map(|a| a[j]);
1046+
1047+
// skip non-finite points
1048+
if ret.iter().all(|x| x.is_finite()) {
1049+
return Some(ret);
1050+
}
1051+
}
1052+
None
1053+
}
1054+
1055+
fn size_hint(&self) -> (usize, Option<usize>) {
1056+
let n = if self.i + 1 >= self.starts.len() {
1057+
0
1058+
} else {
1059+
self.starts.len() - self.i - 1
1060+
};
1061+
(0, Some(n))
1062+
}
1063+
}
1064+
9871065
fn distsq<A: Axis, const K: usize>(a: [A; K], b: [A; K]) -> A {
9881066
let mut total = A::ZERO;
9891067
for i in 0..K {
@@ -1193,4 +1271,37 @@ mod tests {
11931271
assert!(capt.collides(&[0.6, 0.0], 0.2));
11941272
assert!(!capt.collides(&[0.6, 0.0], 0.05));
11951273
}
1274+
1275+
#[test]
1276+
fn get_points() {
1277+
let mut points = [
1278+
[-1.0, 0.0],
1279+
[0.001, 0.0],
1280+
[0.0, 0.5],
1281+
[-1.0, 10.0],
1282+
[-2.0, 10.0],
1283+
[-3.0, 10.0],
1284+
[-0.5, 0.0],
1285+
[-11.0, 1.0],
1286+
[-1.0, -0.5],
1287+
[1.0, 1.0],
1288+
[2.0, 2.0],
1289+
[3.0, 3.0],
1290+
[4.0, 4.0],
1291+
[5.0, 5.0],
1292+
[6.0, 6.0],
1293+
[7.0, 7.0],
1294+
[9.0, 0.0],
1295+
];
1296+
1297+
// sort points in order
1298+
points.sort_by(|p1, p2| p1.partial_cmp(&p2).unwrap());
1299+
1300+
let capt = Capt::<2>::new(&points, (0.0, 0.1), 1);
1301+
println!("{:?}", capt);
1302+
let mut points2 = capt.points().collect::<Vec<_>>();
1303+
points2.sort_by(|p1, p2| p1.partial_cmp(&p2).unwrap());
1304+
1305+
assert_eq!(&points, &*points2);
1306+
}
11961307
}

0 commit comments

Comments
 (0)