From c99cc1eea0a7fe02152348abb0b5725432181a46 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Sun, 15 Dec 2019 23:31:22 +0100 Subject: [PATCH] Add tail recursice bresenham line --- fractional/src/main.rs | 52 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/fractional/src/main.rs b/fractional/src/main.rs index 7667359..9f2222f 100644 --- a/fractional/src/main.rs +++ b/fractional/src/main.rs @@ -18,10 +18,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // +use std::cmp; use std::convert::{TryFrom, TryInto, Into}; -use std::num::TryFromIntError; use std::f64::consts::PI as FPI; use std::fmt::Display; +use std::num::TryFromIntError; use std::ops::{Add,Sub,Neg,Mul,Div}; use fractional::continuous::Continuous; @@ -30,6 +31,42 @@ use fractional::trigonometry::Trig; use fractional::vector::{Vector}; use fractional::transform::{translate, rotate_x, rotate_y, rotate_z, rotate_v}; +// Tail recursive Bresenham line with integer incremental error. +fn line(a :(u32, u32), b :(u32, u32)) -> Vec<(u32, u32)>{ + fn inner( v :&mut [(u32, u32)] + , bx :u32, by :u32 + , dx :i32, dy :i32 + , sx :i32, sy :i32 + , err :i32) { + let (x, y) = v[0]; + + if x != bx || y != by { + let (x, y, err) = match (2*err as i32 >= dy, 2*err as i32 <= dx) { + (true, false) => ((x as i32 + sx) as u32, y, err + dy), + (false, true) => (x, (y as i32 + sy) as u32, err + dx), + _ => ( (x as i32 + sx) as u32 + , (y as i32 + sy) as u32 + , err + dx + dy ), + }; + v[1] = (x, y); + inner(&mut v[1..], bx, by, dx, dy, sx, sy, err); + } + } + + let (ax, ay) = a; + let (bx, by) = b; + + let dx = (bx as i32 - ax as i32).abs(); + let sx :i32 = if ax < bx { 1 } else { -1 }; + let dy = -(by as i32 - ay as i32).abs(); + let sy :i32 = if ay < by { 1 } else { -1 }; + + let mut v :Vec<(u32, u32)> = vec!((0, 0); cmp::max(dx, -dy) as usize + 1); + v[0] = (ax, ay); + inner(&mut v, bx, by, dx, dy, sx, sy, dx + dy); + v +} + fn mean(v: &Vec) -> Result { let r = v.iter().fold(0, |acc, x| acc + x); let l = i64::try_from(v.len())?; @@ -235,6 +272,17 @@ fn _transform(v :Vector, v1 :Vector, v2 :Vector, v3 :Vector) } } +fn _line() { + println!("{:>14} : {:?}", "Line", line((0,1), (6,4))); + println!("{:>14} : {:?}", "Line", line((0,4), (6,1))); + println!("{:>14} : {:?}", "Line", line((6,1), (0,4))); + println!("{:>14} : {:?}", "Line", line((6,4), (0,1))); + println!("{:>14} : {:?}", "Line", line((0,1), (6,8))); + println!("{:>14} : {:?}", "Line", line((0,8), (6,1))); + println!("{:>14} : {:?}", "Line", line((6,1), (0,8))); + println!("{:>14} : {:?}", "Line", line((6,8), (0,1))); +} + fn main() { common_fractional(); println!(); @@ -257,4 +305,6 @@ fn main() { _transform1(); println!(); _transform2(); + println!(); + _line(); }