hexga_math/geometry/vector/
mod.rs1use std::ops::*;
2
3use crate::*;
4
5pub mod prelude;
6
7mod vector_iter;
8pub use vector_iter::*;
9
10pub struct Vector<T, const N : usize>
23{
24 pub array : [T; N]
26}
27impl<T, const N : usize> Default for Vector<T, N> where [T; N] : Default
28{
29 fn default() -> Self { Self { array: ___() } }
30}
31impl<T, const N : usize> Vector<T,N>
32{
33 pub fn from_fn<F>(f : F) -> Self where F : FnMut(usize) -> T { Self::from_array(std::array::from_fn(f)) }
34 pub const fn from_array(array : [T; N]) -> Self { Self { array }}
35 pub fn splat(val : T) -> Self where T: Clone { Self::from_fn(|_| val.clone()) }
36
37 pub fn iter(&self) -> impl Iterator<Item = &T> { self.array.iter() }
38 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> { self.array.iter_mut() }
39 pub fn into_iter(self) -> impl Iterator<Item = T> { self.array.into_iter() }
40}
41impl_generic_array_like_with_op!(Vector);
42
43impl<T, const N : usize> Position<T,N> for Vector<T, N> where Self : Copy, T : Copy
44{
45 fn pos(&self) -> Vector<T,N> {
46 *self
47 }
48
49 fn set_pos(&mut self, pos : Vector<T,N>) -> &mut Self {
50 *self = pos;
51 self
52 }
53}
54
55
56impl<T,const N : usize> Vector<T,N>
57{
58 pub fn area(self) -> T where T: Number
64 {
65 self.iter().fold(T::ONE,|a, b| a * (*b).max_partial(T::ZERO))
66 }
67 pub fn area_usize(self) -> usize where T: Integer
71 {
72 if T::PRIMITIVE_NUMBER_TYPE.is_integer_unsigned()
73 {
74 self.iter().map(|v| v.to_usize()).product()
75 }else
76 {
77 self.iter().fold(usize::ONE,|a, b| a * (*b).max_partial(T::ZERO).to_usize())
78 }
79 }
80
81 pub fn checked_area_usize(self) -> Option<usize> where T: Integer
84 {
85 let mut area = 1usize;
86 for v in self.iter()
87 {
88 if T::PRIMITIVE_NUMBER_TYPE.is_integer_signed() && v < &T::ZERO { return None; }
89 let dim : usize = v.to_usize();
90 area = area.checked_mul(dim)?;
91 }
92 Some(area)
93 }
94
95 pub unsafe fn area_signed(self) -> T where T: Number { self.into_iter().product() }
98
99 pub fn have_area(self) -> bool where T: Number { self.area().is_non_zero() }
101 pub fn have_area_usize(self) -> bool where T: Integer { self.area_usize().is_non_zero() }
103
104 pub fn all_zero(self) -> bool where T: Zero + PartialEq { self.all(|v| v.is_zero()) }
105 pub fn all_non_zero(self) -> bool where T: Zero + PartialEq { self.all(|v| v.is_non_zero()) }
106
107 pub fn any_zero(self) -> bool where T: Zero + PartialEq { self.any(|v| v.is_zero()) }
108 pub fn any_non_zero(self) -> bool where T: Zero + PartialEq { self.any(|v| v.is_non_zero()) }
109
110 pub fn all_positive_or_zero(self) -> bool where T: PositiveOrNegative { self.all(|v| v.is_positive_or_zero()) }
111 pub fn any_positive_or_zero(self) -> bool where T: PositiveOrNegative { self.any(|v| v.is_positive_or_zero()) }
112
113 pub fn all_strictly_positive(self) -> bool where T: PositiveOrNegative { self.all(|v| v.is_strictly_positive()) }
114 pub fn any_strictly_negative(self) -> bool where T: PositiveOrNegative { self.any(|v| v.is_strictly_negative()) }
115
116 #[inline(always)]
118 pub fn is_inside(self, size : Self) -> bool where T: Number
119 {
120 self.all_with(&size, |a, m| *a >= T::ZERO && a < m)
121 }
122 #[inline(always)]
123 pub fn is_outside(self, size : Self) -> bool where T: Number { !self.is_inside(size) }
124
125 #[inline(always)]
126 pub fn is_inside_rect(self, area : Rectangle<T,N>) -> bool where T: Number { area.is_inside(self) }
127
128
129 pub fn sum_axis(self) -> T where T: NumberArithmetic { self.into_iter().sum() }
136
137 pub fn length_manhattan(self) -> T where T: NumberArithmetic, Self : Abs<Output=Self> + Copy { self.abs().sum_axis() }
139 pub fn length_squared(self) -> T where T: NumberArithmetic { self.into_iter().map(|v| v * v).sum() }
140 pub fn have_length(self) -> bool where T: Zero + PartialEq { self.into_iter().any(|c| c.is_non_zero()) }
141
142 pub fn dot(self, other : Self) -> T where T: NumberArithmetic
144 {
145 self.array.into_iter().zip(other.array.into_iter()).fold(T::ZERO, |acc,(a, b)| acc + a * b)
146 }
147
148 pub fn vector_to(self, target : Self) -> Self where Self : Sub<Self,Output = Self> { target - self }
149
150 pub fn to_rect(self) -> Rectangle<T,N> where Self : Zero
152 {
153 Rectangle::new_sized(self)
154 }
155}
156
157impl<Idx, const N : usize> Vector<Idx, N>
163 where Idx : Integer
164{
165 #[inline(always)]
166 pub fn to_index(self, size : Self) -> Option<usize> { self.is_inside(size).then(|| unsafe { self.to_index_unchecked(size) }) }
167
168 #[inline(always)]
169 pub unsafe fn to_index_unchecked(self, size : Self) -> usize
182 {
183 debug_assert!(size.all(|v| *v >= Idx::ZERO));
184
185 let mut index_1d : usize = 0;
186 let mut area_cumulative : usize = 1;
187
188 let mut i = 0;
189 while i < N
190 {
191 let current_axis_len : usize = size[i].to_usize();
192 let current_value : usize = self[i].to_usize();
193
194 index_1d += current_value * area_cumulative;
195 area_cumulative *= current_axis_len;
196 i += 1;
197 }
198 index_1d
199 }
200
201 #[inline(always)]
202 pub fn from_index(index : usize, size : Self) -> Option<Self>
203 {
204 (index < size.area_usize()).then(|| unsafe { Self::from_index_unchecked(index, size) })
205 }
206
207 #[inline(always)]
226 pub unsafe fn from_index_unchecked(index : usize, size : Self) -> Self
227 {
228 debug_assert!(size.all(|v| *v >= Idx::ZERO));
229
230 let mut result = [Idx::ZERO; N];
231 let mut area_cumulative = usize::ONE;
232
233 let mut i = 0;
234 while i < N
235 {
236 let current_axis_len = size[i].to_usize();
237 result[i] = Idx::cast_from((index / area_cumulative) % current_axis_len);
238 area_cumulative *= current_axis_len;
239 i += 1;
240 }
241 Self::from_array(result)
242 }
243
244 pub fn to_grid<F,U>(self, f : F) -> GridBase<U,Idx,N> where F : FnMut(Self) -> U { GridBase::from_fn(self, f) }
245}
246
247
248
249impl<T, const N : usize> Vector<T,N> where Self : NumberArithmetic, T : Float
250{
251 pub fn distance_to(self, target : Self) -> T { self.vector_to(target).length() }
252
253 pub fn length(self) -> T { self.length_squared().sqrt() }
254
255 pub fn normalize(&mut self) -> &mut Self { *self = self.normalized(); self }
256 pub fn normalized(self) -> Self
257 {
258 if self.have_length()
259 {
260 self / Self::splat(self.length())
261 }
262 else
263 {
264 Self::ZERO
265 }
266 }
267
268 pub fn set_angle(&mut self, angle : AngleOf<T>) -> &mut Self where Self : HaveY<T>
270 {
271 let a = angle.to_vector2(self.length()); self.set_x(a.x).set_y(a.y);
272 self
273 }
274
275 pub fn angle(self) -> AngleOf<T> where Self : HaveY<T> { AngleOf::from_radian(self.y().atan2(self.x())) }
277
278 pub fn set_length(&mut self, length : T) { *self = self.normalized() * Self::splat(length); }
279 pub fn with_length(mut self, length : T) -> Self { self.set_length(length); self }
280
281
282
283 pub fn vector_to_limited_by_speed(self, target : Self, speed : T) -> Self where T: PartialOrd
284 {
285 let dif= self.vector_to(target);
286 if dif.is_zero() { return Self::ZERO; };
287
288 let min_dist = speed.min_partial(dif.length());
289 dif.normalized().with_length(min_dist)
290 }
291
292 pub fn move_to(&mut self, target : Self, speed : T) -> bool where T: PartialOrd, Self : AddAssign<Self>
294 {
295 if self.distance_to(target) <= speed
296 {
297 *self = target;
298 return true;
299 }
300 let add = self.vector_to_limited_by_speed(target, speed);
301 *self += add;
302 add.is_zero()
303 }
304}