vec_x/
collection.rs

1use std::hash::Hash;
2use std::ops::Index;
3
4use fxhash::FxBuildHasher;
5use indexmap::IndexSet;
6
7use crate::VecX;
8
9/// A structure representing a set of indexed `VecX`.
10/// It is indexed for unique `VecX` and can efficiently handle sets of VecX in some use cases.
11///
12/// インデックスが付けられた`VecX`の集合を表す構造体です。
13/// 一意の`VecX`に対してインデックスを持ち、ユースケースによってはVecXの集合を効率的に扱えます。
14///
15/// For example, when considering a set of `VecX` representing a vertex army in 3D space, this is useful when there are multiple vertices with the same coordinates.
16/// This method of data management is often employed in 3D data formats.
17///
18/// 例えば、3D空間上の頂点軍を表す`VecX`の集合を考えた際、同じ座標を持つ頂点が複数存在する場合に有効です。
19/// このデータの管理方法は、しばしば3Dデータのフォーマットに採用されています。
20///
21/// ```
22/// use vec_x::{VecX, IndexedVecXs};
23///
24/// let colors: Vec<VecX<u8, 3>> = [
25///     [255, 0, 0],
26///     [0, 255, 0],
27///     [255, 0, 0],
28///     [255, 0, 0],
29///     [0, 0, 255],
30///     [0, 255, 0],
31/// ].into_iter().map(|p| VecX::new(p)).collect::<Vec<_>>();
32/// let indexed_colors = IndexedVecXs::from_vec(colors);
33/// let IndexedVecXs { values, indices } = indexed_colors;
34///
35///
36/// // インデックスされた要素の数は元データの一意な要素の数と一致する
37/// assert_eq!(values.len(), 3);
38/// // 元データでの出現順にインデックスが付けられている
39/// assert_eq!(values[0], VecX::new([255, 0, 0]));
40/// assert_eq!(values[1], VecX::new([0, 255, 0]));
41/// assert_eq!(values[2], VecX::new([0, 0, 255]));
42///
43/// // indicesの要素数は元データの要素数と一致する
44/// assert_eq!(indices.len(), 6);
45/// // 同じ要素は同じインデックスを持つ
46/// assert_eq!(indices, vec![0, 1, 0, 0, 2, 1]);
47/// ```
48///
49/// Also, `IndexedVecXs` implements `Index` traits, allowing access to elements using indexes.
50///
51/// また、`IndexedVecXs`は`Index`トレイトを実装しており、インデックスを使用して要素にアクセスできます。
52///
53/// ```
54/// use vec_x::{VecX, IndexedVecXs};
55///
56/// let colors: Vec<VecX<u8, 3>> = [
57///    [255, 0, 0],
58///    [0, 255, 0],
59/// ].into_iter().map(|p| VecX::new(p)).collect::<Vec<_>>();
60///
61/// let indexed_colors = IndexedVecXs::from_vec(colors);
62///
63/// assert_eq!(indexed_colors[0], VecX::new([255, 0, 0]));
64/// assert_eq!(indexed_colors[1], VecX::new([0, 255, 0]));
65/// ```
66///
67/// Elements of `VecX` must implement `PartialEq`,`Eq`,`Hash`.
68/// This is because we use HashSet internally.
69/// The Rust standard floating-point types do not implement `Eq`,`Hash` (due to NaN having multiple binary representations), so you cannot use `f32` or `f64`.
70///
71/// `VecX`の要素は`PartialEq`,`Eq`,`Hash`を実装している必要があります。
72/// これは内部でHashSetを使用しているためです。
73/// Rust標準の浮動小数点数型は`Eq`,`Hash`を実装していない(NaNが複数のバイナリ表現を持つことに起因する)ため、`f32`や`f64`を使用することはできません。
74///
75/// If you want to handle floating point numbers, consider using [ordered-float crates](https://crates.io/crates/ordered-float).
76///
77/// もし浮動小数点数を扱いたい場合、[ordered-floatクレート](https://crates.io/crates/ordered-float)を使用することを検討してください。
78///
79/// ```compile_fail
80/// use vec_x::{VecX, IndexedVecXs};
81///
82/// let points: Vec<VecX<f64, 3>> = [
83///    [0., 0., 0.],
84///    [1., 0., 0.],
85/// ].into_iter().map(|p| VecX::new(p)).collect::<Vec<_>>();
86///
87/// let indexed_colors = IndexedVecXs::from_vec(points); // compile error
88/// ```
89pub struct IndexedVecXs<T, const N: usize>
90    where T: PartialEq + Eq + Hash + Sized + Send
91{
92    /// unique set of `VecX
93    ///
94    /// 一意な`VecX`の集合
95    pub values: IndexSet<VecX<T, N>, FxBuildHasher>,
96    /// Index referring to `values`.
97    ///
98    /// `values`を参照するインデックス
99    pub indices: Vec<usize>,
100}
101
102impl<T, const N: usize> IndexedVecXs<T, N>
103    where T: PartialEq + Eq + Hash + Sized + Send
104{
105    /// This is not normally used. Use `from_vec` to generate `IndexedVecXs` from `Vec<VecX<T, N>>`.
106    ///
107    /// これは通常使用されません。`Vec<VecX<T, N>>`から`IndexedVecXs`を生成するためには`from_vec`を使用してください。
108    pub fn new(
109        values: IndexSet<VecX<T, N>, FxBuildHasher>,
110        indices: Vec<usize>) -> Self {
111        Self {
112            values,
113            indices,
114        }
115    }
116
117    /// Generate empty `IndexedVecXs`.
118    ///
119    /// 空の`IndexedVecXs`を生成します。
120    pub fn empty() -> Self {
121        Self {
122            values: IndexSet::<VecX<T, N>, FxBuildHasher>::default(),
123            indices: Vec::new(),
124        }
125    }
126
127    /// Returns an iterable structure `IndexedVecXIter`.
128    /// Internally, each time the iterator is consumed, it searches for the corresponding `VecX` from the `values` for the index in the `indices`.
129    ///
130    /// イテレーション可能な構造体`IndexedVecXIter`を返します。
131    /// 内部的には、イテレータが消費されるたびに`values`から`indices`中のインデックスに対応する`VecX`を検索しています。
132    pub fn iter(&self) -> Vec<&VecX<T, N>> {
133        self.indices.iter().map(|i| self.values.get_index(*i).unwrap()).collect::<Vec<_>>()
134    }
135
136    /// Generate `IndexedVecXs` from `Vec<VecX<T, N>>`.
137    ///
138    /// `Vec<VecX<T, N>>`から`IndexedVecXs`を生成します。
139    pub fn from_vec(vec: Vec<VecX<T, N>>) -> Self {
140        let mut values = IndexSet::<VecX<T, N>, FxBuildHasher>::with_capacity_and_hasher(vec.len(), FxBuildHasher::default());
141        let indices = vec.into_iter().map(|value| values.insert_full(value).0).collect();
142
143        Self {
144            values,
145            indices,
146        }
147    }
148
149    /// Generate Vec<&VecX<T, N>> from `IndexedVecXs`.
150    ///
151    /// `IndexedVecXs`からVec<&VecX<T, N>>を生成します。
152    pub fn to_ref_vec(&self) -> Vec<&VecX<T, N>> {
153        self.indices.iter().map(|i| self.values.get_index(*i).unwrap()).collect::<Vec<_>>()
154    }
155
156    /// Inserts a new element.
157    /// Internally inserts a new element in `values` and adds its index to `indices`.
158    /// Returns `true` if a new element is inserted into `values`.
159    ///
160    /// 新しい要素を挿入します。
161    /// 内部的には`values`に新しい要素を挿入し、そのインデックスを`indices`に追加します。
162    /// `values`に新しい要素が挿入された場合は`true`を返します。
163    pub fn insert(&mut self, value: VecX<T, N>) -> bool {
164        let (index, is_new) = self.values.insert_full(value);
165        self.indices.push(index);
166
167        is_new
168    }
169}
170
171
172impl<T, const N: usize> IndexedVecXs<T, N>
173    where T: PartialEq + Eq + Hash + Copy + Sized + Send
174{
175    /// Convert `IndexedVecXs` to `Vec<VecX<T, N>`.
176    ///
177    /// `IndexedVecXs`を`Vec<VecX<T, N>>`に変換します。
178    pub fn to_vec(self) -> Vec<VecX<T, N>> {
179        self.indices.into_iter().map(|i| *self.values.get_index(i).unwrap()).collect::<Vec<_>>()
180    }
181}
182
183impl<T: PartialEq + Eq + Hash, const N: usize> Index<usize> for IndexedVecXs<T, N>
184    where T: PartialEq + Eq + Hash + Sized + Send
185{
186    type Output = VecX<T, N>;
187
188    fn index(&self, index: usize) -> &Self::Output {
189        let i = self.indices.get(index).unwrap();
190        self.values.get_index(*i).unwrap()
191    }
192}
193
194/// Iterator for `IndexedVecXs`.
195/// Returns the elements of `IndexedVecXs` in order.
196///
197/// `IndexedVecXs`のイテレータです。
198/// `IndexedVecXs`の要素を順番に返します。
199pub struct IndexedVecXIter<'a, T, const N: usize>
200    where T: PartialEq + Eq + Hash + Sized + Send
201{
202    collection: &'a IndexedVecXs<T, N>,
203    current_index: usize,
204}
205
206impl<'a, T, const N: usize> Iterator for IndexedVecXIter<'a, T, N>
207    where T: PartialEq + Eq + Hash + Sized + Send
208{
209    type Item = &'a VecX<T, N>;
210
211    fn next(&mut self) -> Option<Self::Item> {
212        if self.current_index < self.collection.indices.len() {
213            self.current_index += 1;
214            Some(&self.collection[self.current_index])
215        } else {
216            None
217        }
218    }
219}