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)]
245 pub fn num_unique_values(&self) -> usize {
246 self.buffer.len()
247 }
248
249 #[inline]
250 pub fn get_unique_val_idx(&self, idx: PointIdx) -> AttributeValueIdx {
251 let idx_usize = usize::from(idx);
252 assert!(
253 idx_usize < self.len(),
254 "Index out of bounds: idx = {}, len = {}",
255 idx_usize,
256 self.len()
257 );
258 if let Some(ref point_to_att_val_map) = self.point_to_att_val_map {
259 point_to_att_val_map[idx]
260 } else {
261 idx_usize.into()
263 }
264 }
265
266 #[inline]
267 pub fn set_name(&mut self, name: String) {
268 self.name = Some(name);
269 }
270
271 #[inline]
272 pub fn get_name(&self) -> Option<&String> {
273 self.name.as_ref()
274 }
275
276 #[inline]
278 pub fn unique_vals_as_slice<Data>(&self) -> &[Data] {
279 assert_eq!(
280 self.buffer.get_num_components() * self.buffer.get_component_type().size(),
281 std::mem::size_of::<Data>(),
282 );
283 unsafe { self.buffer.as_slice::<Data>() }
284 }
285
286 #[inline]
288 pub fn unique_vals_as_slice_mut<Data>(&mut self) -> &mut [Data] {
289 assert_eq!(
290 self.buffer.get_num_components() * self.buffer.get_component_type().size(),
291 std::mem::size_of::<Data>(),
292 );
293 unsafe { self.buffer.as_slice_mut::<Data>() }
294 }
295
296 #[inline]
300 pub unsafe fn unique_vals_as_slice_unchecked<Data>(&self) -> &[Data] {
301 self.buffer.as_slice::<Data>()
303 }
304
305 #[inline]
309 pub unsafe fn unique_vals_as_slice_unchecked_mut<Data>(&mut self) -> &mut [Data] {
310 self.buffer.as_slice_mut::<Data>()
312 }
313
314 pub fn permute(&mut self, indices: &[usize]) {
317 assert!(
318 indices.len() == self.len(),
319 "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
320 indices.len(),
321 self.len()
322 );
323 assert!(
324 indices.iter().all(|&i| i < self.len()),
325 "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
326 indices,
327 self.len()
328 );
329 unsafe {
330 self.buffer.permute_unchecked(indices);
331 }
332 }
333
334 pub fn permute_unchecked(&mut self, indices: &[usize]) {
339 safety_assert!(
340 indices.len() == self.len(),
341 "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
342 indices.len(),
343 self.len()
344 );
345 safety_assert!(
346 indices.iter().all(|&i| i < self.len()),
347 "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
348 indices,
349 self.len()
350 );
351 unsafe {
352 self.buffer.permute_unchecked(indices);
353 }
354 }
355
356 pub fn swap(&mut self, i: usize, j: usize) {
358 assert!(
359 i < self.len() && j < self.len(),
360 "Indices out of bounds: i = {}, j = {}, len = {}",
361 i,
362 j,
363 self.len()
364 );
365 unsafe {
366 self.buffer.swap_unchecked(i, j);
367 }
368 }
369
370 pub fn take_values<Data, const N: usize>(self) -> Vec<Data>
371 where
372 Data: Vector<N>,
373 {
374 assert_eq!(self.get_num_components(), N,);
375 assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
376
377 unsafe { self.buffer.into_vec_unchecked::<Data, N>() }
378 }
379
380 pub fn into_parts<Data, const N: usize>(
381 mut self,
382 ) -> (Vec<Data>, Option<VecPointIdx<AttributeValueIdx>>, Self)
383 where
384 Data: Vector<N>,
385 {
386 let num_components = self.get_num_components();
387 let component_type = self.get_component_type();
388 assert_eq!(num_components, N,);
389 assert_eq!(component_type, Data::Component::get_dyn(),);
390 let mut new_buffer = buffer::attribute::AttributeBuffer::from_vec(Vec::<Data>::new());
391 std::mem::swap(&mut self.buffer, &mut new_buffer);
392 let data = unsafe { new_buffer.into_vec_unchecked::<Data, N>() };
393
394 let mut point_to_att_val_map = None;
395 std::mem::swap(&mut point_to_att_val_map, &mut self.point_to_att_val_map);
396
397 (data, point_to_att_val_map, self)
398 }
399
400 pub fn set_values<Data, const N: usize>(&mut self, data: Vec<Data>)
401 where
402 Data: Vector<N>,
403 {
404 assert_eq!(self.get_num_components(), N,);
405 assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
406 assert_eq!(self.len(), 0);
407 self.buffer = buffer::attribute::AttributeBuffer::from_vec(data);
408 }
409
410 pub fn remove_duplicate_values<Data, const N: usize>(&mut self)
411 where
412 Data: Vector<N>,
413 {
414 let n = self.len();
415 if n <= 1 {
416 return;
417 }
418
419 let values = self.unique_vals_as_slice::<Data>();
420
421 let f64_points: Vec<[f64; N]> = values.iter().map(|v| vector_to_f64_array(v)).collect();
423
424 let tree = ImmutableKdTree::<f64, u32, N, 32>::new_from_slice(&f64_points);
426
427 let mut canonical_index = vec![usize::MAX; n];
430 let mut has_duplicates = false;
431
432 for i in 0..n {
433 if canonical_index[i] != usize::MAX {
434 continue;
436 }
437 canonical_index[i] = i; let neighbors = tree.within_unsorted::<SquaredEuclidean>(&f64_points[i], f64::EPSILON);
441
442 for neighbor in &neighbors {
443 let j = neighbor.item as usize;
444 if j <= i || canonical_index[j] != usize::MAX {
445 continue;
446 }
447 if values[i] == values[j] {
449 canonical_index[j] = i;
450 has_duplicates = true;
451 }
452 }
453 }
454
455 if !has_duplicates {
456 return;
457 }
458
459 let mut old_to_new = vec![0usize; n];
461 let mut keep_indices = Vec::new();
462 let mut new_idx = 0;
463 for i in 0..n {
464 if canonical_index[i] == i {
465 old_to_new[i] = new_idx;
467 keep_indices.push(i);
468 new_idx += 1;
469 }
470 }
471
472 let map_data: Vec<AttributeValueIdx> = (0..n)
474 .map(|i| old_to_new[canonical_index[i]].into())
475 .collect();
476 self.point_to_att_val_map = Some(VecPointIdx::<_>::from(map_data));
477
478 self.buffer.retain_indices(&keep_indices);
480 }
481
482 #[allow(unused)]
483 pub fn remove<Data, const N: usize>(&mut self, p_idx: PointIdx) {
484 let p_idx_usize = usize::from(p_idx);
485 assert!(
486 p_idx_usize < self.len(),
487 "Point index out of bounds: {}",
488 p_idx_usize
489 );
490 if let Some(ref mut point_to_att_val_map) = self.point_to_att_val_map {
491 if (0..point_to_att_val_map.len())
493 .map(PointIdx::from)
494 .filter(|&p| p != p_idx)
495 .any(|p| point_to_att_val_map[p] == point_to_att_val_map[p_idx])
496 {
497 point_to_att_val_map.remove(p_idx);
499 } else {
500 let removed_unique_val_idx = point_to_att_val_map.remove(p_idx);
501 self.buffer.remove::<Data, N>(removed_unique_val_idx.into());
502 for p in 0..point_to_att_val_map.len() {
504 let p = PointIdx::from(p);
505 if point_to_att_val_map[p] > removed_unique_val_idx {
506 point_to_att_val_map[p] = (usize::from(point_to_att_val_map[p]) - 1).into();
507 }
508 }
509 }
510 } else {
511 let a_idx = AttributeValueIdx::from(usize::from(p_idx));
513 self.remove_unique_val::<Data, N>(a_idx);
514 }
515 }
516
517 #[allow(unused)]
518 pub fn remove_dyn(&mut self, p_idx: PointIdx) {
519 assert!(
520 usize::from(p_idx) < self.len(),
521 "Point index out of bounds: {}",
522 usize::from(p_idx)
523 );
524 match self.get_component_type().size() * self.get_num_components() {
525 1 => self.remove::<u8, 1>(p_idx),
526 2 => self.remove::<u16, 1>(p_idx),
527 4 => self.remove::<u32, 1>(p_idx),
528 6 => self.remove::<u16, 3>(p_idx),
529 8 => self.remove::<u64, 1>(p_idx),
530 12 => self.remove::<u32, 3>(p_idx),
531 16 => self.remove::<u64, 2>(p_idx),
532 18 => self.remove::<u64, 3>(p_idx),
533 _ => panic!(
534 "Unsupported component size: {}",
535 self.get_component_type().size()
536 ),
537 }
538 }
539
540 #[allow(unused)]
541 pub fn remove_unique_val<Data, const N: usize>(&mut self, val_idx: AttributeValueIdx) {
542 let val_idx = usize::from(val_idx);
543 assert!(
544 val_idx < self.num_unique_values(),
545 "Attribute value index out of bounds: {}",
546 val_idx
547 );
548 self.buffer.remove::<Data, N>(val_idx);
549 if let Some(ref mut _point_to_att_val_map) = self.point_to_att_val_map {
550 unimplemented!();
551 }
552 }
553
554 pub fn remove_unique_val_dyn(&mut self, val_idx: usize) {
555 assert!(
556 val_idx < self.num_unique_values(),
557 "Attribute value index out of bounds: {}",
558 val_idx
559 );
560 match self.get_component_type().size() * self.get_num_components() {
561 1 => self.buffer.remove::<u8, 1>(val_idx),
562 2 => self.buffer.remove::<u16, 1>(val_idx),
563 4 => self.buffer.remove::<u32, 1>(val_idx),
564 6 => self.buffer.remove::<u16, 3>(val_idx),
565 8 => self.buffer.remove::<u64, 1>(val_idx),
566 12 => self.buffer.remove::<u32, 3>(val_idx),
567 16 => self.buffer.remove::<u64, 2>(val_idx),
568 18 => self.buffer.remove::<u64, 3>(val_idx),
569 _ => panic!(
570 "Unsupported component size: {}",
571 self.get_component_type().size()
572 ),
573 }
574 }
575
576 pub fn retain_points_dyn(&mut self, keep_point_indices: &[usize]) {
579 if let Some(ref map) = self.point_to_att_val_map {
580 let num_unique = self.buffer.len();
582 let mut unique_val_referenced = vec![false; num_unique];
583 let mut new_map = Vec::with_capacity(keep_point_indices.len());
584
585 for &p in keep_point_indices {
586 let val_idx = map[PointIdx::from(p)];
587 unique_val_referenced[usize::from(val_idx)] = true;
588 new_map.push(val_idx);
589 }
590
591 let mut old_unique_to_new = vec![0usize; num_unique];
593 let mut keep_unique_indices = Vec::new();
594 let mut new_unique_idx = 0;
595 for i in 0..num_unique {
596 if unique_val_referenced[i] {
597 old_unique_to_new[i] = new_unique_idx;
598 keep_unique_indices.push(i);
599 new_unique_idx += 1;
600 }
601 }
602
603 let new_map: Vec<AttributeValueIdx> = new_map
605 .iter()
606 .map(|&val_idx| old_unique_to_new[usize::from(val_idx)].into())
607 .collect();
608 self.point_to_att_val_map = Some(VecPointIdx::from(new_map));
609
610 self.buffer.retain_indices(&keep_unique_indices);
612 } else {
613 self.buffer.retain_indices(keep_point_indices);
615 }
616 }
617}
618
619#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
620pub enum ComponentDataType {
621 I8,
622 U8,
623 I16,
624 U16,
625 I32,
626 U32,
627 I64,
628 U64,
629 F32,
630 F64,
631 Invalid,
632}
633
634impl ComponentDataType {
635 #[inline]
637 pub fn size(self) -> usize {
638 match self {
639 ComponentDataType::F32 => 4,
640 ComponentDataType::F64 => 8,
641 ComponentDataType::U8 => 1,
642 ComponentDataType::U16 => 2,
643 ComponentDataType::U32 => 4,
644 ComponentDataType::U64 => 8,
645 ComponentDataType::I8 => 1,
646 ComponentDataType::I16 => 2,
647 ComponentDataType::I32 => 4,
648 ComponentDataType::I64 => 8,
649 ComponentDataType::Invalid => 0,
650 }
651 }
652
653 #[inline]
654 pub fn is_float(self) -> bool {
655 matches!(self, ComponentDataType::F32 | ComponentDataType::F64)
656 }
657
658 #[inline]
660 pub fn get_id(self) -> u8 {
661 match self {
662 ComponentDataType::U8 => 1,
663 ComponentDataType::I8 => 2,
664 ComponentDataType::U16 => 3,
665 ComponentDataType::I16 => 4,
666 ComponentDataType::U32 => 5,
667 ComponentDataType::I32 => 6,
668 ComponentDataType::U64 => 7,
669 ComponentDataType::I64 => 8,
670 ComponentDataType::F32 => 9,
671 ComponentDataType::F64 => 10,
672 ComponentDataType::Invalid => u8::MAX, }
674 }
675
676 #[inline]
678 pub fn write_to<W: ByteWriter>(self, writer: &mut W) {
679 writer.write_u8(self.get_id());
680 }
681
682 #[inline]
684 pub fn from_id(id: usize) -> Result<Self, ()> {
685 match id {
686 1 => Ok(ComponentDataType::I8),
687 2 => Ok(ComponentDataType::U8),
688 3 => Ok(ComponentDataType::I16),
689 4 => Ok(ComponentDataType::U16),
690 5 => Ok(ComponentDataType::I32),
691 6 => Ok(ComponentDataType::U32),
692 7 => Ok(ComponentDataType::I64),
693 8 => Ok(ComponentDataType::U64),
694 9 => Ok(ComponentDataType::F32),
695 10 => Ok(ComponentDataType::F64),
696 _ => Err(()),
697 }
698 }
699
700 #[inline]
702 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
703 let id = reader.read_u8()?;
704 Self::from_id(id as usize).map_err(|_| Err::InvalidDataTypeId(id))
705 }
706}
707
708#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
709pub enum AttributeType {
710 Position,
711 Normal,
712 Color,
713 TextureCoordinate,
714 Custom,
715 Tangent,
716 Material,
717 Joint,
718 Weight,
719 Invalid,
720}
721
722impl AttributeType {
723 pub fn get_minimum_dependency(&self) -> Vec<Self> {
724 match self {
725 Self::Position => Vec::new(),
726 Self::Normal => Vec::new(),
727 Self::Color => Vec::new(),
728 Self::TextureCoordinate => vec![Self::Position],
729 Self::Tangent => Vec::new(),
730 Self::Material => Vec::new(),
731 Self::Joint => Vec::new(),
732 Self::Weight => Vec::new(),
733 Self::Custom => Vec::new(),
734 Self::Invalid => Vec::new(),
735 }
736 }
737
738 #[inline]
740 pub fn get_id(&self) -> u8 {
741 match self {
742 Self::Position => 0,
743 Self::Normal => 1,
744 Self::Color => 2,
745 Self::TextureCoordinate => 3,
746 Self::Custom => 4,
747 Self::Tangent => 5,
748 Self::Material => 6,
749 Self::Joint => 7,
750 Self::Weight => 8,
751 Self::Invalid => u8::MAX, }
753 }
754
755 #[inline]
757 pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
758 writer.write_u8(self.get_id());
759 }
760
761 #[inline]
763 pub fn from_id(id: u8) -> Result<Self, Err> {
764 match id {
765 0 => Ok(Self::Position),
766 1 => Ok(Self::Normal),
767 2 => Ok(Self::Color),
768 3 => Ok(Self::TextureCoordinate),
769 4 => Ok(Self::Custom),
770 5 => Ok(Self::Tangent),
771 6 => Ok(Self::Material),
772 7 => Ok(Self::Joint),
773 8 => Ok(Self::Weight),
774 _ => Err(Err::InvalidDataTypeId(id)),
775 }
776 }
777
778 #[inline]
780 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
781 let id = reader.read_u8()?;
782 Self::from_id(id)
783 }
784}
785
786#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
788pub enum AttributeDomain {
789 Position,
791 Corner,
793}
794
795impl AttributeDomain {
796 pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
798 match self {
799 Self::Position => writer.write_u8(0),
800 Self::Corner => writer.write_u8(1),
801 }
802 }
803
804 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
806 let id = reader.read_u8()?;
807 match id {
808 0 => Ok(Self::Position),
809 1 => Ok(Self::Corner),
810 _ => Err(Err::InvalidAttributeDomainId(id)),
811 }
812 }
813}
814
815#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
816pub struct AttributeId(usize);
817
818impl AttributeId {
819 pub fn new(id: usize) -> Self {
820 Self(id)
821 }
822
823 pub fn as_usize(&self) -> usize {
825 self.0
826 }
827}
828
829#[cfg(test)]
830mod tests {
831 use super::*;
832 use crate::types::NdVector;
833
834 #[test]
835 fn test_attribute() {
836 let data = vec![
837 NdVector::from([1.0f32, 2.0, 3.0]),
838 NdVector::from([4.0f32, 5.0, 6.0]),
839 NdVector::from([7.0f32, 8.0, 9.0]),
840 ];
841 let att = super::Attribute::from(
842 AttributeId::new(0),
843 data.clone(),
844 super::AttributeType::Position,
845 super::AttributeDomain::Position,
846 Vec::new(),
847 );
848 assert_eq!(att.len(), data.len());
849 assert_eq!(
850 att.get::<NdVector<3, f32>, 3>(0.into()),
851 data[0],
852 "{:b}!={:b}",
853 att.get::<NdVector<3, f32>, 3>(0.into()).get(0).to_bits(),
854 data[0].get(0).to_bits()
855 );
856 assert_eq!(att.get_component_type(), super::ComponentDataType::F32);
857 assert_eq!(att.get_num_components(), 3);
858 assert_eq!(att.get_attribute_type(), super::AttributeType::Position);
859 }
860
861 #[test]
862 fn test_attribute_remap() {
863 let positions = vec![
864 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]), ];
871
872 let att = Attribute::new(
873 positions,
874 AttributeType::Position,
875 AttributeDomain::Position,
876 vec![],
877 );
878
879 assert_eq!(
880 att.point_to_att_val_map
881 .unwrap()
882 .into_iter()
883 .map(|v| usize::from(v))
884 .collect::<Vec<_>>(),
885 vec![0, 1, 2, 0, 1, 3],
886 )
887 }
888
889 #[test]
890 fn test_remove() {
891 let positions = vec![
892 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]), ];
899
900 let mut att = Attribute::new(
901 positions,
902 AttributeType::Position,
903 AttributeDomain::Position,
904 vec![],
905 );
906
907 assert_eq!(att.len(), 6);
908 assert_eq!(att.num_unique_values(), 5);
909 assert_eq!(
910 &att.point_to_att_val_map
911 .as_ref()
912 .unwrap()
913 .iter()
914 .map(|&i| usize::from(i))
915 .collect::<Vec<_>>(),
916 &vec![0, 1, 2, 3, 2, 4]
917 );
918 att.remove::<NdVector<3, f32>, 3>(PointIdx::from(2)); assert_eq!(att.len(), 5);
920 assert_eq!(att.num_unique_values(), 5);
921 assert_eq!(
922 &att.point_to_att_val_map
923 .as_ref()
924 .unwrap()
925 .iter()
926 .map(|&i| usize::from(i))
927 .collect::<Vec<_>>(),
928 &vec![0, 1, 3, 2, 4]
929 );
930 att.remove::<NdVector<3, f32>, 3>(PointIdx::from(1)); assert_eq!(att.len(), 4);
932 assert_eq!(att.num_unique_values(), 4);
933 assert_eq!(
934 &att.point_to_att_val_map
935 .as_ref()
936 .unwrap()
937 .iter()
938 .map(|&i| usize::from(i))
939 .collect::<Vec<_>>(),
940 &vec![0, 2, 1, 3]
941 );
942 }
943}