diff options
| author | Andreas Grois <andi@grois.info> | 2018-02-26 08:50:08 +0100 |
|---|---|---|
| committer | Andreas Grois <andi@grois.info> | 2018-02-26 08:50:08 +0100 |
| commit | 3d43006525ee4833fc98c1e06549242eda031bf0 (patch) | |
| tree | 8c994e804b58aed4a7ee016f2367eb558fd47e36 | |
Initial commit. Working, but slow
| -rw-r--r-- | src/main.rs | 151 | ||||
| -rw-r--r-- | src/main.rs~ | 3 |
2 files changed, 154 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..0e1e5ff --- /dev/null +++ b/src/main.rs @@ -0,0 +1,151 @@ +extern crate rand; +extern crate num_complex; +extern crate png; + +use std::io; +use num_complex::Complex; + +//stuff for PNG output +use std::path::Path; +use std::fs::File; +use std::io::BufWriter; +// To use encoder.set() +use png::HasParameters; + +use std::cmp; + +use rand::distributions::{IndependentSample, Range}; + +struct Trajectory +{ + length : usize, + offset : Complex<f64>, + iteration: usize, + current : Complex<f64>, + points : Vec<Complex<f64>> +} + +struct Pixel +{ + r : u32, + g : u32, + b : u32, + a : u32 +} + +impl Trajectory { + fn new(length : usize, offset : Complex<f64>) -> Trajectory { + Trajectory{length : length, offset : offset, iteration : 0, current : Complex::new(0.0,0.0), points : Vec::with_capacity(length)} + } + + fn is_done(&self) -> bool{ + self.length == self.iteration+1 + } + + fn advance(&mut self) -> bool { + if self.is_done(){ + return false; + } + self.iteration = self.iteration+1; + self.current = self.current * self.current + self.offset; + self.points.push(self.current); + return !self.is_done(); + } + + fn run(&mut self, bailout : f64){ + let mut done = false; + while !done{ + done = done || !self.advance(); + if self.current.norm_sqr() > bailout*bailout { + done = true + } + } + } +} + +fn write_png(filename : &str, pixels : &Vec<Pixel>, max_cnt : u32, width : u32, height : u32){ + let mut png_data : Vec<u8> = Vec::with_capacity(pixels.len()*4); + for pix in pixels.iter() + { + png_data.push(((pix.r*255)/max_cnt) as u8); + png_data.push(((pix.g*255)/max_cnt) as u8); + png_data.push(((pix.b*255)/max_cnt) as u8); + //png_data.push(((pix.a*255)/max_cnt) as u8); //nope, a will not be normalized + png_data.push(255); + } + + let path = Path::new(filename); + let file = File::create(path).unwrap(); + let ref mut w = BufWriter::new(file); + + let mut encoder = png::Encoder::new(w, width, height); + encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight); + let mut writer = encoder.write_header().unwrap(); + + writer.write_image_data(&png_data.as_slice()).unwrap(); // Save +} + +fn get_pixel(path_point : &Complex<f64>, width : i32, height : i32) -> i32{ + if path_point.re < -2.5 || path_point.re > 1.0 || path_point.im < -1.0 || path_point.im > 1.0 { + return -1; + } + let x_index = ((width as f64) * ((path_point.re + 2.5)/3.5)) as i32; + let y_index = ((height as f64) * ((path_point.im + 1.0)/2.0)) as i32; + return x_index + y_index*width; +} + + +fn main() { + + let x = 1920; + let y = 1080; + + let trajectory_count = 1000000; + let path_length = 10000; + + let bailout = 50.0; + + //arrays would do, if we knew size at compile time. We do right now, but we want them tweakable later on + let mut workspace = Vec::with_capacity(x*y); + for _number in 0..x*y { + workspace.push(Pixel{r:0, g:0, b:0,a:1}); + } + + + let mut max_cnt = 1; + + let x_range = Range::new(-2.5,1.0); + let y_range = Range::new(-1.0,1.0); + let mut rng = rand::thread_rng(); + + + for _traj in 0..trajectory_count { + let offset = Complex::new(x_range.ind_sample(&mut rng),y_range.ind_sample(&mut rng)); + let mut traj = Trajectory::new(path_length,offset); + traj.run(bailout); + if traj.current.norm_sqr() < bailout*bailout { + continue; + } + + for point in traj.points{ + let mirror_point = point.conj(); + let pix = [get_pixel(&point, x as i32, y as i32),get_pixel(&mirror_point, x as i32, y as i32)]; + if pix[0] < 0 || pix[1] < 0 { + continue; + } + + for index in pix.iter() { + let mut item = &mut workspace[*index as usize]; + item.r = item.r + 1; + item.g = item.g + 1; + item.b = item.g + 1; + max_cnt = cmp::max(cmp::max(max_cnt,item.b),cmp::max(item.r,item.g)); + } + } + + } + + + + write_png(r"image.png",&workspace, max_cnt,x as u32,y as u32); +} diff --git a/src/main.rs~ b/src/main.rs~ new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs~ @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} |
