Version 1 of 2d matrix command

Updated 2004-10-13 18:25:32

alove 13 Oct 2004 - What I'm presenting here is essentially a new TCL command that allows you to very easily create a two dimensional matrix and then ad or delete data from it.

Currently there is no elegant way to do this is TCL. You either have to create a list-within-a-list using lindex and lreplace/lrange, or else use a combination of arrays and lists, which is equally awkward. Just figuring out how to create a two dimensional matrix is quite a task!

It would be so much nicer if you could just define a matrix and then set or get variables, like so:

  defx mymatrix 1 50 1 50
  setx mymatrix 3 4 "wow!"
  set a [getx mymatrix 3 4]

So I created this code, which allows you to do just that:

 package require Tcl 8.4
 wm title . "Matrix"
 text .text -height 20 -width 50 -font arial -padx 10 -pady 10
 pack .text -expand yes -fill both

 proc defx {var a b c d} {
 global "$var"
 set ${var}(row1) $a
 set ${var}(row2) $b
 set ${var}(col1) $c
 set ${var}(col2) $d
 for {set x $c} {$x <= $d} {incr x} {lappend z 0}
 for {set x $a} {$x <= $b} {incr x} {set ${var}($x) $z}
 }

 proc setx {var a b value} {
 global "$var"
 set b1 [expr {$b - [set ${var}(col1)]}]
 set ${var}($a) [lreplace [set ${var}($a)] $b1 $b1 $value]
 } 

 proc getx {var a b} {
 global "$var"
 set b1 [expr {$b - [set ${var}(col1)]}]
 return [lrange [set ${var}($a)] $b1 $b1]
 } 

 proc delx {var a} {
 global "$var"
 set a1 [set ${var}(row2)] 
 for {set x $a} {$x < $a1} {incr x} {
 set x1 [expr {$x + 1}]
 set ${var}($x) [set ${var}($x1)]
 }
 set c [set ${var}(col1)]
 set d [set ${var}(col2)]
 for {set x $c} {$x <= $d} {incr x} {lappend z 0}
 set ${var}($a1) $z 
 }


 # test the matrix.  Ranges must be positive integers.
 set a 1;         set b 10;        set c 1;         set d 5
 defx wow $a $b $c $d
 setx wow 4 2 hello
 setx wow 5 3 big
 setx wow 6 4 world
 setx wow 10 5 poof
 delx wow 5

 .text insert end "Matrix wow (rows $a-$b cols $c-$d) \n\n"
 for {set x $a} {$x <= $b} {incr x} {
 for {set y $c} {$y <= $d} {incr y} {
 .text insert end "[getx wow $x $y] \t"
 }
 .text insert end "\n"
 }        

Essentially there are three procedures here, plus an optional fourth one called delx that allows you to delete rows, and have all the rows below adjusted, as if you had a list stack in a database.

This 2D matrix has a lot of uses: for 2D graphics in games, for databases, for plotting points in graphs, basically anything that requires two dimensions.

I think this would be a really useful new command if it were compiled into the TCL core for speed. As it is, it can be used for any matrix that doesn't require super speed. You just put the three (or four) procedures into your code and you've got these matrix commands available.

But please let me know what you think. Any comments are appreciated. alove 13 Oct 2004 -


[ Category Graphics

Category Animation ]