Version 3 of Viewer for functions of two variables

Updated 2003-05-22 06:29:28

Arjen Markus (20 May 2003) This is just another one of those little applications that may come in handy sometimes. Though it is not as flexible as it probably should be - no facilities for entering the expression in a GUI, no adjustment of the scaling nor of the viewpoint - still it can be a useful tool or the starting point of one.

http://mini.net/files/view3d.jpg (though the original is animated)

Suggestions welcome.


Marco Maggi Interesting. Will this always work? I mean: hidden lines will be hidden correctly for all the functions?


The code below contains several examples of functions that can be viewed.


 # view3d.tcl --
 #    Simple 3D viewer for functions of two independent variables
 #

 package require Tk

 # project2d --
 #    Project points in 3D space onto a 2D canvas
 # Arguments:
 #    xyzcrd    List of coordinate triplets
 # Result:
 #    List of xy-coordinates on the canvas
 # Note:
 #    Requires previous definition of viewpoint
 #
 proc project2d {xyzcrd} {
    variable project_params

    foreach {x1 y1 z1 x2 y2 z2} $project_params {break}
    foreach {x y z} $xyzcrd {
       set xc [expr {220.0+$x*$x1+$y*$y1+$z*$z1}]
       set yc [expr {320.0-($x*$x2+$y*$y2+$z*$z2)}]
       lappend result $xc $yc
    }
    return $result
 }

 # setViewpoint --
 #    Define the viewpoint
 # Arguments:
 #    xv     X-coordinate of viewpoint
 #    yv     Y-coordinate of viewpoint
 #    zv     Z-coordinate of viewpoint
 # Result:
 #    None
 # Side effect:
 #    Variable project_params filled
 #
 proc setViewpoint {xv yv zv} {
    variable project_params

    set x1 $yv
    set y1 [expr {-$xv}]
    set z1 0.0
    set x2 [expr {$xv*$zv}]
    set y2 [expr {$yv*$zv}]
    set z2 [expr {$xv*$xv+$yv*$yv}]

    set r  [expr {sqrt($x1*$x1+$y1*$y1+$z1*$z1)/200.0}]
    set x1 [expr {$x1/$r}]
    set y1 [expr {$y1/$r}]
    set z1 [expr {$z1/$r}]
    set r  [expr {sqrt($x2*$x2+$y2*$y2+$z2*$z2)/200.0}]
    set x2 [expr {$x2/$r}]
    set y2 [expr {$y2/$r}]
    set z2 [expr {$z2/$r}]

    set project_params [list $x1 $y1 $z1 $x2 $y2 $z2]
 }

 # drawFunction --
 #    Draw the function using a range of -1,1 for both x and y
 # Arguments:
 #    func     Expression taking x and y as arguments
 # Result:
 #    None
 # Note:
 #    Assumes a viewpoint from the right angle (i.e. xv < 0)
 #
 proc drawFunction {func} {

    set nostps 20
    set x10 -1.0
    set y10  0.0
    set dx1 [expr {2.0/$nostps}]
    set dy1  0.0
    set x20  0.0
    set y20 -1.0
    set dx2  0.0
    set dy2 [expr {2.0/$nostps}]

    for {set j 0} {$j < $nostps} {incr j} {
       for {set i 0} {$i < $nostps} {incr i} {
          set x1 [expr {$x10+$dx1*$i+$x20+$dx2*$j}]
          set y1 [expr {$y10+$dy1*$i+$y20+$dy2*$j}]
          set x2 [expr {$x1+$dx1}]
          set y2 [expr {$y1+$dy1}]
          set x3 [expr {$x2+$dx2}]
          set y3 [expr {$y2+$dy2}]
          set x4 [expr {$x3-$dx1}]
          set y4 [expr {$y3-$dy1}]

          set x $x1; set y $y1; set z1 [expr $func]
          set x $x2; set y $y2; set z2 [expr $func]
          set x $x3; set y $y3; set z3 [expr $func]
          set x $x4; set y $y4; set z4 [expr $func]

          set crds [project2d [list $x1 $y1 $z1 \
                                    $x2 $y2 $z2 \
                                    $x3 $y3 $z3 \
                                    $x4 $y4 $z4 ] ]
          .c create polygon $crds -fill white -outline black
       }
    }
 }

 # main --
 #    Main code:
 #    - Create the canvas
 #    - Set a viewpoint
 #    - Draw some function
 #

 canvas .c -background white -width 500 -height 500
 pack   .c -fill both

 set count 0

 proc draw {} {
    global count
    set zp [expr {3.0+2.0*sin(0.02*$count)}]
    incr count
    setViewpoint -3.0 -2.0 $zp
    .c delete all
    #drawFunction {(0.7-($x*$x+$y*$y))*(0.7-($x*$x+$y*$y))}
    #drawFunction {$x*(0.5-$x)*(0.5-($y*$y))}
    drawFunction {cos(3.0*$x)*cos(3.0*$y)}

    after 10 draw
 }

 after 0 draw

[ Category Mathematics

Category Graphics

]