Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Graph a function

 [1/1] from: philb::upnaway::com at: 18-Mar-2001 19:34


Hi List, I have been playing around with a program to graph a function .... The functon draw-line function is based on draw-line2.r by Larry Palmiter (cheers Larry) The GUI is still work in progress .... To use the program just type in a function of x into the input field .... and hit the draw button. You have the following options for plotting a function : View /change the graph limits by hitting the settings button. Change the graph color by hitting the Graph Color button. You can plot a graph as point or joined up points using the choice button. Clear the current image by hitting the clear paper button. Some pretty functions to get you started ..... 5 * sin (0.5 * pi * x) 5 * sin (x * x) exp(0.1 * x) * (sin(4 * pi * x)) 5 * sin (4 * pi / x) 5 * exp(- x) * sin (0.5 * pi * x) 10 / ((3 * x * x) + (4 * x) - 3) The program understands the following standard maths functions sin (radians), cos (radians), tan (radians), sinh, cosh, tanh, exp, fac (factorial) as well as all the normal recol functions. Note that it uses rebol's left to right priority for evaluating expressions, so 5 + 3 * 4 = 32 not 5 + (3 * 4) = 17 (as expected) Anyway .... enjoy Cheers Phil REBOL [ Title: "Graph a function" File: %Graph-v1.0.r Author: "Phil Bevan" Date: 3-Oct-2000 Version: 0.0.1 Purpose: { Graph a function draw-line function adapted from drawline.r by Larry Palmiter } ] ; Convert Degrees to Radians & Radians to Degrees rad: function [x] [] [ x * pi / 180 ] deg: function [x] [] [ x * 180 / pi ] ; trig functions sin: function [x] [] [return sine/radians x] cos: function [x] [] [return cosine/radians x] tan: function [x] [] [return tangent/radians x] ; square-root sqrt: function [x] [] [return square-root x] ; hyperbolic trig functions sinh: function [x] [] [return ((exp(x)) - (exp(- x))) / 2] cosh: function [x] [] [return ((exp(x)) + (exp(- x))) / 2] tanh: function [x] [] [return ((exp(2 * x)) - 1) / ((exp(2 * x)) + 1)] fac: func [x [integer!] /local fa i] [ if x < 0 [return none] fa: 1.0 i: 1 while [i <= x] [ fa: fa * i i: i + 1 ] return fa ] ; create a function create-function: function [t-func [string!]] [f] [ ; return a newly created function if error? try [f: to-block load t-func] [return none] function [x [any-type!]] [] f ] ; paper object paper: make object! [ size: 0x0 x-min: -1 x-max: 1 y-min: -1 y-max: 1 grid: yes x-grid: 20 y-grid: 20 grid-color: red axes: yes axes-color: black paper-color: white pen-color: black axes-color: black image: none crt: func [ size [pair!] xmin [decimal!] xmax [decimal!] ymin [decimal!] ymax [decimal!] ] [ self/size: size self/x-min: xmin self/x-max: xmax self/y-min: ymin self/y-max: ymax self/image: to-image to-pair reduce [size/x size/y] clear-im self/image self/paper-color ] ] ; clear the image to a colour clear-im: func [im [image!] color [tuple!] /local j] [ repeat j im/size/x * im/size/y [poke im j color] ] ; plot a point plot: func [im [image!] p col [tuple!] /local i xs ys] [ set [xs ys] [im/size/x im/size/y] i: ys - p/y * xs + p/x if any [i <= 0 i > (im/size/x * im/size/y)] [return] poke im i col ] draw-line: func [ {draw line from point a to b using Bresenham's algorithm} im [image!] a [pair!] b [pair!] color [tuple!] /local d inc dpr dpru p set-pixel xs ys ][ set [xs ys] [im/size/x im/size/y] set-pixel: func [p c] [poke im (ys - p/y * xs + p/x) c] if any [a/x < 1 a/y < 1 a/x > xs a/y > ys b/x < 1 b/y < 1 b/x > xs b/y > ys] [return] d: abs (b - a) inc: 1x1 if a/x > b/x [inc/x: -1] if a/y > b/y [inc/y: -1] either d/x >= d/y [ dpr: 2 * d/y dpru: dpr - (2 * d/x) p: dpr - d/x loop d/x + 1 [ set-pixel a color either p > 0 [ a: a + inc p: p + dpru ][ a/x: a/x + inc/x p: p + dpr ] ] ][ dpr: 2 * d/x dpru: dpr - (2 * d/y) p: dpr - d/y loop d/y + 1 [ set-pixel a color either p > 0 [ a: a + inc p: p + dpru ][ a/y: a/y + inc/y p: p + dpr ] ] ] ] ; Fixed Width field Styles new-styles: stylize [ fix-area: area font [name: "courier new" size: 12] wrap fix-field: field font [name: "courier new" size: 12] fix-text: text font [name: "courier new" size: 12] ] ; initialise the graph init-graph: func [paper [object!]] [ clear-im paper/image paper/paper-color draw-axes paper ] draw-axes: func [paper /local pt] [ pt: coordinates paper 0 0 if all [pt/y >= 0 pt/y < paper/size/y] [draw-line paper/image to-pair reduce [1 pt/y] to-pair reduce [(paper/size/x - 1) pt/y] paper/axes-color] ; x-axis if all [pt/x >= 0 pt/x < paper/size/x] [draw-line paper/image to-pair reduce [pt/x 1] to-pair reduce [pt/x paper/size/y] paper/axes-color]; y-axis ] ; convert to co-ordinates coordinates: func [paper [object!] x [number!] y [number!] /local xc yc] [ xd: x - paper/x-min xp: (paper/x-max - paper/x-min) / paper/size/x xc: xd / xp if any [xc < 0 xc > paper/size/x] [-1] if error? try[xc: to-integer xc] [return none] yd: y - paper/y-min yp: (paper/y-max - paper/y-min) / paper/size/y yc: yd / yp if any [yc < 0 yc > paper/size/y] [-1] if error? try[yc: to-integer yc] [return none] return make pair! reduce [xc yc] ] ; Draw the graph draw-graph: func [paper [object!] t-fx [string!] trace [string!] /local x x-step fx pt last-pt] [ if t-fx = "" [request/ok "No function entered" return] f-fx: create-function t-fx if not function? :f-fx [request/ok "Improper function entered" return] last-pt: none x-step: (paper/x-max - paper/x-min) / paper/size/x for x paper/x-min paper/x-max x-step [ if not error? try [fx: f-fx x] [ pt: coordinates paper x fx if pt <> none [ switch trace [ "Point" [plot paper/image pt paper/pen-color] "Line" [ either last-pt <> none [draw-line paper/image last-pt pt paper/pen-color] [plot paper/image pt paper/pen-color] ] ] ] last-pt: pt ] ] ] ; Graph Paper settings gr-settings: func [ paper [object!] gr-face [object!] /local prefs f-xmin f-xmax f-ymin f-ymax f-paper-color f-pen-color lv-valid ] [ prefs: view/new layout [ backdrop 0.150.0 styles new-styles origin 10x10 below at 10x10 text "Min X" 60x24 text "Max X" 60x24 text "Min Y" 60x24 text "Max Y" 60x24 text "Paper Color" 80x24 text "Pen Color" 80x24 text "Clear" 80x24 return f-xmin: fix-field to-string(paper/x-min) f-xmax: fix-field to-string(paper/x-max) f-ymin: fix-field to-string(paper/y-min) f-ymax: fix-field to-string(paper/y-max) f-paper-color: fix-field to-string(paper/paper-color) f-pen-color: fix-field to-string(paper/pen-color) cb-clear: check with [state: false] button "Apply" [ lv-valid: yes if error? try [paper/x-min: to-decimal f-xmin/text] [request/ok Invalid Min X value entered lv-valid: no] if error? try [paper/x-max: to-decimal f-xmax/text] [request/ok Invalid Max X value entered lv-valid: no] if error? try [paper/y-min: to-decimal f-ymin/text] [request/ok Invalid Min Y value entered lv-valid: no] if error? try [paper/y-max: to-decimal f-ymax/text] [request/ok Invalid Min Y value entered lv-valid: no] if error? try [paper/paper-color: to-tuple f-paper-color/text] [request/ok "Invalid Paper Color entered" lv-valid: no] if error? try [paper/pen-color: to-tuple f-pen-color/text] [request/ok "Invalid Pen Color entered" lv-valid: no] if cb-clear/data = true [ init-graph paper show gr-face ] if lv-valid = yes [unview prefs] ] ] ] ; ; Main Line ; x-size: 500 y-size: 500 gr-size: to-pair reduce [x-size y-size] eq-size: to-pair reduce [x-size 24] gr-paper: make paper [] gr-paper/crt gr-size -10.0 10.0 -10.0 10.0 draw-axes gr-paper ; ; view the window ; view layout [ backdrop 0.150.0 origin 5x5 styles new-styles below at 5x5 gr-paper-f: image gr-paper/image across t-func1: fix-field eq-size return r-trace: choice 120.20.120 100x24 data ["Line" "Point"] button "Graph Color" [ gr-col: request-color/color gr-paper/pen-color if gr-col <> none [gr-paper/pen-color: gr-col] ] button "Draw f(x)" 100x24 [ draw-graph gr-paper t-func1/text first r-trace/data show gr-paper-f ] return button "Settings" 100x24 [gr-settings gr-paper gr-paper-f] button "Clear Paper" 100x24 [ init-graph gr-paper show gr-paper-f ] button "Save (png)" [ t-save-name: request-file/title/keep/file "Save Graph as png" "Save" graph.png if t-save-name <> none [ if error? try [save/png to-file t-save-name gr-paper/image] [request/OK "Unable to Save graph"] ] ] ]