#!/usr/bin/wish -f ## ## SCRIPT: draw_superformulaShape_colorFilled_withShadedBorder.tk ## ## ## PURPOSE: This Tk GUI script facilitates the creation of a color-filled ## 'super-formula shape' with shading to a background color, around ## the border of the shape. ## ## This script makes this shaded shape via a Tk image 'structure' ## placed on a Tk canvas widget. ## ## The image is put on the canvas via a Tk canvas 'image create' command ## --- and the image is generated via 'put -to $x $y' ## commands on the image. ## ## The rectangular image-structure covers the entire canvas widget. The ## superformula-shape lies within the canvas (and the image structure) ## with a margin around it. In the margin, outside the ## superformula-shape on the canvas, a user-selected 'background' color ## is applied. ## ######################### ## REFERENCES and CREDITS: ## ## This Tk script is PARTLY based on my Tk script at http://wiki.tcl.tk/36916 ## - 'GUI for Drawing 'Superformula' shapes, with choice of colors' --- ## which, in turn, was based on a Tk script at the web page ## called 'Superformula' at http://wiki.tcl.tk/12977 --- ## by Gerard Sookahet (GS) in 2004 November. On that page, GS points ## out that the equation for the 'super-formula' is: ## ## R(theta) = ( |cos(m*theta/4)/a| ^ n2 + |sin(m*theta/4)/b| ^ n3 ) ^ -1/n1 ## ## GS points out: ## "Superformula was proposed by Johan Gielis (a Belgian botanist) in 1997. ## He has modified and generalized the superellipse formula discovered by ## Gabriel Lamé in 1818 (a French mathematician). Superformula consists in ## a simple 2D analytical expression allowing to draw a wide variety of ## geometric and natural shapes (starfish, petals, snowflakes) by choosing ## suitable values relevant to few parameters." ## ## Those 2 previous scripts used canvas 'create polygon' commands to ## generate the superformula-shape --- NOT 'create image'. ## ## The canvas 'create image' (and 'put' commands) technique used in this ## script is based on two of my scripts that used this technique to ## make SHADED EDGES around 'super-ellipses' and around ## color-gradient-rectangles. ## ## See ## http://wiki.tcl.tk/37004 - ## GUI for Drawing 'Super-ellipses', with nice shaded edges ## and ## http://wiki.tcl.tk/ - ## GUI for Drawing Rectangular 'Buttons' with nice shaded edges ## ##+############################################ ## SOME NOTES ON THE 'SUPER-FORMULA' PARAMETERS: ## ## Note that 'm' generates protrusions/intrusions on the shape. ## As theta goes from 0 to 2*pi in the formula above, and if m=2, ## the angle m*theta/4 goes from 0 to pi --- one 'hump' of a sine ## or cosine curve. In general, if m = 2*n, then there will be ## (at least) n protrusions/intrusions. ## ## We will make the 'm' scale the first scale of several, since it ## fundamentally changes the shape. ## ## By some experimenting with the GUI, one finds ## that if 'a' and 'b' are kept equal ## and if 'n2' and 'n3' are kept equal, ## the shape will tend to be symmetric. ## This makes sense by looking at the formula above. ## ## We will make changing the 'a' scale make the 'b' scale change with it. ## We will make changing the 'n2' scale make the 'n3' scale change with it. ## Then the user can change the 'b' and 'n3' scales to make them ## different from the 'a' and 'n2' scales, resp. ## ## Note that the numerators of the 2 terms in absolute value marks (and ## raised to the exponents n2 and n3) are sin and cos which have a max ## value of 1. If n1 = n2 = n3 = 2 and a = b, for example, then the ## formula looks like ## R = ( |cos(...)/a| ^ 2 + |sin(...)/a| ^ 2 ) ^ -1/2 ## And the fundamental trigonometric identity ## cos(...) ^ 2 + sin (...) ^ 2 = 1 ## allows us to simplify this to ## R = (a ^ -2) ^ -1/2 = a ## So for R(theta) to be on the order of 200 (pixels), the denominators ## (a and b) will generally need to be on the order of 200 --- when ## n1 = n2 = n3 = 2 and a = b. ## ## Note that when n1 = 4 --- and n2 = n3 = 2 and a = b, then the ## last equation above becomes ## R = (a ^ -2) ^ -1/4 = a ^ 1/2 = sqrt( a ) ## So (when a & b > 1) the bigger n1 becomes, the smaller the radius becomes. ## And (when a & b < 1) the bigger n1 becomes, the larger the radius becomes ## (but it is less than 1). ## So n1 can be used to zoom in/out of the view of the image/shape. ## ## If we look at the 'resolution' and range of the scales and ## initial values in the Gerard Sookahet demo code, we see: ## Resolution From To Initial Value ## ---------- ---- ---- ------------- ## m - 0.2 0 34 6.0 ## n1 - 0.1 0.1 17 3.0 ## n2 - 0.1 0 17 1.0 ## n3 - 0.1 0 17 1.0 ## a - 0.01 0.1 10 1.0 ## b - 0.01 0.1 10 1.0 ## ## (We will change resolution of 'm' to 2.0 --- to avoid 'cusps' from ## appearing on the right of the shape, at theta = 0, as the m-scale ## sliderbar is moved. ## The shape should then remain smooth --- no partial humps with ## sharp-pointed 'drop-offs' --- as 'm' is changed.) ## ##+##################### ## THE SHADING TECHNIQUE (for the 3D effect): ## ## For detail on the shading technique applied to super-ellipses, ## see wiki.tcl.tk/37004 - ## GUI for Drawing 'Super-ellipses', with nice shaded edges. ## ## The edge-shading effect for the super-ellipse benefited from the equation ## for a super-ellipse --- more precisely, the equation for its edge: ## |x/a|^n + |y/b|^n = 1 ## ## The interior of the super-ellipse is given by the inequality ## |x/a|^n + |y/b|^n <= 1 ## ## The edge shading (3D effect) was obtained by using a 'metric' on the ## points x,y in the super-ellipse --- a value 'v', between 0 and 1, ## given by: ## v = |x/a|^n + |y/b|^n ## for each point inside the super-ellipse. ## ## The equation for v dictates that the value of v is 1 on the border of ## the super-ellipse and declines to 0 towards the center. ## ## (1.0 - $v) is applied to the user-selected 'unshaded' RGB-color for ## the super-ellipse --- and $v applied to the user-selected RGB ## background color. A weighted-average of these pairs of RGB values ## gives us the color at any x,y point in the superellipse. (Note that the ## values of x and y gave us the 'v' value to apply to get the 'shaded' ## color at x,y.) ## ## To keep the shading from being too spread out at the edge of ## the super-ellipse, we used a POWER of v rather than v. Note that ## a power of v, like v to the 12th, is still a floating point number ## between 0 and 1. ## ## NOW CONSIDER THE 'SUPER-FORMULA': ## To do the shading of our 'super-formula shape', it would be great ## if we had a 'metric' on the points x,y in our canvas that is 0.0 in ## the middle of the 'super-formula shape' and 1.0 on the boundary of ## the 'super-formula shape'. ## ## We can use the formula for R(theta) --- on the boundary of the ## 'super-formula shape' --- to give us such a metric. ## ## Let us say that x,y coordinates on the 'super-formula shape' outline ## --- and anywhere on the canvas --- are measured from the center of ## the canvas. ## ## The distance from the origin to the point x,y is given by the ## Pythagorean formula: r = sqrt( x^2 + y^2 ). ## ## Furthermore, our point x,y makes an angle 'theta', say with the ## x-axis. ## ## Then let us define our 'color-metric' to be ## ## v = r(x,y) / R(theta) ## ## where 'theta' is the angle whose sine is y/r --- and cosine is x/r. ## OR ... 'theta' can be determined from the ratio y/r and the quadrant ## in which the point x,y lies. ## ## Note that little-r is the distance to x,y. And big-R is the number ## given by the super-formula. ## ## Note that for a point x,y in the interior of the 'super-formula shape', ## the ratio r/R is less than one --- because the point x,y lies on ## a radial line from 0,0 to the boundary of the 'super-formula shape', ## and the distance to that boundary is R, which is greater than r. ## ## Furthermore, the metric is zero at the origin (x,y)=(0,0), because ## r = sqrt( 0^2 + 0^2) = 0. ## ## Furthermore, on the boundary of the 'super-formula shape', the values ## r and R are the same (because they define the same point) --- so the ## metric is equal to 1.0. ## ## And for x,y points outside the 'super-formula shape', v = r/R ## is greater than 1.0. ## ## So we have a suitable metric, v. ## ## At a point x,y, we determine the 'shaded color' at the point by ## using a color interpolated between the user-selected 'fill' color ## (color1) of the 'super-formula shape' and the user-selected ## background color (color2). ## ## We calculate the 'shaded color' at x,y by calulating a weighted average ## based on applying the factor (1.0 - $v) to color1 --- and applying $v ## to color2. That is, shaded-color = (1 - v) * color1 + v * color2. ## ## We actually calculate via formulas like ## shaded-R = (1 - v) * R1 + v * R2 ## shaded-G = (1 - v) * G1 + v * G2 ## shaded-B = (1 - v) * B1 + v * B2 ## ## Thus we will get the edge-shading (the 3D effect) for the ## 'super-formula shape'. ## ## Actually, it turns out that 1-v/v gives a rather washed-out (too ## gradual) shading effect. It is better if we raise v to a power N ## and use v^N and (1 - v^N). It turns out that N = 12 gives pretty nice ## shading, but rather than hard-code the value of N, we provide a ## scale widget on the GUI so that the user can set the value of N. ## ##+############## ## THE GUI DESIGN: ## ## The GUI made by this Tk script contains a rectangular ## canvas widget on which the color-filled superformula shape ## will be drawn. ## ## The GUI includes 6 'scale' widgets whose slider-bars can ## be used to change the values of m, n1, n2, n3, a, and b. ## ## The GUI also includes a button to call a color selector GUI ## to set the 'fill' color of the super-formula shape. ## ## Another button calls the same color selector GUI to set a ## background color --- which is also the color we gradiate ## toward at the boundary of the 'super-formula shape'. ## ## (Note that we could put another color selector button on the ## GUI to select the border color to be a different color from ## the background color of the canvas area.) ## ## A redraw includes clearing the canvas and redrawing the ## super-formula shape. ## ## A redraw should be done (a) whenever any of the 6 scales change, ## (b) whenever a color button is used to change a color, and ## (c) whenever the window (and thus the canvas) is resized --- ## so that the image/shape will be redrawn in the center of ## the canvas. ## ## PERFORMANCE CONSIDERATIONS: ## Since the redraw has a lot of pixels to color, especially when ## the canvas is expanded to a pretty large size, a redraw may ## take several seconds. ## ## So it is probably not going to be feasible/pleasing to do redraws ## 'dynamically' with the '-command' option of the 'scale' widgets. ## ## For now, I have defined a button1-release binding on each of ## the scale widgets to trigger a redraw --- only when the user ## finishes dragging the sliderbar of any scale. ## ## However, it should be pointed out that if erasing the ## canvas and calculating-colors and putting the colors in the ## super-formula shape completes within a small fraction of a second, ## would be feasible to do the redraws 'dynamically' with each ## sliderbar, via the '-command' option. (But it might heat up ## the CPU doing those operations --- by quite a few degrees.) ## ############################ ## USING THE GENERATED IMAGE: ## A screen/window capture utility (like 'gnome-screenshot' ## on Linux) can be used to capture the GUI image in a GIF ## or PNG file, say. ## ## If necessary, an image editor (like 'mtpaint' on Linux) ## can be used to crop the window capture image. The image ## could also be down-sized --- say to make a 'bullet' image ## file or an icon-background image file. ## ## The colored image file could be used with a utility (like the ## ImageMagick 'convert' command) to change the outer, background ## color to TRANSPARENT, making a partially transparent GIF ## (or PNG) file. Then the semi-transparent image file could be used, ## for 'bullets' in HTML pages or in Tk GUI's --- or for the ## background of icons or buttons for use in GUIs. ## ## The image could also be taken into a scalable vector graphics ## (SVG) editor (like Inkscape on Linux) and the SVG editor used ## to add anti-aliased text to the image. OR, the shape can be ## used as an underlying pattern to reproduce the shape as a ## scalable shape, by using curve drawing tools of the SVG editor. ## ##+######################################################################## ## 'CANONICAL' STRUCTURE OF THIS TK CODE: ## ## 0) Set general window & widget parms (win-name, win-position, ## win-color-scheme, fonts, widget-geometry-parms, win-size-control). ## ## 1a) Define ALL frames (and sub-frames, if any). ## 1b) Pack ALL frames and sub-frames. ## ## 2) Define all widgets in the frames. Pack them. ## ## 3) Define keyboard or mouse/touchpad/touch-sensitive-screen action ## BINDINGS, if needed. ## ## 4) Define PROCS, if needed. ## ## 5) Additional GUI INITIALIZATION (typically with one or two of ## the procs), if needed. ## ## ## Some detail about the code structure of this particular script: ## ## 1a) Define ALL frames: ## ## Top-level : '.fRleft' , '.fRright' ## ## Sub-frames: '.fRleft.fRbuttons' ## '.fRleft.fRscaleM' ## '.fRleft.fRscaleN1' ## '.fRleft.fRscaleN2' ## '.fRleft.fRscaleN3' ## '.fRleft.fRscaleA' ## '.fRleft.fRscaleB' ## '.fRleft.fRscaleN' ## '.fRleft.fRinfo' ## ## The canvas widget will go in '.fRright'. ## ## 1b) Pack ALL frames. ## ## 2) Define all widgets in the frames (and pack them): ## ## - In '.fRleft.fRbuttons': ## 1 button widget ('Exit'), (perhaps 'Help' someday) ## and ## 2 buttons (for setting the super-formula shape's ## fill & the background/canvas color), ## and ## 1 label widget to display the current color ## values (in hex). ## ## - In '.fRleft.fRscaleX': ## 1 'label' and 1 'scale' widget, in each scale-frame ## for superformula shape parameters --- ## m, n1, n2, n3, a, b --- and N ## (where N is an exponent used to control the ## extent of the edge-shading.) ## ## - In '.fRleft.fRinfo': ## 1 label widget to show some 'how-to' usage info. ## 1 label widget to show the superformula --- and ## current super-formula parameter values. ## ## - In '.fRright': 1 'canvas' widget ## ## 3) Define bindings: ## ## - a button1-release on each of the 7 scale widgets causes a redraw ## ## NOTE3: The color changes should trigger a redraw, but we do not ## need bindings to do those redraws. ## The redraws can be done in procs that are used to ## set each of the colors. ## ## 4) Define procs: ## ## - 'ReDraw' - to clear the canvas and redraw the pixels ## in the image rectangle that contains the ## super-formula shape ## --- for the current values of the 7 scale ## parameters and the fill & background colors. ## ## - set_scale_n3_to_n2_redraw - to move n3 slider with n2 slider ## ## - set_scale_b_to_a_redraw - to move b slider with a slider ## ## - 'set_shape_color1' - shows a color selector GUI and uses the ## user-selected color to 'fill' the ## super-formula shape on the canvas ## ## - 'set_color_background' - shows a color selector GUI and uses the ## user-selected color to reset the color of ## the canvas background ## ## - 'ReDraw_if_canvas_resized' - to do a redraw when a ## event is detected on the canvas --- ## but only if the canvas has been resized. ## ## 5) Additional GUI initialization: Execute proc 'ReDraw' once with ## an initial, example set of parms ## --- 7 acale vars, COLOR1hex, ## COLORbkGNDhex --- ## to start with a super-formula shape on ## the canvas rather than a blank canvas. ## ## Also in this section, we define a binding for ## - a (resize) event on the canvas --- to cause a redraw. ##+######################################################################## ## DEVELOPED WITH: ## Tcl-Tk 8.5 on Ubuntu 9.10 (2009-october release, 'Karmic Koala'). ## ## $ wish ## % puts "$tcl_version $tk_version" ## showed 8.5 8.5 on Ubuntu 9.10 ## after Tcl-Tk 8.4 was replaced by 8.5 --- to get anti-aliased fonts. ##+####################################################################### ## MAINTENANCE HISTORY: ## Created by: Blaise Montandon 2012oct18 ## Changed by: ...... ......... 2012 ##+####################################################################### ##+####################################################################### ## Set general window parms (win-title,win-position). ##+####################################################################### wm title . "Edge-shaded 'Super-formula' shape, on a single-color canvas" wm iconname . "Superformula" wm geometry . +15+30 ##+###################################################### ## Set the color scheme for the window and its widgets --- ## and set the initial color for the SF-shape interior ## and the canvas background (outside the SF-shape). ##+###################################################### tk_setPalette "#e0e0e0" ## Initialize the super-formula shape 'fill' color. # set COLOR1r 255 # set COLOR1g 255 # set COLOR1b 255 set COLOR1r 255 set COLOR1g 0 set COLOR1b 255 set COLOR1hex [format "#%02X%02X%02X" $COLOR1r $COLOR1g $COLOR1b] ## Initialize the super-formula shape 'boundary' color ## to gradiate to, from the 'fill' color. ## NOT USED. ## We use the background color as the color to gradiate to. # # set COLOR2r 255 # # set COLOR2g 255 # # set COLOR2b 0 # # set COLOR2r 0 # set COLOR2g 255 # set COLOR2b 255 # set COLOR2hex [format "#%02X%02X%02X" $COLOR2r $COLOR2g $COLOR2b] ## Initialize the background color for the canvas. # set COLORbkGNDr 60 # set COLORbkGNDg 60 # set COLORbkGNDb 60 set COLORbkGNDr 0 set COLORbkGNDg 0 set COLORbkGNDb 0 set COLORbkGNDhex \ [format "#%02X%02X%02X" $COLORbkGNDr $COLORbkGNDg $COLORbkGNDb] # set listboxBKGD "#f0f0f0" # set entryBKGD "#f0f0f0" ##+######################################################## ## Use a VARIABLE-WIDTH FONT for label and button widgets. ## ## Use a FIXED-WIDTH FONT for listboxes (and ## entry fields, if any). ##+######################################################## font create fontTEMP_varwidth \ -family {comic sans ms} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_varwidth \ -family {comic sans ms} \ -size -12 \ -weight bold \ -slant roman ## Some other possible (similar) variable width fonts: ## Arial ## Bitstream Vera Sans ## DejaVu Sans ## Droid Sans ## FreeSans ## Liberation Sans ## Nimbus Sans L ## Trebuchet MS ## Verdana font create fontTEMP_fixedwidth \ -family {liberation mono} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_fixedwidth \ -family {liberation mono} \ -size -12 \ -weight bold \ -slant roman ## Some other possible fixed width fonts (esp. on Linux): ## Andale Mono ## Bitstream Vera Sans Mono ## Courier 10 Pitch ## DejaVu Sans Mono ## Droid Sans Mono ## FreeMono ## Nimbus Mono L ## TlwgMono ##+########################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. width and height of canvas, and padding for Buttons) ##+########################################################### set initCanWidthPx 400 set initCanHeightPx 300 set minCanHeightPx 24 # set BDwidthPx_canvas 2 set BDwidthPx_canvas 0 ## BUTTON geom parameters: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 ## LABEL geom parameters: set BDwidthPx_label 2 ## SCALE geom parameters: set BDwidthPx_scale 2 set initScaleLengthPx 300 set scaleWidthPx 10 ##+################################################################### ## Set a MINSIZE of the window. ## ## For width, allow for the minwidth of the '.fRbuttons' frame: ## about 3 buttons (Exit,Color1,ColorBkgnd). ## We want to at least be able to see the Exit button. ## ## For height, allow ## 2 chars high for the '.fRbuttons' frame, ## 200 pixels high for the '.fRscales' frame, and ## 3 chars high for the label widget in the '.fRinfo' frame. ##+################################################################### set minWinWidthPx [font measure fontTEMP_varwidth \ "Exit Fill Background"] ## Add some pixels to account for right-left-side window decoration ## (about 8 pixels), about 3 x 4 pixels/widget for borders/padding for ## 6 widgets --- 3 buttons. set minWinWidthPx [expr 20 + $minWinWidthPx] ## MIN HEIGHT --- ## for the 9 sub-frames '.fRleft.fRbuttons', 7 '.fRleft.fRscaleX', ## and '.fRleft.fRinfo'. ## Allow ## 2 char high for 'fRbuttons' ## 2 char high for each of the 7 scale frames ## 6 char high for 'fRinfo' set CharHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr 10 * $CharHeightPx] ## Add about 28 pixels for top-bottom window decoration, ## about 9x4 pixels for each of the 9 stacked frames and their ## widgets (their borders/padding). set minWinHeightPx [expr $minWinHeightPx + 64] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## We allow the window to be resizable and we pack the canvas with ## '-fill both -expand 1' so that the canvas can be enlarged by enlarging ## the window. ## If you want to make the window un-resizable, ## you can use the following statement. # wm resizable . 0 0 ##+################################################################ ## DEFINE *ALL* THE FRAMES: ## ## Top-level : '.fRleft' '.fRright' ## ## Sub-frames: '.fRleft.fRbuttons' ## '.fRleft.fRscaleM' ## '.fRleft.fRscaleN1' ## '.fRleft.fRscaleN2' ## '.fRleft.fRscaleN3' ## '.fRleft.fRscaleA' ## '.fRleft.fRscaleB' ## '.fRleft.fRscaleN' ## '.fRleft.fRinfo' ##+################################################################ # set BDwidth_frame 2 # set RELIEF_frame raised set BDwidth_frame 0 set RELIEF_frame flat frame .fRleft -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRright -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRbuttons -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleM -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleN1 -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleN2 -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleN3 -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleA -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleB -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRscaleN -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRleft.fRinfo -relief $RELIEF_frame -borderwidth $BDwidth_frame ##+############################## ## PACK the top-level FRAMES. ##+############################## pack .fRleft \ -side left \ -anchor nw \ -fill x \ -expand 0 pack .fRright \ -side left \ -anchor nw \ -fill both \ -expand 1 ##+############################## ## PACK the sub-FRAMES. ##+############################## pack .fRleft.fRbuttons \ .fRleft.fRscaleM \ .fRleft.fRscaleN1 \ .fRleft.fRscaleN2 \ .fRleft.fRscaleN3 \ .fRleft.fRscaleA \ .fRleft.fRscaleB \ .fRleft.fRscaleN \ .fRleft.fRinfo \ -side top \ -anchor nw \ -fill x \ -expand 0 ##+######################################################### ## OK. Now we are ready to define the widgets in the frames. ##+######################################################### ##+##################################################################### ## In the '.fRleft.fRbuttons' FRAME --- DEFINE-and-PACK ## - an exit-button, ## and ## - 2 buttons ( to specify colors) ## and ## - a label widget, to show current color values (in hex) ## --- and if there is room, show the current ## values of the 6 scale parameters ##+##################################################################### button .fRleft.fRbuttons.buttEXIT \ -text "Exit" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} ## Add this button someday? # button .fRleft.fRbuttons.buttHELP \ # -text "Help" \ # -font fontTEMP_varwidth \ # -padx $PADXpx_button \ # -pady $PADYpx_button \ # -relief raised \ # -bd $BDwidthPx_button \ # -command {help} button .fRleft.fRbuttons.buttCOLOR1 \ -text "\ Fill Color" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command "set_shape_color1" ## Not used. Someday? # button .fRleft.fRbuttons.buttCOLOR2 \ # -text "\ # Edge-gradient # Color" \ # -font fontTEMP_varwidth \ # -padx $PADXpx_button \ # -pady $PADYpx_button \ # -relief raised \ # -bd $BDwidthPx_button \ # -command "set_shape_color2" button .fRleft.fRbuttons.buttCOLORbkGND \ -text "\ Background Color" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command "set_background_color" ## The text for labelCOLORS is set in the ReDraw proc. ## It is done there to make sure that the colors used for ## the current drawing are displayed correctly. label .fRleft.fRbuttons.labelCOLORS \ -text "" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_button ##+########################################### ## Pack the widgets in the 'fRbuttons' frame. ##+########################################### pack .fRleft.fRbuttons.buttEXIT \ .fRleft.fRbuttons.buttCOLOR1 \ .fRleft.fRbuttons.buttCOLORbkGND \ .fRleft.fRbuttons.labelCOLORS \ -side left \ -anchor w \ -fill none \ -expand 0 # .fRleft.fRbuttons.buttHELP \ # .fRleft.fRbuttons.buttCOLOR2 \ ##+################################################################## ## In the '.fRleft.fRscaleM' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleM.label \ -text "m" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set m 12 scale .fRleft.fRscaleM.scaleM \ -from 0 -to 34 \ -resolution 2 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable m \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleM.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleM.scaleM \ -side left \ -anchor w \ -fill x \ -expand 1 ##+################################################################## ## In the '.fRleft.fRscaleN1' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleN1.label \ -text "n1" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set n1 6.0 scale .fRleft.fRscaleN1.scaleN1 \ -from 0.1 -to 17 \ -resolution 0.1 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable n1 \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleN1.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleN1.scaleN1 \ -side left \ -anchor w \ -fill x \ -expand 1 ##+################################################################## ## In the '.fRleft.fRscaleN2' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleN2.label \ -text "n2" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set n2 6.0 scale .fRleft.fRscaleN2.scaleN2 \ -from 0 -to 17 \ -resolution 0.1 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable n2 \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleN2.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleN2.scaleN2 \ -side left \ -anchor w \ -fill x \ -expand 1 ##+################################################################## ## In the '.fRleft.fRscaleN3' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleN3.label \ -text "n3" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set n3 6.0 scale .fRleft.fRscaleN3.scaleN3 \ -from 0 -to 17 \ -resolution 0.1 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable n3 \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleN3.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleN3.scaleN3 \ -side left \ -anchor w \ -fill x \ -expand 1 ##+################################################################## ## In the '.fRleft.fRscaleA' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleA.label \ -text "a" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set a 100.0 scale .fRleft.fRscaleA.scaleA \ -from 0.1 -to 1000 \ -resolution 0.1 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable a \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleA.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleA.scaleA \ -side left \ -anchor w \ -fill x \ -expand 1 ##+################################################################## ## In the '.fRleft.fRscaleB' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleB.label \ -text "b" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set b 100.0 scale .fRleft.fRscaleB.scaleB \ -from 0.1 -to 1000 \ -resolution 0.1 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable b \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleB.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleB.scaleB \ -side left \ -anchor w \ -fill x \ -expand 1 ##+################################################################## ## In the '.fRleft.fRscaleN' FRAME ---- DEFINE-and-PACK ## 1 LABEL and 1 SCALE widget. ##+################################################################### label .fRleft.fRscaleN.label \ -text "N" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set N 12 scale .fRleft.fRscaleN.scaleN \ -from 1 -to 30 \ -resolution 1 \ -length $initScaleLengthPx \ -font fontTEMP_SMALL_varwidth \ -variable N \ -showvalue true \ -orient hor \ -bd $BDwidthPx_scale \ -width $scaleWidthPx # -command "ReDraw" pack .fRleft.fRscaleN.label \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRleft.fRscaleN.scaleN \ -side left \ -anchor w \ -fill x \ -expand 1 ##+###################################################### ## DEFINE-and-PACK a 'label' widget ## in the '.fRleft.fRinfo' FRAME ##+###################################################### label .fRleft.fRinfo.labelFORMULA \ -text "\ Click on the top four troughs to step through changes. Drag the slider of the bottom 3 scales to see significant change. Super-formula: R(theta) = ( |cos(m x theta/4) / a| ^ n2 + |sin(m x theta/4) / b| ^ n3 ) ^ -1/n1 and the x,y coordinates on the super-formula shape curve are given by R x cos(theta) & R x sin(theta). N is an exponent; controls extent of shading." \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_button label .fRleft.fRinfo.labelPROCESSING \ -text "" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_button ## The text for labelPROCESSING is set in the ReDraw proc. ## It is used to indicate when calculations are in progress, ## as well as to show the draw-time (elapsed) when ## calculation and redrawing is done. pack .fRleft.fRinfo.labelFORMULA \ .fRleft.fRinfo.labelPROCESSING \ -side top \ -anchor nw \ -fill x \ -expand 0 ##+###################################################### ## DEFINE-and-PACK the 'canvas' widget ## in the '.fRright' FRAME ##+###################################################### ## We set highlightthickness & borderwidth of the canvas to ## zero, as suggested on page 558, Chapter 37, 'The Canvas ## Widget', in the 4th edition of the book 'Practical ## Programming in Tcl and Tk'. ##+###################################################### canvas .fRright.can \ -width $initCanWidthPx \ -height $initCanHeightPx \ -relief flat \ -highlightthickness 0 \ -borderwidth 0 pack .fRright.can \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+######################################## ## END OF the DEFINITION OF THE GUI WIDGETS ##+######################################## ##+############################### ## BINDINGS SECTION: ##+############################### ## The following bind causes an extra ReDraw ## when the GUI is first configured via an 'update' below ## in the GUI initialization section. ## (And 'update' causes about 40 redraws if ## we use '.' instead of '.fRright.can'.) ## We move this statement to the bottom of this script. # bind .fRright.can "ReDraw 0" bind .fRleft.fRscaleM.scaleM "ReDraw 0" bind .fRleft.fRscaleN1.scaleN1 "ReDraw 0" bind .fRleft.fRscaleN2.scaleN2 "set_scale_n3_to_n2_redraw 0" bind .fRleft.fRscaleN3.scaleN3 "ReDraw 0" bind .fRleft.fRscaleA.scaleA "set_scale_b_to_a_redraw 0" bind .fRleft.fRscaleB.scaleB "ReDraw 0" bind .fRleft.fRscaleN.scaleN "ReDraw 0" ##+###################################################################### ## PROCS SECTION: ## ## - ReDraw - Called by button1-release bindings on the ## 7 scale widgets, by the set-color procs, ## and in the GUI initialization section at the ## bottom of this script. ## ## Draws the super-formula shape on the canvas for ## the current scale parameter values and for the ## current color var values. ## ## - set_scale_n3_to_n2_redraw - called by a button1-release binding for scale-n3 ## ## - set_scale_b_to_a_redraw - called by a button1-release binding for scale-b ## ## - set_shape_color1 - called by color1 (fill) button '-command' ## ## - set_shape_color2 - called by color2 (outline) button '-command' ## (NOT USED, yet) ## ## - set_background_color - called by background color button '-command' ## ## - ReDraw_if_canvas_resized - called by 'bind' to canvas ## ##+####################################################################### ##+##################################################################### ## proc ReDraw - ## ## PURPOSE: ## Draws the super-formula shape on the canvas. ## ## Because we cannot count on any symmetry in the 'super-formula ## shape', this proc does NOT the draw a horizontal scan-line at a time, ## with calls like: ## imgID put $hexcolorsLIST -to 0 $y ## where 0 $y is the leftmost position of a horizontal line of ## hexcolors for the pixels. ## ## Instead, we 'poke' a hex-color value into each pixel with calls ## like: ## imgID put $hexcolor -to $x $y ## ## CALLED BY: bindings (in the BINDINGS section) --- and by set-color procs ## --- and by the GUI initialization section at the bottom of ## this script. ## ## NOTE: The 'x' argument is to avoid an error when the scale '-command' ## passes a scale value as an argument to the command. This is in ## case we try using the '-command' option of the scale widgets to ## do the redraws 'dynamically' as a sliderbar is moved. ##+##################################################################### ## For reference in the math statements below, the 'superformula' is: ## r(theta) = ## ( |cos(m*theta/4)/a| ^ n2 + |sin(m*theta/4)/b| ^ n3 ) ^ -1/n1 ##+##################################################################### ## Set the value of pi and 2-times-pi JUST ONCE. set pi [expr {4.0 * atan(1.0)}] set twopi [expr {2 * $pi}] proc ReDraw {x} { global m n1 n2 n3 a b N \ pi twopi \ COLOR1r COLOR1g COLOR1b COLOR1hex \ COLORbkGNDr COLORbkGNDg COLORbkGNDb COLORbkGNDhex ## COLOR2r COLOR2g COLOR2b COLOR2hex \ set denomTOL 0.00001 ## Set the current time, for determining elapsed ## time for building the 'photo' image. set t0 [clock milliseconds] ## Indicate that drawing calculations are starting. .fRleft.fRbuttons.labelCOLORS configure -text "\ Current Colors: Fill - $COLOR1hex Background - $COLORbkGNDhex ** CALCULATIONS IN PROGRESS **" ## We could put the PROCESSING info at the bottom of the GUI, ## but that is a little too out-of-sight. # .fRleft.fRinfo.labelPROCESSING configure -text "\ # ** CALCULATIONS IN PROGRESS **" ## This 'update' makes sure that this label update is displayed. update ## Change the title of the window to show calculations are in process. ## (This shows how we could put a msg in the window title bar, ## instead of in a label in the GUI.) # wm title . \ # "** DRAWING CALCULATIONS ARE IN PROGRESS ** Please wait." ## Delete the current image structure. ## We especially need to do this when the canvas has been re-sized, ## so that we can redraw the image according to the new canvas size. (?) catch {image delete imgID} ## Get the current canvas size. set curCanWidthPx [winfo width .fRright.can] set curCanHeightPx [winfo height .fRright.can] ## Initialize the width & height of the image that we are going to create ## --- to the size of the canvas --- ## and let us make each dimension of the image an even integer (pixels). set imgWidthPx $curCanWidthPx set imgHeightPx $curCanHeightPx if {$imgWidthPx % 2 == 1} { incr imgWidthPx -1 } if {$imgHeightPx % 2 == 1} { incr imgHeightPx -1 } ## Make the new image structure. image create photo imgID -width $imgWidthPx -height $imgHeightPx ## Put the new image 'structure' on the canvas. ## (Note to myself: Should this statement be at top or bottom of this proc? ## Does this mainly matter the first time the canvas is used?) .fRright.can create image 0 0 -anchor nw -image imgID ## Get the half width and height of the image rectangle --- with which ## which is the same as the pixel-coordinates of the origin. set xmidPx [expr {$imgWidthPx / 2}] set ymidPx [expr {$imgHeightPx / 2}] ######################################################################### ## HERE IS THE 'GUTS': ## In a loop over yPx and xPx, where yPx and xPx are measured from the ## top left of the canvas/image rectangle, we calculate the hex-color ## for each pixel, from x = xPx - xmidPx and y = yPx - ymidPx, ## according to our 'color-metric': ## ## v = r(x,y) / R(theta) ## ## where r(x,y) = sqrt( x^2 + y^2 ) ## and ## where 'theta' is the angle whose cosine is x/r --- and sine is y/r. ## OR ... 'theta' can be determined from the ratio y/r and the quadrant ## in which the point x,y lies. ## ## R(theta) is given by ## ( |cos(m*theta/4)/a| ^ n2 + |sin(m*theta/4)/b| ^ n3 ) ^ -1/n1 ## ## For each x,y, we calculate each theta between 0 and 2*pi radians. ####################################################################### for {set yPx 0} {$yPx < $imgHeightPx} {incr yPx} { for {set xPx 0} {$xPx < $imgWidthPx} {incr xPx} { set x [expr {$xPx - $xmidPx}] set y [expr {$yPx - $ymidPx}] set r [expr {sqrt( ($x * $x) + ($y * $y) )}] ## Determine 'theta'. ## ## First, we disregard the sign of $y and get theta ## as if x,y were in the first quadrant. ## So theta should be between 0 and pi/2. ## ## Ideally, we could simply use ## set theta [expr {asin( abs($y) / $r )}] ## but we need to handle the case when $r is zero or very near. AND ## we do some checking to try to make sure asin does not throw an error ## say do to some precision errors in computing $yratio.) if { $r < $denomTOL } { set yratio 0.0 } else { set yratio [expr {abs($y) / $r}] } if {$yratio > 1.0} {set yratio 1.0} set theta [expr {asin( $yratio )}] ## Adjust theta if x,y is in the 2nd quadrant. if { $x < 0.0 && $y >= 0.0 } { set theta [expr {$pi - $theta}] } ## Adjust theta if x,y is in the 3rd quadrant. if { $x <= 0.0 && $y < 0.0 } { set theta [expr {$pi + $theta}] } ## Adjust theta if x,y is in the 4th quadrant. if { $x > 0.0 && $y < 0.0 } { set theta [expr {$twopi - $theta}] } ## FOR TESTING: # if { $x == 20 && $y == 100 } { # puts "ReDraw > x: $x y: $y r: $r theta: $theta" # } ## For this 'theta', calculate R --- piece by piece. Recall: ## ( |cos(m*theta/4)/a| ^ n2 + |sin(m*theta/4)/b| ^ n3 ) ^ -1/n1 set t [expr {$m*$theta/4.0}] set term1 [expr {abs(cos($t)/$a)}] set term1 [expr {pow($term1,$n2)}] set term2 [expr {abs(sin($t)/$b)}] set term2 [expr {pow($term2,$n3)}] set R [expr {pow($term1+$term2,1.0/$n1)}] ## This statement essentially applies the ## minus sign of the exponent -1/n1. set R [expr {1.0/$R}] ## FOR TESTING: # if { $x == 20 && $y == 100 } { # puts "ReDraw > x: $x y: $y R: $R t: $t" # puts " m: $m n1: $n1 n2: $n2 n3: $n3 a: $a b: $b" # puts " term1: $term1 term2: $term2" # } ## Calculate our 'color-metric': v = r / R. set v [ expr {$r / $R}] ## According to the value of v, set the pixel color that we will ## put at $xPx, $yPx. ## ## If v > 1.0, the point x,y is outside the 'super-formula shape', ## so we set the pixel to the background color. ## ## The shading at the edges falls off too slowly if we use ## v or even v to the 4th. The power 12 gives good shading. if {$v > 1.0} { imgID put $COLORbkGNDhex -to $xPx $yPx } else { ## We should be inside or on the 'super-formula shape'. set vpow [expr {pow($v,$N)}] set oneMinusVpow [expr {1.0 - $vpow}] set R [expr {int(($vpow * $COLORbkGNDr) + ($oneMinusVpow * $COLOR1r))}] set G [expr {int(($vpow * $COLORbkGNDg) + ($oneMinusVpow * $COLOR1g))}] set B [expr {int(($vpow * $COLORbkGNDb) + ($oneMinusVpow * $COLOR1b))}] if {$R > 255} {set R 255} if {$G > 255} {set G 255} if {$B > 255} {set B 255} if {$R < 0} {set R 0} if {$G < 0} {set G 0} if {$B < 0} {set B 0} set hexcolor [format "#%02X%02X%02X" $R $G $B] ## Put the color at $xPx $yPx. imgID put $hexcolor -to $xPx $yPx } ## END OF if {$v > 1.0} } ## END OF for {set xPx 0} {$xPx < $imgWidthPx} {incr xPx} } ## END OF for {set yPx 0} {$yPx < $imgHeightPx} {incr yPx} ## Make sure the text on the COLORS and PROCESSING label widgets ## is up to date. .fRleft.fRbuttons.labelCOLORS configure -text "\ Current Colors: Fill - $COLOR1hex Background - $COLORbkGNDhex DRAW TIME: [expr {[clock milliseconds] - $t0}] millisecs elapsed" update ## We could put the PROCESSING info at the bottom of the GUI, ## but that is a little too out-of-sight. # .fRleft.fRinfo.labelPROCESSING configure -text "\ # DRAW TIME: [expr {[clock milliseconds] - $t0}] millisecs elapsed" ## We do not need to show the following. The user should be able to ## see the current parm values above each scale widget. ## # Current super-formula shape parameters: # m = $m ; n1 = $n1 ; n2 = $n2 ; n3 = $n3 ; a = $a ; b = $b ## Change the title of the window to show execution time. ## (This shows how we could put a msg in the window title bar, ## instead of in a label in the GUI.) # wm title . \ # "Redraw DONE. [expr {[clock milliseconds] - $t0}] millisecs elapsed." } ## END OF proc 'ReDraw' ##+########################################## ## proc set_scale_n3_to_n2_redraw ##+########################################## proc set_scale_n3_to_n2_redraw {x} { global n2 n3 set n3 $n2 ReDraw 0 } ## END OF proc 'set_scale_n3_to_n2_redraw' ##+########################################## ## proc set_scale_b_to_a_redraw ##+########################################## proc set_scale_b_to_a_redraw {x} { global a b set b $a ReDraw 0 } ## END OF proc 'set_scale_b_to_a_redraw' ##+##################################################################### ## proc 'set_shape_color1' ##+##################################################################### ## PURPOSE: ## ## This procedure is invoked to get an RGB triplet ## via 3 RGB slider bars on the FE Color Selector GUI. ## ## Uses that RGB value to set a 'fill' color. ## ## Arguments: none ## ## CALLED BY: .fRleft.fRbuttons.buttCOLOR1 button ##+##################################################################### proc set_shape_color1 {} { global COLOR1r COLOR1g COLOR1b COLOR1hex # global feDIR_tkguis ## FOR TESTING: # puts "COLOR1r: $COLOR1r" # puts "COLOR1g: $COLOR1g" # puts "COLOR1b: $COLOR1b" set TEMPrgb [ exec \ ./sho_colorvals_via_sliders3rgb.tk \ $COLOR1r $COLOR1g $COLOR1b] # $feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk \ ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLOR1hex "#$hexRGB" set COLOR1r $r255 set COLOR1g $g255 set COLOR1b $b255 ## Redraw the geometry in the new interior color. ReDraw 0 } ## END OF proc 'set_shape_color1' ##+##################################################################### ## proc 'set_shape_color2' (NOT USED, yet) ##+##################################################################### ## PURPOSE: ## ## This procedure is invoked to get an RGB triplet ## via 3 RGB slider bars on the FE Color Selector GUI. ## ## Uses that RGB value to set an 'edge' color. ## ## Arguments: none ## ## CALLED BY: .fRleft.fRbuttons.buttCOLOR2 button ##+##################################################################### proc set_shape_color2 {} { global COLOR2r COLOR2g COLOR2b COLOR2hex # global feDIR_tkguis ## FOR TESTING: # puts "COLOR2r: $COLOR2r" # puts "COLOR2g: $COLOR2g" # puts "COLOR2b: $COLOR2b" set TEMPrgb [ exec \ ./sho_colorvals_via_sliders3rgb.tk \ $COLOR2r $COLOR2g $COLOR2b] # $feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk \ ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLOR2hex "#$hexRGB" set COLOR2r $r255 set COLOR2g $g255 set COLOR2b $b255 ## Redraw the geometry in the new edge color. ReDraw 0 } ## END OF proc 'set_shape_color2' ##+##################################################################### ## proc 'set_background_color' ##+##################################################################### ## PURPOSE: ## ## This procedure is invoked to get an RGB triplet ## via 3 RGB slider bars on the FE Color Selector GUI. ## ## Uses that RGB value to set the color of the canvas --- ## on which all the tagged items (lines) lie. ## ## Arguments: none ## ## CALLED BY: .fRleft.fRbuttons.buttCOLORbkGND button ##+##################################################################### proc set_background_color {} { global COLORbkGNDr COLORbkGNDg COLORbkGNDb COLORbkGNDhex # global feDIR_tkguis ## FOR TESTING: # puts "COLORbkGNDr: $COLORbkGNDr" # puts "COLORbkGNDg: $COLORbkGNDb" # puts "COLORbkGNDb: $COLORbkGNDb" set TEMPrgb [ exec \ ./sho_colorvals_via_sliders3rgb.tk \ $COLORbkGNDr $COLORbkGNDg $COLORbkGNDb] # $feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk \ ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLORbkGNDhex "#$hexRGB" set COLORbkGNDr $r255 set COLORbkGNDg $g255 set COLORbkGNDb $b255 ## Redraw the geometry in the new background color. ReDraw 0 } ## END OF proc 'set_background_color' ##+############################################################# ## proc ReDraw_if_canvas_resized ## ## CALLED BY: bind .fRright.can ## at bottom of this script. ##+############################################################# proc ReDraw_if_canvas_resized {} { global PREVcanWidthPx PREVcanHeightPx set CURcanWidthPx [winfo width .fRright.can] set CURcanHeightPx [winfo height .fRright.can] if { $CURcanWidthPx != $PREVcanWidthPx || \ $CURcanHeightPx != $PREVcanHeightPx} { ReDraw 0 set PREVcanWidthPx $CURcanWidthPx set PREVcanHeightPx $CURcanHeightPx } } ## END OF ReDraw_if_canvas_resized ##+##################################################### ## Additional GUI initialization, if needed (or wanted). ##+##################################################### ## Set initial scale widget variables. set m 12 set n1 6.0 set n2 6.0 set n3 6.0 set a 150.0 set b 150.0 set N 12 ## Initialize the canvas with 'ReDraw'. ## Need 'update' here to set the size of the canvas, ## because 'ReDraw' uses 'winfo' to get the width and ## height of the canvas. ## See the 'bind ' command below. update ReDraw 0 ## After this script drops into the Tk event-handling loop, ## this bind command causes redraws whenever the canvas is resized. set PREVcanWidthPx [winfo width .fRright.can] set PREVcanHeightPx [winfo height .fRright.can] bind .fRright.can "ReDraw_if_canvas_resized"