1use bincode::de::{BorrowDecode, BorrowDecoder, Decode, Decoder};
2use bincode::enc::{Encode, Encoder};
3use bincode::error::{DecodeError, EncodeError};
4use cu29_clock::CuTime;
5use cu29_soa_derive::Soa;
6use derive_more::{Add, Deref, Div, From, Mul, Sub};
7use serde::Serialize;
8use uom::si::f32::{Length, Ratio};
9use uom::si::length::meter;
10use uom::si::ratio::percent;
11
12#[derive(Default, PartialEq, Debug, Copy, Clone, Add, Deref, Sub, From, Mul, Div, Serialize)]
13pub struct Reflectivity(Ratio);
14
15impl From<f32> for Reflectivity {
16 fn from(value: f32) -> Self {
17 Self(Ratio::new::<percent>(value))
18 }
19}
20
21impl Encode for Reflectivity {
23 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
24 let Reflectivity(ratio) = self;
25 Encode::encode(&ratio.value, encoder)
26 }
27}
28
29impl Decode<()> for Reflectivity {
31 fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
32 let value: f32 = Decode::decode(decoder)?;
33 Ok(Reflectivity(Ratio::new::<percent>(value)))
34 }
35}
36
37impl<'de> BorrowDecode<'de, ()> for Reflectivity {
39 fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
40 let value: f32 = Decode::decode(decoder)?;
41 Ok(Reflectivity(Ratio::new::<percent>(value)))
42 }
43}
44
45#[derive(Default, PartialEq, Debug, Copy, Clone, Add, Deref, Sub, From, Mul, Div, Serialize)]
46pub struct Distance(pub Length);
47
48impl Encode for Distance {
50 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
51 let Distance(length) = self;
52 Encode::encode(&length.value, encoder)
53 }
54}
55
56impl From<f32> for Distance {
57 fn from(value: f32) -> Self {
58 Self(Length::new::<meter>(value))
59 }
60}
61
62impl Decode<()> for Distance {
64 fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
65 let value: f32 = Decode::decode(decoder)?;
66 Ok(Distance(Length::new::<meter>(value)))
67 }
68}
69
70impl<'de> BorrowDecode<'de, ()> for Distance {
72 fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
73 let value: f32 = Decode::decode(decoder)?;
74 Ok(Distance(Length::new::<meter>(value)))
75 }
76}
77
78#[derive(Default, Clone, PartialEq, Debug, Soa, Serialize)]
83pub struct PointCloud {
84 pub tov: CuTime, pub x: Distance,
86 pub y: Distance,
87 pub z: Distance,
88 pub i: Reflectivity,
89 pub return_order: u8, }
91
92impl Encode for PointCloud {
93 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
94 self.tov.encode(encoder)?;
95 self.x.encode(encoder)?;
96 self.y.encode(encoder)?;
97 self.z.encode(encoder)?;
98 self.i.encode(encoder)?;
99 self.return_order.encode(encoder)
100 }
101}
102
103impl Decode<()> for PointCloud {
104 fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, DecodeError> {
105 let tov = CuTime::decode(decoder)?;
106 let x = Distance::decode(decoder)?;
107 let y = Distance::decode(decoder)?;
108 let z = Distance::decode(decoder)?;
109 let i = Reflectivity::decode(decoder)?;
110 let return_order = u8::decode(decoder)?;
111 Ok(PointCloud {
112 tov,
113 x,
114 y,
115 z,
116 i,
117 return_order,
118 })
119 }
120}
121
122impl PointCloud {
123 pub fn new(tov: CuTime, x: f32, y: f32, z: f32, i: f32, return_order: Option<u8>) -> Self {
124 Self {
125 tov,
126 x: Distance(Length::new::<meter>(x)),
127 y: Distance(Length::new::<meter>(y)),
128 z: Distance(Length::new::<meter>(z)),
129 i: Reflectivity(Ratio::new::<percent>(i)),
130 return_order: return_order.unwrap_or(0),
131 }
132 }
133
134 pub fn new_uom(
135 tov: CuTime,
136 x: Length,
137 y: Length,
138 z: Length,
139 i: Ratio,
140 return_order: Option<u8>,
141 ) -> Self {
142 Self {
143 tov,
144 x: Distance(x),
145 y: Distance(y),
146 z: Distance(z),
147 i: Reflectivity(i),
148 return_order: return_order.unwrap_or(0),
149 }
150 }
151}
152
153impl<const N: usize> PointCloudSoa<N> {
154 pub fn sort(&mut self) {
156 self.quicksort(0, N - 1);
157 }
158
159 fn quicksort(&mut self, low: usize, high: usize) {
161 if low < high {
162 let pivot_index = self.partition(low, high);
163 if pivot_index > 0 {
164 self.quicksort(low, pivot_index - 1);
165 }
166 self.quicksort(pivot_index + 1, high);
167 }
168 }
169
170 fn partition(&mut self, low: usize, high: usize) -> usize {
172 let pivot = self.tov[high];
173 let mut i = low;
174 for j in low..high {
175 if self.tov[j] <= pivot {
176 self.swap(i, j);
177 i += 1;
178 }
179 }
180 self.swap(i, high);
181 i
182 }
183
184 pub fn swap(&mut self, a: usize, b: usize) {
186 self.tov.swap(a, b);
187 self.x.swap(a, b);
188 self.y.swap(a, b);
189 self.z.swap(a, b);
190 self.i.swap(a, b);
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197 use cu29_clock::CuDuration;
198
199 #[test]
200 fn test_point_payload() {
201 let payload = PointCloud::new(CuDuration(1), 1.0, 2.0, 3.0, 0.0, None);
202 assert_eq!(payload.x.0.value, 1.0);
203 assert_eq!(payload.y.0.value, 2.0);
204 assert_eq!(payload.z.0.value, 3.0);
205 }
206
207 #[test]
208 fn test_length_add_sub() {
209 let a = Distance(Length::new::<meter>(1.0));
210 let b = Distance(Length::new::<meter>(2.0));
211 let c = a + b;
212 assert_eq!(c.value, 3.0);
213 let d = c - a;
214 assert_eq!(d.value, 2.0);
215 }
216
217 #[test]
218 fn test_encoding_length() {
219 let a = Distance(Length::new::<meter>(1.0));
220 let mut encoded = vec![0u8; 1024]; let length =
223 bincode::encode_into_slice(a, &mut encoded, bincode::config::standard()).unwrap();
224 assert_eq!(length, 4);
225 }
226}