Skip to content

Commit

Permalink
This version does not work, singleton is incorrect
Browse files Browse the repository at this point in the history
  • Loading branch information
Jort van Waes committed Sep 19, 2023
1 parent 5265b99 commit 0379adc
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 70 deletions.
1 change: 1 addition & 0 deletions src/controller/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ static ORBIT_RADIUS: f64 = 2.0;
static SUPERSAMPLING_AMOUNT: u8 = 1;
static WINDOW_SCALE: f64 = 1.0;

#[derive(Clone, Copy)]
pub struct Config {
// Window dimensions in pixels
pub window_width: usize,
Expand Down
157 changes: 96 additions & 61 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn handle_key_events(
c,
p,
m,
vars.translation_amount.into(),
MandelbrotModel::get_instance().vars.translation_amount.into(),
0,
*supersampling_amount,
*coloring_function,
Expand All @@ -158,7 +158,7 @@ fn handle_key_events(
c,
p,
m,
-i16::from(vars.translation_amount),
-i16::from(MandelbrotModel::get_instance().vars.translation_amount),
0,
*supersampling_amount,
*coloring_function,
Expand All @@ -168,7 +168,7 @@ fn handle_key_events(
p,
m,
0,
-i16::from(vars.translation_amount),
-i16::from(MandelbrotModel::get_instance().vars.translation_amount),
*supersampling_amount,
*coloring_function,
),
Expand All @@ -177,51 +177,71 @@ fn handle_key_events(
p,
m,
0,
vars.translation_amount.into(),
MandelbrotModel::get_instance().vars.translation_amount.into(),
*supersampling_amount,
*coloring_function,
),
Key::R => c.reset(),
Key::NumPadPlus => vars.increment_translation_amount(),
Key::NumPadMinus => vars.decrement_translation_amount(),
Key::NumPadAsterisk => vars.increment_scale_numerator(),
Key::NumPadSlash => vars.decrement_scale_numerator(),
Key::LeftBracket => c.scale(vars.scaling_factor()),
Key::RightBracket => c.scale(vars.inverse_scaling_factor()),
Key::V => println!("Center: {:?}, scale: {:?}", c.center(), c.get_scale()),
Key::Key1 => c.set_view(&VIEW_1),
Key::Key2 => c.set_view(&VIEW_2),
Key::Key3 => c.set_view(&VIEW_3),
Key::Key4 => c.set_view(&VIEW_4),
Key::Key5 => c.set_view(&VIEW_5),
Key::Key6 => c.set_view(&VIEW_6),
Key::Key7 => c.set_view(&VIEW_7),
Key::Key8 => c.set_view(&VIEW_8),
Key::Key9 => c.set_view(&VIEW_9),
Key::Key0 => c.set_view(&VIEW_0),
Key::R => MandelbrotModel::get_instance().c.reset(),
Key::NumPadPlus => MandelbrotModel::get_instance().vars.increment_translation_amount(),
Key::NumPadMinus => MandelbrotModel::get_instance().vars.decrement_translation_amount(),
Key::NumPadAsterisk => MandelbrotModel::get_instance().vars.increment_scale_numerator(),
Key::NumPadSlash => MandelbrotModel::get_instance().vars.decrement_scale_numerator(),
Key::LeftBracket => MandelbrotModel::get_instance()
.c
.scale(MandelbrotModel::get_instance().vars.scaling_factor()),
Key::RightBracket => MandelbrotModel::get_instance()
.c
.scale(MandelbrotModel::get_instance().vars.inverse_scaling_factor()),
Key::V => println!(
"Center: {:?}, scale: {:?}",
MandelbrotModel::get_instance().c.center(),
MandelbrotModel::get_instance().c.get_scale()
),
Key::Key1 => MandelbrotModel::get_instance().c.set_view(&VIEW_1),
Key::Key2 => MandelbrotModel::get_instance().c.set_view(&VIEW_2),
Key::Key3 => MandelbrotModel::get_instance().c.set_view(&VIEW_3),
Key::Key4 => MandelbrotModel::get_instance().c.set_view(&VIEW_4),
Key::Key5 => MandelbrotModel::get_instance().c.set_view(&VIEW_5),
Key::Key6 => MandelbrotModel::get_instance().c.set_view(&VIEW_6),
Key::Key7 => MandelbrotModel::get_instance().c.set_view(&VIEW_7),
Key::Key8 => MandelbrotModel::get_instance().c.set_view(&VIEW_8),
Key::Key9 => MandelbrotModel::get_instance().c.set_view(&VIEW_9),
Key::Key0 => MandelbrotModel::get_instance().c.set_view(&VIEW_0),
Key::K => k.print(),
Key::S => {
let time_stamp = chrono::Utc::now().to_string();
if config.window_scale == 1.0 {

Check warning on line 213 in src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

strict comparison of `f32` or `f64`

warning: strict comparison of `f32` or `f64` --> src/lib.rs:213:20 | 213 | if config.window_scale == 1.0 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(config.window_scale - 1.0).abs() < error_margin` | = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp = note: `#[warn(clippy::float_cmp)]` implied by `#[warn(clippy::pedantic)]`
p.save_as_png(&time_stamp, &c.get_view(), m, *image_supersampling_amount);
MandelbrotModel::get_instance().p.save_as_png(
&time_stamp,
&MandelbrotModel::get_instance().c.get_view(),
m,
*image_supersampling_amount,
);
} else {
let mut image_p: PixelBuffer = PixelBuffer::new(PixelPlane::new(config.image_width, config.image_height));
let mut image_c: ComplexPlane = ComplexPlane::new(config.image_width, config.image_height);
image_p.color_channel_mapping = p.color_channel_mapping;
image_c.set_view(&c.get_view());
image_p.color_channel_mapping = MandelbrotModel::get_instance().p.color_channel_mapping;
image_c.set_view(&MandelbrotModel::get_instance().c.get_view());
rendering::render_complex_plane_into_buffer(&mut image_p, &image_c, m, *image_supersampling_amount, *coloring_function);
image_p.save_as_png(&time_stamp, &c.get_view(), m, *image_supersampling_amount);
image_p.save_as_png(
&time_stamp,
&MandelbrotModel::get_instance().c.get_view(),
m,
*image_supersampling_amount,
);
}
}
Key::I => c.set_view(&View::new(ask("x"), ask("y"), ask("scale"))),
Key::I => MandelbrotModel::get_instance()
.c
.set_view(&View::new(ask("x"), ask("y"), ask("scale"))),
Key::A => {
*coloring_function = pick_option(&[
("HSV", TrueColor::new_from_hsv_colors),
("Bernstein polynomials", TrueColor::new_from_bernstein_polynomials),
])

Check warning on line 241 in src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

consider adding a `;` to the last statement for consistent formatting

warning: consider adding a `;` to the last statement for consistent formatting --> src/lib.rs:238:17 | 238 | / *coloring_function = pick_option(&[ 239 | | ("HSV", TrueColor::new_from_hsv_colors), 240 | | ("Bernstein polynomials", TrueColor::new_from_bernstein_polynomials), 241 | | ]) | |__________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned = note: `#[warn(clippy::semicolon_if_nothing_returned)]` implied by `#[warn(clippy::pedantic)]` help: add a `;` here | 238 ~ *coloring_function = pick_option(&[ 239 + ("HSV", TrueColor::new_from_hsv_colors), 240 + ("Bernstein polynomials", TrueColor::new_from_bernstein_polynomials), 241 + ]); |
}
Key::M => m.max_iterations = ask("max_iterations"),
Key::O => p.color_channel_mapping = ask("color_channel_mapping"),
Key::M => MandelbrotModel::get_instance().m.max_iterations = ask("max_iterations"),
Key::O => MandelbrotModel::get_instance().p.color_channel_mapping = ask("color_channel_mapping"),
Key::Q => {
*supersampling_amount = ask::<u8>("supersampling_amount").clamp(1, 64);
*image_supersampling_amount = *supersampling_amount;
Expand All @@ -231,9 +251,15 @@ fn handle_key_events(
_ => (),
}
match key {
Key::NumPadPlus | Key::NumPadMinus => println!("translation_amount: {}", vars.translation_amount),
Key::NumPadSlash | Key::NumPadAsterisk => println!("scale factor: {}/{}", vars.scale_numerator, vars.scale_denominator),
Key::Up | Key::Down | Key::Left | Key::Right => c.print(),
Key::NumPadPlus | Key::NumPadMinus => {
println!("translation_amount: {}", MandelbrotModel::get_instance().vars.translation_amount)

Check warning on line 255 in src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

consider adding a `;` to the last statement for consistent formatting

warning: consider adding a `;` to the last statement for consistent formatting --> src/lib.rs:255:17 | 255 | println!("translation_amount: {}", MandelbrotModel::get_instance().vars.translation_amount) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `println!("translation_amount: {}", MandelbrotModel::get_instance().vars.translation_amount);` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
}
Key::NumPadSlash | Key::NumPadAsterisk => println!(
"scale factor: {}/{}",
MandelbrotModel::get_instance().vars.scale_numerator,
MandelbrotModel::get_instance().vars.scale_denominator
),
Key::Up | Key::Down | Key::Left | Key::Right => MandelbrotModel::get_instance().c.print(),
Key::R
| Key::Key1
| Key::Key2
Expand All @@ -253,7 +279,7 @@ fn handle_key_events(
| Key::O
| Key::Q => {
rendering::render_complex_plane_into_buffer(p, c, m, *supersampling_amount, *coloring_function);
c.print();
MandelbrotModel::get_instance().c.print();
}
_ => (),
}
Expand All @@ -266,8 +292,8 @@ fn was_clicked(current: bool, previous: bool) -> bool {

fn handle_left_mouse_clicked(x: f32, y: f32, c: &ComplexPlane) {

Check warning on line 293 in src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `c`

warning: unused variable: `c` --> src/lib.rs:293:46 | 293 | fn handle_left_mouse_clicked(x: f32, y: f32, c: &ComplexPlane) { | ^ help: if this is intentional, prefix it with an underscore: `_c`
println!("\nMouseButton::Left -> Info at ({x}, {y})");
//let iterations = p.iterations_at_point(x as usize, y as usize, m.max_iterations); //TODO: fix this
let complex = c.complex_from_pixel_plane(x.into(), y.into());
//let iterations = MandelbrotModel::get_instance().p.iterations_at_point(x as usize, y as usize, MandelbrotModel::get_instance().m.max_iterations); //TODO: fix this
let complex = MandelbrotModel::get_instance().c.complex_from_pixel_plane(x.into(), y.into());
println!("Complex: {:?}", complex);
//println!("iterations: {}", iterations);
println!();
Expand All @@ -283,12 +309,15 @@ fn handle_right_mouse_clicked(
coloring_function: ColoringFunction,
) {
println!("\nMouseButton::Right -> Move to ({x}, {y})");
let new_center = c.complex_from_pixel_plane(x.into(), y.into());
println!("c.center: {:?}", c.center());
let new_center = MandelbrotModel::get_instance().c.complex_from_pixel_plane(x.into(), y.into());
println!(
"MandelbrotModel::get_instance().c.center: {:?}",
MandelbrotModel::get_instance().c.center()
);
println!("new_center: {:?}", new_center);

rendering::translate_to_center_and_render_efficiently(c, p, m, &new_center, supersampling_amount, coloring_function);
c.print();
MandelbrotModel::get_instance().c.print();
println!();
}

Expand Down Expand Up @@ -346,15 +375,15 @@ fn handle_mouse_events(
///Prints Mandelbrot ASCII art :) </br>
///Prints the `application_banner`, `author_banner`, and `version`
fn print_banner() {
//Made using: https://patorjk.com/software/taag/#p=display&f=Big&t=Mandelbrot
//Made using: https://patorjk.com/software/taag/#MandelbrotModel::get_instance().p=display&f=Big&t=Mandelbrot
let application_banner = r"
__ __ _ _ _ _
| \/ | | | | | | | |
| \ / | __ _ _ __ __| | ___| | |__ _ __ ___ | |_
| |\/| |/ _` | '_ \ / _` |/ _ \ | '_ \| '__/ _ \| __|
| | | | (_| | | | | (_| | __/ | |_) | | | (_) | |_
|_| |_|\__,_|_| |_|\__,_|\___|_|_.__/|_| \___/ \__|";
//Made using: https://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=by%20Jort
//Made using: https://patorjk.com/software/taag/#MandelbrotModel::get_instance().p=display&f=Small%20Slant&t=by%20Jort
let author_banner = r"
__ __ __
/ / __ __ __ / /__ ____/ /_
Expand All @@ -380,20 +409,10 @@ fn print_command_info() {
/// # Errors
/// Currently does not return any Errors
pub fn run(config: &Config) -> Result<(), Box<dyn Error>> {
// Complex plane dimensions and increments
let mut c = ComplexPlane::new(config.window_width, config.window_height);
// Pixel plane and buffer
let mut p = PixelBuffer::new(PixelPlane::new(config.window_width, config.window_height));
// User interaction variables
let mut vars = InteractionVariables::default();
// Multithreading variables
let amount_of_threads = num_cpus::get(); //Amount of CPU threads to use, TODO: use this value in rendering functions
// Mandelbrot set iterator
let mut m: MandelbrotFunction = MandelbrotFunction::new(config.max_iterations, config.orbit_radius);
//Coloring function
let mut coloring_function = COLORING_FUNCTION;
//Color channel mapping
p.color_channel_mapping = COLOR_CHANNEL_MAPPING;
//MandelbrotModel::get_instance().p.color_channel_mapping = COLOR_CHANNEL_MAPPING;
//SSAA multiplier
let mut supersampling_amount = config.supersampling_amount;
//Image SSAA multiplier
Expand Down Expand Up @@ -478,33 +497,42 @@ pub fn run(config: &Config) -> Result<(), Box<dyn Error>> {
key_bindings.add(Key::C, "Prints the configuration variables", empty_closure);
key_bindings.print();

p.pixel_plane.print();
c.print();
MandelbrotModel::get_instance().p.pixel_plane.print();
MandelbrotModel::get_instance().c.print();
println!(
"Mandelbrot set parameters: max. iterations is {} and orbit radius is {}",
config.max_iterations, config.orbit_radius
);
println!("Amount of CPU threads that will be used for rendering: {}", amount_of_threads);
println!(
"Amount of CPU threads that will be used for rendering: {}",
MandelbrotModel::get_instance().amount_of_threads
);
println!("Supersampling amount used for rendering: {}x", supersampling_amount);
println!();

println!("Rendering Mandelbrot set default view");
rendering::render_complex_plane_into_buffer(&mut p, &c, &m, supersampling_amount, coloring_function);
rendering::render_complex_plane_into_buffer(
&mut MandelbrotModel::get_instance().p,
&MandelbrotModel::get_instance().c,
&MandelbrotModel::get_instance().m,
supersampling_amount,
coloring_function,
);

// Main loop
while window.is_open() && !window.is_key_down(Key::Escape) {
// Update the window with the new buffer
window
.update_with_buffer(&p.pixels, config.window_width, config.window_height)
.update_with_buffer(&MandelbrotModel::get_instance().p.pixels, config.window_width, config.window_height)
.unwrap();

// Handle any window events
handle_key_events(
&window,
&mut c,
&mut p,
&mut m,
&mut vars,
&mut MandelbrotModel::get_instance().c,
&mut MandelbrotModel::get_instance().p,
&mut MandelbrotModel::get_instance().m,
&mut MandelbrotModel::get_instance().vars,
&key_bindings,
&mut supersampling_amount,
&mut image_supersampling_amount,
Expand All @@ -513,7 +541,14 @@ pub fn run(config: &Config) -> Result<(), Box<dyn Error>> {
);

//Handle any mouse events
handle_mouse_events(&window, &mut c, &mut p, &m, supersampling_amount, coloring_function);
handle_mouse_events(
&window,
&mut MandelbrotModel::get_instance().c,
&mut MandelbrotModel::get_instance().p,
&MandelbrotModel::get_instance().m,
supersampling_amount,
coloring_function,
);
}

Ok(())
Expand Down
7 changes: 1 addition & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
use std::env;

Check warning on line 1 in src/main.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `std::env`

warning: unused import: `std::env` --> src/main.rs:1:5 | 1 | use std::env; | ^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
use std::process;

use mandelbrot::{self, Config, MandelbrotModel};
use mandelbrot::{self, MandelbrotModel};

fn main() {
MandelbrotModel::get_instance().config = Config::build(env::args()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});

if let Err(err) = mandelbrot::run(&MandelbrotModel::get_instance().config) {
eprintln!("Application error: {}", err);
process::exit(1);
Expand Down
27 changes: 24 additions & 3 deletions src/model/mandelbrot_model.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
use lazy_static::lazy_static;
use std::sync::{Mutex, MutexGuard};
use std::{
env, process,
sync::{Mutex, MutexGuard},
};

use crate::Config;
use crate::{Config, InteractionVariables};

use super::{complex_plane::ComplexPlane, mandelbrot_function::MandelbrotFunction, pixel_buffer::PixelBuffer, pixel_plane::PixelPlane};

lazy_static! {
static ref MANDELBROT_MODEL_INSTANCE: Mutex<MandelbrotModel> = Mutex::new(MandelbrotModel::new());
}

pub struct MandelbrotModel {
pub config: Config,
pub c: ComplexPlane,
pub p: PixelBuffer,
pub vars: InteractionVariables,
pub amount_of_threads: usize,
pub m: MandelbrotFunction,
}

impl MandelbrotModel {
pub fn new() -> MandelbrotModel {
MandelbrotModel { config: Config::new() }
let config = Config::build(env::args()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
MandelbrotModel {
config: config.clone(),

Check warning on line 31 in src/model/mandelbrot_model.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `Config` which implements the `Copy` trait

warning: using `clone` on type `Config` which implements the `Copy` trait --> src/model/mandelbrot_model.rs:31:21 | 31 | config: config.clone(), | ^^^^^^^^^^^^^^ help: try removing the `clone` call: `config` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy note: the lint level is defined here --> src/lib.rs:9:5 | 9 | clippy::complexity | ^^^^^^^^^^^^^^^^^^ = note: `#[warn(clippy::clone_on_copy)]` implied by `#[warn(clippy::complexity)]`
c: ComplexPlane::new(config.window_width, config.window_height),
p: PixelBuffer::new(PixelPlane::new(config.window_width, config.window_height)),
vars: InteractionVariables::default(),
amount_of_threads: num_cpus::get(),
m: MandelbrotFunction::new(config.max_iterations, config.orbit_radius),
}
}

Check warning on line 38 in src/model/mandelbrot_model.rs

View workflow job for this annotation

GitHub Actions / clippy

you should consider adding a `Default` implementation for `MandelbrotModel`

warning: you should consider adding a `Default` implementation for `MandelbrotModel` --> src/model/mandelbrot_model.rs:25:5 | 25 | / pub fn new() -> MandelbrotModel { 26 | | let config = Config::build(env::args()).unwrap_or_else(|err| { 27 | | eprintln!("Problem parsing arguments: {}", err); 28 | | process::exit(1); ... | 37 | | } 38 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 24 + impl Default for MandelbrotModel { 25 + fn default() -> Self { 26 + Self::new() 27 + } 28 + } |

/// Returns the singleton MandelbrotModel instance.

Check warning on line 40 in src/model/mandelbrot_model.rs

View workflow job for this annotation

GitHub Actions / clippy

item in documentation is missing backticks

warning: item in documentation is missing backticks --> src/model/mandelbrot_model.rs:40:31 | 40 | /// Returns the singleton MandelbrotModel instance. | ^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown = note: `#[warn(clippy::doc_markdown)]` implied by `#[warn(clippy::pedantic)]` help: try | 40 | /// Returns the singleton `MandelbrotModel` instance. | ~~~~~~~~~~~~~~~~~
Expand Down

0 comments on commit 0379adc

Please sign in to comment.