|
extern crate lodepng; |
|
extern crate homework_2; // Change this here |
|
|
|
use std::ops::Range; |
|
use std::ptr; |
|
|
|
use homework_2::Polynomial; // Change this here |
|
|
|
fn main() { |
|
let mut image = Image::new(500, 500); |
|
|
|
let polynomial_one = Polynomial::from(vec![1.0, 0.0, 0.0, 0.0]); |
|
let polynomial_two = Polynomial::from(vec![0.0, 1.0, 0.0, 0.0]); |
|
let polynomial_three = Polynomial::from(vec![1.0, 1.0, 0.0, 0.0]); |
|
|
|
image.draw(&polynomial_one, Color(255, 0, 0)); |
|
image.draw(&polynomial_two, Color(0, 255, 0)); |
|
image.draw(&polynomial_three, Color(180, 180, 0)); |
|
|
|
image.write_png_file("out.png").expect("Could not save file"); |
|
} |
|
|
|
#[repr(packed)] |
|
#[derive(Debug, Clone, Copy)] |
|
struct Color(u8, u8, u8); |
|
|
|
struct Image { |
|
pub width: usize, |
|
pub height: usize, |
|
pub bitmap: Vec<Color>, |
|
} |
|
|
|
trait Drawable { |
|
fn draw_on(&self, &mut Image, color: Color); |
|
} |
|
|
|
impl Image { |
|
pub fn new(width: usize, height: usize) -> Self { |
|
let mut bitmap = Vec::<Color>::with_capacity(width * height); |
|
|
|
unsafe { |
|
bitmap.set_len(width * height); |
|
ptr::write_bytes(bitmap.as_mut_ptr(), 255, width * height); |
|
} |
|
|
|
Self { width, height, bitmap } |
|
} |
|
|
|
pub fn draw(&mut self, figure: &Drawable, color: Color) { |
|
figure.draw_on(self, color); |
|
} |
|
|
|
pub fn set_pixel(&mut self, x: usize, y: usize, color: Color) { |
|
if x >= self.width || y >= self.height { |
|
return; |
|
} |
|
|
|
self.bitmap[x + y * self.width] = color; |
|
} |
|
|
|
pub fn write_png_file(&self, file_name: &str) -> Result<(), lodepng::Error> { |
|
lodepng::encode24_file(file_name, &self.bitmap, self.width, self.height) |
|
} |
|
} |
|
|
|
fn convert_linear_coordinates(x: f64, from: &Range<f64>, to: &Range<f64>) -> f64 { |
|
let x_fraction = (x - from.start) / (from.end - from.start); |
|
|
|
x_fraction * (to.end - to.start) + to.start |
|
} |
|
|
|
impl Drawable for Polynomial { |
|
fn draw_on(&self, image: &mut Image, color: Color) { |
|
let x_range = Range { start: -1_f64, end: 1_f64 }; |
|
let x_pixel_range = Range { start: 0.0, end: image.width as f64 }; |
|
let y_range = Range { start: -1_f64, end: 1_f64 }; |
|
let y_pixel_range = Range { start: image.height as f64, end: 0.0 }; |
|
|
|
let step = (x_range.end - x_range.start) / (image.width + image.height) as f64; |
|
|
|
let mut x = x_range.start; |
|
while x <= x_range.end { |
|
let y = self.apply(x); |
|
|
|
let x_pixel = convert_linear_coordinates(x, &x_range, &x_pixel_range); |
|
let y_pixel = convert_linear_coordinates(y, &y_range, &y_pixel_range); |
|
|
|
if x_pixel >= 0.0 && y_pixel >= 0.0 { |
|
image.set_pixel(x_pixel as usize, y_pixel as usize, color); |
|
} |
|
|
|
x += step; |
|
} |
|
} |
|
} |