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}