initial commit

This commit is contained in:
nora 2021-03-01 17:00:02 +01:00
parent 7577fc6041
commit 764d2ff644
3 changed files with 308 additions and 25 deletions

213
src/MandelbrotSet.java Normal file
View file

@ -0,0 +1,213 @@
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class MandelbrotSet {
public static void main(String[] args) {
double progress = 0;
double amount;
// I think there might be some stuff mixed up in the code but it works
// not sure though
double[][] interestingPoints = { { -0.75, 0 }, { -0.77568377, 0.13646737 } };
// important settings-------------------------------------------------------------
int pointNumber = 1;
int quality = 2; // 0 = very low, 1 = low, 2 = medium, 3 = high, 4 = ultra, any number bigger than 5 = custom
double zoomSpeed = 1.1; // >1
int frames = 100;
int width = 1920;
//................................................................................
// less important settings
boolean advancedIndicators = true;
double forceCenterX = interestingPoints[pointNumber][0];
double forceCenterY = interestingPoints[pointNumber][1];
boolean imageMode = true;
int height = 1080;
boolean locked = true;
float ratio = 2 / 3f; // .2 for editor 2/3 for image
double zoom = 1;
int iterations;
double threshold = 100;
char low = ' ';
char high = '#';
if (quality == 0) {
iterations = 20;
} else if (quality == 1) {
iterations = 50;
} else if (quality == 2) {
iterations = 100;
} else if (quality == 3) {
iterations = 500;
} else if (quality == 4) {
iterations = 1000;
} else {
iterations = quality;
}
double offsetX;
double offsetY;
if (locked) {
height = (int) ((float) width * ratio);
}
// TIME
long startTime = System.currentTimeMillis();
for (int frameCounter = 0; frameCounter < frames; frameCounter++) {
// progress = 0;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
File f = null;
// the printed image is 3 * 2 (from x = -3 to x = 1 and
double stepSizeX = (3 / (float) width) / zoom;
double stepSizeY = (2 / (float) height) / zoom;
offsetX = forceCenterX - width / 2 * stepSizeX;
offsetY = -(forceCenterY - height / 2 * stepSizeY);
// calculate coords using stepSize and hardcoded corner coords:
// create an array of complex numbers, where the position of each sample will be stored
CNumber[][] coords = new CNumber[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
coords[i][j] = new CNumber(); // fill the array
coords[i][j].real = offsetX + stepSizeX * i; // calculate the position on the real numberline
coords[i][j].imag = offsetY - stepSizeY * j; // calculate the position on the imaginary numberline
}
}
// calculate values
double[][] values = new double[width][height]; // new array of booleans for the drawing
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
values[i][j] = checkMandelbrot(coords[i][j], iterations, threshold); // check if the number is inside of th set
}
}
if (imageMode) {
createImage(image, frameCounter, f, width, height, values);
} else {
// draw
draw(low, high, width, height, values);
}
System.out.println("------------------------Frame " + frameCounter + " finished------------------------");
zoom *= zoomSpeed;
}
// TIME
long endtime = System.currentTimeMillis();
long completionTimeLong = endtime - startTime;
double completionTimeSec = (double) completionTimeLong / 1000.0;
System.out.println("Calculated " + frames + " frame/s. Process took " + completionTimeSec + "s");
}
static void draw(char low, char high, int width, int height, double[][] values) {
// a method to draw a filled rectangle of size width * height
// each cell can be low or high, and it will show the corresponding char in each cell
String line;
for (int i = 0; i < height; i++) {
line = "";
// for every line:
for (int j = 0; j < width; j++) {
// for every char:
double value = values[j][i];
if (value >= 1) {
line += high;
} else {
line += low;
}
}
System.out.println(line);
}
}
static double checkMandelbrot(CNumber number, int iterations, double threshold) {
// start
CNumber n = new CNumber();
CNumber c = number;
// first
n = CNumber.add(n, c);
for (int i = 0; i < iterations; i++) {
n = CNumber.add(CNumber.multiply(n, n), c); // CNumber.multiply(n, n)
}
// System.out.println(n.real + " " + n.imag);
if (n.real < threshold && n.imag < threshold) {
return 1;
} else {
return 0;
}
}
static void createImage(BufferedImage image, int counter, File f, int width, int height, double[][] values) {
System.out.println("Frame: " + counter + " | Started creating image...");
int p0 = getColorAsInt(0, 0, 0, 0);
int p1 = getColorAsInt(0, 50, 50, 50);
int p2 = getColorAsInt(0, 100, 100, 100);
int p3 = getColorAsInt(0, 150, 150, 150);
int p4 = getColorAsInt(0, 200, 200, 200);
int pMax = getColorAsInt(0, 255, 255, 255);
int threshold1 = 10;
int threshold2 = 20;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
if (values[i][j] >= 1) {
image.setRGB(i, j, p0);
} else {
image.setRGB(i, j, pMax);
}
}
}
try {
f = new File("sequence\\Sequence" + counter + ".png");
ImageIO.write(image, "png", f);
System.out.println(f.getAbsolutePath());
} catch (IOException e) {
System.out.println(e);
}
System.out.println("Frame: " + counter + " | Finished creating image.");
}
public static int getColorAsInt(int a, int r, int g, int b) {
int p1 = (a << 24) | (r << 16) | (g << 8) | b;
return p1;
}
}
// ^ originaler italienischer spaghetti code ^

View file

@ -1,16 +1,61 @@
use std::error::Error;
use std::time::SystemTime;
use std::ops::{Add, Mul};
pub fn main(config: Config) -> Result<String, Box<dyn Error>> {
let start_time = SystemTime::now().elapsed()?;
let coords = calculate_sample_points(&config);
let end_time = SystemTime::now().elapsed()?;
println!("Time: {}", end_time.as_micros() - start_time.as_micros());
Ok(String::from("hi"))
}
#[derive(Copy, Clone)]
fn calculate_sample_points(config: &Config) -> Box<Vec<Vec<CNumber>>> {
let step_size_x = 3.0 / config.width;
let step_size_y = 2.0 / config.height;
let offset_x = config.center.real - config.width / 2.0 * step_size_x;
let offset_y = -(config.center.imag - config.height / 2.0 * step_size_y);
let mut coords: Box<Vec<Vec<CNumber>>> =
Box::from(vec![vec![CNumber::new(0.0, 0.0); config.width as usize]; config.height as usize]);
for i in 0..config.width as usize {
for j in 0..config.height as usize {
coords[j][i].real = offset_x + step_size_x * i as f64;
coords[j][i].imag = offset_y + step_size_y * j as f64;
}
}
println!("{:?}", coords[0][0]);
coords
}
fn check_mandelbrot(number: &CNumber, iter: i32, threshold: f64) -> i32 {
let mut n = CNumber::new(0.0, 0.0);
let c = number;
n = n + c;
for _ in 0..iter {
n = n * n + c;
}
if n.real < threshold && n.imag < threshold {
1
} else {
0
}
}
fn draw(values: Box<Vec<Vec<i32>>>) -> String {
let mut lines = vec![];
}
#[derive(Copy, Clone, Debug)]
struct CNumber {
real: f64,
imag: f64,
@ -20,44 +65,43 @@ impl CNumber {
fn new(real: f64, imag: f64) -> CNumber {
CNumber { real, imag }
}
}
fn add_mut(&mut self, other: CNumber) {
self.real += other.real;
self.imag += other.imag;
}
impl Add for &CNumber {
type Output = CNumber;
fn mul_mut(&mut self, other: CNumber) {
self.real = self.real * self.real - other.imag * other.imag;
self.imag = self.real * other.imag + other.real * self.imag;
fn add(&self, b: CNumber) -> Self::Output {
let real = self.real + b.real;
let imag = self.imag + b.imag;
CNumber { real, imag }
}
}
fn add_c(a: &CNumber, b: &CNumber) -> CNumber {
let real = a.real + b.real;
let imag = a.imag + b.imag;
impl Mul for &CNumber {
type Output = CNumber;
CNumber { real, imag }
fn mul(self, b: Self) -> Self::Output {
let real = self.real * self.real - b.imag * b.imag;
let imag = self.real * b.imag + b.real * self.imag;
CNumber { real, imag }
}
}
fn mul_c(a: &CNumber, b: &CNumber) -> CNumber {
let real = a.real * a.real - b.imag * b.imag;
let imag = a.real * b.imag + b.real * a.imag;
CNumber { real, imag }
}
pub struct Config {
quality: i32,
width: i32,
threshold: f32,
width: f64,
threshold: f64,
//-- calculated
height: i32,
height: f64,
center: CNumber,
iterations: i32,
}
impl Config {
pub fn new(point_number: usize, quality: i32, width: i32, threshold: f32) -> Config{
pub fn new(point_number: usize, quality: i32, width: i32, threshold: f32) -> Config {
let height = width as f32 * 0.2;
let interesting_points = vec![CNumber::new(-0.75, 0.0), CNumber::new(-0.77568377, 0.13646737)];
@ -72,8 +116,27 @@ impl Config {
};
Config {
quality, width, height: height as i32,
center, iterations, threshold,
quality,
width: width as f64,
height: height as f64,
center,
iterations,
threshold: threshold as f64,
}
}
}
//#[cfg(tests)]
mod tests {
use crate::{Config, calculate_sample_points};
#[test]
fn correct_size_points() {
let config = Config::new(1, 0, 100, 0.0);
let result = calculate_sample_points(&config);
result[0][0];
result[0][99];
}
}

View file

@ -1,3 +1,10 @@
use mandelbrot_set::Config;
fn main() {
println!("Hello, world!");
let config = Config::new(1, 3, 100, 100.0);
match mandelbrot_set::main(config) {
Ok(s) => println!("{}", s),
Err(e) => println!("Error: {}", e)
}
}