[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] ]]