Version 17 of A Graph plotter

Updated 2006-05-13 07:29:53

GWM Based on A Little graph Plotter. See also Fun with Functions, Another Graphing Widget.

Corrected May 2006 for missing proc.

Modified to draw a set of points or multiple sets of points on a canvas. The proc plot takes a list of data to be plotted and a set of titles (one per graph). The data format is: [list of xposition [list of ypositions (1,2 or more)]]] eg:

set res [0.0 {0.0 1.0} 0.333 {0.327 0.944 } 0.6667 {0.618 0.785}]

will define 3 points at x = 0, .333, .6667 with 2 y coordinates per x position (2 graphs). Better example data at the end of this page.

  package require math

  proc graphscale {v vmin vmax pixels} {
        return [expr {$pixels*($v-$vmin)/($vmax-$vmin)}]
  }

  proc plot {res titles} { ;# adapted the simple graph plotter found on http://wiki.tcl.tk/8552
  # --------------------------
  #   params
  # --------------------------
  # title
  # canvas width & height
  array set params \
  {
    title     {Graph}
    width     400
    height    400
   }

  # canvas
         if [winfo exists .c] { ;# delete it. Same as clear.
          destroy .c
        }
          canvas .c -width $params(width) -height $params(height) \
              -xscrollincrement 1 -bg beige
  pack .c

  wm title . $params(title)

 # get range of x & y
        set xmin 100000000
        set xmax -100000000
        set ymin 100000000
        set ymax -100000000
        set vv0 [lindex $res 1]
        set nvars [llength $vv0]
          foreach {r y} $res {
                set xmin [::math::min $xmin $r]
                set xmax [::math::max $xmax $r]
                  foreach yv $y { ;# get range of Y coordinate
                        set ymin [::math::min $ymin $yv]
                        set ymax [::math::max $ymax $yv]
                }
        }

 #how often tick marks
     set tspace [expr ($xmax-$xmin)/8.0] ;# how often to draw grid in X
     set nexttic [expr int($xmin/$tspace)*$tspace]
        foreach {r y} $res { ;# draw grid
                if {$r >= $nexttic} {
                        set xpix [graphscale $nexttic $xmin $xmax $params(width)]
                      set nexttic [expr $nexttic+$tspace]
                      .c create text [expr $xpix-10] 0 -anchor n -text $r -fill gray
                      .c create line $xpix 0 $xpix $params(height) -fill gray
                }
         }

 #how often Ytick marks
     set tspace [expr ($ymax-$ymin)/8.0] ;# how often to draw grid in X
     set nexttic [expr int($ymin/$tspace)*$tspace]
        while {$nexttic < $ymax} { ;# draw grid
                set ypix [graphscale $nexttic $ymax $ymin $params(height)]
                      set nexttic [expr $nexttic+$tspace]
                      .c create text 10 [expr $ypix-10] -anchor n -text $nexttic -fill gray
                      .c create line 0 $ypix $params(width) $ypix -fill gray
         }

 #label graphs
      .c create text 20 10 -anchor n -text [lindex $titles 0] -fill red
      .c create text 20 25 -anchor n -text [lindex $titles 1] -fill black

        for {set iy 0} {$iy<$nvars} {incr iy} {
        set color "black"
        if {$iy==1} {set color "red"}
        if {$iy==2} {set color "green"}
        set coordlist {}
        foreach {r y} $res {
                set xpix [graphscale $r $xmin $xmax $params(width)]
                set vv [lindex $y $iy]
                set v [graphscale $vv $ymax $ymin $params(height)]
                lappend coordlist $xpix $v
           set rold $xpix
           set yold $v         ;# vector of y values
         }
            .c create line $coordlist -fill $color
    }
    update
 }

 # Exercise the graph thus:
 set plot {}
 for {set i 0} {$i<20} {incr i} { lappend plot [expr $i/3.0] [expr sin($i/3.0)]}
 plot $plot "Sine"

 # Or 2 graphs (values of sin(x) and cos(x) are placed in a list of results at x):

 set plot {}
 for {set i 0} {$i<20} {incr i} { lappend plot [expr $i/3.0] [list [expr sin($i/3.0)] [expr cos($i/3.0)]]}
 plot $plot {"Sine" "Cos"}

DPO - In the plot proc above, there is a call to a "scale" command. This does not match the tk usage which requires a path as the first arg. What "scale" command is this? It fails for me. (I am forced to use tcl 8.0.5 due to API limitations)

GWM Sorry, a bit slow to respond here... supplied new function graphscale and renamed old proc scale to graphscale. This works a bit better.


Category Plotting