1use {TypedVector2D, TypedPoint2D, TypedVector3D, TypedPoint3D, TypedTransform2D, TypedTransform3D};
11use {TypedSize2D, TypedRect, vec2, point2, vec3, point3};
12use num::*;
13use trig::Trig;
14use core::ops::{Add, Sub, Neg, Mul, Div};
15use core::marker::PhantomData;
16use core::fmt;
17
18#[derive(EuclidMatrix)]
39#[repr(C)]
40pub struct TypedTranslation2D<T, Src, Dst> {
41 pub x: T,
42 pub y: T,
43 #[doc(hidden)]
44 pub _unit: PhantomData<(Src, Dst)>,
45}
46
47impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst> {
48 #[inline]
49 pub fn new(x: T, y: T) -> Self {
50 TypedTranslation2D {
51 x,
52 y,
53 _unit: PhantomData,
54 }
55 }
56}
57
58impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
59where
60 T : Copy
61{
62 #[inline]
63 pub fn to_array(&self) -> [T; 2] {
64 [self.x, self.y]
65 }
66
67 #[inline]
68 pub fn to_tuple(&self) -> (T, T) {
69 (self.x, self.y)
70 }
71}
72
73impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
74where
75 T : Copy + Zero
76{
77 #[inline]
78 pub fn identity() -> Self {
79 let _0 = T::zero();
80 TypedTranslation2D::new(_0, _0)
81 }
82}
83
84impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
85where
86 T: Zero + PartialEq
87{
88 #[inline]
89 pub fn is_identity(&self) -> bool {
90 self.x == T::zero() && self.y == T::zero()
91 }
92}
93
94impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
95where
96 T: Copy + Add<T, Output = T>
97{
98 #[inline]
100 pub fn transform_point(&self, p: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
101 point2(p.x + self.x, p.y + self.y)
102 }
103
104 #[inline]
106 pub fn transform_rect(&self, r: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
107 TypedRect {
108 origin: self.transform_point(&r.origin),
109 size: self.transform_size(&r.size),
110 }
111 }
112
113 #[inline]
115 pub fn transform_size(&self, s: &TypedSize2D<T, Src>) -> TypedSize2D<T, Dst> {
116 TypedSize2D::new(s.width, s.height)
117 }
118
119 pub fn to_vector(&self) -> TypedVector2D<T, Src> {
121 vec2(self.x, self.y)
122 }
123}
124
125impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
126where
127 T: Copy + Neg<Output = T>
128{
129 #[inline]
131 pub fn inverse(&self) -> TypedTranslation2D<T, Dst, Src> {
132 TypedTranslation2D::new(-self.x, -self.y)
133 }
134}
135
136impl<T, Src, Dst1, Dst2> Add<TypedTranslation2D<T, Dst1, Dst2>>
137for TypedTranslation2D<T, Src, Dst1>
138where
139 T: Copy + Add<T, Output = T>
140{
141 type Output = TypedTranslation2D<T, Src, Dst2>;
142 fn add(self, other: TypedTranslation2D<T, Dst1, Dst2>) -> TypedTranslation2D<T, Src, Dst2> {
143 TypedTranslation2D::new(
144 self.x + other.x,
145 self.y + other.y,
146 )
147 }
148}
149
150impl<T, Src, Dst1, Dst2>
151 Sub<TypedTranslation2D<T, Dst1, Dst2>>
152 for TypedTranslation2D<T, Src, Dst2>
153where
154 T: Copy + Sub<T, Output = T>
155{
156 type Output = TypedTranslation2D<T, Src, Dst1>;
157 fn sub(self, other: TypedTranslation2D<T, Dst1, Dst2>) -> TypedTranslation2D<T, Src, Dst1> {
158 TypedTranslation2D::new(
159 self.x - other.x,
160 self.y - other.y,
161 )
162 }
163}
164
165impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
166where
167 T: Copy
168 + Clone
169 + Add<T, Output = T>
170 + Mul<T, Output = T>
171 + Div<T, Output = T>
172 + Sub<T, Output = T>
173 + Trig
174 + PartialOrd
175 + One
176 + Zero,
177{
178 #[inline]
180 pub fn to_transform(&self) -> TypedTransform2D<T, Src, Dst> {
181 TypedTransform2D::create_translation(self.x, self.y)
182 }
183}
184
185impl<T, Src, Dst> From<TypedVector2D<T, Src>> for TypedTranslation2D<T, Src, Dst>
186where
187 T: Copy
188{
189 fn from(v: TypedVector2D<T, Src>) -> Self {
190 TypedTranslation2D::new(v.x, v.y)
191 }
192}
193
194impl<T, Src, Dst> Into<TypedVector2D<T, Src>> for TypedTranslation2D<T, Src, Dst>
195where
196 T: Copy
197{
198 fn into(self) -> TypedVector2D<T, Src> {
199 vec2(self.x, self.y)
200 }
201}
202
203impl<T, Src, Dst> Into<TypedTransform2D<T, Src, Dst>> for TypedTranslation2D<T, Src, Dst>
204where
205 T: Copy
206 + Clone
207 + Add<T, Output = T>
208 + Mul<T, Output = T>
209 + Div<T, Output = T>
210 + Sub<T, Output = T>
211 + Trig
212 + PartialOrd
213 + One
214 + Zero,
215{
216 fn into(self) -> TypedTransform2D<T, Src, Dst> {
217 self.to_transform()
218 }
219}
220
221impl <T, Src, Dst> Default for TypedTranslation2D<T, Src, Dst>
222 where T: Copy + Zero
223{
224 fn default() -> Self {
225 Self::identity()
226 }
227}
228
229impl<T, Src, Dst> fmt::Debug for TypedTranslation2D<T, Src, Dst>
230where T: Copy + fmt::Debug {
231 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232 self.to_array().fmt(f)
233 }
234}
235
236
237
238#[derive(EuclidMatrix)]
243#[repr(C)]
244pub struct TypedTranslation3D<T, Src, Dst> {
245 pub x: T,
246 pub y: T,
247 pub z: T,
248 #[doc(hidden)]
249 pub _unit: PhantomData<(Src, Dst)>,
250}
251
252impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst> {
253 #[inline]
254 pub fn new(x: T, y: T, z: T) -> Self {
255 TypedTranslation3D {
256 x,
257 y,
258 z,
259 _unit: PhantomData,
260 }
261 }
262}
263
264impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
265where
266 T: Copy
267{
268 #[inline]
269 pub fn to_array(&self) -> [T; 3] {
270 [self.x, self.y, self.z]
271 }
272
273 #[inline]
274 pub fn to_tuple(&self) -> (T, T, T) {
275 (self.x, self.y, self.z)
276 }
277}
278
279impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
280where
281 T: Copy + Zero
282{
283 #[inline]
284 pub fn identity() -> Self {
285 let _0 = T::zero();
286 TypedTranslation3D::new(_0, _0, _0)
287 }
288}
289
290impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
291where
292 T: Zero + PartialEq
293{
294 #[inline]
295 pub fn is_identity(&self) -> bool {
296 self.x == T::zero() && self.y == T::zero() && self.z == T::zero()
297 }
298}
299
300impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
301where
302 T: Copy + Add<T, Output = T>
303{
304 #[inline]
306 pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> TypedPoint3D<T, Dst> {
307 point3(p.x + self.x, p.y + self.y, p.z + self.z)
308 }
309
310 #[inline]
312 pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
313 point2(p.x + self.x, p.y + self.y)
314 }
315
316 #[inline]
318 pub fn transform_rect(&self, r: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
319 TypedRect {
320 origin: self.transform_point2d(&r.origin),
321 size: self.transform_size(&r.size),
322 }
323 }
324
325 #[inline]
327 pub fn transform_size(&self, s: &TypedSize2D<T, Src>) -> TypedSize2D<T, Dst> {
328 TypedSize2D::new(s.width, s.height)
329 }
330
331 pub fn to_vector(&self) -> TypedVector3D<T, Src> {
333 vec3(self.x, self.y, self.z)
334 }
335}
336
337impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
338where
339 T: Copy + Neg<Output = T>
340{
341 #[inline]
343 pub fn inverse(&self) -> TypedTranslation3D<T, Dst, Src> {
344 TypedTranslation3D::new(-self.x, -self.y, -self.z)
345 }
346}
347
348impl<T, Src, Dst1, Dst2> Add<TypedTranslation3D<T, Dst1, Dst2>>
349for TypedTranslation3D<T, Src, Dst1>
350where
351 T: Copy + Add<T, Output = T>
352{
353 type Output = TypedTranslation3D<T, Src, Dst2>;
354 fn add(self, other: TypedTranslation3D<T, Dst1, Dst2>) -> TypedTranslation3D<T, Src, Dst2> {
355 TypedTranslation3D::new(
356 self.x + other.x,
357 self.y + other.y,
358 self.z + other.z,
359 )
360 }
361}
362
363impl<T, Src, Dst1, Dst2>
364 Sub<TypedTranslation3D<T, Dst1, Dst2>>
365 for TypedTranslation3D<T, Src, Dst2>
366where
367 T: Copy + Sub<T, Output = T>
368{
369 type Output = TypedTranslation3D<T, Src, Dst1>;
370 fn sub(self, other: TypedTranslation3D<T, Dst1, Dst2>) -> TypedTranslation3D<T, Src, Dst1> {
371 TypedTranslation3D::new(
372 self.x - other.x,
373 self.y - other.y,
374 self.z - other.z,
375 )
376 }
377}
378
379impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
380where
381 T: Copy + Clone +
382 Add<T, Output=T> +
383 Sub<T, Output=T> +
384 Mul<T, Output=T> +
385 Div<T, Output=T> +
386 Neg<Output=T> +
387 PartialOrd +
388 Trig +
389 One + Zero,
390{
391 #[inline]
393 pub fn to_transform(&self) -> TypedTransform3D<T, Src, Dst> {
394 TypedTransform3D::create_translation(self.x, self.y, self.z)
395 }
396}
397
398impl<T, Src, Dst> From<TypedVector3D<T, Src>> for TypedTranslation3D<T, Src, Dst>
399where
400 T: Copy
401{
402 fn from(v: TypedVector3D<T, Src>) -> Self {
403 TypedTranslation3D::new(v.x, v.y, v.z)
404 }
405}
406
407impl<T, Src, Dst> Into<TypedVector3D<T, Src>> for TypedTranslation3D<T, Src, Dst>
408where
409 T: Copy
410{
411 fn into(self) -> TypedVector3D<T, Src> {
412 vec3(self.x, self.y, self.z)
413 }
414}
415
416impl<T, Src, Dst> Into<TypedTransform3D<T, Src, Dst>> for TypedTranslation3D<T, Src, Dst>
417where
418 T: Copy + Clone +
419 Add<T, Output=T> +
420 Sub<T, Output=T> +
421 Mul<T, Output=T> +
422 Div<T, Output=T> +
423 Neg<Output=T> +
424 PartialOrd +
425 Trig +
426 One + Zero,
427{
428 fn into(self) -> TypedTransform3D<T, Src, Dst> {
429 self.to_transform()
430 }
431}
432
433impl <T, Src, Dst> Default for TypedTranslation3D<T, Src, Dst>
434 where T: Copy + Zero
435{
436 fn default() -> Self {
437 Self::identity()
438 }
439}
440
441impl<T, Src, Dst> fmt::Debug for TypedTranslation3D<T, Src, Dst>
442where T: Copy + fmt::Debug {
443 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444 self.to_array().fmt(f)
445 }
446}
447
448#[test]
449fn simple_translation2d() {
450 use rect;
451
452 struct A;
453 struct B;
454
455 type Translation = TypedTranslation2D<i32, A, B>;
456 type SrcRect = TypedRect<i32, A>;
457 type DstRect = TypedRect<i32, B>;
458
459 let tx = Translation::new(10, -10);
460 let r1: SrcRect = rect(10, 20, 30, 40);
461 let r2: DstRect = tx.transform_rect(&r1);
462 assert_eq!(r2, rect(20, 10, 30, 40));
463
464 let inv_tx = tx.inverse();
465 assert_eq!(inv_tx.transform_rect(&r2), r1);
466
467 assert!((tx + inv_tx).is_identity());
468}
469
470#[test]
471fn simple_translation3d() {
472 struct A;
473 struct B;
474
475 type Translation = TypedTranslation3D<i32, A, B>;
476 type SrcPoint = TypedPoint3D<i32, A>;
477 type DstPoint = TypedPoint3D<i32, B>;
478
479 let tx = Translation::new(10, -10, 100);
480 let p1: SrcPoint = point3(10, 20, 30);
481 let p2: DstPoint = tx.transform_point3d(&p1);
482 assert_eq!(p2, point3(20, 10, 130));
483
484 let inv_tx = tx.inverse();
485 assert_eq!(inv_tx.transform_point3d(&p2), p1);
486
487 assert!((tx + inv_tx).is_identity());
488}