Showing
4 changed files
with
188 additions
and
121 deletions
fractional/src/geometry.rs
0 → 100644
| 1 | +// | ||
| 2 | +// Basic geometric things... | ||
| 3 | +// | ||
| 4 | +// Georg Hopp <georg@steffers.org> | ||
| 5 | +// | ||
| 6 | +// Copyright © 2019 Georg Hopp | ||
| 7 | +// | ||
| 8 | +// This program is free software: you can redistribute it and/or modify | ||
| 9 | +// it under the terms of the GNU General Public License as published by | ||
| 10 | +// the Free Software Foundation, either version 3 of the License, or | ||
| 11 | +// (at your option) any later version. | ||
| 12 | +// | ||
| 13 | +// This program is distributed in the hope that it will be useful, | ||
| 14 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | +// GNU General Public License for more details. | ||
| 17 | +// | ||
| 18 | +// You should have received a copy of the GNU General Public License | ||
| 19 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | +// | ||
| 21 | +use std::convert::From; | ||
| 22 | +use std::ops::{Add,Sub,Neg,Mul,Div}; | ||
| 23 | +use std::fmt::Debug; | ||
| 24 | + | ||
| 25 | +use crate::easel::{Canvas,Coordinate,Coordinates,Polygon}; | ||
| 26 | +use crate::transform::TMatrix; | ||
| 27 | +use crate::trigonometry::Trig; | ||
| 28 | +use crate::vector::Vector; | ||
| 29 | + | ||
| 30 | +#[derive(Debug)] | ||
| 31 | +pub struct Polyeder<T> | ||
| 32 | +where T: Add + Sub + Neg + Mul + Div + Copy + Trig { | ||
| 33 | + points :Vec<Vector<T>>, | ||
| 34 | + faces :Vec<Vec<usize>>, | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +pub trait Primitives<T> | ||
| 38 | +where T: Add + Sub + Neg + Mul + Div + Copy + Trig + From<i32> { | ||
| 39 | + fn transform(&self, m :&TMatrix<T>) -> Self; | ||
| 40 | + fn project(&self, camera :&Camera<T>) -> Vec<Polygon>; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +pub struct Camera<T> | ||
| 44 | +where T: Add + Sub + Neg + Mul + Div + Copy + Trig { | ||
| 45 | + width :T, | ||
| 46 | + height :T, | ||
| 47 | + fovx :T, | ||
| 48 | + fovy :T, | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +impl<T> Camera<T> | ||
| 52 | +where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | ||
| 53 | + + Mul<Output = T> + Div<Output = T> | ||
| 54 | + + Copy + Trig + From<i32> { | ||
| 55 | + pub fn new(c :&dyn Canvas, angle :i32) -> Self { | ||
| 56 | + let width = <T as From<i32>>::from(c.width() as i32); | ||
| 57 | + let height = <T as From<i32>>::from(c.height() as i32); | ||
| 58 | + | ||
| 59 | + // The calculations for fovx and fovy are taken from a book, but I | ||
| 60 | + // have the impression, coming from my limited algebra knowledge, | ||
| 61 | + // that they are always equal… | ||
| 62 | + Camera { width: width | ||
| 63 | + , height: height | ||
| 64 | + , fovx: T::cot(angle) * width | ||
| 65 | + , fovy: width / height * T::cot(angle) * height } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + pub fn project(&self, v :Vector<T>) -> Coordinate { | ||
| 69 | + let f2 = From::<i32>::from(2); | ||
| 70 | + let xs = v.x() / v.z() * self.fovx + self.width / f2; | ||
| 71 | + let ys = v.y() / v.z() * self.fovy + self.height / f2; | ||
| 72 | + | ||
| 73 | + Coordinate(T::round(&xs), T::round(&ys)) | ||
| 74 | + } | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +impl<T> Polyeder<T> | ||
| 78 | +where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | ||
| 79 | + + Mul<Output = T> + Div<Output = T> | ||
| 80 | + + Copy + Trig + From<i32> { | ||
| 81 | + // https://rechneronline.de/pi/tetrahedron.php | ||
| 82 | + pub fn tetrahedron(a :T) -> Polyeder<T> { | ||
| 83 | + let f0 :T = From::<i32>::from(0); | ||
| 84 | + let f3 :T = From::<i32>::from(3); | ||
| 85 | + let f4 :T = From::<i32>::from(4); | ||
| 86 | + let f6 :T = From::<i32>::from(6); | ||
| 87 | + let f12 :T = From::<i32>::from(12); | ||
| 88 | + | ||
| 89 | + let yi :T = a / f12 * T::sqrt(f6).unwrap(); | ||
| 90 | + let yc :T = a / f4 * T::sqrt(f6).unwrap(); | ||
| 91 | + let zi :T = T::sqrt(f3).unwrap() / f6 * a; | ||
| 92 | + let zc :T = T::sqrt(f3).unwrap() / f3 * a; | ||
| 93 | + let ah :T = a / From::<i32>::from(2); | ||
| 94 | + | ||
| 95 | + // half the height in y | ||
| 96 | + let _yh :T = a / f6 * T::sqrt(f6).unwrap(); | ||
| 97 | + // half the deeps in z | ||
| 98 | + let _zh :T = T::sqrt(f3).unwrap() / f4 * a; | ||
| 99 | + | ||
| 100 | + Polyeder{ points: vec!( Vector( f0, yc, f0) | ||
| 101 | + , Vector(-ah, -yi, -zi) | ||
| 102 | + , Vector( ah, -yi, -zi) | ||
| 103 | + , Vector( f0, -yi, zc) ) | ||
| 104 | + , faces: vec!( vec!(1, 2, 3) | ||
| 105 | + , vec!(1, 0, 2) | ||
| 106 | + , vec!(3, 0, 1) | ||
| 107 | + , vec!(2, 0, 3) )} | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + pub fn cube(a :T) -> Polyeder<T> { | ||
| 111 | + let ah :T = a / From::<i32>::from(2); | ||
| 112 | + | ||
| 113 | + Polyeder{ points: vec!( Vector(-ah, ah, -ah) // 0 => front 1 | ||
| 114 | + , Vector(-ah, -ah, -ah) // 1 => front 2 | ||
| 115 | + , Vector( ah, -ah, -ah) // 2 => front 3 | ||
| 116 | + , Vector( ah, ah, -ah) // 3 => front 4 | ||
| 117 | + , Vector(-ah, ah, ah) // 4 => back 1 | ||
| 118 | + , Vector(-ah, -ah, ah) // 5 => back 2 | ||
| 119 | + , Vector( ah, -ah, ah) // 6 => back 3 | ||
| 120 | + , Vector( ah, ah, ah) ) // 7 => back 4 | ||
| 121 | + , faces: vec!( vec!(0, 1, 2, 3) // front | ||
| 122 | + , vec!(7, 6, 5, 4) // back | ||
| 123 | + , vec!(1, 5, 6, 2) // top | ||
| 124 | + , vec!(0, 3, 7, 4) // bottom | ||
| 125 | + , vec!(0, 4, 5, 1) // left | ||
| 126 | + , vec!(2, 6, 7, 3) )} // right | ||
| 127 | + } | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +impl<T> Primitives<T> for Polyeder<T> | ||
| 131 | +where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> | ||
| 132 | + + Mul<Output = T> + Div<Output = T> | ||
| 133 | + + Copy + Trig + From<i32> + From<i32> { | ||
| 134 | + fn transform(&self, m :&TMatrix<T>) -> Self { | ||
| 135 | + Polyeder{ points: self.points.iter().map(|p| m.apply(p)).collect() | ||
| 136 | + , faces: self.faces.to_vec() } | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + fn project(&self, camera :&Camera<T>) -> Vec<Polygon> { | ||
| 140 | + fn polygon<I>(c :I) -> Polygon | ||
| 141 | + where I: Iterator<Item = Coordinate> { | ||
| 142 | + Polygon(Coordinates(c.collect())) | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + let to_coord = |p :&usize| camera.project(self.points[*p]); | ||
| 146 | + let to_poly = |f :&Vec<usize>| polygon(f.iter().map(to_coord)); | ||
| 147 | + | ||
| 148 | + self.faces.iter().map(to_poly).collect() | ||
| 149 | + } | ||
| 150 | +} |
| @@ -29,6 +29,7 @@ pub mod transform; | @@ -29,6 +29,7 @@ pub mod transform; | ||
| 29 | pub mod trigonometry; | 29 | pub mod trigonometry; |
| 30 | pub mod vector; | 30 | pub mod vector; |
| 31 | pub mod xcb; | 31 | pub mod xcb; |
| 32 | +pub mod geometry; | ||
| 32 | 33 | ||
| 33 | use fractional::Fractional; | 34 | use fractional::Fractional; |
| 34 | use vector::Vector; | 35 | use vector::Vector; |
| @@ -38,6 +38,8 @@ use fractional::transform::{TMatrix, translate, rotate_x, rotate_y, rotate_z, ro | @@ -38,6 +38,8 @@ use fractional::transform::{TMatrix, translate, rotate_x, rotate_y, rotate_z, ro | ||
| 38 | use fractional::xcb::XcbEasel; | 38 | use fractional::xcb::XcbEasel; |
| 39 | use fractional::easel::Canvas; | 39 | use fractional::easel::Canvas; |
| 40 | 40 | ||
| 41 | +use fractional::geometry::{Camera,Polyeder,Primitives}; | ||
| 42 | + | ||
| 41 | fn mean(v: &Vec<i64>) -> Result<Fractional, TryFromIntError> { | 43 | fn mean(v: &Vec<i64>) -> Result<Fractional, TryFromIntError> { |
| 42 | let r = v.iter().fold(0, |acc, x| acc + x); | 44 | let r = v.iter().fold(0, |acc, x| acc + x); |
| 43 | let l = i64::try_from(v.len())?; | 45 | let l = i64::try_from(v.len())?; |
| @@ -340,48 +342,10 @@ fn main() { | @@ -340,48 +342,10 @@ fn main() { | ||
| 340 | 342 | ||
| 341 | let (tx, rx) = mpsc::channel(); | 343 | let (tx, rx) = mpsc::channel(); |
| 342 | 344 | ||
| 343 | - // TODO I ran into overflow issues using fractionals so for now | ||
| 344 | - // use floating point values. | ||
| 345 | - // https://rechneronline.de/pi/tetrahedron.php | ||
| 346 | - // yi = a / 12 * √6 | ||
| 347 | - let yi = 60.0 / 12.0 * 6.0.sqrt().unwrap(); | ||
| 348 | - // yc = a / 4 * √6 | ||
| 349 | - let yc = 60.0 / 4.0 * 6.0.sqrt().unwrap(); | ||
| 350 | - // zi = √3 / 6 * a | ||
| 351 | - let zi = 3.0.sqrt().unwrap() / 6.0 * 60.0; | ||
| 352 | - // zc = √3 / 3 * a | ||
| 353 | - let zc = 3.0.sqrt().unwrap() / 3.0 * 60.0; | ||
| 354 | - | ||
| 355 | - let i = Vector( 0.0, yc, 0.0); | ||
| 356 | - let j = Vector(-30.0, -yi, -zi); | ||
| 357 | - let k = Vector( 30.0, -yi, -zi); | ||
| 358 | - let l = Vector( 0.0, -yi, zc); | ||
| 359 | - | ||
| 360 | - let cf1 = Vector(-30.0, 30.0, -30.0); | ||
| 361 | - let cf2 = Vector(-30.0, -30.0, -30.0); | ||
| 362 | - let cf3 = Vector( 30.0, -30.0, -30.0); | ||
| 363 | - let cf4 = Vector( 30.0, 30.0, -30.0); | ||
| 364 | - | ||
| 365 | - let cb1 = Vector(-30.0, 30.0, 30.0); | ||
| 366 | - let cb2 = Vector(-30.0, -30.0, 30.0); | ||
| 367 | - let cb3 = Vector( 30.0, -30.0, 30.0); | ||
| 368 | - let cb4 = Vector( 30.0, 30.0, 30.0); | ||
| 369 | - | ||
| 370 | - fn to_screen(c: &dyn Canvas, v :Vector<f64>) -> Coordinate { | ||
| 371 | - // TODO .. these are in fact constants that should be stored once | ||
| 372 | - // somewhere… Rust doesn't let me make this static here. | ||
| 373 | - // In a way they are part of the canvas and they should change as the | ||
| 374 | - // canvas is changing… | ||
| 375 | - let fovx :f64 = 1.0 / <f64 as Trig>::tan(50); | ||
| 376 | - let fovy :f64 = c.width() as f64 / c.height() as f64 * fovx; | ||
| 377 | - | ||
| 378 | - let xs = ( v.x() / v.z() * fovx * c.width() as f64 ).round() as i32 | ||
| 379 | - + c.width() as i32 / 2; | ||
| 380 | - let ys = ( -v.y() / v.z() * fovy * c.height() as f64 ).round() as i32 | ||
| 381 | - + c.height() as i32 / 2; | ||
| 382 | - | ||
| 383 | - Coordinate(xs, ys) | ||
| 384 | - } | 345 | + let tetrahedron = Polyeder::tetrahedron(60.0); |
| 346 | + let cube = Polyeder::cube(60.0); | ||
| 347 | + let camera = Camera::<f64>::new(&canvas, 40); // the orig. view angle | ||
| 348 | + // was 50. | ||
| 385 | 349 | ||
| 386 | canvas.start_events(tx); | 350 | canvas.start_events(tx); |
| 387 | 351 | ||
| @@ -389,88 +353,24 @@ fn main() { | @@ -389,88 +353,24 @@ fn main() { | ||
| 389 | let step = Duration::from_millis(25); | 353 | let step = Duration::from_millis(25); |
| 390 | let mut last = Instant::now(); | 354 | let mut last = Instant::now(); |
| 391 | thread::spawn(move || { | 355 | thread::spawn(move || { |
| 392 | - //const DWC :f64 = 10.0; | ||
| 393 | - | ||
| 394 | loop { | 356 | loop { |
| 395 | - let deg = ((start.elapsed() / 20).as_millis() % 360) as i32; | 357 | + let deg = ((start.elapsed() / 25).as_millis() % 360) as i32; |
| 396 | let rot1 :TMatrix<f64> = rotate_z(deg) | 358 | let rot1 :TMatrix<f64> = rotate_z(deg) |
| 397 | * rotate_x(-deg*2) | 359 | * rotate_x(-deg*2) |
| 398 | * translate(Vector(0.0, 0.0, 150.0)); | 360 | * translate(Vector(0.0, 0.0, 150.0)); |
| 399 | 361 | ||
| 400 | - let rot2 :TMatrix<f64> = rotate_z(deg) | ||
| 401 | - * rotate_y(-deg*2) | 362 | + let rot2 :TMatrix<f64> = rotate_z(-deg*2) |
| 363 | + * rotate_y(deg) | ||
| 402 | * translate(Vector(0.0, 0.0, 150.0)); | 364 | * translate(Vector(0.0, 0.0, 150.0)); |
| 403 | 365 | ||
| 404 | - let ia = rot1.apply(&i); | ||
| 405 | - let ja = rot1.apply(&j); | ||
| 406 | - let ka = rot1.apply(&k); | ||
| 407 | - let la = rot1.apply(&l); | ||
| 408 | - | ||
| 409 | - let cf1a = rot2.apply(&cf1); | ||
| 410 | - let cf2a = rot2.apply(&cf2); | ||
| 411 | - let cf3a = rot2.apply(&cf3); | ||
| 412 | - let cf4a = rot2.apply(&cf4); | ||
| 413 | - | ||
| 414 | - let cb1a = rot2.apply(&cb1); | ||
| 415 | - let cb2a = rot2.apply(&cb2); | ||
| 416 | - let cb3a = rot2.apply(&cb3); | ||
| 417 | - let cb4a = rot2.apply(&cb4); | ||
| 418 | - | ||
| 419 | - let pg1 = Polygon(Coordinates(vec!( to_screen(&canvas, ja) | ||
| 420 | - , to_screen(&canvas, ka) | ||
| 421 | - , to_screen(&canvas, la) ))); | ||
| 422 | - let pg2 = Polygon(Coordinates(vec!( to_screen(&canvas, ja) | ||
| 423 | - , to_screen(&canvas, ia) | ||
| 424 | - , to_screen(&canvas, ka) ))); | ||
| 425 | - let pg3 = Polygon(Coordinates(vec!( to_screen(&canvas, la) | ||
| 426 | - , to_screen(&canvas, ia) | ||
| 427 | - , to_screen(&canvas, ja) ))); | ||
| 428 | - let pg4 = Polygon(Coordinates(vec!( to_screen(&canvas, ka) | ||
| 429 | - , to_screen(&canvas, ia) | ||
| 430 | - , to_screen(&canvas, la) ))); | ||
| 431 | - | ||
| 432 | - // front: cf1 cf2 cf3 cf4 | ||
| 433 | - let cf = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a) | ||
| 434 | - , to_screen(&canvas, cf2a) | ||
| 435 | - , to_screen(&canvas, cf3a) | ||
| 436 | - , to_screen(&canvas, cf4a) ))); | ||
| 437 | - // back: cb4 cb3 cb2 cb1 | ||
| 438 | - let cb = Polygon(Coordinates(vec!( to_screen(&canvas, cb4a) | ||
| 439 | - , to_screen(&canvas, cb3a) | ||
| 440 | - , to_screen(&canvas, cb2a) | ||
| 441 | - , to_screen(&canvas, cb1a) ))); | ||
| 442 | - // top: cf2 cb2 cb3 cf3 | ||
| 443 | - let ct = Polygon(Coordinates(vec!( to_screen(&canvas, cf2a) | ||
| 444 | - , to_screen(&canvas, cb2a) | ||
| 445 | - , to_screen(&canvas, cb3a) | ||
| 446 | - , to_screen(&canvas, cf3a) ))); | ||
| 447 | - // bottom: cf1 cf4 cb4 cb1 | ||
| 448 | - let co = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a) | ||
| 449 | - , to_screen(&canvas, cf4a) | ||
| 450 | - , to_screen(&canvas, cb4a) | ||
| 451 | - , to_screen(&canvas, cb1a) ))); | ||
| 452 | - // left: cf1 cb1 cb2 cf2 | ||
| 453 | - let cl = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a) | ||
| 454 | - , to_screen(&canvas, cb1a) | ||
| 455 | - , to_screen(&canvas, cb2a) | ||
| 456 | - , to_screen(&canvas, cf2a) ))); | ||
| 457 | - // right: cf3 cb3 cb4 cf4 | ||
| 458 | - let cr = Polygon(Coordinates(vec!( to_screen(&canvas, cf3a) | ||
| 459 | - , to_screen(&canvas, cb3a) | ||
| 460 | - , to_screen(&canvas, cb4a) | ||
| 461 | - , to_screen(&canvas, cf4a) ))); | ||
| 462 | - | ||
| 463 | canvas.clear(); | 366 | canvas.clear(); |
| 464 | - canvas.draw(&pg1, Coordinate(0,0), 0xFFFF00); | ||
| 465 | - canvas.draw(&pg2, Coordinate(0,0), 0xFFFF00); | ||
| 466 | - canvas.draw(&pg3, Coordinate(0,0), 0xFFFF00); | ||
| 467 | - canvas.draw(&pg4, Coordinate(0,0), 0xFFFF00); | ||
| 468 | - canvas.draw( &cf, Coordinate(0,0), 0x0000FF); | ||
| 469 | - canvas.draw( &cb, Coordinate(0,0), 0x0000FF); | ||
| 470 | - canvas.draw( &ct, Coordinate(0,0), 0x0000FF); | ||
| 471 | - canvas.draw( &co, Coordinate(0,0), 0x0000FF); | ||
| 472 | - canvas.draw( &cl, Coordinate(0,0), 0x0000FF); | ||
| 473 | - canvas.draw( &cr, Coordinate(0,0), 0x0000FF); | 367 | + |
| 368 | + for pg in tetrahedron.transform(&rot1).project(&camera) { | ||
| 369 | + canvas.draw(&pg, Coordinate(0,0), 0xFFFF00); | ||
| 370 | + } | ||
| 371 | + for pg in cube.transform(&rot2).project(&camera) { | ||
| 372 | + canvas.draw(&pg, Coordinate(0,0), 0x0000FF); | ||
| 373 | + } | ||
| 474 | 374 | ||
| 475 | let passed = Instant::now() - last; | 375 | let passed = Instant::now() - last; |
| 476 | let f = (passed.as_nanos() / step.as_nanos()) as u32; | 376 | let f = (passed.as_nanos() / step.as_nanos()) as u32; |
| @@ -26,17 +26,19 @@ | @@ -26,17 +26,19 @@ | ||
| 26 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | 26 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 27 | // | 27 | // |
| 28 | use std::cmp::Ordering; | 28 | use std::cmp::Ordering; |
| 29 | +use std::ops::Div; | ||
| 29 | use std::ops::Neg; | 30 | use std::ops::Neg; |
| 30 | use std::marker::Sized; | 31 | use std::marker::Sized; |
| 31 | use crate::{Fractional, Error}; | 32 | use crate::{Fractional, Error}; |
| 32 | use crate::continuous::Continuous; | 33 | use crate::continuous::Continuous; |
| 33 | 34 | ||
| 34 | pub trait Trig { | 35 | pub trait Trig { |
| 35 | - fn pi() -> Self; | ||
| 36 | - fn recip(self) -> Self; | ||
| 37 | - fn sqrt(self) -> Result<Self, Error> where Self: Sized; | ||
| 38 | - fn sintab() -> Vec<Self> where Self: Sized; | ||
| 39 | - fn tantab() -> Vec<Self> where Self: Sized; | 36 | + fn pi() -> Self; |
| 37 | + fn recip(self) -> Self; | ||
| 38 | + fn round(&self) -> i32; | ||
| 39 | + fn sqrt(self) -> Result<Self, Error> where Self: Sized; | ||
| 40 | + fn sintab() -> Vec<Self> where Self: Sized; | ||
| 41 | + fn tantab() -> Vec<Self> where Self: Sized; | ||
| 40 | 42 | ||
| 41 | fn sin(d :i32) -> Self | 43 | fn sin(d :i32) -> Self |
| 42 | where Self: Sized + Neg<Output = Self> + Copy { | 44 | where Self: Sized + Neg<Output = Self> + Copy { |
| @@ -73,6 +75,11 @@ pub trait Trig { | @@ -73,6 +75,11 @@ pub trait Trig { | ||
| 73 | }, | 75 | }, |
| 74 | } | 76 | } |
| 75 | } | 77 | } |
| 78 | + | ||
| 79 | + fn cot(d :i32) -> Self | ||
| 80 | + where Self: Sized + Copy + From<i32> + Div<Output = Self> { | ||
| 81 | + Into::<Self>::into(1) / Self::tan(d) | ||
| 82 | + } | ||
| 76 | } | 83 | } |
| 77 | 84 | ||
| 78 | // Try to keep precision as high as possible while having a denominator | 85 | // Try to keep precision as high as possible while having a denominator |
| @@ -91,6 +98,11 @@ impl Trig for Fractional { | @@ -91,6 +98,11 @@ impl Trig for Fractional { | ||
| 91 | Fractional(d, n) | 98 | Fractional(d, n) |
| 92 | } | 99 | } |
| 93 | 100 | ||
| 101 | + fn round(&self) -> i32 { | ||
| 102 | + let Fractional(n, d) = self; | ||
| 103 | + (n / d) as i32 | ||
| 104 | + } | ||
| 105 | + | ||
| 94 | // This is a really bad approximation of sqrt for a fractional... | 106 | // This is a really bad approximation of sqrt for a fractional... |
| 95 | // for (9/3) it will result 3 which if way to far from the truth, | 107 | // for (9/3) it will result 3 which if way to far from the truth, |
| 96 | // which is ~1.7320508075 | 108 | // which is ~1.7320508075 |
| @@ -198,6 +210,10 @@ impl Trig for f64 { | @@ -198,6 +210,10 @@ impl Trig for f64 { | ||
| 198 | self.recip() | 210 | self.recip() |
| 199 | } | 211 | } |
| 200 | 212 | ||
| 213 | + fn round(&self) -> i32 { | ||
| 214 | + f64::round(*self) as i32 | ||
| 215 | + } | ||
| 216 | + | ||
| 201 | fn sqrt(self) -> Result<Self, Error> { | 217 | fn sqrt(self) -> Result<Self, Error> { |
| 202 | let x = self.sqrt(); | 218 | let x = self.sqrt(); |
| 203 | match x.is_nan() { | 219 | match x.is_nan() { |
Please
register
or
login
to post a comment