See [Fun with functions] for a quite improved version (still little ;-) ---- [Richard Suchenwirth] -- Of course there is BLT, but Tcl is just such a great wheel reinvention tool ;-) Somebody asked on comp.lang.tcl whether there's software for plotting functions, and I just needed a little challenge. So here it is: ''fun2points'' tabulates x/y values for a given function, ''plotpoints'' draws, scales, and moves such a tabulated function (or whatever other x/y coordinates - stock quotes over time?) on a given canvas, and some wrapping lines as usage example. Sheer fun... #!/bin/sh # next lines restarts \ exec wish "$0" ${1+"$@"} proc fun2points {fun args} { array set opt { -from -4.0 -to 4.0 -step .1 } array set opt $args set res [list] for {set x $opt(-from)} {$x <= $opt(-to)} {set x [expr {$x+$opt(-step)}]} { if {![catch {expr $fun} y]} {lappend res $x $y} } set res } proc plotpoints {w points args} { eval $w create line $points $args set maxx [set minx [lindex $points 0]] set maxy [set miny [lindex $points 1]] foreach {x y} $points { if {$x<$minx} {set minx $x} if {$x>$maxx} {set maxx $x} if {$y<$miny} {set miny $y} if {$y>$maxy} {set maxy $y} } $w create line $minx 0 $maxx 0 $w create line 0 $miny 0 $maxy set xfac [expr 0.95*[$w cget -width]/($maxx-$minx)] set yfac [expr 0.95*[$w cget -height]/($maxy-$miny)] $w scale all 0 0 $xfac -$yfac foreach {minxc minyc} [$w bbox all] break $w move all [expr -$minxc+5] [expr -$minyc+5] } set fun [lindex $argv 0] pack [canvas .c] plotpoints .c [fun2points $fun] -fill red wm title . $fun # usage example: funplot.tcl 'sin($x)' ---- Here are actually some problems. This script probably runs on UNIX, but not on Windows 2000. I had to change it to the following form to be able to run it from the wish. #!/bin/sh # next lines restarts \ # the following line doesn't do anything under windows, does it? # exec wish "$0" ${1+"$@"} proc fun2points {fun args} { array set opt { -from -4.0 -to 4.0 -step .1 } array set opt $args set res [list] for {set x $opt(-from)} {$x <= $opt(-to)} {set x [expr {$x+$opt(-step)}]} { # i had to exchange the following line: # if {![catch {expr $fun} y]} {lappend res $x $y} set func $fun append func ($x) lappend res $x [expr $func] } set res } proc plotpoints {w points args} { eval $w create line $points $args set maxx [set minx [lindex $points 0]] set maxy [set miny [lindex $points 1]] foreach {x y} $points { if {$x<$minx} {set minx $x} if {$x>$maxx} {set maxx $x} if {$y<$miny} {set miny $y} if {$y>$maxy} {set maxy $y} } $w create line $minx 0 $maxx 0 $w create line 0 $miny 0 $maxy set xfac [expr 0.95*[$w cget -width]/($maxx-$minx)] set yfac [expr 0.95*[$w cget -height]/($maxy-$miny)] $w scale all 0 0 $xfac -$yfac foreach {minxc minyc} [$w bbox all] break $w move all [expr -$minxc+5] [expr -$minyc+5] } proc funplot {argv} { set fun [lindex $argv 0] if {[winfo exists .c]} {destroy .c} pack [canvas .c] plotpoints .c [fun2points $fun] -fill red wm title . $fun } # i also had to exchange the usage # usage example: funplot sin There is something very weird also: x should run up to 4.0 in this example, but it runs only to 3.9 :-( ''Does anyone understand this, please?'' Yes - comparing doubles is [a real problem]. Since I just wanted to cover the range from -Pi to +Pi, I didn't look that hard, but you're right, and can isolate the problem to expr {3.9+.01>1.0} which returns 1. so a cleaner test condition would have been for ... {($x-$opt(-to))<0.00001} ... or another delta that bridges the gap between real and evident - [RS] ---- BLT is at http://www.tcltk.com/blt/ . See also emu-graph, padgraph at http://www.shlrc.mq.edu.au/~steve/tcl