2018-07-08 17:57:19 +02:00
|
|
|
extern crate wasm_bindgen;
|
2018-09-20 16:20:42 -07:00
|
|
|
extern crate web_sys;
|
2018-07-08 17:57:19 +02:00
|
|
|
|
2018-09-20 16:20:42 -07:00
|
|
|
use std::ops::Add;
|
2018-09-24 13:49:12 -07:00
|
|
|
use wasm_bindgen::Clamped;
|
2018-09-20 16:20:42 -07:00
|
|
|
use wasm_bindgen::prelude::*;
|
2018-09-24 13:49:12 -07:00
|
|
|
use web_sys::{CanvasRenderingContext2d, ImageData};
|
2018-07-08 17:57:19 +02:00
|
|
|
|
|
|
|
#[wasm_bindgen]
|
2018-09-20 16:20:42 -07:00
|
|
|
pub fn draw(
|
|
|
|
ctx: &CanvasRenderingContext2d,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
real: f64,
|
|
|
|
imaginary: f64,
|
|
|
|
) -> Result<(), JsValue> {
|
|
|
|
// The real workhorse of this algorithm, generating pixel data
|
|
|
|
let c = Complex { real, imaginary, };
|
2018-09-24 13:49:12 -07:00
|
|
|
let mut data = get_julia_set(width, height, c);
|
|
|
|
let data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&mut data), width, height)?;
|
|
|
|
ctx.put_image_data(&data, 0.0, 0.0)
|
2018-07-08 17:57:19 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 16:20:42 -07:00
|
|
|
fn get_julia_set(width: u32, height: u32, c: Complex) -> Vec<u8> {
|
|
|
|
let mut data = Vec::new();
|
|
|
|
|
|
|
|
let param_i = 1.5;
|
|
|
|
let param_r = 1.5;
|
|
|
|
let scale = 0.005;
|
|
|
|
|
|
|
|
for x in 0..width {
|
|
|
|
for y in 0..height {
|
|
|
|
let z = Complex {
|
|
|
|
real: y as f64 * scale - param_r,
|
|
|
|
imaginary: x as f64 * scale - param_i,
|
|
|
|
};
|
|
|
|
let iter_index = get_iter_index(z, c);
|
|
|
|
data.push((iter_index / 4) as u8);
|
|
|
|
data.push((iter_index / 2) as u8);
|
|
|
|
data.push(iter_index as u8);
|
|
|
|
data.push(255);
|
|
|
|
}
|
|
|
|
}
|
2018-07-08 17:57:19 +02:00
|
|
|
|
2018-09-20 16:20:42 -07:00
|
|
|
data
|
2018-07-08 17:57:19 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 16:20:42 -07:00
|
|
|
fn get_iter_index(z: Complex, c: Complex) -> u32 {
|
|
|
|
let mut iter_index: u32 = 0;
|
|
|
|
let mut z = z;
|
|
|
|
while iter_index < 900 {
|
|
|
|
if z.norm() > 2.0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
z = z.square() + c;
|
|
|
|
iter_index += 1;
|
|
|
|
}
|
|
|
|
iter_index
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
struct Complex {
|
|
|
|
real: f64,
|
|
|
|
imaginary: f64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Complex {
|
|
|
|
fn square(self) -> Complex {
|
|
|
|
let real = (self.real * self.real) - (self.imaginary * self.imaginary);
|
|
|
|
let imaginary = 2.0 * self.real * self.imaginary;
|
|
|
|
Complex { real, imaginary }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn norm(&self) -> f64 {
|
|
|
|
(self.real * self.real) + (self.imaginary * self.imaginary)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Add<Complex> for Complex {
|
|
|
|
type Output = Complex;
|
2018-07-08 17:57:19 +02:00
|
|
|
|
2018-09-20 16:20:42 -07:00
|
|
|
fn add(self, rhs: Complex) -> Complex {
|
|
|
|
Complex {
|
|
|
|
real: self.real + rhs.real,
|
|
|
|
imaginary: self.imaginary + rhs.imaginary,
|
|
|
|
}
|
|
|
|
}
|
2018-07-08 17:57:19 +02:00
|
|
|
}
|