From 8274976de63456d92a2048f8191e2a738ff7e8ca Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Thu, 5 Dec 2019 16:43:32 +0100 Subject: [PATCH] Add basic geometric transformations --- fractional/src/lib.rs | 3 + fractional/src/main.rs | 52 ++++++++++++++ fractional/src/transform.rs | 137 ++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 fractional/src/transform.rs diff --git a/fractional/src/lib.rs b/fractional/src/lib.rs index ba6fae9..b18c369 100644 --- a/fractional/src/lib.rs +++ b/fractional/src/lib.rs @@ -23,5 +23,8 @@ extern crate lazy_static; pub mod fractional; pub mod trigonometry; pub mod vector; +pub mod transform; use fractional::{Fractional}; +use trigonometry::{sin, cos}; +use vector::{Vector}; diff --git a/fractional/src/main.rs b/fractional/src/main.rs index 0709250..8fef224 100644 --- a/fractional/src/main.rs +++ b/fractional/src/main.rs @@ -25,6 +25,7 @@ use std::f64::consts::PI as FPI; use fractional::fractional::{Fractional, from_vector, Continuous}; use fractional::trigonometry::{sin, cos, tan, PI}; use fractional::vector::{Vector}; +use fractional::transform::{translate, rotate_x, rotate_y, rotate_z, rotate_v}; fn mean(v: &Vec) -> Result { let r = v.iter().fold(0, |acc, x| acc + x); @@ -148,6 +149,55 @@ fn _vector() { println!("{:>14} : {}", "v2 * v1", v2 * v1); } +fn _transform() { + let v = Vector(1.into(), 1.into(), 1.into()); + let v1 = Vector(1.into(), 2.into(), 3.into()); + let mt = translate(v); + + println!("{:>14} : {}", "Vector v1", v1); + println!("{:>14} : {}", "translate v1", mt.apply(&v1)); + println!(); + + let v2 = Vector(1.into(), 1.into(), 0.into()); + println!("{:>14} : {}", "Vector v2", v2); + for d in [ 30, 45, 60, 90, 120, 135, 150, 180 + , 210, 225, 240, 270, 300, 315, 330 ].iter() { + let m = rotate_x(*d as i32); + println!("{:>14} : {}", format!("rot_x {} v2", d), m.apply(&v2)); + } + println!(); + + println!("{:>14} : {}", "Vector v2", v2); + for d in [ 30, 45, 60, 90, 120, 135, 150, 180 + , 210, 225, 240, 270, 300, 315, 330 ].iter() { + let m = rotate_y(*d as i32); + println!("{:>14} : {}", format!("rot_y {} v2", d), m.apply(&v2)); + } + println!(); + + for d in [ 30, 45, 60, 90, 120, 135, 150, 180 + , 210, 225, 240, 270, 300, 315, 330 ].iter() { + let m = rotate_x(*d as i32) * rotate_y(*d as i32); + println!("{:>14} : {}", format!("rot_xy {} v2", d), m.apply(&v2)); + } + println!(); + + let v3 = Vector(1.into(), 0.into(), 1.into()); + println!("{:>14} : {}", "Vector v3", v3); + for d in [ 30, 45, 60, 90, 120, 135, 150, 180 + , 210, 225, 240, 270, 300, 315, 330 ].iter() { + let m = rotate_z(*d as i32); + println!("{:>14} : {}", format!("rot_z {} v3", d), m.apply(&v3)); + } + println!(); + + for d in [ 30, 45, 60, 90, 120, 135, 150, 180 + , 210, 225, 240, 270, 300, 315, 330 ].iter() { + let m = rotate_v(&v, *d as i32); + println!("{:>14} : {}", format!("rot_v {} v2", d), m.apply(&v2)); + } +} + fn main() { common_fractional(); println!(); @@ -164,4 +214,6 @@ fn main() { _tan(); println!(); _vector(); + println!(); + _transform(); } diff --git a/fractional/src/transform.rs b/fractional/src/transform.rs new file mode 100644 index 0000000..2469f2f --- /dev/null +++ b/fractional/src/transform.rs @@ -0,0 +1,137 @@ +// +// Transformation of vectors in a given coordinate system... +// +// Georg Hopp +// +// Copyright © 2019 Georg Hopp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +use std::ops::{Mul}; +use crate::{Fractional, cos, sin, Vector}; + +pub struct TMatrix( (Fractional, Fractional, Fractional, Fractional) + , (Fractional, Fractional, Fractional, Fractional) + , (Fractional, Fractional, Fractional, Fractional) + , (Fractional, Fractional, Fractional, Fractional) ); + +pub fn translate(v :Vector) -> TMatrix { + let Vector(x, y, z) = v; + + TMatrix( (1.into(), 0.into(), 0.into(), 0.into()) + , (0.into(), 1.into(), 0.into(), 0.into()) + , (0.into(), 0.into(), 1.into(), 0.into()) + , ( x, y, z, 1.into()) ) +} + +pub fn rotate_x(a :i32) -> TMatrix { + TMatrix( (1.into(), 0.into(), 0.into(), 0.into()) + , (0.into(), cos(a), -sin(a), 0.into()) + , (0.into(), sin(a), cos(a), 0.into()) + , (0.into(), 0.into(), 0.into(), 1.into()) ) +} + +pub fn rotate_y(a :i32) -> TMatrix { + TMatrix( ( cos(a), 0.into(), sin(a), 0.into()) + , (0.into(), 1.into(), 0.into(), 0.into()) + , ( -sin(a), 0.into(), cos(a), 0.into()) + , (0.into(), 0.into(), 0.into(), 1.into()) ) +} + +pub fn rotate_z(a :i32) -> TMatrix { + TMatrix( ( cos(a), -sin(a), 0.into(), 0.into()) + , ( sin(a), cos(a), 0.into(), 0.into()) + , (0.into(), 0.into(), 1.into(), 0.into()) + , (0.into(), 0.into(), 0.into(), 1.into()) ) +} + +pub fn rotate_v(v :&Vector, a :i32) -> TMatrix { + let Vector(x, y, z) = *v; + + let zero :Fractional = 0.into(); + let one :Fractional = 1.into(); + + TMatrix( ( (one - cos(a)) * x * x + cos(a) + , (one - cos(a)) * x * y - sin(a) * z + , (one - cos(a)) * x * z + sin(a) * y + , zero ) + , ( (one - cos(a)) * x * y + sin(a) * z + , (one - cos(a)) * y * y + cos(a) + , (one - cos(a)) * y * z - sin(a) * x + , zero ) + , ( (one - cos(a)) * x * z - sin(a) * y + , (one - cos(a)) * y * z + sin(a) * x + , (one - cos(a)) * z * z + cos(a) + , zero ) + , (0.into(), 0.into(), 0.into(), 1.into()) ) +} + +pub fn scale(v :Vector) -> TMatrix { + let Vector(x, y, z) = v; + + TMatrix( ( x, 0.into(), 0.into(), 0.into()) + , (0.into(), y, 0.into(), 0.into()) + , (0.into(), 0.into(), z, 0.into()) + , (0.into(), 0.into(), 0.into(), 1.into()) ) +} + +impl TMatrix { + pub fn apply(&self, v :&Vector) -> Vector { + let TMatrix( (a11, a12, a13, a14) + , (a21, a22, a23, a24) + , (a31, a32, a33, a34) + , (a41, a42, a43, a44) ) = *self; + let Vector(x, y, z) = *v; + + let v = Vector( a11 * x + a21 * y + a31 * z + a41 + , a12 * x + a22 * y + a32 * z + a42 + , a13 * x + a23 * y + a33 * z + a43 ); + let Fractional(wn, wd) = a14 * x + a24 * y + a34 * z + a44; + + v.mul(&Fractional(wd, wn)) + } +} + +impl Mul for TMatrix { + type Output = Self; + + // ATTENTION: This is not commutative, nor assoziative. + fn mul(self, other :Self) -> Self { + let TMatrix( (a11, a12, a13, a14) + , (a21, a22, a23, a24) + , (a31, a32, a33, a34) + , (a41, a42, a43, a44) ) = self; + let TMatrix( (b11, b12, b13, b14) + , (b21, b22, b23, b24) + , (b31, b32, b33, b34) + , (b41, b42, b43, b44) ) = other; + + TMatrix( ( a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41 + , a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42 + , a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43 + , a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44 ) + , ( a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41 + , a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42 + , a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43 + , a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44 ) + , ( a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41 + , a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42 + , a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43 + , a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44 ) + , ( a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41 + , a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42 + , a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43 + , a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44 ) ) + } +}