use image::{ImageBuffer, Rgb};
use vector2d::Vector2D;
use crate::listops::*;
const SQUARE_RADIUS: i32 = 13;
#[derive(Debug)]
struct Bounds {
smallest: i32,
largest: i32,
}
#[derive(Debug, Clone)]
pub struct PlotSettings {
pub plot_color: Color,
}
impl Default for PlotSettings {
fn default() -> PlotSettings {
PlotSettings {plot_color: Color::set_vals(50, 50, 230)}
}
}
impl Custom for PlotSettings {
fn custom_plot(r: u8, g: u8, b: u8) -> PlotSettings {
PlotSettings {plot_color: Color::set_vals(r, g, b)}
}
}
pub trait Custom {
fn custom_plot(r: u8, g: u8, b: u8) -> PlotSettings;
}
#[derive(Debug)]
struct OffsetValues {
origin_x: i32,
origin_y: i32,
}
trait GetOffsetValues {
fn get_offset(pair_x: &Bounds, pair_y: &Bounds) -> OffsetValues;
}
impl GetOffsetValues for OffsetValues {
fn get_offset(pair_x: &Bounds, pair_y: &Bounds) -> OffsetValues {
let mut origin_x_temp = 0;
let mut origin_y_temp = pair_y.largest / 2;
let origin_x_abs = pair_x.largest.abs() + pair_x.smallest.abs();
let origin_y_abs = pair_y.largest.abs() + pair_y.smallest.abs();
if pair_x.smallest.is_negative() {
if pair_x.largest.is_positive() {
origin_x_temp = origin_x_abs / 2;
}
else if pair_x.largest.is_negative() {
origin_x_temp = (origin_x_abs as f32 * 1.8) as i32;
}
}
else if pair_x.smallest.is_positive() {
origin_x_temp = origin_x_abs / 4;
}
if pair_y.smallest.is_negative() {
if pair_y.largest.is_positive() {
origin_y_temp = origin_y_abs / 2;
}
else if pair_y.largest.is_negative() {
origin_y_temp = (origin_y_abs as f32 * 1.8) as i32;
}
}
else if pair_y.smallest.is_positive() {
origin_y_temp = (origin_y_abs as f32 / 1.5) as i32;
}
OffsetValues { origin_x: (origin_x_temp), origin_y: (origin_y_temp) }
}
}
#[derive(Debug, Clone)]
pub struct Color {
pub red: u8,
pub blue: u8,
pub green: u8,
}
trait ColorSet {
fn set_vals(r: u8, g: u8, b: u8) -> Color;
}
impl ColorSet for Color {
fn set_vals(r: u8, g: u8, b: u8) -> Color {
Color {
red: (r),
green: (g),
blue: (b),
}
}
}
impl Default for Color {
fn default() -> Color {
Color {
red: 255,
blue: 255,
green: 255,
}
}
}
fn create_canvas(bounds_x: &Bounds, bounds_y: &Bounds, ofv: &OffsetValues) -> ImageBuffer<Rgb<u8>, Vec<u8>> {
let plot = Color::default();
let black_clr = Color::set_vals(10, 10, 10);
let total_width = bounds_x.largest.abs() + bounds_x.smallest.abs();
let total_height = bounds_y.largest.abs() + bounds_y.smallest.abs();
let mut imgbuf = image::ImageBuffer::new(total_width as u32, total_height as u32);
let mut curr_clr = &plot;
for x in 0..total_width {
for y in 0..total_height {
let pixel = imgbuf.get_pixel_mut(x.try_into().unwrap(), y.try_into().unwrap());
*pixel = image::Rgb([plot.red, plot.green, plot.blue]);
}
}
for x in 0..total_width {
for y in 0..total_height {
if x > ofv.origin_x && x < ofv.origin_x + 5 {
curr_clr = &black_clr;
}
else if y > ofv.origin_y && y < ofv.origin_y + 5 {
curr_clr = &black_clr;
}
else {curr_clr = &plot;}
let pixel = imgbuf.get_pixel_mut(x.try_into().unwrap(), y.try_into().unwrap());
*pixel = image::Rgb([curr_clr.red, curr_clr.green, curr_clr.blue]);
}
}
imgbuf
}
fn shrink_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut float_vec = Vec::new();
let mut temp = 0;
for i in vec {
if *i == 0 {temp = 1;} else {temp = 0;}
if i.is_negative() {
let temp_num = round((switch_sign(&(*i)) as f32).log(1.05), 0) as i32;
float_vec.push(switch_sign(&temp_num));
}
else {
float_vec.push(round(((*i + temp) as f32).log(1.05), 0) as i32);
}
}
float_vec
}
fn vec_controller(vec: &Vec<i32>) -> Vec<i32> {
let mut new_vec = Vec::new();
match find_largest_abs_elem(vec.clone()) {
i if i >= 1000 => new_vec = shrink_vec(&vec),
i if i <= -1000 => new_vec = shrink_vec(&vec),
i if i < 1000 && i > 0 => new_vec = vec.to_owned(),
i if i > -1000 && i < 0 => new_vec = vec.to_owned(),
_ => println!("Invalid element input"),
}
new_vec = new_vec.into_iter().map(|x| x + 1).collect();
new_vec
}
pub fn plot_tbl(_vec_x: &Vec<i32>, _vec_y: &Vec<i32>, settings: &PlotSettings, source: &str) {
let vec_x = vec_controller(_vec_x);
let vec_y = vec_controller(_vec_y);
if vec_x.len() != vec_y.len() {panic!("Error: Vector X and Y does not have the same number of elements!");}
let bounds_x = Bounds{smallest: find_smallest_elem(&vec_x), largest: find_largest_elem(&vec_x)};
let bounds_y = Bounds{smallest: find_smallest_elem(&vec_y), largest: find_largest_elem(&vec_y)};
let off_vals = OffsetValues::get_offset(&bounds_x, &bounds_y);
let mut imgbuf = create_canvas(&bounds_x, &bounds_y, &off_vals);
for i in 0..vec_x.len() {
for j in get_elem_pos(&vec_x[i], &vec_y[i], &off_vals.origin_x, &off_vals.origin_y) {
let pixel = imgbuf.get_pixel_mut(j.x as u32, j.y as u32);
*pixel = image::Rgb([settings.plot_color.red, settings.plot_color.green, settings.plot_color.blue]);
}
}
imgbuf.save(source).unwrap();
}
fn get_elem_pos(x_pos: &i32, y_pos: &i32, x_clamp: &i32, y_clamp: &i32) -> Vec<Vector2D<i32>>{
let x = x_pos + x_clamp;
let y = y_clamp - (*y_pos as f32 / 1.5) as i32;
gen_sq_map(&x, &y)
}
fn gen_sq_map(x_pos: &i32, y_pos: &i32) -> Vec<Vector2D<i32>> {
let mut map = Vec::new();
for i in *x_pos..SQUARE_RADIUS + *x_pos {
for j in *y_pos..SQUARE_RADIUS + *y_pos {
let element: Vector2D<i32> = Vector2D { x: i - 4, y: j - 4};
map.push(element);
}
}
map
}