You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
14 KiB
427 lines
14 KiB
//
|
|
// Test our fractional crate / module...
|
|
//
|
|
// Georg Hopp <georg@steffers.org>
|
|
//
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
//
|
|
use std::convert::{TryFrom, TryInto, Into};
|
|
use std::f64::consts::PI as FPI;
|
|
use std::fmt::{Debug, Display};
|
|
use std::marker::Send;
|
|
use std::num::TryFromIntError;
|
|
use std::ops::{Add,Sub,Neg,Mul,Div};
|
|
use std::sync::mpsc;
|
|
use std::thread;
|
|
use std::time::{Duration, Instant};
|
|
|
|
use fractional::continuous::Continuous;
|
|
use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline
|
|
, Polygon, Canvas, Fillable };
|
|
use fractional::fractional::{Fractional, from_vector};
|
|
use fractional::trigonometry::Trig;
|
|
use fractional::vector::Vector;
|
|
use fractional::transform::{TMatrix, Transformable};
|
|
use fractional::xcb::XcbEasel;
|
|
use fractional::geometry::{Camera, DirectLight, Polyeder, Primitives};
|
|
|
|
fn mean(v: &Vec<i64>) -> Result<Fractional, TryFromIntError> {
|
|
let r = v.iter().fold(0, |acc, x| acc + x);
|
|
let l = i64::try_from(v.len())?;
|
|
Ok(Fractional(r, l))
|
|
}
|
|
|
|
fn common_fractional() {
|
|
let a = vec![3, 6, 1, 9];
|
|
let b = from_vector(&a);
|
|
let c = mean(&a).unwrap(); // This might fail if the len of the
|
|
// vector (usize) does not fit into i32.
|
|
let cr :f64 = c.try_into().unwrap();
|
|
|
|
println!(" [i32] : {:?}", a);
|
|
println!(" [Fractional] : {:?}", b);
|
|
println!(" mean of [i32] : {}" , c);
|
|
println!(" as f64 : {}" , cr);
|
|
println!(" again as f64 : {}" , TryInto::<f64>::try_into(c).unwrap());
|
|
}
|
|
|
|
fn continuous() {
|
|
let d = Fractional(45, 16);
|
|
let e = Fractional(16, 45);
|
|
|
|
let dc :Continuous = (&d).into();
|
|
let ec :Continuous = (&e).into();
|
|
|
|
println!("cont frac of d : {} => {:?}", d, dc);
|
|
println!("cont frac of e : {} => {:?}", e, ec);
|
|
println!(" reverted dc : {:?} {}", dc, Into::<Fractional>::into(&dc));
|
|
println!(" reverted ec : {:?} {}", ec, Into::<Fractional>::into(&ec));
|
|
}
|
|
|
|
fn sqrt() {
|
|
let f = Fractional(-9, 4);
|
|
let fr :f64 = f.try_into().unwrap();
|
|
let sq = f.sqrt();
|
|
let _sq = fr.sqrt();
|
|
|
|
println!("{:>14} : {:?} / {}", format!("sqrt {}", f), sq, _sq);
|
|
|
|
for f in [ Fractional(9, 4)
|
|
, Fractional(45, 16)
|
|
, Fractional(16, 45)
|
|
, Fractional(9, 3) ].iter() {
|
|
let fr :f64 = (*f).try_into().unwrap();
|
|
let sq = f.sqrt().unwrap();
|
|
let sqr :f64 = sq.try_into().unwrap();
|
|
let _sqr = fr.sqrt();
|
|
|
|
println!("{:>14} : {} {} / {}", format!("sqrt {}", f), sq, sqr, _sqr);
|
|
}
|
|
}
|
|
|
|
fn pi() {
|
|
let pi = Fractional::pi();
|
|
let pir :f64 = pi.try_into().unwrap();
|
|
let pit :(i32, i32) = pi.try_into().unwrap();
|
|
let pi2r :f64 = (pi * pi).try_into().unwrap();
|
|
|
|
println!(" Rust π : {}" , FPI);
|
|
println!(" π : {} {}" , pi, pir);
|
|
println!(" π as tuple : {:?}" , pit);
|
|
println!(" Rust π² : {}" , FPI * FPI);
|
|
println!(" π² : {} {}" , pi * pi, pi2r);
|
|
}
|
|
|
|
fn _sin() {
|
|
for d in [ 0, 30, 45, 90, 135, 180, 225, 270, 315
|
|
, 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() {
|
|
let s = Fractional::sin(*d as i32);
|
|
let sr :f64 = s.try_into().unwrap();
|
|
let _s = f64::sin(*d as f64 * FPI / 180.0);
|
|
|
|
println!("{:>14} : {} {} / {}", format!("sin {}", d), s, sr, _s);
|
|
}
|
|
}
|
|
|
|
fn _tan() {
|
|
for d in [ 0, 30, 45, 90, 135, 180, 225, 270, 315
|
|
, 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() {
|
|
let t = Fractional::tan(*d as i32);
|
|
let tr :f64 = t.try_into().unwrap();
|
|
let _t = f64::tan(*d as f64 * FPI / 180.0);
|
|
|
|
println!("{:>14} : {} {} / {}", format!("tan {}", d), t, tr, _t);
|
|
}
|
|
}
|
|
|
|
fn _cos() {
|
|
for d in [ 0, 30, 45, 90, 135, 180, 225, 270, 315
|
|
, 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() {
|
|
let c = Fractional::cos(*d as i32);
|
|
let cr :f64 = c.try_into().unwrap();
|
|
let _c = f64::cos(*d as f64 * FPI / 180.0);
|
|
|
|
println!("{:>14} : {} {} / {}", format!("cos {}", d), c, cr, _c);
|
|
}
|
|
}
|
|
|
|
fn _vector1() {
|
|
let v1 = Vector(1.into(), 2.into(), 3.into());
|
|
let v2 = Vector(2.into(), 2.into(), 3.into());
|
|
let s :Fractional = 3.into();
|
|
|
|
_vector(v1, v2, s);
|
|
}
|
|
|
|
fn _vector2() {
|
|
let v1 = Vector(1.0, 2.0, 3.0);
|
|
let v2 = Vector(2.0, 2.0, 3.0);
|
|
let s = 3.0;
|
|
|
|
_vector(v1, v2, s);
|
|
}
|
|
|
|
fn _vector<T>(v1 :Vector<T>, v2 :Vector<T>, s :T)
|
|
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
|
|
+ Mul<Output = T> + Div<Output = T> + Trig + Copy + Display {
|
|
println!("{:>14} : {}", "Vector v1", v1);
|
|
println!("{:>14} : {}", "Vector v2", v2);
|
|
println!("{:>14} : {}", "magnitude v1", v1.mag());
|
|
println!("{:>14} : {}", "-v1", -v1);
|
|
println!("{:>14} : {}", "v1 + v1", v1 + v1);
|
|
println!("{:>14} : {}", "v1 - v1", v1 - v1);
|
|
println!("{:>14} : {}", "v2 - v1", v2 - v1);
|
|
println!("{:>14} : {}", format!("v1 * {}", s), v1.mul(&s));
|
|
println!("{:>14} : {}", "norm v1", v1.norm());
|
|
println!("{:>14} : {}", "magnitude norm v1", v1.norm().mag());
|
|
println!("{:>14} : {}", "magnitude v1", v1.mag());
|
|
println!("{:>14} : {}", "norm * magnitude", v1.norm().mul(&v1.mag()));
|
|
println!("{:>14} : {}", "distance v1 v2", v1.distance(v2));
|
|
println!("{:>14} : {}", "distance v2 v1", v2.distance(v1));
|
|
println!("{:>14} : {}", "v1 dot v2", v1.dot(v2));
|
|
println!("{:>14} : {}", "v2 dot v1", v2.dot(v1));
|
|
println!("{:>14} : {}", "v1 * v2", v1 * v2);
|
|
println!("{:>14} : {}", "v2 * v1", v2 * v1);
|
|
}
|
|
|
|
fn _transform1() {
|
|
let v = Vector(Fractional(1,1), Fractional(1,1), Fractional(1,1));
|
|
let v1 = Vector(Fractional(1,1), Fractional(2,1), Fractional(3,1));
|
|
let v2 = Vector(Fractional(1,1), Fractional(1,1), Fractional(0,1));
|
|
let v3 = Vector(Fractional(1,1), Fractional(0,1), Fractional(1,1));
|
|
|
|
_transform(v, v1, v2, v3);
|
|
}
|
|
|
|
fn _transform2() {
|
|
let v = Vector(1.0, 1.0, 1.0);
|
|
let v1 = Vector(1.0, 2.0, 3.0);
|
|
let v2 = Vector(1.0, 1.0, 0.0);
|
|
let v3 = Vector(1.0, 0.0, 1.0);
|
|
|
|
_transform(v, v1, v2, v3);
|
|
}
|
|
|
|
fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>)
|
|
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
|
|
+ Mul<Output = T> + Div<Output = T> + Trig
|
|
+ Debug + From<i32> + Copy + Display {
|
|
|
|
println!("{:>14} : {}", "Vector v1", v1);
|
|
println!( "{:>14} : {}", "translate v1"
|
|
, v.transform(&TMatrix::translate(v)));
|
|
println!();
|
|
|
|
fn _rot<T>( o :&str , n :&str , v :&Vector<T>
|
|
, fs :&[&dyn Fn(i32) -> TMatrix<T>] )
|
|
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
|
|
+ Mul<Output = T> + Div<Output = T> + Trig
|
|
+ Debug + From<i32> + Copy + Display {
|
|
|
|
for d in [ 30, 45, 60, 90, 120, 135, 150, 180
|
|
, 210, 225, 240, 270, 300, 315, 330 ].iter() {
|
|
let mi = fs.iter().map(|f| f(*d as i32));
|
|
println!( "{:>14} : {}"
|
|
, format!("{} {} {}", o, d, n)
|
|
, v.transform(&TMatrix::combine(mi)) );
|
|
}
|
|
}
|
|
|
|
println!("{:>14} : {}", "Vector v2", v2);
|
|
_rot("rot_x", "v2", &v2, &[&TMatrix::rotate_x]);
|
|
println!();
|
|
_rot("rot_y", "v2", &v2, &[&TMatrix::rotate_y]);
|
|
println!();
|
|
_rot("rot_xy", "v2", &v2, &[&TMatrix::rotate_x, &TMatrix::rotate_y]);
|
|
println!();
|
|
println!("{:>14} : {}", "Vector v3", v3);
|
|
_rot("rot_z", "v3", &v3, &[&TMatrix::rotate_z]);
|
|
println!();
|
|
|
|
for d in [ 30, 45, 60, 90, 120, 135, 150, 180
|
|
, 210, 225, 240, 270, 300, 315, 330 ].iter() {
|
|
println!( "{:>14} : {}"
|
|
, format!("rot_v {} v2", d)
|
|
, v2.transform(&TMatrix::rotate_v(&v, *d as i32)) );
|
|
}
|
|
}
|
|
|
|
fn _line() {
|
|
let a = (Coordinate(0, 1, 0.0), Coordinate(6, 4, 0.0));
|
|
let b = (Coordinate(0, 4, 0.0), Coordinate(6, 1, 0.0));
|
|
let c = (Coordinate(1, 0, 0.0), Coordinate(6, 8, 0.0));
|
|
let d = (Coordinate(1, 8, 0.0), Coordinate(6, 0, 0.0));
|
|
|
|
for i in [a, b, c, d].iter() {
|
|
println!("{:>14} : {}", Line(i.0, i.1), Line(i.0, i.1).plot());
|
|
println!("{:>14} : {}", Line(i.1, i.0), Line(i.1, i.0).plot());
|
|
}
|
|
|
|
println!();
|
|
let pl = Polyline(
|
|
Coordinates(vec!(a.0, a.1, b.0, b.1, c.0, c.1, d.0, d.1)));
|
|
println!("{:>14} : {}", pl, pl.plot());
|
|
|
|
println!();
|
|
let pg = Polygon(
|
|
Coordinates(vec!( Coordinate( 0, -10, 0.0)
|
|
, Coordinate( 10, 10, 0.0)
|
|
, Coordinate(-10, 10, 0.0) )));
|
|
println!("{:>14} : {}", pg, pg.plot());
|
|
|
|
let i = Vector(Fractional( 0,1), Fractional(-30,1), Fractional(0,1));
|
|
let j = Vector(Fractional( 30,1), Fractional( 30,1), Fractional(0,1));
|
|
let k = Vector(Fractional(-30,1), Fractional( 30,1), Fractional(0,1));
|
|
|
|
let rot :TMatrix<Fractional> = TMatrix::rotate_z(20);
|
|
let Vector(ix, iy, _) = i.transform(&rot);
|
|
let Vector(jx, jy, _) = j.transform(&rot);
|
|
let Vector(kx, ky, _) = k.transform(&rot);
|
|
|
|
fn to_i32(x :Fractional) -> i32 {
|
|
let Fractional(n, d) = x;
|
|
(n / d + if (n % d).abs() < (n / 2).abs() { 0 } else { 1 }) as i32
|
|
}
|
|
|
|
println!();
|
|
let pg = Polygon(
|
|
Coordinates(vec!( Coordinate(to_i32(ix) + 100, to_i32(iy) + 100, 0.0)
|
|
, Coordinate(to_i32(jx) + 100, to_i32(jy) + 100, 0.0)
|
|
, Coordinate(to_i32(kx) + 100, to_i32(ky) + 100, 0.0) )));
|
|
println!("{:>14} : {}", pg, pg.plot());
|
|
|
|
let i = Vector( 0.0, -30.0, 0.0);
|
|
let j = Vector( 30.0, 30.0, 0.0);
|
|
let k = Vector(-30.0, 30.0, 0.0);
|
|
|
|
let rot :TMatrix<f64> = TMatrix::rotate_z(20);
|
|
let Vector(ix, iy, _) = i.transform(&rot);
|
|
let Vector(jx, jy, _) = j.transform(&rot);
|
|
let Vector(kx, ky, _) = k.transform(&rot);
|
|
|
|
fn to_i32_2(x :f64) -> i32 {
|
|
x.round() as i32
|
|
}
|
|
|
|
println!();
|
|
let pg = Polygon(
|
|
Coordinates(vec!( Coordinate(to_i32_2(ix) + 100, to_i32_2(iy) + 100, 0.0)
|
|
, Coordinate(to_i32_2(jx) + 100, to_i32_2(jy) + 100, 0.0)
|
|
, Coordinate(to_i32_2(kx) + 100, to_i32_2(ky) + 100, 0.0) )));
|
|
println!("{:>14} : {}", pg, pg.plot());
|
|
}
|
|
|
|
fn _democanvas<T>( xcb :&XcbEasel
|
|
, title :&'static str
|
|
, tx :mpsc::Sender<i32>
|
|
, _triangle :Polyeder<T>
|
|
, tetrahedron :Polyeder<T>
|
|
, cube :Polyeder<T>
|
|
, light :DirectLight<T> )
|
|
where T: 'static + Add<Output = T> + Sub<Output = T> + Neg<Output = T>
|
|
+ Mul<Output = T> + Div<Output = T>
|
|
+ Debug + Copy + Trig + Send + From<i32> + PartialOrd {
|
|
|
|
let mut canvas = xcb.canvas(151, 151).unwrap();
|
|
let camera = Camera::<T>::new(&canvas, 45); // the orig. view angle
|
|
// was 50.
|
|
|
|
canvas.set_title(title);
|
|
canvas.init_events();
|
|
canvas.start_events(tx.clone());
|
|
|
|
thread::spawn(move || {
|
|
let start = Instant::now();
|
|
let step = Duration::from_millis(25);
|
|
let mut last = Instant::now();
|
|
|
|
let t = TMatrix::translate(Vector(0.into() , 0.into() , 150.into()));
|
|
|
|
loop {
|
|
let deg = ((start.elapsed() / 25).as_millis() % 360) as i32;
|
|
|
|
let rz = TMatrix::rotate_z(deg);
|
|
let rx = TMatrix::rotate_x(-deg*2);
|
|
let ry = TMatrix::rotate_y(-deg*2);
|
|
|
|
let rot1 = TMatrix::combine(vec!(rz, rx, t));
|
|
let rot2 = TMatrix::combine(vec!(rz, ry, t));
|
|
|
|
let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00)
|
|
, ( cube.transform(&rot2), 0x0000FF) );
|
|
//let objects = vec!( ( cube.transform(&rot2), 0x0000FF) );
|
|
//let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) );
|
|
//let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) );
|
|
|
|
canvas.clear();
|
|
|
|
for (o, color) in objects {
|
|
for (pg, c) in o.project(&camera, &light, color) {
|
|
//canvas.draw(&pg, Coordinate(0, 0, 0.into()), c);
|
|
(&pg).fill(&mut canvas, c);
|
|
//(&pg).debug();
|
|
//println!("\n");
|
|
}
|
|
}
|
|
|
|
let passed = Instant::now() - last;
|
|
let f = (passed.as_nanos() / step.as_nanos()) as u32;
|
|
|
|
if f > 1 {
|
|
println!("{} !!! Detected frame drop", title);
|
|
}
|
|
|
|
last = last + step*(f + 1);
|
|
canvas.put_text( Coordinate(10, 15, 0.into())
|
|
, &format!( "sleep: {:?}"
|
|
, last - Instant::now() ));
|
|
canvas.show();
|
|
thread::sleep(last - Instant::now());
|
|
}
|
|
});
|
|
}
|
|
|
|
fn main() {
|
|
common_fractional();
|
|
println!();
|
|
continuous();
|
|
println!();
|
|
sqrt();
|
|
println!();
|
|
pi();
|
|
println!();
|
|
_sin();
|
|
println!();
|
|
_cos();
|
|
println!();
|
|
_tan();
|
|
println!();
|
|
_vector1();
|
|
println!();
|
|
_vector2();
|
|
println!();
|
|
_transform1();
|
|
println!();
|
|
_transform2();
|
|
println!();
|
|
_line();
|
|
|
|
let xcb = XcbEasel::new().unwrap();
|
|
let (tx, rx) = mpsc::channel();
|
|
|
|
|
|
_democanvas( &xcb, "Something...(f64)", tx.clone()
|
|
, Polyeder::triangle(60.0)
|
|
, Polyeder::tetrahedron(100.0)
|
|
, Polyeder::cube(56.25)
|
|
, DirectLight::new(Vector(0.0, 0.0, 1.0)) );
|
|
/*
|
|
_democanvas( &xcb, "Something...(Fractional)", tx.clone()
|
|
, Polyeder::triangle(Fractional(60,1))
|
|
, Polyeder::tetrahedron(Fractional(80,1))
|
|
, Polyeder::cube(Fractional(55,1))
|
|
, DirectLight::new(Vector( Fractional(0,1)
|
|
, Fractional(0,1)
|
|
, Fractional(1,1) )) );
|
|
*/
|
|
|
|
for x in rx {
|
|
match x {
|
|
1 => break,
|
|
_ => {},
|
|
}
|
|
}
|
|
}
|