FE 'tkGooie' Utilities

Shaded3D group

Tk GUI to Draw

with color-shaded
3D-like edges

(FE = Freedom Environment)

FE color-shaded, 3D-like
'Super-Formula-shape' maker
'tkGooie' interface.

FE Home Page > FE Downloads Page >

FE 'tkGooies' Description Page >

FE 'tkGooies' 'IMAGEcreatorsShaded3D' Page >

This 'draw_SUPER-FORMULA-SHAPE_colorShaded3D' tkGooie Page

to Tcl-Tk Code to
with color-shaded, 3D-like edges'

I am interested in making nice images for 'toolchest' and 'drawer' backgrounds (and other GUI embellishments), as I have indicated at the pages at wiki.tcl.tk (and on this freedomenv.com site) --- such as


On a page that presents code for a GUI for Drawing 'Super-ellipses', with nice shaded edges on this site (and at wiki.tcl.tk), I presented code for a GUI that uses 'create image' on a canvas, along with 'put' commands, to implement the drawing of a 'super-ellipse' with nice 'edge shading' --- shading from a user-specified color for the super-ellipse to a user-specified color for a surrounding background.

(Thanks to 'ulis', deceased in 2008, for his donated script that led to that much-enhanced script. R.I.P.)

The edge-shading technique was based on using a 'color-metric' scalar parameter given by the equation for the super-ellipse:

v = |x/a|^n + |y/b|^n

I was able to use this 'color-metric' technique to create another Tk script that provides nice 'edge shading' for a rectangle with a color gradient across it (in the x or y direction).

A page on this site (and at wiki.tcl.tk) presents code for a GUI for Drawing Rectangular 'Buttons' with nice shaded edges. In that case the color-metric that I used was of the form:

v = max(abs(x/xhalf), abs(y/yhalf))

where x and y are measured from an 'origin' in the middle of the rectangle, and xhalf and yhalf represent the half-width and half-height of the rectangle.

In both the super-ellipse case and the color-gradient-rectangle case, I tranformed a script based on a canvas-'create line' technique to a script that used a canvas-'create image' technique.

A 'color metric' for the super-formula shape

I decided that I would return to the script that I posted at the wiki.tcl.tk page titled "GUI for Drawing 'Superformula' shapes, with choice of colors", and use that script --- that is based on a canvas-'create polygon' technique --- to create a superformula-shape drawing script that uses a canvas-'create image' technique.

By doing that, I would be able to get nicer looking superformula shapes --- that is, with nice 3D-looking edge shading --- for future use on Tk GUI's. I just needed to come up with a 'color-metric' to use for the superformula shape.

Here is a description of the 'color-metric' that I devised. It is a 'little-r-over-big-R' formula.

The equation for the border of the 'superformula shape' is:

  R(theta) = ( |cos(m*theta/4)/a| ^ n2 + |sin(m*theta/4)/b| ^ n3 ) ^ -1/n1

(You use this radius along with cos(theta) and sin(theta) to get the x,y coordinates of points on the border of the 'superformula shape'.)

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. '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.

Using the 'color metric' to color a pixel
inside of (or outside of) the super-formula shape:

As we scan across the pixels of the rectangular image area, we can convert integer pixel coordinates (i,j) to 'real-number' 'world coordinates' (x,y) --- with (x,y) = (0.0,0.0) being somewhere in the middle of the rectangular image area.

At a point (x,y) in the super-formula shape, the metric v is less than or equal to 1.0. At a point (x,y) outside the super-formula shape, the metric v is greater than 1.0. For those external points, we simply set the color of the corresponding-pixel to the user-selected background color.

We determine the 'shaded color' at a point inside the super-formula shape by using a color interpolated between (1) the user-selected 'fill' color (color1) for the 'super-formula shape' and (2) the user-selected background color (color2).

We calculate the 'shaded color' at (x,y) by calculating a weighted average based on applying the factor (1.0 - v) to color1 --- and applying v to color2 (the 'edge' color). 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 and 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 for the super-formula shape, 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.

Assembling the pieces

Now it was a matter of putting the pieces together. I took 'pieces' from the 2 scripts that I posted at on pages titled


I ended up with the following GUI --- which is shows a 'super-formula shape' somewhat reminiscent of the hair-style of some of the Simpsons cartoon characters.

Note that I have supplied 2 buttons on the GUI with which to set the 'fill' color and the 'background' color. Those 2 buttons call on a color-selector-GUI script to set those colors.

You can make that color-selector script by cutting-and-pasting the code from the page that offers a non-obfuscated color selector GUI on this site.


Note that I added an N-scale widget to the GUI to allow the user to control an exponent that is used to control the 'extent'-or-'intensity' of the shading at the border of the 'superformula shape'.

I also added a display of 'elapsed time' for each redraw --- by using the Tcl 'clock milliseconds' command.

When I developed the script that I posted at wiki.tcl.tk and on this site, at GUI for Drawing 'Super-ellipses', with nice shaded edges, I learned my lesson about needing to use braces with 'expr' statements --- for much better execution times. (Brent Welch et. al. point this out before page 8 in the 4th edition of 'Practical Programming in Tcl and Tk' --- although they do not follow this advice in many 'expr' examples later in the book.)

It made a huge difference, so, in this script (and in all my Tk scripts henceforth), I consistently use braces with ALL 'expr' commands --- in particular, in the compute-intensive 'ReDraw' proc and in the procs that are called by 'ReDraw'.


Below is the code that produced this GUI.

There are comments near the top of the code, in a section titled 'USING THE GENERATED IMAGE', that describe how one could make use of images produced by this GUI.

I follow my usual 'canonical' structure for Tk code, for this Tk script:

  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.
  1b) Pack   ALL frames and sub-frames.

  2) Define & pack all widgets in the frames.

  3) Define keyboard and mouse/touchpad/touch-sensitive-screen action
     BINDINGS, if needed.

  4) Define PROCS, if needed.

  5) Additional GUI initialization (typically with one or more of
     the procs), if needed.

This Tk coding structure is discussed in more detail on the page A Canonical Structure for Tk Code --- and variations.

This Tk coding structure makes it easy for me to find code sections --- while generating and testing this script, and when looking for code snippets to include in other scripts (code re-use).

Experimenting with the GUI

As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus Tk scripts, so far), I provide the four main pack parameters --- '-side', '-anchor', '-fill', and '-expand' --- on all the 'pack' commands for the frames and widgets.

I think I have found a good setting of the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets of this GUI. In particular ...

The 'canvas' widget expands/contracts appropriately when the window size is changed --- and button and label widgets stay fixed in size and relative-location as the window size is changed.

If anyone wants to change the way the GUI configures itself as the main window size is changed, they can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets --- to get the widget behavior that they want.


Additional GUI experimentation: You could change the fonts used for the various GUI widgets. For example, you could change '-weight' from 'bold' to 'normal' --- or '-slant' from 'roman' to 'italic'. Or change font families.

Furthermore, there are variables used to set geometry parameters of widgets --- parameters such as border-widths and padding. And you could change the '-relief' values for frames and widgets. Feel free to experiment with those 'appearance' parameters as well.

Some features of the code

There are plenty of comments in the code to describe what most of the code-sections are doing.

The most complex code is in the 'ReDraw' proc. See the comments in that proc to see how it is implemented.

See the top of the 'PROCS' section for a list of the procs used in this Tk script. See comments in the procs for details on the purpose of each proc and for details on the methods by which each proc was implemented.

Below is a quick overview of the procs --- to give an idea of the 'guts' of this utility:

 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 the color1 (fill) button

 set_shape_color2           - called by the color2 (outline) button
                              (NOT USED, yet --- may be implemented as an enhancement)

 set_background_color       - called by the background color button

Comments in the Code

It is my hope that the copious comments in the code might help Tcl-Tk coding 'newbies' get started in making GUI's like this. Without the comments --- especially in the 'ReDraw' proc --- the code might look even more cryptic than it already is.

Without the comments, potential young Tcler's might be tempted to return to their iPhones and iPads and iPods --- to watch America's/France's/Italy's/Antarctica's Funniest Home Videos.

The Tcl-Tk script CODE

Here is a link to CODE for the Tk script

With your web browser, you can 'right-click' on this link --- and in the menu that pops up, select an item like 'Save Link Target As ...' --- to save this file to your local computer.

Then you can rename the file to remove the '.txt' suffix. Make sure that you have execute permission set on the file --- in order to execute the script.


By making parameter 'pairs' like 'a' and 'b' (or 'n2' and 'n3') different, you can get some effects like putting some 'indentations' in the initial disk-like shape --- giving a star-fish-like shape:

And by adjusting the exponent 'm' to a high value, you can add a lot of 'protrusions' to the initial disk-like shape --- giving a sea-urchin-like shape:

(This image seems to have a glowing, optical-illusion type of effect.)

Control of the edge shading

On the subject of trying to get really nice shading at the border of the 'superformula shape':

I put the N-scale widget on the GUI to adjust a 'pow' (power) function exponent to change the 'extensity' (extent and/or intensity) of the shading at the edge of the 'superformula shape'.

You will find that low powers (like 1 or 4 or even 6) give a really 'washed-out' border to the shape. It takes a rather high value (like 12) to get a good-looking edge.

That means that v^12 and (1 - v^12) gives a better-looking border when blending 'fill' color at a point x,y with the background color --- better than using the weighted average of the 2 colors using v and (1-v).

Drawing times

I decided to NOT 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 hex-colors for the pixels.

Instead, I 'poked' a hex-color value into each pixel with calls like:

imgID put $hexcolor -to $x $y

    If I were to reprogram this script for speed, I would 'build' horizontal scan-lines and whenever the 'metric' of a point on the scan-line was greater than one, I would color the pixel with the background color.


The display of the elapsed time for the draw is seen at the bottom of the GUI. I later changed that display to the top of the GUI --- so that it is more noticeable, even if the user shrinks the window size so that the bottom of the GUI is no longer showing. (See the image at the top of this page.)

I found that with any parameter combinations that I tried, with the initial default window size, the draw times were between 2.8 and 3.2 seconds.

And when I increased the window to my full monitor size (1024x768), the draw times were still less than 5.1 seconds.

So, in a quite reasonable amount of time, with this utility, you can get some nice high-quality images --- to use for 'buttons', 'bullets', icon-backgrounds, and logo-backgrounds.

And I have the option of enhancing the Tk script on this page, to provide a few more capabilities to this 'button' generator --- including some changes to reduce draw times. That is a really great thing about Tk scripts. You have the code, hence you can change the utility to do what you want or need.


There are several items that I can foresee wanting to implement in the future to make this Tk script a little bit better:

  • Add a 'Help' button
    In the help text I would add how-to-use information --- such as:
    The user can control the size of the generated image by resizing the entire GUI window. That causes the Tk 'canvas' to resize, and the size of the image to generate is determined from the canvas size.

  • Add 2 widgets by which to set ImgWidth and ImgHeight (pixels) precisely
    This would allow the user to set the generated image size precisely.

  • 'Stretch' the super-formula shape within the image area
    In this first release, the super-formula shape is always drawn within the image area with the same height as width --- that is, there is no option to allow the shape to be 'stretched' in the x or y directions. We could allow the image to be drawn according to the aspect ratio determined from the ImgWidth and ImgHeight settings.

  • Improve the draw-speed, by a factor of 2 or more
    As indicated above, we could probably improve the draw-speed significantly by saving up the hex-colors for pixels in a Tcl 'list' and then apply those colors to the image 'structure' one horizontal scan-line at a time.

    In fact, there is at least one small demo script on wiki.tcl.tk in which a Tcl-er has saved up all the hex-colors for an entire image (in a list of horizontal scan-line lists --- a list of lists) and applied all of them to the image 'structure' in one 'put' call. That may be worth a try with this utility.

I may implement these enhancements sometime in the future.

(If I use this script as a starting point for another 'image-creator_color-shaded_3D-like' utility, then I will probably implement these enhancements in that new utility --- and then, in an ideal world, go back to this utility and implement the enhancements.)


As I have said on several other code-donation pages on this freedomenv.com site and on the Tclers' wiki at wiki.tcl.tk ...

There's a lot to like about a utility that is 'free freedom' --- that is, no-cost and open-source so that you can modify/enhance/fix it without having to wait for someone else to do it for you (which may be never).

A BIG THANK YOU to Ousterhout for starting Tcl-Tk, and a BIG THANK YOU to the Tcl-Tk developers and maintainers who have kept the simply MAH-velous 'wish' interpreter going.

Bottom of this page for
Tcl-Tk Code to
with color-shaded 3D-edges

--- a utility in the FE 'tkGooies' system,
in the 'IMAGEcreatorsShaded3D' group.

To return to a previously visited web page location, click on the Back button of your web browser a sufficient number of times. OR, use the History-list option of your web browser.
OR ...

< Go to Top of Page, above. >

Page history:

The code was created in 2012 --- and posted 2012 Oct 18 at http://wiki.tcl.tk/37156.

This FE web page was created 2014 May 10 --- as a backup and alternative to the wiki.tcl.tk page.

This page was changed 2015 Oct 07.
(Small changes.)

Page was changed 2015 Dec 30.
(Added some links.)

Page was changed 2019 Feb 28.
(Added css and javascript to try to handle text-size for smartphones, esp. in portrait orientation.)

Page was changed 2019 Jun 13.
(Specified image widths in percents to size the images according to width of the browser window.)

The code here MAY BECOME more 'up-to-date' than the code posted on the Tcler's Wiki ---
wiki.tcl-lang.org --- formerly wiki.tcl.tk.