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