1use crate::safety_assert;
2use serde::Serialize;
3
4use kiddo::immutable::float::kdtree::ImmutableKdTree;
5use kiddo::SquaredEuclidean;
6
7use super::buffer;
8use crate::bit_coder::{ByteReader, ByteWriter};
9use crate::types::DataValue;
10use crate::types::{AttributeValueIdx, PointIdx, VecPointIdx, Vector};
11
12fn vector_to_f64_array<Data: Vector<N>, const N: usize>(v: &Data) -> [f64; N] {
13 let mut out = [0.0f64; N];
14 for (i, slot) in out.iter_mut().enumerate() {
15 *slot = (*v.get(i)).to_f64();
16 }
17 out
18}
19
20#[derive(Debug, thiserror::Error)]
21pub enum Err {
22 #[error("Invalid attribute domain id: {0}")]
24 InvalidAttributeDomainId(u8),
25 #[error("Reader error: {0}")]
27 ReaderError(#[from] crate::bit_coder::ReaderErr),
28 #[error("Invalid DataTypeId: {0}")]
29 InvalidDataTypeId(u8),
30}
31
32#[derive(Debug, Clone)]
38pub struct Attribute {
39 id: AttributeId,
41
42 buffer: buffer::attribute::AttributeBuffer,
44
45 att_type: AttributeType,
47
48 domain: AttributeDomain,
50
51 parents: Vec<AttributeId>,
53
54 point_to_att_val_map: Option<VecPointIdx<AttributeValueIdx>>,
58
59 name: Option<String>,
61}
62
63impl Attribute {
64 pub fn new<Data, const N: usize>(
65 data: Vec<Data>,
66 att_type: AttributeType,
67 domain: AttributeDomain,
68 parents: Vec<AttributeId>,
69 ) -> Self
70 where
71 Data: Vector<N>,
72 {
73 let id = AttributeId::new(0); let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
75 let mut out = Self {
76 id,
77 buffer,
78 parents,
79 att_type,
80 domain,
81 point_to_att_val_map: None,
82 name: None,
83 };
84 out.remove_duplicate_values::<Data, N>();
85 out
86 }
87
88 pub fn new_empty(
89 id: AttributeId,
90 att_type: AttributeType,
91 domain: AttributeDomain,
92 component_type: ComponentDataType,
93 num_components: usize,
94 ) -> Self {
95 let buffer = buffer::attribute::AttributeBuffer::new(component_type, num_components);
96 Self {
97 id,
98 buffer,
99 parents: Vec::new(),
100 att_type,
101 domain,
102 point_to_att_val_map: None,
103 name: None,
104 }
105 }
106
107 pub fn from<Data, const N: usize>(
108 id: AttributeId,
109 data: Vec<Data>,
110 att_type: AttributeType,
111 domain: AttributeDomain,
112 parents: Vec<AttributeId>,
113 ) -> Self
114 where
115 Data: Vector<N>,
116 {
117 let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
118 let mut out = Self {
119 id,
120 buffer,
121 parents,
122 att_type,
123 domain,
124 point_to_att_val_map: None,
125 name: None,
126 };
127 out.remove_duplicate_values::<Data, N>();
128 out
129 }
130
131 pub fn from_without_removing_duplicates<Data, const N: usize>(
132 id: AttributeId,
133 data: Vec<Data>,
134 att_type: AttributeType,
135 domain: AttributeDomain,
136 parents: Vec<AttributeId>,
137 ) -> Self
138 where
139 Data: Vector<N>,
140 {
141 let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
142 Self {
143 id,
144 buffer,
145 parents,
146 att_type,
147 domain,
148 point_to_att_val_map: None,
149 name: None,
150 }
151 }
152
153 pub fn get<Data, const N: usize>(&self, p_idx: PointIdx) -> Data
154 where
155 Data: Vector<N>,
156 Data::Component: DataValue,
157 {
158 self.buffer.get(self.get_unique_val_idx(p_idx))
159 }
160
161 pub fn get_unique_val<Data, const N: usize>(&self, val_idx: AttributeValueIdx) -> Data
162 where
163 Data: Vector<N>,
164 Data::Component: DataValue,
165 {
166 self.buffer.get(val_idx)
167 }
168
169 pub fn get_component_type(&self) -> ComponentDataType {
170 self.buffer.get_component_type()
171 }
172
173 #[inline]
174 #[allow(unused)]
175 pub fn set_component_type(&mut self, component_type: ComponentDataType) {
176 self.buffer.set_component_type(component_type);
177 }
178
179 #[inline]
180 #[allow(unused)]
181 pub fn set_num_components(&mut self, num_components: usize) {
182 self.buffer.set_num_components(num_components);
183 }
184
185 pub fn get_data_as_bytes(&self) -> &[u8] {
186 self.buffer.as_slice_u8()
187 }
188
189 #[inline]
190 #[allow(unused)]
191 pub fn get_as_bytes(&self, i: usize) -> &[u8] {
192 &self.buffer.as_slice_u8()[i
193 * self.buffer.get_num_components()
194 * self.buffer.get_component_type().size()
195 ..(i + 1) * self.buffer.get_num_components() * self.buffer.get_component_type().size()]
196 }
197
198 pub fn set_point_to_att_val_map(
199 &mut self,
200 point_to_att_val_map: Option<VecPointIdx<AttributeValueIdx>>,
201 ) {
202 self.point_to_att_val_map = point_to_att_val_map;
203 }
204
205 pub fn take_point_to_att_val_map(self) -> Option<VecPointIdx<AttributeValueIdx>> {
206 self.point_to_att_val_map
207 }
208
209 #[inline]
210 pub fn get_id(&self) -> AttributeId {
211 self.id
212 }
213
214 #[inline]
215 pub fn get_num_components(&self) -> usize {
216 self.buffer.get_num_components()
217 }
218
219 #[inline]
220 pub fn get_attribute_type(&self) -> AttributeType {
221 self.att_type
222 }
223
224 #[inline]
225 pub fn get_domain(&self) -> AttributeDomain {
226 self.domain
227 }
228
229 #[inline]
230 pub fn get_parents(&self) -> &Vec<AttributeId> {
231 self.parents.as_ref()
232 }
233
234 #[inline(always)]
236 pub fn len(&self) -> usize {
237 if let Some(f) = &self.point_to_att_val_map {
238 f.len()
239 } else {
240 self.buffer.len()
241 }
242 }
243
244 #[inline(always)]
246 pub fn is_empty(&self) -> bool {
247 self.len() == 0
248 }
249
250 #[inline(always)]
251 pub fn num_unique_values(&self) -> usize {
252 self.buffer.len()
253 }
254
255 pub fn mint(&mut self, src: PointIdx) -> PointIdx {
264 let src_val = self.get_unique_val_idx(src);
265 let num_unique = self.num_unique_values();
266 let map = self.point_to_att_val_map.get_or_insert_with(|| {
267 (0..num_unique)
268 .map(AttributeValueIdx::from)
269 .collect::<Vec<_>>()
270 .into()
271 });
272 let new_idx = PointIdx::from(map.len());
273 map.push(src_val);
274 new_idx
275 }
276
277 #[inline]
278 pub fn get_unique_val_idx(&self, idx: PointIdx) -> AttributeValueIdx {
279 let idx_usize = usize::from(idx);
280 assert!(
281 idx_usize < self.len(),
282 "Index out of bounds: idx = {}, len = {}",
283 idx_usize,
284 self.len()
285 );
286 if let Some(ref point_to_att_val_map) = self.point_to_att_val_map {
287 point_to_att_val_map[idx]
288 } else {
289 idx_usize.into()
291 }
292 }
293
294 #[inline]
295 pub fn set_name(&mut self, name: String) {
296 self.name = Some(name);
297 }
298
299 #[inline]
300 pub fn get_name(&self) -> Option<&String> {
301 self.name.as_ref()
302 }
303
304 #[inline]
306 pub fn unique_vals_as_slice<Data>(&self) -> &[Data] {
307 assert_eq!(
308 self.buffer.get_num_components() * self.buffer.get_component_type().size(),
309 std::mem::size_of::<Data>(),
310 );
311 unsafe { self.buffer.as_slice::<Data>() }
312 }
313
314 #[inline]
316 pub fn unique_vals_as_slice_mut<Data>(&mut self) -> &mut [Data] {
317 assert_eq!(
318 self.buffer.get_num_components() * self.buffer.get_component_type().size(),
319 std::mem::size_of::<Data>(),
320 );
321 unsafe { self.buffer.as_slice_mut::<Data>() }
322 }
323
324 #[inline]
328 pub unsafe fn unique_vals_as_slice_unchecked<Data>(&self) -> &[Data] {
329 self.buffer.as_slice::<Data>()
331 }
332
333 #[inline]
337 pub unsafe fn unique_vals_as_slice_unchecked_mut<Data>(&mut self) -> &mut [Data] {
338 self.buffer.as_slice_mut::<Data>()
340 }
341
342 pub fn permute(&mut self, indices: &[usize]) {
345 assert!(
346 indices.len() == self.len(),
347 "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
348 indices.len(),
349 self.len()
350 );
351 assert!(
352 indices.iter().all(|&i| i < self.len()),
353 "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
354 indices,
355 self.len()
356 );
357 unsafe {
358 self.buffer.permute_unchecked(indices);
359 }
360 }
361
362 pub fn permute_unchecked(&mut self, indices: &[usize]) {
367 safety_assert!(
368 indices.len() == self.len(),
369 "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
370 indices.len(),
371 self.len()
372 );
373 safety_assert!(
374 indices.iter().all(|&i| i < self.len()),
375 "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
376 indices,
377 self.len()
378 );
379 unsafe {
380 self.buffer.permute_unchecked(indices);
381 }
382 }
383
384 pub fn swap(&mut self, i: usize, j: usize) {
386 assert!(
387 i < self.len() && j < self.len(),
388 "Indices out of bounds: i = {}, j = {}, len = {}",
389 i,
390 j,
391 self.len()
392 );
393 unsafe {
394 self.buffer.swap_unchecked(i, j);
395 }
396 }
397
398 pub fn take_values<Data, const N: usize>(self) -> Vec<Data>
399 where
400 Data: Vector<N>,
401 {
402 assert_eq!(self.get_num_components(), N,);
403 assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
404
405 unsafe { self.buffer.into_vec_unchecked::<Data, N>() }
406 }
407
408 pub fn into_parts<Data, const N: usize>(
409 mut self,
410 ) -> (Vec<Data>, Option<VecPointIdx<AttributeValueIdx>>, Self)
411 where
412 Data: Vector<N>,
413 {
414 let num_components = self.get_num_components();
415 let component_type = self.get_component_type();
416 assert_eq!(num_components, N,);
417 assert_eq!(component_type, Data::Component::get_dyn(),);
418 let mut new_buffer = buffer::attribute::AttributeBuffer::from_vec(Vec::<Data>::new());
419 std::mem::swap(&mut self.buffer, &mut new_buffer);
420 let data = unsafe { new_buffer.into_vec_unchecked::<Data, N>() };
421
422 let mut point_to_att_val_map = None;
423 std::mem::swap(&mut point_to_att_val_map, &mut self.point_to_att_val_map);
424
425 (data, point_to_att_val_map, self)
426 }
427
428 pub fn set_values<Data, const N: usize>(&mut self, data: Vec<Data>)
429 where
430 Data: Vector<N>,
431 {
432 assert_eq!(self.get_num_components(), N,);
433 assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
434 assert_eq!(self.len(), 0);
435 self.buffer = buffer::attribute::AttributeBuffer::from_vec(data);
436 }
437
438 pub fn remove_duplicate_values<Data, const N: usize>(&mut self)
439 where
440 Data: Vector<N>,
441 {
442 let n = self.len();
443 if n <= 1 {
444 return;
445 }
446
447 let values = self.unique_vals_as_slice::<Data>();
448
449 let f64_points: Vec<[f64; N]> = values.iter().map(|v| vector_to_f64_array(v)).collect();
451
452 let tree = ImmutableKdTree::<f64, u32, N, 32>::new_from_slice(&f64_points);
454
455 let mut canonical_index = vec![usize::MAX; n];
458 let mut has_duplicates = false;
459
460 for i in 0..n {
461 if canonical_index[i] != usize::MAX {
462 continue;
464 }
465 canonical_index[i] = i; let neighbors = tree.within_unsorted::<SquaredEuclidean>(&f64_points[i], f64::EPSILON);
469
470 for neighbor in &neighbors {
471 let j = neighbor.item as usize;
472 if j <= i || canonical_index[j] != usize::MAX {
473 continue;
474 }
475 if values[i] == values[j] {
477 canonical_index[j] = i;
478 has_duplicates = true;
479 }
480 }
481 }
482
483 if !has_duplicates {
484 return;
485 }
486
487 let mut old_to_new = vec![0usize; n];
489 let mut keep_indices = Vec::new();
490 let mut new_idx = 0;
491 for i in 0..n {
492 if canonical_index[i] == i {
493 old_to_new[i] = new_idx;
495 keep_indices.push(i);
496 new_idx += 1;
497 }
498 }
499
500 let map_data: Vec<AttributeValueIdx> = (0..n)
502 .map(|i| old_to_new[canonical_index[i]].into())
503 .collect();
504 self.point_to_att_val_map = Some(VecPointIdx::<_>::from(map_data));
505
506 self.buffer.retain_indices(&keep_indices);
508 }
509
510 #[allow(unused)]
511 pub fn remove<Data, const N: usize>(&mut self, p_idx: PointIdx) {
512 let p_idx_usize = usize::from(p_idx);
513 assert!(
514 p_idx_usize < self.len(),
515 "Point index out of bounds: {}",
516 p_idx_usize
517 );
518 if let Some(ref mut point_to_att_val_map) = self.point_to_att_val_map {
519 if (0..point_to_att_val_map.len())
521 .map(PointIdx::from)
522 .filter(|&p| p != p_idx)
523 .any(|p| point_to_att_val_map[p] == point_to_att_val_map[p_idx])
524 {
525 point_to_att_val_map.remove(p_idx);
527 } else {
528 let removed_unique_val_idx = point_to_att_val_map.remove(p_idx);
529 self.buffer.remove::<Data, N>(removed_unique_val_idx.into());
530 for p in 0..point_to_att_val_map.len() {
532 let p = PointIdx::from(p);
533 if point_to_att_val_map[p] > removed_unique_val_idx {
534 point_to_att_val_map[p] = (usize::from(point_to_att_val_map[p]) - 1).into();
535 }
536 }
537 }
538 } else {
539 let a_idx = AttributeValueIdx::from(usize::from(p_idx));
541 self.remove_unique_val::<Data, N>(a_idx);
542 }
543 }
544
545 #[allow(unused)]
546 pub fn remove_dyn(&mut self, p_idx: PointIdx) {
547 assert!(
548 usize::from(p_idx) < self.len(),
549 "Point index out of bounds: {}",
550 usize::from(p_idx)
551 );
552 match self.get_component_type().size() * self.get_num_components() {
553 1 => self.remove::<u8, 1>(p_idx),
554 2 => self.remove::<u16, 1>(p_idx),
555 4 => self.remove::<u32, 1>(p_idx),
556 6 => self.remove::<u16, 3>(p_idx),
557 8 => self.remove::<u64, 1>(p_idx),
558 12 => self.remove::<u32, 3>(p_idx),
559 16 => self.remove::<u64, 2>(p_idx),
560 18 => self.remove::<u64, 3>(p_idx),
561 _ => panic!(
562 "Unsupported component size: {}",
563 self.get_component_type().size()
564 ),
565 }
566 }
567
568 #[allow(unused)]
569 pub fn remove_unique_val<Data, const N: usize>(&mut self, val_idx: AttributeValueIdx) {
570 let val_idx = usize::from(val_idx);
571 assert!(
572 val_idx < self.num_unique_values(),
573 "Attribute value index out of bounds: {}",
574 val_idx
575 );
576 self.buffer.remove::<Data, N>(val_idx);
577 if let Some(ref mut _point_to_att_val_map) = self.point_to_att_val_map {
578 unimplemented!();
579 }
580 }
581
582 pub fn remove_unique_val_dyn(&mut self, val_idx: usize) {
583 assert!(
584 val_idx < self.num_unique_values(),
585 "Attribute value index out of bounds: {}",
586 val_idx
587 );
588 match self.get_component_type().size() * self.get_num_components() {
589 1 => self.buffer.remove::<u8, 1>(val_idx),
590 2 => self.buffer.remove::<u16, 1>(val_idx),
591 4 => self.buffer.remove::<u32, 1>(val_idx),
592 6 => self.buffer.remove::<u16, 3>(val_idx),
593 8 => self.buffer.remove::<u64, 1>(val_idx),
594 12 => self.buffer.remove::<u32, 3>(val_idx),
595 16 => self.buffer.remove::<u64, 2>(val_idx),
596 18 => self.buffer.remove::<u64, 3>(val_idx),
597 _ => panic!(
598 "Unsupported component size: {}",
599 self.get_component_type().size()
600 ),
601 }
602 }
603
604 pub fn retain_points_dyn(&mut self, keep_point_indices: &[usize]) {
607 if let Some(ref map) = self.point_to_att_val_map {
608 let num_unique = self.buffer.len();
610 let mut unique_val_referenced = vec![false; num_unique];
611 let mut new_map = Vec::with_capacity(keep_point_indices.len());
612
613 for &p in keep_point_indices {
614 let val_idx = map[PointIdx::from(p)];
615 unique_val_referenced[usize::from(val_idx)] = true;
616 new_map.push(val_idx);
617 }
618
619 let mut old_unique_to_new = vec![0usize; num_unique];
621 let mut keep_unique_indices = Vec::new();
622 let mut new_unique_idx = 0;
623 for i in 0..num_unique {
624 if unique_val_referenced[i] {
625 old_unique_to_new[i] = new_unique_idx;
626 keep_unique_indices.push(i);
627 new_unique_idx += 1;
628 }
629 }
630
631 let new_map: Vec<AttributeValueIdx> = new_map
633 .iter()
634 .map(|&val_idx| old_unique_to_new[usize::from(val_idx)].into())
635 .collect();
636 self.point_to_att_val_map = Some(VecPointIdx::from(new_map));
637
638 self.buffer.retain_indices(&keep_unique_indices);
640 } else {
641 self.buffer.retain_indices(keep_point_indices);
643 }
644 }
645}
646
647#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
648pub enum ComponentDataType {
649 I8,
650 U8,
651 I16,
652 U16,
653 I32,
654 U32,
655 I64,
656 U64,
657 F32,
658 F64,
659 Invalid,
660}
661
662impl ComponentDataType {
663 #[inline]
665 pub fn size(self) -> usize {
666 match self {
667 ComponentDataType::F32 => 4,
668 ComponentDataType::F64 => 8,
669 ComponentDataType::U8 => 1,
670 ComponentDataType::U16 => 2,
671 ComponentDataType::U32 => 4,
672 ComponentDataType::U64 => 8,
673 ComponentDataType::I8 => 1,
674 ComponentDataType::I16 => 2,
675 ComponentDataType::I32 => 4,
676 ComponentDataType::I64 => 8,
677 ComponentDataType::Invalid => 0,
678 }
679 }
680
681 #[inline]
682 pub fn is_float(self) -> bool {
683 matches!(self, ComponentDataType::F32 | ComponentDataType::F64)
684 }
685
686 #[inline]
688 pub fn get_id(self) -> u8 {
689 match self {
690 ComponentDataType::U8 => 1,
691 ComponentDataType::I8 => 2,
692 ComponentDataType::U16 => 3,
693 ComponentDataType::I16 => 4,
694 ComponentDataType::U32 => 5,
695 ComponentDataType::I32 => 6,
696 ComponentDataType::U64 => 7,
697 ComponentDataType::I64 => 8,
698 ComponentDataType::F32 => 9,
699 ComponentDataType::F64 => 10,
700 ComponentDataType::Invalid => u8::MAX, }
702 }
703
704 #[inline]
706 pub fn write_to<W: ByteWriter>(self, writer: &mut W) {
707 writer.write_u8(self.get_id());
708 }
709
710 #[inline]
712 pub fn from_id(id: usize) -> Option<Self> {
713 match id {
714 1 => Some(ComponentDataType::I8),
715 2 => Some(ComponentDataType::U8),
716 3 => Some(ComponentDataType::I16),
717 4 => Some(ComponentDataType::U16),
718 5 => Some(ComponentDataType::I32),
719 6 => Some(ComponentDataType::U32),
720 7 => Some(ComponentDataType::I64),
721 8 => Some(ComponentDataType::U64),
722 9 => Some(ComponentDataType::F32),
723 10 => Some(ComponentDataType::F64),
724 _ => None,
725 }
726 }
727
728 #[inline]
730 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
731 let id = reader.read_u8()?;
732 Self::from_id(id as usize).ok_or(Err::InvalidDataTypeId(id))
733 }
734}
735
736#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
737pub enum AttributeType {
738 Position,
739 Normal,
740 Color,
741 TextureCoordinate,
742 Custom,
743 Tangent,
744 Material,
745 Joint,
746 Weight,
747 Invalid,
748}
749
750impl AttributeType {
751 pub fn get_minimum_dependency(&self) -> Vec<Self> {
752 match self {
753 Self::Position => Vec::new(),
754 Self::Normal => Vec::new(),
755 Self::Color => Vec::new(),
756 Self::TextureCoordinate => vec![Self::Position],
757 Self::Tangent => Vec::new(),
758 Self::Material => Vec::new(),
759 Self::Joint => Vec::new(),
760 Self::Weight => Vec::new(),
761 Self::Custom => Vec::new(),
762 Self::Invalid => Vec::new(),
763 }
764 }
765
766 #[inline]
768 pub fn get_id(&self) -> u8 {
769 match self {
770 Self::Position => 0,
771 Self::Normal => 1,
772 Self::Color => 2,
773 Self::TextureCoordinate => 3,
774 Self::Custom => 4,
775 Self::Tangent => 5,
776 Self::Material => 6,
777 Self::Joint => 7,
778 Self::Weight => 8,
779 Self::Invalid => u8::MAX, }
781 }
782
783 #[inline]
785 pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
786 writer.write_u8(self.get_id());
787 }
788
789 #[inline]
791 pub fn from_id(id: u8) -> Result<Self, Err> {
792 match id {
793 0 => Ok(Self::Position),
794 1 => Ok(Self::Normal),
795 2 => Ok(Self::Color),
796 3 => Ok(Self::TextureCoordinate),
797 4 => Ok(Self::Custom),
798 5 => Ok(Self::Tangent),
799 6 => Ok(Self::Material),
800 7 => Ok(Self::Joint),
801 8 => Ok(Self::Weight),
802 _ => Err(Err::InvalidDataTypeId(id)),
803 }
804 }
805
806 #[inline]
808 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
809 let id = reader.read_u8()?;
810 Self::from_id(id)
811 }
812}
813
814#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
816pub enum AttributeDomain {
817 Position,
819 Corner,
821}
822
823impl AttributeDomain {
824 pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
826 match self {
827 Self::Position => writer.write_u8(0),
828 Self::Corner => writer.write_u8(1),
829 }
830 }
831
832 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
834 let id = reader.read_u8()?;
835 match id {
836 0 => Ok(Self::Position),
837 1 => Ok(Self::Corner),
838 _ => Err(Err::InvalidAttributeDomainId(id)),
839 }
840 }
841}
842
843#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
844pub struct AttributeId(usize);
845
846impl AttributeId {
847 pub fn new(id: usize) -> Self {
848 Self(id)
849 }
850
851 pub fn as_usize(&self) -> usize {
853 self.0
854 }
855}
856
857#[cfg(test)]
858mod tests {
859 use super::*;
860 use crate::types::NdVector;
861
862 #[test]
863 fn test_attribute() {
864 let data = vec![
865 NdVector::from([1.0f32, 2.0, 3.0]),
866 NdVector::from([4.0f32, 5.0, 6.0]),
867 NdVector::from([7.0f32, 8.0, 9.0]),
868 ];
869 let att = super::Attribute::from(
870 AttributeId::new(0),
871 data.clone(),
872 super::AttributeType::Position,
873 super::AttributeDomain::Position,
874 Vec::new(),
875 );
876 assert_eq!(att.len(), data.len());
877 assert_eq!(
878 att.get::<NdVector<3, f32>, 3>(0.into()),
879 data[0],
880 "{:b}!={:b}",
881 att.get::<NdVector<3, f32>, 3>(0.into()).get(0).to_bits(),
882 data[0].get(0).to_bits()
883 );
884 assert_eq!(att.get_component_type(), super::ComponentDataType::F32);
885 assert_eq!(att.get_num_components(), 3);
886 assert_eq!(att.get_attribute_type(), super::AttributeType::Position);
887 }
888
889 #[test]
890 fn test_attribute_remap() {
891 let positions = vec![
892 NdVector::from([0.0f32, 0.0, 0.0]), NdVector::from([1.0f32, 0.0, 0.0]), NdVector::from([0.5f32, 1.0, 0.0]), NdVector::from([0.0f32, 0.0, 0.0]), NdVector::from([1.0f32, 0.0, 0.0]), NdVector::from([2.0f32, 0.0, 0.0]), ];
899
900 let att = Attribute::new(
901 positions,
902 AttributeType::Position,
903 AttributeDomain::Position,
904 vec![],
905 );
906
907 assert_eq!(
908 att.point_to_att_val_map
909 .unwrap()
910 .into_iter()
911 .map(usize::from)
912 .collect::<Vec<_>>(),
913 vec![0, 1, 2, 0, 1, 3],
914 )
915 }
916
917 #[test]
918 fn test_remove() {
919 let positions = vec![
920 NdVector::from([0.0f32, 0.0, 0.0]), NdVector::from([1.0f32, 0.0, 0.0]), NdVector::from([2.0f32, 0.0, 0.0]), NdVector::from([3.0f32, 0.0, 0.0]), NdVector::from([2.0f32, 0.0, 0.0]), NdVector::from([5.0f32, 0.0, 0.0]), ];
927
928 let mut att = Attribute::new(
929 positions,
930 AttributeType::Position,
931 AttributeDomain::Position,
932 vec![],
933 );
934
935 assert_eq!(att.len(), 6);
936 assert_eq!(att.num_unique_values(), 5);
937 assert_eq!(
938 &att.point_to_att_val_map
939 .as_ref()
940 .unwrap()
941 .iter()
942 .map(|&i| usize::from(i))
943 .collect::<Vec<_>>(),
944 &vec![0, 1, 2, 3, 2, 4]
945 );
946 att.remove::<NdVector<3, f32>, 3>(PointIdx::from(2)); assert_eq!(att.len(), 5);
948 assert_eq!(att.num_unique_values(), 5);
949 assert_eq!(
950 &att.point_to_att_val_map
951 .as_ref()
952 .unwrap()
953 .iter()
954 .map(|&i| usize::from(i))
955 .collect::<Vec<_>>(),
956 &vec![0, 1, 3, 2, 4]
957 );
958 att.remove::<NdVector<3, f32>, 3>(PointIdx::from(1)); assert_eq!(att.len(), 4);
960 assert_eq!(att.num_unique_values(), 4);
961 assert_eq!(
962 &att.point_to_att_val_map
963 .as_ref()
964 .unwrap()
965 .iter()
966 .map(|&i| usize::from(i))
967 .collect::<Vec<_>>(),
968 &vec![0, 2, 1, 3]
969 );
970 }
971}