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