1use serde::Serialize;
2
3use super::{buffer, shared::DataValue};
4use crate::core::shared::{AttributeValueIdx, PointIdx, VecPointIdx, Vector};
5use crate::prelude::{ByteReader, ByteWriter};
6
7#[derive(Debug, thiserror::Error)]
8pub enum Err {
9 #[error("Invalid attribute domain id: {0}")]
11 InvalidAttributeDomainId(u8),
12 #[error("Reader error: {0}")]
14 ReaderError(#[from] crate::core::bit_coder::ReaderErr),
15 #[error("Invalid DataTypeId: {0}")]
16 InvalidDataTypeId(u8),
17}
18
19#[derive(Debug, Clone)]
25pub struct Attribute {
26 id: AttributeId,
28
29 buffer: buffer::attribute::AttributeBuffer,
31
32 att_type: AttributeType,
34
35 domain: AttributeDomain,
37
38 parents: Vec<AttributeId>,
40
41 point_to_att_val_map: Option<VecPointIdx<AttributeValueIdx>>,
45
46 name: Option<String>,
48}
49
50impl Attribute {
51 pub fn new<Data, const N: usize>(
52 data: Vec<Data>,
53 att_type: AttributeType,
54 domain: AttributeDomain,
55 parents: Vec<AttributeId>,
56 ) -> Self
57 where
58 Data: Vector<N>,
59 {
60 let id = AttributeId::new(0); let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
62 let mut out = Self {
63 id,
64 buffer,
65 parents,
66 att_type,
67 domain,
68 point_to_att_val_map: None,
69 name: None,
70 };
71 out.remove_duplicate_values::<Data, N>();
72 out
73 }
74
75 pub fn new_empty(
76 id: AttributeId,
77 att_type: AttributeType,
78 domain: AttributeDomain,
79 component_type: ComponentDataType,
80 num_components: usize,
81 ) -> Self {
82 let buffer = buffer::attribute::AttributeBuffer::new(component_type, num_components);
83 Self {
84 id,
85 buffer,
86 parents: Vec::new(),
87 att_type,
88 domain,
89 point_to_att_val_map: None,
90 name: None,
91 }
92 }
93
94 pub(crate) fn from<Data, const N: usize>(
95 id: AttributeId,
96 data: Vec<Data>,
97 att_type: AttributeType,
98 domain: AttributeDomain,
99 parents: Vec<AttributeId>,
100 ) -> Self
101 where
102 Data: Vector<N>,
103 {
104 let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
105 let mut out = Self {
106 id,
107 buffer,
108 parents,
109 att_type,
110 domain,
111 point_to_att_val_map: None,
112 name: None,
113 };
114 out.remove_duplicate_values::<Data, N>();
115 out
116 }
117
118 pub(crate) fn from_without_removing_duplicates<Data, const N: usize>(
119 id: AttributeId,
120 data: Vec<Data>,
121 att_type: AttributeType,
122 domain: AttributeDomain,
123 parents: Vec<AttributeId>,
124 ) -> Self
125 where
126 Data: Vector<N>,
127 {
128 let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
129 Self {
130 id,
131 buffer,
132 parents,
133 att_type,
134 domain,
135 point_to_att_val_map: None,
136 name: None,
137 }
138 }
139
140 pub fn get<Data, const N: usize>(&self, p_idx: PointIdx) -> Data
141 where
142 Data: Vector<N>,
143 Data::Component: DataValue,
144 {
145 self.buffer.get(self.get_unique_val_idx(p_idx))
146 }
147
148 pub fn get_unique_val<Data, const N: usize>(&self, val_idx: AttributeValueIdx) -> Data
149 where
150 Data: Vector<N>,
151 Data::Component: DataValue,
152 {
153 self.buffer.get(val_idx)
154 }
155
156 pub fn get_component_type(&self) -> ComponentDataType {
157 self.buffer.get_component_type()
158 }
159
160 #[inline]
161 #[allow(unused)]
162 pub(crate) fn set_component_type(&mut self, component_type: ComponentDataType) {
163 self.buffer.set_component_type(component_type);
164 }
165
166 #[inline]
167 #[allow(unused)]
168 pub(crate) fn set_num_components(&mut self, num_components: usize) {
169 self.buffer.set_num_components(num_components);
170 }
171
172 pub(crate) fn get_data_as_bytes(&self) -> &[u8] {
173 self.buffer.as_slice_u8()
174 }
175
176 #[inline]
177 #[allow(unused)]
178 pub(crate) fn get_as_bytes(&self, i: usize) -> &[u8] {
179 &self.buffer.as_slice_u8()[i
180 * self.buffer.get_num_components()
181 * self.buffer.get_component_type().size()
182 ..(i + 1) * self.buffer.get_num_components() * self.buffer.get_component_type().size()]
183 }
184
185 pub(crate) fn set_point_to_att_val_map(
186 &mut self,
187 point_to_att_val_map: Option<VecPointIdx<AttributeValueIdx>>,
188 ) {
189 self.point_to_att_val_map = point_to_att_val_map;
190 }
191
192 pub(crate) fn take_point_to_att_val_map(self) -> Option<VecPointIdx<AttributeValueIdx>> {
193 self.point_to_att_val_map
194 }
195
196 #[inline]
197 pub fn get_id(&self) -> AttributeId {
198 self.id
199 }
200
201 #[inline]
202 pub fn get_num_components(&self) -> usize {
203 self.buffer.get_num_components()
204 }
205
206 #[inline]
207 pub fn get_attribute_type(&self) -> AttributeType {
208 self.att_type
209 }
210
211 #[inline]
212 pub fn get_domain(&self) -> AttributeDomain {
213 self.domain
214 }
215
216 #[inline]
217 pub fn get_parents(&self) -> &Vec<AttributeId> {
218 self.parents.as_ref()
219 }
220
221 #[inline(always)]
223 pub fn len(&self) -> usize {
224 if let Some(f) = &self.point_to_att_val_map {
225 f.len()
226 } else {
227 self.buffer.len()
228 }
229 }
230
231 #[inline(always)]
232 pub fn num_unique_values(&self) -> usize {
233 self.buffer.len()
234 }
235
236 #[inline]
237 pub fn get_unique_val_idx(&self, idx: PointIdx) -> AttributeValueIdx {
238 let idx_usize = usize::from(idx);
239 assert!(
240 idx_usize < self.len(),
241 "Index out of bounds: idx = {}, len = {}",
242 idx_usize,
243 self.len()
244 );
245 if let Some(ref point_to_att_val_map) = self.point_to_att_val_map {
246 point_to_att_val_map[idx]
247 } else {
248 idx_usize.into()
250 }
251 }
252
253 #[inline]
254 pub fn set_name(&mut self, name: String) {
255 self.name = Some(name);
256 }
257
258 #[inline]
259 pub fn get_name(&self) -> Option<&String> {
260 self.name.as_ref()
261 }
262
263 #[inline]
265 pub fn unique_vals_as_slice<Data>(&self) -> &[Data] {
266 assert_eq!(
267 self.buffer.get_num_components() * self.buffer.get_component_type().size(),
268 std::mem::size_of::<Data>(),
269 );
270 unsafe { self.buffer.as_slice::<Data>() }
271 }
272
273 #[inline]
275 pub fn unique_vals_as_slice_mut<Data>(&mut self) -> &mut [Data] {
276 assert_eq!(
277 self.buffer.get_num_components() * self.buffer.get_component_type().size(),
278 std::mem::size_of::<Data>(),
279 );
280 unsafe { self.buffer.as_slice_mut::<Data>() }
281 }
282
283 #[inline]
287 pub unsafe fn unique_vals_as_slice_unchecked<Data>(&self) -> &[Data] {
288 self.buffer.as_slice::<Data>()
290 }
291
292 #[inline]
296 pub unsafe fn unique_vals_as_slice_unchecked_mut<Data>(&mut self) -> &mut [Data] {
297 self.buffer.as_slice_mut::<Data>()
299 }
300
301 pub fn permute(&mut self, indices: &[usize]) {
304 assert!(
305 indices.len() == self.len(),
306 "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
307 indices.len(),
308 self.len()
309 );
310 assert!(
311 indices.iter().all(|&i| i < self.len()),
312 "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
313 indices,
314 self.len()
315 );
316 unsafe {
317 self.buffer.permute_unchecked(indices);
318 }
319 }
320
321 pub fn permute_unchecked(&mut self, indices: &[usize]) {
326 debug_assert!(
327 indices.len() == self.len(),
328 "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
329 indices.len(),
330 self.len()
331 );
332 debug_assert!(
333 indices.iter().all(|&i| i < self.len()),
334 "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
335 indices,
336 self.len()
337 );
338 unsafe {
339 self.buffer.permute_unchecked(indices);
340 }
341 }
342
343 pub fn swap(&mut self, i: usize, j: usize) {
345 assert!(
346 i < self.len() && j < self.len(),
347 "Indices out of bounds: i = {}, j = {}, len = {}",
348 i,
349 j,
350 self.len()
351 );
352 unsafe {
353 self.buffer.swap_unchecked(i, j);
354 }
355 }
356
357 pub fn take_values<Data, const N: usize>(self) -> Vec<Data>
358 where
359 Data: Vector<N>,
360 {
361 assert_eq!(self.get_num_components(), N,);
362 assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
363
364 unsafe { self.buffer.into_vec_unchecked::<Data, N>() }
365 }
366
367 pub fn into_parts<Data, const N: usize>(
368 mut self,
369 ) -> (Vec<Data>, Option<VecPointIdx<AttributeValueIdx>>, Self)
370 where
371 Data: Vector<N>,
372 {
373 let num_components = self.get_num_components();
374 let component_type = self.get_component_type();
375 assert_eq!(num_components, N,);
376 assert_eq!(component_type, Data::Component::get_dyn(),);
377 let mut new_buffer = buffer::attribute::AttributeBuffer::from_vec(Vec::<Data>::new());
378 std::mem::swap(&mut self.buffer, &mut new_buffer);
379 let data = unsafe { new_buffer.into_vec_unchecked::<Data, N>() };
380
381 let mut point_to_att_val_map = None;
382 std::mem::swap(&mut point_to_att_val_map, &mut self.point_to_att_val_map);
383
384 (data, point_to_att_val_map, self)
385 }
386
387 pub fn set_values<Data, const N: usize>(&mut self, data: Vec<Data>)
388 where
389 Data: Vector<N>,
390 {
391 assert_eq!(self.get_num_components(), N,);
392 assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
393 assert_eq!(self.len(), 0);
394 self.buffer = buffer::attribute::AttributeBuffer::from_vec(data);
395 }
396
397 pub fn remove_duplicate_values<Data, const N: usize>(&mut self)
398 where
399 Data: Vector<N>,
400 {
401 let mut duplicate_indeces = Vec::new();
402 let mut point_to_att_val_map = VecPointIdx::<_>::from(
404 (0..self.len())
405 .map(|i| i.into())
406 .collect::<Vec<AttributeValueIdx>>(),
407 );
408 for (i, val) in self.unique_vals_as_slice::<Data>().iter().enumerate() {
409 if i == self.len() - 1 {
410 break;
412 }
413 if duplicate_indeces.contains(&i) {
414 continue;
416 }
417 let mut local_duplicate_indeces = Vec::new();
418 for (j, other_val) in self.unique_vals_as_slice::<Data>()[i + 1..]
419 .iter()
420 .enumerate()
421 {
422 if val == other_val {
423 local_duplicate_indeces.push(i + 1 + j);
424 }
425 }
426 if local_duplicate_indeces.is_empty() {
427 continue;
428 }
429
430 for &duplicate_idx in local_duplicate_indeces.iter() {
431 let duplicate_idx = PointIdx::from(duplicate_idx);
433 point_to_att_val_map[duplicate_idx] = i.into();
434 }
435 duplicate_indeces.extend(local_duplicate_indeces);
436 }
437 let mut curr_max = 0;
438 for p in 0..point_to_att_val_map.len() {
439 let p = PointIdx::from(p);
440 let val_idx = point_to_att_val_map[p];
441 if usize::from(val_idx) == curr_max + 1 {
442 curr_max += 1;
444 } else if usize::from(val_idx) > curr_max + 1 {
445 curr_max += 1;
447 for q in usize::from(p)..point_to_att_val_map.len() {
448 let q = PointIdx::from(q);
449 if point_to_att_val_map[q] == val_idx {
450 point_to_att_val_map[q] = curr_max.into();
451 }
452 }
453 }
454 }
455 if !duplicate_indeces.is_empty() {
456 self.point_to_att_val_map = Some(point_to_att_val_map);
457 }
458 duplicate_indeces.sort_unstable();
460 for i in duplicate_indeces.into_iter().rev() {
461 self.buffer.remove::<Data, N>(i);
462 }
463 }
464
465 pub(crate) fn remove<Data, const N: usize>(&mut self, p_idx: PointIdx) {
466 let p_idx_usize = usize::from(p_idx);
467 assert!(
468 p_idx_usize < self.len(),
469 "Point index out of bounds: {}",
470 p_idx_usize
471 );
472 if let Some(ref mut point_to_att_val_map) = self.point_to_att_val_map {
473 if (0..point_to_att_val_map.len())
475 .map(PointIdx::from)
476 .filter(|&p| p != p_idx)
477 .any(|p| point_to_att_val_map[p] == point_to_att_val_map[p_idx])
478 {
479 point_to_att_val_map.remove(p_idx);
481 } else {
482 let removed_unique_val_idx = point_to_att_val_map.remove(p_idx);
483 self.buffer.remove::<Data, N>(removed_unique_val_idx.into());
484 for p in 0..point_to_att_val_map.len() {
486 let p = PointIdx::from(p);
487 if point_to_att_val_map[p] > removed_unique_val_idx {
488 point_to_att_val_map[p] = (usize::from(point_to_att_val_map[p]) - 1).into();
489 }
490 }
491 }
492 } else {
493 let a_idx = AttributeValueIdx::from(usize::from(p_idx));
495 self.remove_unique_val::<Data, N>(a_idx);
496 }
497 }
498
499 pub(crate) fn remove_dyn(&mut self, p_idx: PointIdx) {
500 assert!(
501 usize::from(p_idx) < self.len(),
502 "Point index out of bounds: {}",
503 usize::from(p_idx)
504 );
505 match self.get_component_type().size() * self.get_num_components() {
506 1 => self.remove::<u8, 1>(p_idx),
507 2 => self.remove::<u16, 1>(p_idx),
508 4 => self.remove::<u32, 1>(p_idx),
509 6 => self.remove::<u16, 3>(p_idx),
510 8 => self.remove::<u64, 1>(p_idx),
511 12 => self.remove::<u32, 3>(p_idx),
512 16 => self.remove::<u64, 2>(p_idx),
513 18 => self.remove::<u64, 3>(p_idx),
514 _ => panic!(
515 "Unsupported component size: {}",
516 self.get_component_type().size()
517 ),
518 }
519 }
520
521 pub(crate) fn remove_unique_val<Data, const N: usize>(&mut self, val_idx: AttributeValueIdx) {
522 let val_idx = usize::from(val_idx);
523 assert!(
524 val_idx < self.num_unique_values(),
525 "Attribute value index out of bounds: {}",
526 val_idx
527 );
528 self.buffer.remove::<Data, N>(val_idx);
529 if let Some(ref mut _point_to_att_val_map) = self.point_to_att_val_map {
530 unimplemented!();
531 }
532 }
533
534 pub fn remove_unique_val_dyn(&mut self, val_idx: usize) {
535 assert!(
536 val_idx < self.num_unique_values(),
537 "Attribute value index out of bounds: {}",
538 val_idx
539 );
540 match self.get_component_type().size() * self.get_num_components() {
541 1 => self.buffer.remove::<u8, 1>(val_idx),
542 2 => self.buffer.remove::<u16, 1>(val_idx),
543 4 => self.buffer.remove::<u32, 1>(val_idx),
544 6 => self.buffer.remove::<u16, 3>(val_idx),
545 8 => self.buffer.remove::<u64, 1>(val_idx),
546 12 => self.buffer.remove::<u32, 3>(val_idx),
547 16 => self.buffer.remove::<u64, 2>(val_idx),
548 18 => self.buffer.remove::<u64, 3>(val_idx),
549 _ => panic!(
550 "Unsupported component size: {}",
551 self.get_component_type().size()
552 ),
553 }
554 }
555}
556
557#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
558pub enum ComponentDataType {
559 I8,
560 U8,
561 I16,
562 U16,
563 I32,
564 U32,
565 I64,
566 U64,
567 F32,
568 F64,
569 Invalid,
570}
571
572impl ComponentDataType {
573 #[inline]
575 pub fn size(self) -> usize {
576 match self {
577 ComponentDataType::F32 => 4,
578 ComponentDataType::F64 => 8,
579 ComponentDataType::U8 => 1,
580 ComponentDataType::U16 => 2,
581 ComponentDataType::U32 => 4,
582 ComponentDataType::U64 => 8,
583 ComponentDataType::I8 => 1,
584 ComponentDataType::I16 => 2,
585 ComponentDataType::I32 => 4,
586 ComponentDataType::I64 => 8,
587 ComponentDataType::Invalid => 0,
588 }
589 }
590
591 #[inline]
592 pub fn is_float(self) -> bool {
593 matches!(self, ComponentDataType::F32 | ComponentDataType::F64)
594 }
595
596 #[inline]
598 pub fn get_id(self) -> u8 {
599 match self {
600 ComponentDataType::U8 => 1,
601 ComponentDataType::I8 => 2,
602 ComponentDataType::U16 => 3,
603 ComponentDataType::I16 => 4,
604 ComponentDataType::U32 => 5,
605 ComponentDataType::I32 => 6,
606 ComponentDataType::U64 => 7,
607 ComponentDataType::I64 => 8,
608 ComponentDataType::F32 => 9,
609 ComponentDataType::F64 => 10,
610 ComponentDataType::Invalid => u8::MAX, }
612 }
613
614 #[inline]
616 pub fn write_to<W: ByteWriter>(self, writer: &mut W) {
617 writer.write_u8(self.get_id());
618 }
619
620 #[inline]
622 pub fn from_id(id: usize) -> Result<Self, ()> {
623 match id {
624 1 => Ok(ComponentDataType::I8),
625 2 => Ok(ComponentDataType::U8),
626 3 => Ok(ComponentDataType::I16),
627 4 => Ok(ComponentDataType::U16),
628 5 => Ok(ComponentDataType::I32),
629 6 => Ok(ComponentDataType::U32),
630 7 => Ok(ComponentDataType::I64),
631 8 => Ok(ComponentDataType::U64),
632 9 => Ok(ComponentDataType::F32),
633 10 => Ok(ComponentDataType::F64),
634 _ => Err(()),
635 }
636 }
637
638 #[inline]
640 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
641 let id = reader.read_u8()?;
642 Self::from_id(id as usize).map_err(|_| Err::InvalidDataTypeId(id))
643 }
644}
645
646#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
647pub enum AttributeType {
648 Position,
649 Normal,
650 Color,
651 TextureCoordinate,
652 Custom,
653 Tangent,
654 Material,
655 Joint,
656 Weight,
657 Invalid,
658}
659
660impl AttributeType {
661 pub fn get_minimum_dependency(&self) -> Vec<Self> {
662 match self {
663 Self::Position => Vec::new(),
664 Self::Normal => Vec::new(),
665 Self::Color => Vec::new(),
666 Self::TextureCoordinate => vec![Self::Position],
667 Self::Tangent => Vec::new(),
668 Self::Material => Vec::new(),
669 Self::Joint => Vec::new(),
670 Self::Weight => Vec::new(),
671 Self::Custom => Vec::new(),
672 Self::Invalid => Vec::new(),
673 }
674 }
675
676 #[inline]
678 pub(crate) fn get_id(&self) -> u8 {
679 match self {
680 Self::Position => 0,
681 Self::Normal => 1,
682 Self::Color => 2,
683 Self::TextureCoordinate => 3,
684 Self::Custom => 4,
685 Self::Tangent => 5,
686 Self::Material => 6,
687 Self::Joint => 7,
688 Self::Weight => 8,
689 Self::Invalid => u8::MAX, }
691 }
692
693 #[inline]
695 pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
696 writer.write_u8(self.get_id());
697 }
698
699 #[inline]
701 pub(crate) fn from_id(id: u8) -> Result<Self, Err> {
702 match id {
703 0 => Ok(Self::Position),
704 1 => Ok(Self::Normal),
705 2 => Ok(Self::Color),
706 3 => Ok(Self::TextureCoordinate),
707 4 => Ok(Self::Custom),
708 5 => Ok(Self::Tangent),
709 6 => Ok(Self::Material),
710 7 => Ok(Self::Joint),
711 8 => Ok(Self::Weight),
712 _ => Err(Err::InvalidDataTypeId(id)),
713 }
714 }
715
716 #[inline]
718 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
719 let id = reader.read_u8()?;
720 Self::from_id(id)
721 }
722}
723
724#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
726pub enum AttributeDomain {
727 Position,
729 Corner,
731}
732
733impl AttributeDomain {
734 pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
736 match self {
737 Self::Position => writer.write_u8(0),
738 Self::Corner => writer.write_u8(1),
739 }
740 }
741
742 pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
744 let id = reader.read_u8()?;
745 match id {
746 0 => Ok(Self::Position),
747 1 => Ok(Self::Corner),
748 _ => Err(Err::InvalidAttributeDomainId(id)),
749 }
750 }
751}
752
753#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
754pub struct AttributeId(usize);
755
756impl AttributeId {
757 pub fn new(id: usize) -> Self {
758 Self(id)
759 }
760
761 pub fn as_usize(&self) -> usize {
763 self.0
764 }
765}
766
767#[cfg(test)]
768mod tests {
769 use super::*;
770 use crate::core::shared::NdVector;
771
772 #[test]
773 fn test_attribute() {
774 let data = vec![
775 NdVector::from([1.0f32, 2.0, 3.0]),
776 NdVector::from([4.0f32, 5.0, 6.0]),
777 NdVector::from([7.0f32, 8.0, 9.0]),
778 ];
779 let att = super::Attribute::from(
780 AttributeId::new(0),
781 data.clone(),
782 super::AttributeType::Position,
783 super::AttributeDomain::Position,
784 Vec::new(),
785 );
786 assert_eq!(att.len(), data.len());
787 assert_eq!(
788 att.get::<NdVector<3, f32>, 3>(0.into()),
789 data[0],
790 "{:b}!={:b}",
791 att.get::<NdVector<3, f32>, 3>(0.into()).get(0).to_bits(),
792 data[0].get(0).to_bits()
793 );
794 assert_eq!(att.get_component_type(), super::ComponentDataType::F32);
795 assert_eq!(att.get_num_components(), 3);
796 assert_eq!(att.get_attribute_type(), super::AttributeType::Position);
797 }
798
799 #[test]
800 fn test_attribute_remap() {
801 let positions = vec![
802 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]), ];
809
810 let att = Attribute::new(
811 positions,
812 AttributeType::Position,
813 AttributeDomain::Position,
814 vec![],
815 );
816
817 assert_eq!(
818 att.point_to_att_val_map
819 .unwrap()
820 .into_iter()
821 .map(|v| usize::from(v))
822 .collect::<Vec<_>>(),
823 vec![0, 1, 2, 0, 1, 3],
824 )
825 }
826
827 #[test]
828 fn test_remove() {
829 let positions = vec![
830 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]), ];
837
838 let mut att = Attribute::new(
839 positions,
840 AttributeType::Position,
841 AttributeDomain::Position,
842 vec![],
843 );
844
845 assert_eq!(att.len(), 6);
846 assert_eq!(att.num_unique_values(), 5);
847 assert_eq!(
848 &att.point_to_att_val_map
849 .as_ref()
850 .unwrap()
851 .iter()
852 .map(|&i| usize::from(i))
853 .collect::<Vec<_>>(),
854 &vec![0, 1, 2, 3, 2, 4]
855 );
856 att.remove::<NdVector<3, f32>, 3>(PointIdx::from(2)); assert_eq!(att.len(), 5);
858 assert_eq!(att.num_unique_values(), 5);
859 assert_eq!(
860 &att.point_to_att_val_map
861 .as_ref()
862 .unwrap()
863 .iter()
864 .map(|&i| usize::from(i))
865 .collect::<Vec<_>>(),
866 &vec![0, 1, 3, 2, 4]
867 );
868 att.remove::<NdVector<3, f32>, 3>(PointIdx::from(1)); assert_eq!(att.len(), 4);
870 assert_eq!(att.num_unique_values(), 4);
871 assert_eq!(
872 &att.point_to_att_val_map
873 .as_ref()
874 .unwrap()
875 .iter()
876 .map(|&i| usize::from(i))
877 .collect::<Vec<_>>(),
878 &vec![0, 2, 1, 3]
879 );
880 }
881}