This commit is contained in:
Simon Gardling 2022-02-11 09:53:23 -05:00
parent be2d6a2f71
commit 4c072d3d96
2 changed files with 54 additions and 17 deletions

View File

@ -1,11 +1,20 @@
use crate::DrawResult;
use meval::Expr;
use plotters::prelude::*;
use plotters_canvas::CanvasBackend;
use web_sys::HtmlCanvasElement;
use meval::Expr;
/// Draw power function f(x) = x^power.
pub fn draw(element: HtmlCanvasElement, func_str: &str, min_x: f32, max_x: f32, min_y: f32, max_y: f32, num_interval: usize, resolution: i32) -> DrawResult<(impl Fn((i32, i32))-> Option<(f32, f32)>, f32)> {
pub fn draw(
element: HtmlCanvasElement,
func_str: &str,
min_x: f32,
max_x: f32,
min_y: f32,
max_y: f32,
num_interval: usize,
resolution: i32,
) -> DrawResult<(impl Fn((i32, i32)) -> Option<(f32, f32)>, f32)> {
let expr: Expr = func_str.parse().unwrap();
let func = expr.bind("x").unwrap();
@ -28,7 +37,7 @@ pub fn draw(element: HtmlCanvasElement, func_str: &str, min_x: f32, max_x: f32,
chart.configure_mesh().x_labels(3).y_labels(3).draw()?;
let data = (1..=resolution)
.map(|x| (((x as f32/resolution as f32))*(&absrange))+&min_x)
.map(|x| ((x as f32 / resolution as f32) * (&absrange)) + &min_x)
.map(|x| (x, func(x as f64) as f32))
.filter(|(_, y)| &min_y <= y && y <= &max_y);
@ -37,7 +46,11 @@ pub fn draw(element: HtmlCanvasElement, func_str: &str, min_x: f32, max_x: f32,
let (data2, area) = integral_rectangles(min_x, step, num_interval, &func); // Get rectangle coordinates and the total area
// Draw rectangles
chart.draw_series(data2.iter().map(|(x1, x2, y)| Rectangle::new([(*x2, *y), (*x1, 0.0)], &BLUE)))?;
chart.draw_series(
data2
.iter()
.map(|(x1, x2, y)| Rectangle::new([(*x2, *y), (*x1, 0.0)], &BLUE)),
)?;
root.present()?;
let output = chart.into_coord_trans();
@ -46,7 +59,12 @@ pub fn draw(element: HtmlCanvasElement, func_str: &str, min_x: f32, max_x: f32,
// Creates and does the math for creating all the rectangles under the graph
#[inline(always)]
fn integral_rectangles(min_x: f32, step: f32, num_interval: usize, func: &dyn Fn(f64) -> f64) -> (Vec<(f32, f32, f32)>, f32) {
fn integral_rectangles(
min_x: f32,
step: f32,
num_interval: usize,
func: &dyn Fn(f64) -> f64,
) -> (Vec<(f32, f32, f32)>, f32) {
let mut area: f32 = 0.0; // sum of all rectangles' areas
let mut tmp1: f32; // Top left Y value that's tested
let mut tmp2: f32; // Top right Y value that's tested

View File

@ -11,7 +11,7 @@ pub type DrawResult<T> = Result<T, Box<dyn std::error::Error>>;
#[wasm_bindgen]
pub struct Chart {
convert: Box<dyn Fn((i32, i32)) -> Option<(f32, f32)>>,
area: f32
area: f32,
}
/// Result of screen to chart coordinates conversion.
@ -23,8 +23,27 @@ pub struct Point {
#[wasm_bindgen]
impl Chart {
pub fn draw(canvas: HtmlCanvasElement, func: &str, min_x: f32, max_x: f32, min_y: f32, max_y: f32, num_interval: usize, resolution: i32) -> Result<Chart, JsValue> {
let output = func_plot::draw(canvas, func, min_x, max_x, min_y, max_y, num_interval, resolution).map_err(|err| err.to_string())?;
pub fn draw(
canvas: HtmlCanvasElement,
func: &str,
min_x: f32,
max_x: f32,
min_y: f32,
max_y: f32,
num_interval: usize,
resolution: i32,
) -> Result<Chart, JsValue> {
let output = func_plot::draw(
canvas,
func,
min_x,
max_x,
min_y,
max_y,
num_interval,
resolution,
)
.map_err(|err| err.to_string())?;
let map_coord = output.0;
Ok(Chart {
convert: Box::new(move |coord| map_coord(coord).map(|(x, y)| (x.into(), y.into()))),