(* $Id: plot.ml,v 1.1 2010/10/19 10:02:36 garrigue Exp $ *) open Graphics open StdLabels exception Overflow class window = object (win) val mutable minx = 0. val mutable maxx = 0.1 val mutable miny = 0. val mutable maxy = 0.1 val mutable width = 1 val mutable height = 1 method conv x y = let x' = (x -. minx) /. (maxx -. minx) *. float width and y' = (y -. miny) /. (maxy -. miny) *. float height in if abs_float x' > 16000. || abs_float y' > 16000. then raise Overflow; (truncate (x'+.0.5), truncate (y'+.0.5)) method draw_curve l = ignore begin List.fold_left l ~init:true ~f: begin fun start (x,y) -> try let (x',y') = win#conv x y in if start then moveto x' y'; lineto x' y'; false with Overflow -> true end end method create_curve f = let rec points accu i = if i < 0 then accu else let x = float i /. float width *. (maxx -. minx) +. minx in let y = try f x with _ -> 1./.0. in points ((x,y) :: accu) (i-1) in points [] (width - 1) method adjust_size points = open_graph ""; width <- size_x()-1; height <- size_y()-1; minx <- 0.; maxx <- 0.; miny <- 0.; maxy <- 0.; List.iter points ~f: begin fun (x,y) -> if x < minx then minx <- x; if x > maxx then maxx <- x; if y < miny then miny <- y; if y > maxy then maxy <- y end; if minx = maxx then maxx <- maxx +. 0.1; if miny = maxy then maxy <- maxy +. 0.1; miny <- miny *. 1.1; maxy <- maxy *. 1.1; win#draw_axis () method draw_line x0 y0 x1 y1 = let (x0,y0) = win#conv x0 y0 in let (x1,y1) = win#conv x1 y1 in draw_segments [|x0,y0,x1,y1|] method draw_axis () = let sx = maxx -. minx in let dx = 10. ** floor (log (sx/.5.) /. log 10.) in let sy = maxy -. miny in let dy = 10. ** floor (log (sy/.5.) /. log 10.) in win#draw_line minx 0. maxx 0.; win#draw_line 0. miny 0. maxy; for i = truncate (minx /. dx) to truncate (maxx /. dx) do let sz = sy /. float (height - 1) in let sz = if i mod 10 = 0 then sz *. 3. else if i mod 5 = 0 then sz *. 2. else sz and x = float i *. dx in win#draw_line x (-. sz) x sz done; for i = truncate (miny /. dy) to truncate (maxy /. dy) do let sz = sx /. float (width - 1) in let sz = if i mod 10 = 0 then sz *. 3. else if i mod 5 = 0 then sz *. 2. else sz and y = float i *. dy in win#draw_line (-. sz) y sz y done end let win = new window let create_curve = win#create_curve let adjust_size = win#adjust_size let draw_curve = win#draw_curve