diff --git a/Cargo.toml b/Cargo.toml index 32ad5c4..3d0d767 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] meval = "0.2.0" +image = "0.24.8" diff --git a/grid_image.png b/grid_image.png new file mode 100644 index 0000000..32e6587 Binary files /dev/null and b/grid_image.png differ diff --git a/src/function.rs b/src/function.rs new file mode 100644 index 0000000..7964f4b --- /dev/null +++ b/src/function.rs @@ -0,0 +1,149 @@ +pub fn default_points(points: &mut [[f64;2];3]) { + if points.iter().all(|row| row.iter().all(|&x| x == 0.0)) { + *points = [[-1.0,1.0], [2.0,4.0], [3.0,9.0]]; + } +} + +pub fn group_by_x(arr: &mut [[f64;2];3]) { + arr.sort_by(|a, b| a[0].partial_cmp(&b[0]).unwrap_or(std::cmp::Ordering::Equal)); +} + +pub fn get_points(args: Vec) -> [[f64;2];3] { + let mut points: [[f64; 2]; 3] = [[0.0; 2]; 3]; + + for (i, part) in args.iter().enumerate().take(3) { + let values: Vec = part + .split(':') + .filter_map(|s| s.parse().ok()) + .collect(); + + if values.len() == 2 { + points[i][0] = values[0]; + points[i][1] = values[1]; + } else { + println!("Invalid input format: {}", part); + println!("Usage: $0 -1:1 3:-5 10:1.5") + } + } + + #[cfg(debug_assertions)] + default_points(&mut points); + + points +} + +fn nearest_to_zero(arr: &[[f64;2];3]) -> usize { + let mut nearest = arr[1][1]; + let mut nearest_index = 0; + for (i, point) in arr.iter().enumerate() { + if nearest < point[1].abs() { + nearest = point[i-1]; + nearest_index = i-1; + } + } + nearest_index +} + +pub fn straight_string(m: f64, points: &[[f64;2];3]) -> String { + format!( + "{}x{}", + if m != 1.0 { + format!("{} * ", m) + } else { + "".to_string() + }, + { + let lowest_y = nearest_to_zero(points); + let result = points[lowest_y][0] - points[lowest_y][1] * m; + if result != 0.0 { + format!( + "{}{}", + if result < 0.0 { + " - ".to_string() + } else { + " + ".to_string() + }, + result.abs() + ) + } else { + "".to_string() + } + } + ) +} + +pub fn square_string(points: &[[f64;2];3]) -> String { + let a = -((points[0][0] * points[1][1] - + points[0][0] * points[2][1] - + points[1][0] * points[0][1] + + points[1][0] * points[2][1] + + points[2][0] * points[0][1] - + points[2][0] * points[1][1]) + / + ((points[0][0] - points[1][0]) * + (points[0][0] - points[2][0]) * + (points[1][0] - points[2][0]))); + + let b = (points[0][0].powi(2) * points[1][1] - + points[0][0].powi(2) * points[2][1] - + points[1][0].powi(2) * points[0][1] + + points[1][0].powi(2) * points[2][1] + + points[2][0].powi(2) * points[0][1] - + points[2][0].powi(2) * points[1][1]) + / + ((points[0][0] - points[1][0]) * + (points[0][0] - points[2][0]) * + (points[1][0] - points[2][0])); + + let c = (points[0][0].powi(2) * points[1][0] * points[2][1] - + points[0][0].powi(2) * points[2][0] * points[1][1] - + points[0][0] * points[1][0].powi(2) * points[2][1] + + points[0][0] * points[2][0].powi(2) * points[1][1] + + points[1][0].powi(2) * points[2][0] * points[0][1] - + points[1][0] * points[2][0].powi(2) * points[0][1]) + / + ((points[0][0] - points[1][0]) * + (points[0][0] - points[2][0]) * + (points[1][0] - points[2][0])); + + format!( + "{}x^2{}{}", + if a == -1.0 { + "-".to_string() + } else if a != 1.0 { + format!("{}{}", a, " * ") + } else { + "".to_string() + }, + if b != 0.0 { + format!( + "{}{}", + if b < 0.0 { + " - ".to_string() + } else { + " + ".to_string() + }, + if b != 1.0 { + format!("{} * x", b.abs()) + } else { + "x".to_string() + } + ) + } else { + "".to_string() + }, + if c != 0.0 { + format!( + "{}{}", + if c < 0.0 { + " - ".to_string() + } else { + " + ".to_string() + }, + c.abs() + ) + } else { + "".to_string() + } + ) +} diff --git a/src/image.rs b/src/image.rs new file mode 100644 index 0000000..0c8e285 --- /dev/null +++ b/src/image.rs @@ -0,0 +1,21 @@ +use image::{ImageBuffer, RgbImage, Rgb}; + +pub fn get_image(width: u32, height: u32) -> ImageBuffer, Vec> { + let mut img = RgbImage::new(width, height); + let grid_spacing = 100; + let grid_color = Rgb([255,9,255]); + + for x in (0..width).step_by(grid_spacing) { + for y in 0..height { + img.put_pixel(x, y, grid_color); + } + } + for y in (0..height).step_by(grid_spacing) { + for x in 0..width { + img.put_pixel(x, y, grid_color); + } + } + img +} + + diff --git a/src/main.rs b/src/main.rs index 6ec17c8..2334a6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,13 @@ use std::env; +mod function; +mod image; +use crate::function::*; + fn main() { let args: Vec = env::args().skip(1).take(3).collect(); - let mut points: [[f64; 2]; 3] = [[0.0; 2]; 3]; - - for (i, part) in args.iter().enumerate().take(3) { - let values: Vec = part - .split(':') - .filter_map(|s| s.parse().ok()) - .collect(); - - if values.len() == 2 { - points[i][0] = values[0]; - points[i][1] = values[1]; - } else { - println!("Invalid input format: {}", part); - println!("Usage: $0 -1:1 3:-5 10:1.5") - } - } - - #[cfg(debug_assertions)] - default_points(&mut points); + let mut points = get_points(args); group_by_x(&mut points); let m1 = (points[0][1] - points[1][1]) / (points[0][0] - points[1][0]); @@ -34,135 +20,53 @@ fn main() { if function.contains("NaN") { panic!("Contains NaN, this is probably the result of bad math"); } - // let expr2 = tokenize(function.as_str()).unwrap(); - // println!("{:?}", expr2); + let rust_function = function.parse::().unwrap().bind("x").unwrap(); let result = rust_function(9.0); println!("{}", result); -} -fn default_points(points: &mut [[f64;2];3]) { - if points.iter().all(|row| row.iter().all(|&x| x == 0.0)) { - *points = [[-1.0,1.0], [2.0,4.0], [3.0,9.0]]; + /* + let width = 7000; + let height = 7000; + let color = [255, 0, 0]; + let mut img = get_image(4000, 4000); + let step: f64 = format!("0.{}1", "0".repeat(6)).parse().unwrap(); + let mut points = vec![]; + + let mut i = 0.0; + while i <= 3.0 { + points.push(i); + i += step; } -} -fn group_by_x(arr: &mut [[f64;2];3]) { - arr.sort_by(|a, b| a[0].partial_cmp(&b[0]).unwrap_or(std::cmp::Ordering::Equal)); -} -fn nearest_to_zero(arr: &[[f64;2];3]) -> usize { - let mut nearest = arr[1][1]; - let mut nearest_index = 0; - for (i, point) in arr.iter().enumerate() { - if nearest < point[1].abs() { - nearest = point[i-1]; - nearest_index = i-1; + // println!("{points:?}"); + + + let mut x; + let mut y; + // let mut x_result_tmp; + // let mut y_result_tmp; + for point in points { + // NOTE: convert later to u32 because deviding may change actual value + x = point * 1000.0_f64; + y = rust_function(point) * 1000.0; + if width as f64 / 2.0 + y < (width - 5) as f64 { + img.put_pixel( + (width as f64 / 2.0 + x).round() as u32, + (height as f64 / 2.0 - y) as u32, + Rgb(color) + ); + img.put_pixel( + (width as f64 / 2.0 - x).round() as u32, + (height as f64 / 2.0 - y).round() as u32, + Rgb(color) + ); } } - nearest_index + + img.save("grid_image.png").expect("Failed to save image"); + */ } -fn straight_string(m: f64, points: &[[f64;2];3]) -> String { - format!( - "{}x{}", - if m != 1.0 { - format!("{} * ", m) - } else { - "".to_string() - }, - { - let lowest_y = nearest_to_zero(points); - let result = points[lowest_y][0] - points[lowest_y][1] * m; - if result != 0.0 { - format!( - "{}{}", - if result < 0.0 { - " - ".to_string() - } else { - " + ".to_string() - }, - result.abs() - ) - } else { - "".to_string() - } - } - ) -} -fn square_string(points: &[[f64;2];3]) -> String { - let a = -((points[0][0] * points[1][1] - - points[0][0] * points[2][1] - - points[1][0] * points[0][1] + - points[1][0] * points[2][1] + - points[2][0] * points[0][1] - - points[2][0] * points[1][1]) - / - ((points[0][0] - points[1][0]) * - (points[0][0] - points[2][0]) * - (points[1][0] - points[2][0]))); - - let b = (points[0][0].powi(2) * points[1][1] - - points[0][0].powi(2) * points[2][1] - - points[1][0].powi(2) * points[0][1] + - points[1][0].powi(2) * points[2][1] + - points[2][0].powi(2) * points[0][1] - - points[2][0].powi(2) * points[1][1]) - / - ((points[0][0] - points[1][0]) * - (points[0][0] - points[2][0]) * - (points[1][0] - points[2][0])); - - let c = (points[0][0].powi(2) * points[1][0] * points[2][1] - - points[0][0].powi(2) * points[2][0] * points[1][1] - - points[0][0] * points[1][0].powi(2) * points[2][1] + - points[0][0] * points[2][0].powi(2) * points[1][1] + - points[1][0].powi(2) * points[2][0] * points[0][1] - - points[1][0] * points[2][0].powi(2) * points[0][1]) - / - ((points[0][0] - points[1][0]) * - (points[0][0] - points[2][0]) * - (points[1][0] - points[2][0])); - - format!( - "{}x^2{}{}", - if a == -1.0 { - "-".to_string() - } else if a != 1.0 { - format!("{}{}", a, " * ") - } else { - "".to_string() - }, - if b != 0.0 { - format!( - "{}{}", - if b < 0.0 { - " - ".to_string() - } else { - " + ".to_string() - }, - if b != 1.0 { - format!("{} * x", b.abs()) - } else { - "x".to_string() - } - ) - } else { - "".to_string() - }, - if c != 0.0 { - format!( - "{}{}", - if c < 0.0 { - " - ".to_string() - } else { - " + ".to_string() - }, - c.abs() - ) - } else { - "".to_string() - } - ) -}