#!/usr/bin/wish -f ##+######################################################################## ## ## SCRIPT: tkNapoleonsTheorem.tk ## ## PURPOSE: This Tk script is meant to demonstrate Napoleon's Theorem: ## ## If 3 EQUILATERAL triangles are constructed on the sides of ## ANY triangle, either ALL 3 OUTWARD or ALL 3 INWARD, the centers ## of those 3 equilateral triangles themselves form an EQUILATERAL ## triangle. ## ## The triangle thus formed is called the 'outer' or 'inner' Napoleon ## triangle. ## ## In addition, it turns out: ## The difference in area of the 'outer' and 'inner' two Napoleon ## triangles equals the area of the 'original' triangle. ## ## This script is meant to 'dynamically' demonstrate these facts ## by allowing the user to 'drag' any point of the 'original' ## triangle to form a new triangle. ## ## In all, the figure involves up to 1+4+4 = 9 triangles, depending on ## whether 'outward', 'inward', both, or neither are requested: ## a) the 'original', arbitrary triangle, ## b) the 3 'outward' equilateral triangles based on the 3 sides of the ## 'original' triangle, which we will call 'outer-base' triangles, and ## the 'outer' equilateral triangle whose 3 sides connect the centers ## of the 3 'base' 'outward' equilateral triangles, ## c) the 3 'inward' equilateral triangles based on the 3 sides of the ## 'original' triangle, which we will call 'inner-base' triangles, and ## the 'inner' equilateral triangle whose 3 sides connect the centers ## of the 3 'base' 'inward' equilateral triangles. ## ## When the user finishes the 'drag' (releases the mouse-button): ## 1) The moved point of the 'original' triangle is deleted and ## redrawn in its new position. ## 2) The 2 affected sides (line-segments) of the 'original', ## arbitrary triangle are deleted and redrawn. ## Also, if 'outward' or 'inward' are requested: ## 3) Two of three 'outer/inner-base' equilateral triangles are redrawn, ## by deleting and redrawing the 2 sides of the 2 outer/inner equilateral ## triangles that are 'based' on the 2 redrawn sides of the 'original' triangle. ## 4) Two of the 3 centers of the 3 'outer/inner-base' equilateral triangles ## are recalculated. ## 5) The three sides of the 'outer' or 'inner' equilateral triangle ## that connect the centers are deleted and redrawn --- yielding a ## new 'outer' or 'inner' equilateral triangle. ## ## NOTE: I tried allowing BOTH the 6 'outward' and 'inward' equilateral triangles ## and the 2 Napoleon triangles ('outer' and 'inner') to be drawn on the ## canvas at the same time, but the image (9 triangles in all) was hard ## to interpret. So I decided to use 2 'radiobutton' widgets, instead of ## 2 'checkbutton' widgets, for the user to specify 'outward' or 'inward', ## but not both. ## ## These operations may be done in a different order. For example, ## some deletions may be grouped together, and some re-draws may be ## grouped together. ## ## We may 'tag' the 3 points of the 'original', arbitrary triangle ## with names like A,B,C. ## ## And we may 'tag' the 'peak' points of the three 'base' equilateral ## triangles ('outward' and 'inward') with names like ## peakABout,peakBCout,peakCAout --- and peakABin,peakBCin,peakCAin. ## ## And we may 'tag' the 'center' points of the three 'base' equilateral ## triangles with names like centABout,centBCout,centCAout --- and ## centABin,centBCin,centCAin. ## ## GUI FEATURES: ## This GUI uses a Tk 'canvas' widget to show the up-to-9 triangles. ## ## The line segments of the triangles are drawn with 'create line' ## commands on the canvas. ## The 3 points of the 'original' triangle are indicated by use of ## 'create oval' commands. ## ## We use a rectangular drawing area (the Tk 'canvas' widget), and ## we allow the user to control the size (in pixels) of that ## drawing area by the user resizing the entire GUI window --- which ## results in the canvas being automatically resized by the ## Tk 'pack' geometry manager. ## ## The delete-and-redraw operations are automatically triggered ## when the user releases the mouse button after moving one of ## the 3 points of the 'original' triangle. ## ## (The 3 vertices/points of the 'original' triangle are the ## only objects on the canvas that are moveable by the user. ## All other objects --- such as line-segments and text items ## --- are redrawn automatically for the user.) ## ## Three 'Color' buttons on the GUI allow the user to specify ## - background color of the Tk canvas widget ## - color of the line segments of the up-to-9 triangles ## - color of the vertex points of triangles, at least the ## 3 vertex points of the 'original' triangle. ## ## A 'ShowState' button on the GUI may be used to report on ## the state of the current image, such as: ## - coordinates of the various triangle vertex points ## - lengths of the line-segments/sides of triangles ## - area of the 'outer' or 'inner' triangles. ## ## (The lengths of the sides of each of the 8 equilateral triangles ## should be equal --- the 3 'base' 'outward' and 'inward' ## equilateral triangles and the one 'outer' and the one 'inner' ## equilateral triangle. ## ## In particular, the lengths of the sides of the 'outer' ## and 'inner' triangles being equal confirms that those ## two triangles are indeed equilateral triangles --- ## as the theorem declares.) ## ## A 'Help' button on the GUI describes how the GUI operates ## and describes the geometry involved in Napoleon's Theorem. ## ##+######################### ## PLANNED LAYOUT OF THE GUI: ## ## FrameNames ## VVVVVVVVVV ## ----------------------------------------------------------------------------- ## tkNapoleonsTheorem ## [window title] ## ----------------------------------------------------------------------------- ## ## .fRbuttons {Exit} {Help} {ShowState} {Backgd {Line {Point Draw 3 equi. triangles: O outward O inward O both ## Color} Color} Color} ## ## .fRmsg [ .......... Message line --- for advice to the user .................. ] ## ## .fRcanvas ----------------------------------------------------------------------------- ## | | ## | | ## | | ## | [Canvas for displaying the triangles | ## | in a rectangular image area. No scrollbars.] | ## | | ## | | ## | | ## | | ## ----------------------------------------------------------------------------- ## ## SKETCH CONVENTIONS for this GUI sketch: ## ## SQUARE-BRACKETS indicate a comment (not to be placed on the GUI). ## BRACES indicate a Tk 'button' widget. ## ## A COLON indicates that the text before the colon is on a 'label' widget. ## CAPITAL-O indicates a Tk 'radiobutton' widget. ## CAPITAL-X indicates a Tk 'checkbutton' widget (if any). ## ## UNDERSCORES indicate a Tk 'entry' widget (if any). ## <---O---> indicates a horizontal Tk 'scale' widget (if any). ## ## A combination of VERTICAL-BAR CHARACTERS AND HYPHEN CHARACTERS, ## that outline a RECTANGULAR SHAPE, are used to indicate either a ## Tk 'canvas' widget or a Tk 'listbox' widget or a Tk 'text' widget. ## ## SCROLL-BAR 'ARROW-HEADS' (for a 'canvas', 'listbox', or 'text' Tk widget) ## are drawn as follows: ## ## UP ARROW-HEAD is drawn with a CAPITAL-A. ## DOWN ARROW-HEAD is drawn with a CAPITAL-V. ## LEFT ARROW-HEAD is drawn with a LESS-THAN sign. ## RIGHT ARROW-HEAD is drawn with a GREATER-THAN sign. ## ## UP-and-DOWN ARROW-HEADS at the right/left of the box shape indicate ## a VERTICAL SCROLL-BAR there. ## ## LEFT-and-RIGHT ARROW-HEADS at the bottom/top of the box shape indicate ## a HORIZONTAL SCROLL-BAR there. ## ## The arrow-heads on a horizontal scrollbar are joined by hyphens, rather than ## underscores. ## ## A LINE (HYPHENS or VERTICAL-BARS) WITH AN 'ARROW-HEAD' AT EACH END indicates ## a Tk 'scale' widget --- horizontal or vertical, respectively. ## ##+################## ## GUI WIDGET SUMMARY: ## ## This GUI will contain about: ## ## 6 'button' widgets ## 2 'label' widgets ## 2 'radiobutton' widgets ## 1 'canvas' widget (with no x-y scrollbars) ## ## 0 'entry' widgets ## 0 'checkbutton' widgets ## 0 'scale' widgets ## 0 'listbox' widgets ## 0 'text' widgets ## ##+################################## ## METHOD USED to perform the drawing: ## ## We specify the point coordinates in 'pixel coordinates' on ## the Tk 'canvas' widget --- rather than using 'world coordinates' ## and mapping the 'world coordinates' to 'pixel coordinates' on ## the Tk 'canvas' widget. ## ## At any time we can query the width and height of the 'canvas' ## widget and note that, in pixel coordinates, the canvas-box is ## UpperLeft Corner: 0,0 ## LowerRight Corner: ImgWidthPx,ImgHeightPx ## ## In other words, the x-pixel-coordinates vary from zero ## on the left of the canvas and increase to the right ## --- and the y-pixel-coordinates vary from zero ## at the top of the canvas and increase to the bottom. ## ## Lines are drawn on the canvas using 'create line' commands ## that specify the pixel coordinates of 2 points. ## ## Points are drawn on the canvas using 'create oval' commands ## with the center of the oval at pixel coordinates of a point. ## ## Some text items might be put on the canvas, such as labels ## for points, by use of 'create text' commands on the canvas. ## ############################################ ## METHOD OF CALCULATING THE 'PEAK' POINT OF ## THE 'BASE' EQUILATERAL TRIANGLES: ## ## We have 3 'peak' points to calculate for the 3 'base' equilateral ## triangles --- actually, 3 'outward' and 3 'inward' 'peak' points. ## ## There are 3 sides --- AB,BC,CA --- on which to draw the 'base' ## equilateral triangles. We consider the triangle on side AB --- ## with end-points at points (Ax,Ay) and (Bx,By). ## ## Let us imagine an equilateral triangle with 3 sides of length one ## based on side AB. We can find the 'peak' point by finding the ## midpoint of AB which divides AB into 2 segments of length 1/2. ## ## Then imagine rotating the line segment from the midpoint to B ## by 90 degrees COUNTER-CLOCKWISE. Then we extend that line-segment ## of length 1/2 by the factor sqrt(3). That will locate the 'peak' ## point we seek in one direction, say 'outward'. ## ## To get the 'inward' peak point, we can imagine rotating the line ## segment from the midpoint to B by 90 degrees CLOCKWISE. Then ## we extend that line-segment of length 1/2 by the factor sqrt(3). ## ## Since we were using equilateral triangles with sides of length one, ## to scale to our actual distances, we multiply by the length of ## side AB. ## ## In summary, we rotate the line segment from the midpoint to B ## by 90 degrees COUNTER-CLOCKWISE (or CLOCKWISE) --- and extend the ## segment by the factor sqrt(3) --- thus locating a 'peak' point ## in the 'outward' (or 'inward') direction. ## ## Now we just need an algebraic way to perform the rotation and ## the sqrt(3) extension to get the coordinates of a 'peak' point. ## ## We can imagine the midpoint of AB -- (midABx,midABy) --- being ## the origin of a coordinate system. We want to rotate the point ## (dx,dy) = (Bx - midABx , By - midABy) 90 degrees counter-clockwise. ## ## Rather than using a complicated triangle diagrams and some ## Euclid-like reasoning to determine the coordinates of the point ## after rotation by 90 degrees, we note that we can use 'complex' ## number arithmetic to do the rotation. ## ## We note that the point (dx,dy) can be thought of as a complex ## number --- dx + (i * dy). When we multiply a complex number by ## i = sqrt(-1), we get a new complex number whose coordinates ## are the rotation of the complex number by 90 degrees counter-clockwise. ## ## So (dx,dy) rotated 90 degrees counter-clockwise is given by ## (dx + i*dy) * i = -dy + i*dx = (-dy,dx) ## ## To scale this point by sqrt(3), we get (-dy*sqrt(3), dx*sqrt(3)) ## for the 'peak' point --- relative to the origin based at midpoint ## (midABx,midABy). ## ## Now we must translate the origin to get the 'peak' point in the ## original coordinate system. So given midpoint (midABx,midABy) ## and point (Bx,By), we find that the 'peak' point coordinates are ## (midABx - dy*sqrt(3), midABy + dx*sqrt(3)) where ## dx = Bx - midABx ## and ## dy = By - midABy ## ## This gives us the 'outward-peak' point. ## ## --- ## ## To get the 'inward' peak point, we could multiply by ## -i instead of i, to rotate the line-segment from the midpoint ## of AB to B by 90 degrees CLOCKWISE. ## ## So (dx,dy) rotated 90 degrees counter-clockwise is given by ## (dx + i*dy) * -i = dy - i*dx = (dy,-dx) ## ## Then we find that the 'inward-peak' point coordinates are ## (midABx + dy*sqrt(3), midABy - dx*sqrt(3)) where ## dx = Bx - midABx ## and ## dy = By - midABy ## ############################################## ## METHOD OF CALCULATING THE 'CENTER' POINT OF ## THE 'BASE' EQUILATERAL TRIANGLES: ## ## The center point of the 'base' equilateral triangles can ## be found by the same method as finding the 'peak' points ## --- except that the rotated line-segment (half of line AB) ## is extended by sqrt(3)/3 instead of sqrt(3). ## ## This factor can be determined by considering an equilateral ## triangle with sides of length one. Each angle of the triangle ## is 60 degrees. The center of the triangle lies on the line ## from the midpoint of AB to the 'peak' point of the triangle. ## ## And the center point is the intersection of any of the other ## 2 lines from a midpoint of a side of the triangle to the ## 'peak' point opposite that side. That line bisects the ## 60 degree angle, so it is a 30 degree angle. ## ## The ratio of the sides of a 30-60-90 degree triangle are ## 1/2 : sqrt(3)/2 : 1 --- by the Pythagorean theorem and the ## fact that the angles in the equilateral triangle are ## 60 degrees, and the bisector of any of the angles (giving ## a 30 degree angle) is perpendicular to the opposite side ## and bisects the opposite side (length = 1/2). ## ## P ## . ## /.\ ## / . \ ## / . \ ## 1 / . \ 1 ## / * \ ## / X . * \ ## /______.____*_\ ## A B ## midAB ## 1/2 1/2 ## ## In this triangle representing a 'base' equilateral triangle, ## based on side AB of the 'original' triangle, the height to ## the peak point, P, is sqrt(3)/2. ## ## The height X represents the height of the center point above ## the base AB. The small triangle formed by the center point, ## the point B, and the midpoint 'midAB' is also a 30-60-90 ## triangle. So the ratio of X to 1/2 should equal the ratio ## 1/2 to sqrt(3)/2. That is, ## ## X / (1/2) = (1/2) / (sqrt(3)/2) ## ## Multiplying both sides by 1/2 gives ## ## X = 1 / (2 *sqrt(3)) ## ## But 1 / sqrt(3) = sqrt(3) / 3. So ## ## X = (1/3) * (sqrt(3) / 2) ## ## So X is one-third of the height of the equilateral triangle. ## ## Then we find that the 'center' point coordinates are ## (midABx - dy*sqrt(3)/3, midABy + dx*sqrt(3)/3) where ## dx = Bx - midABx ## and ## dy = By - midABy ## for the center point of an 'outward' equilateral 'base' triangle. ## ## And for the center point of an 'inward' equilateral 'base' ## triangle, then we find that the 'center' point coordinates are ## (midABx + dy*sqrt(3)/3, midABy - dx*sqrt(3)/3) where ## dx = Bx - midABx ## and ## dy = By - midABy ## ##+####################### ## CAPTURING THE GUI IMAGE: ## ## A screen/window capture utility (like 'gnome-screenshot' ## on Linux) can be used to capture the GUI image in a PNG ## or GIF 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 smaller image ## suitable for use in a web page or an email. ## ##+####################################################################### ## 'CANONICAL' STRUCTURE OF THIS CODE: ## ## 0) Set general window parms (win-name, win-position, win-color-scheme, ## fonts, widget-geom-parms, win-size-control, text-array-for-labels-etc). ## ## 1a) Define ALL frames (and sub-frames, if any). ## 1b) Pack the frames. ## ## 2) Define & pack all widgets in the frames, frame by frame. ## After all the widgets for a frame are defined, pack them in the frame. ## ## 3) Define keyboard or mouse/touchpad/touch-sensitive-screen 'event' ## BINDINGS, if needed. ## ## 4) Define PROCS, if needed. ## ## 5) Additional GUI INITIALIZATION (typically with one or more of ## the procs), if needed. ## ##+################################# ## Some detail of the code structure of this particular script: ## ## 1a) Define ALL frames: ## ## Top-level : ## '.fRbuttons' - to contain 'Exit', 'Help', 'ShowState' and ## several color buttons. ## ## '.fRmsg' - to contain a label widget ## ## '.fRcanvas' - to contain a canvas widget, which will display ## the circle and polygon(s). ## ## 1b) Pack ALL frames. ## ## 2) Define & pack all widgets in the frames -- basically going through ## frames & their interiors in left-to-right, or top-to-bottom order. ## ## 3) Define BINDINGS: such as button1-release on the 'canvas' widget ## (See the BINDINGS section below, for details.) ## ## 4) Define PROCS: such as a 'redraw' procs for the button1-release ## on the 'canvas' widget ## (See the PROCS section below, for details.) ## ## 5) Additional GUI Initialization: ## - call 'initDdraw' to put the initial drawing of 5 or 6 triangles ## on the canvas, for a given initial setting of coordinates of ## points A,B,C. ## ##+####################################################################### ## DEVELOPED WITH: Tcl-Tk 8.5 on Ubuntu 9.10 (2009-october, 'Karmic Koala') ## ## $ wish ## % puts "$tcl_version $tk_version" ## ## showed ## 8.5 8.5 ## but this script should work in most previous 8.x versions, and probably ## even in some 7.x versions (if font handling is made 'old-style'). ##+####################################################################### ## MAINTENANCE HISTORY: ## Started by: Blaise Montandon 2016aug27 Started coding based on tkGooie ## script 'tkVarignonsTheorem.tk'. ## Changed by: Blaise Montandon 2016oct04 Added the 'both' radiobutton and ## 'finalized' the code for release. ##+######################################################################## ##+###################################################### ## Set WINDOW TITLE and POSITION. ##+###################################################### wm title . "tkNapoleonsTheorem - Centers of Equilateral Triangles on Any Triangle Yield an Equilateral Triangle" wm iconname . "NapoleonTriangles" wm geometry . +8+30 ##+###################################################### ## Set the COLOR SCHEME for the window and its widgets --- ## such as listbox and entry field background color. ##+###################################################### tk_setPalette "#f0f0f0" set radbuttBKGD "#c0c0c0" # set chkbuttBKGD "#c0c0c0" # set scaleBKGD "#f0f0f0" # set entryBKGD "#ffffff" # set listboxBKGD "#ffffff" ##+######################################################## ## DEFINE (temporary) FONT NAMES. ## ## We use a VARIABLE-WIDTH font for text on LABEL and ## BUTTON widgets. ## ## We use a FIXED-WIDTH font for LISTBOX lists, ## for Help-text in a TEXT widget, and for ## the text in 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) ##+########################################################### ## LABEL widget geom settings: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 set RELIEF_label_lo "flat" ## BUTTON widget geom settings: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 ## We generally default to relief "raised" for all 'button' widgets. ## BUT, in case you want to experiment: set RELIEF_button "raised" ## RADIOBUTTON geom parameters: set PADXpx_radbutt 0 set PADYpx_radbutt 0 set BDwidthPx_radbutt 1 set RELIEF_radbutt_hi "raised" ## COMMENTED WIDGET GEOM PARMS - NOT USED, yet: if {0} { ## CHECKBUTTON geom parameters: set PADXpx_chkbutt 0 set PADYpx_chkbutt 0 set BDwidthPx_chkbutt 1 set RELIEF_chkbutt_hi "raised" ## ENTRY widget geom settings: set BDwidthPx_entry 2 ## SCALE widget geom parameters: # set BDwidthPx_scale 2 # set scaleThicknessPx 10 } ## END OF COMMENTED WIDGET GEOM PARMS. ## CANVAS widget geom settings: set initCanWidthPx 350 set initCanHeightPx 450 # set BDwidthPx_canvas 2 set BDwidthPx_canvas 0 set RELIEF_canvas "flat" ##+############################################################## ## Set a TEXT-ARRAY to hold text for buttons & labels on the GUI. ## NOTE: This can aid INTERNATIONALIZATION. This array can ## be set according to a nation/region parameter. ##+############################################################## ## if { "$VARlocale" == "en"} ## For the '.fRbuttons' frame: set aRtext(buttonEXIT) "Exit" set aRtext(buttonHELP) "Help" set aRtext(buttonSTATE) "ShowState" set aRtext(buttonRESET) "Reset" set aRtext(buttonCOLORbkgd) "Backgrnd Color" set aRtext(buttonCOLORline) "Line Color" set aRtext(buttonCOLORpoint) "Point Color" set aRtext(labelRADBUTTS) "Draw 3 equilateral triangles:" set aRtext(radbuttOUTER) "outward" set aRtext(radbuttINNER) "inward" set aRtext(radbuttBOTH) "both" ## For the '.fRmsg' frame: set aRtext(labelINIT) \ "** Highlight and drag any of the 3 triangle vertices A, B, or C. The figure will be redrawn. See 'Help'. **" set aRtext(labelDRAG) "** Highlight and drag point A, B, or C. **" ## END OF if { "$VARlocale" == "en"} ##+###################################################################### ## Set a MIN-SIZE of the window (roughly). ## ## For WIDTH, allow for the min-width of the '.fRbuttons' frame. ## ## For HEIGHT, allow for the stacked frames: ## 2 chars high for the '.fRbuttons' frame, ## 1 char high for the '.fRmsg' frame, ## at least 50 pixels high for the '.fRcanvas' frame. ##+##################################################################### ## FOR WIDTH: set minWidthPx [font measure fontTEMP_varwidth \ " $aRtext(buttonEXIT) $aRtext(buttonHELP) $aRtext(buttonSTATE) \ Color Color Color $aRtext(labelRADBUTTS) $aRtext(radbuttOUTER) $aRtext(radbuttINNER) $aRtext(radbuttBOTH)"] ## We add some pixels to account for right-left-size of ## window-manager decoration (~8 pixels) and some pixels for ## frame/widget borders (9 widgets x 4 pixels/widget = 36 pixels). set minWinWidthPx [expr {44 + $minWidthPx}] ## For HEIGHT --- for ## 2 chars high for the '.fRbuttons' frame, ## 1 char high for the '.fRmsg' frame, ## 50 pixels high for the '.fRcanvas' frame. set charHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {3 * $charHeightPx}] ## Add about 50 pixels for height of the canvas ## AND add about 20 pixels for top-bottom window decoration -- ## and some pixels for top-and-bottom of frame/widget borders ## (3 widgets x 4 pixels/widget = 12 pixels). set minWinHeightPx [expr {82 + $minWinHeightPx}] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## 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 : '.fRbuttons' '.fRmsg' '.fRcanvas' ## ## Sub-frames: none ##+################################################################ ## FOR TESTING change 0 to 1: ## (Example1: To see appearance of frames when borders are drawn.) ## (Example2: To see sizes of frames for various '-fill' options.) ## (Example3: To see how frames expand as window is resized.) if {0} { set RELIEF_frame raised set BDwidthPx_frame 2 } else { set RELIEF_frame flat set BDwidthPx_frame 0 } frame .fRbuttons -relief $RELIEF_frame -bd $BDwidthPx_frame # frame .fRmsg -relief $RELIEF_frame -bd $BDwidthPx_frame frame .fRmsg -relief raised -bd 2 # frame .fRcanvas -relief $RELIEF_frame -bd $BDwidthPx_frame frame .fRcanvas -relief raised -bd 2 ##+############################## ## PACK the FRAMES. ##+############################## pack .fRbuttons \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRmsg \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRcanvas \ -side top \ -anchor n \ -fill both \ -expand 1 ##+########################################################## ## The FRAMES ARE PACKED. START PACKING WIDGETS IN THE FRAMES. ##+########################################################## ##+########################################################## ## In FRAME '.fRbuttons' - ## DEFINE six 'BUTTON' WIDGETS --- Exit, Help, ShowState --- ## and 3 color buttons --- and a LABEL and 2 RADIOBUTTONS. ## Then PACK them. ##+########################################################## button .fRbuttons.buttEXIT \ -text "$aRtext(buttonEXIT)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} button .fRbuttons.buttHELP \ -text "$aRtext(buttonHELP)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {popup_msgVarWithScroll .topHelp "$HELPtext" +150+50} button .fRbuttons.buttRESET \ -text "$aRtext(buttonRESET)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {reset} button .fRbuttons.buttSTATE \ -text "$aRtext(buttonSTATE)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {show_state} button .fRbuttons.buttCOLORbkgd \ -text "$aRtext(buttonCOLORbkgd)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command "set_background_color" button .fRbuttons.buttCOLORline \ -text "$aRtext(buttonCOLORline)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command "set_line_color" button .fRbuttons.buttCOLORpoint \ -text "$aRtext(buttonCOLORpoint)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command "set_point_color" label .fRbuttons.labelRADBUTTS \ -text "$aRtext(labelRADBUTTS)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief $RELIEF_label_lo \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label ## We initialize this widget var (and others) ## in the GUI initialization section at the ## bottom of this script. # set VARradbuttsOUTorIN "out" radiobutton .fRbuttons.radbuttOUTER \ -text "$aRtext(radbuttOUTER)" \ -font fontTEMP_varwidth \ -variable VARradbuttsOUTorIN \ -value "out" \ -anchor w \ -selectcolor "$radbuttBKGD" \ -padx $PADXpx_radbutt \ -pady $PADYpx_radbutt \ -relief $RELIEF_radbutt_hi radiobutton .fRbuttons.radbuttINNER \ -text "$aRtext(radbuttINNER)" \ -font fontTEMP_varwidth \ -variable VARradbuttsOUTorIN \ -value "in" \ -anchor w \ -selectcolor "$radbuttBKGD" \ -padx $PADXpx_radbutt \ -pady $PADYpx_radbutt \ -relief $RELIEF_radbutt_hi radiobutton .fRbuttons.radbuttBOTH \ -text "$aRtext(radbuttBOTH)" \ -font fontTEMP_varwidth \ -variable VARradbuttsOUTorIN \ -value "outANDin" \ -anchor w \ -selectcolor "$radbuttBKGD" \ -padx $PADXpx_radbutt \ -pady $PADYpx_radbutt \ -relief $RELIEF_radbutt_hi ## Pack the widgets in frame '.fRbuttons'. pack .fRbuttons.buttEXIT \ .fRbuttons.buttHELP \ .fRbuttons.buttRESET \ .fRbuttons.buttSTATE \ .fRbuttons.buttCOLORbkgd \ .fRbuttons.buttCOLORline \ .fRbuttons.buttCOLORpoint \ .fRbuttons.labelRADBUTTS \ .fRbuttons.radbuttOUTER \ .fRbuttons.radbuttINNER \ .fRbuttons.radbuttBOTH \ -side left \ -anchor w \ -fill none \ -expand 0 ##+######################################################## ## In FRAME '.fRmsg' - ## DEFINE one LABEL widget. Then PACK it. ##+####################################################### label .fRmsg.labelMSG \ -text "" \ -font fontTEMP_varwidth \ -width 100 \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bg "#ff9999" \ -bd $BDwidthPx_label ## Pack the widgets in frame '.fRmsg'. pack .fRmsg.labelMSG \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+######################################################## ## In FRAME '.fRcanvas' - ## DEFINE a CANVAS WIDGET (no scrollbars). Then PACK it. ## ## 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 .fRcanvas.can \ -width $initCanWidthPx \ -height $initCanHeightPx \ -relief flat \ -highlightthickness 0 \ -borderwidth 0 ## COMMENT OUT SCROLLBAR DEFINITIONS. if {0} { \ -yscrollcommand ".fRcanvas.scrolly set" \ -xscrollcommand ".fRcanvas.scrollx set" scrollbar .fRcanvas.scrolly \ -orient vertical \ -command ".fRcanvas.can yview" scrollbar .fRcanvas.scrollx \ -orient horizontal \ -command ".fRcanvas.can xview" } ## END OF COMMENTED SCROLLBARS. ##+####################################################### ## Pack the widgets in frame '.fRcanvas'. ## ## NOTE: ## NEED TO PACK THE SCROLLBARS BEFORE THE CANVAS WIDGET. ## OTHERWISE THE CANVAS WIDGET TAKES ALL THE FRAME SPACE. ##+####################################################### ## COMMENTED PACKING OF THE SCROLLBARS. if {0} { pack .fRcanvas.scrolly \ -side right \ -anchor e \ -fill y \ -expand 0 pack .fRcanvas.scrollx \ -side bottom \ -anchor s \ -fill x \ -expand 0 ## !!!NEED TO USE '-expand 0' FOR THE X AND Y SCROLLBARS, so that ## the canvas is allowed to fill the remaining frame-space nicely ## --- without a gap between the canvas and its scrollbars. } ## END OF COMMENTED PACKING OF SCROLLBARS. pack .fRcanvas.can \ -side top \ -anchor n \ -fill both \ -expand 1 ##+################################################## ## END OF DEFINITION of the GUI widgets. ##+################################################## ## Start of BINDINGS, PROCS, Added-GUI-INIT sections. ##+################################################## ##+################################################################## ##+################################################################## ## BINDINGS SECTION: ##+################################################################## ##+########################################################################### ## BINDINGS for 3 'ORIGINAL TRIANGLE' VERTEX/POINT OBJECTS on the canvas widget: ## ## Note that (except for button1-motion on the canvas) we are NOT putting ## bindings on the entire canvas. We use '.fRcanvas.can bind TAGpointOrigTri' ## to avoid move-operations being performed on objects on the canvas ## other than the 3 vertex points of the 'original' triangle. ## ## In other words, we do not want these bindings to allow the user to move ## - the 3 'peak' points that define the 3 'base' equilateral triangles ## - the sides/lines of the 'original' triangle and the 3 'base' equilateral triangles ## - the sides/lines of the 'outer' or 'inner' triangle connecting the centers of ## the 3 'base' triangles ## - any text objects put on the canvas. ## ## See the 'plot.tcl' demo that comes with Tcl-Tk. ## Example location: /usr/share/doc/tk8.5/examples/plot.tcl ##+########################################################################### .fRcanvas.can bind TAGpointOrigTri {pointSelect %x %y} bind .fRcanvas.can {pointMove %x %y} .fRcanvas.can bind TAGpointOrigTri {pointMoveEnd %x %y} ##+####################################################################### ## Let us give a color-change hint when a point is a 'subject' for ## button1-press action --- i.e. subject to movement by the user. ##+####################################################################### .fRcanvas.can bind TAGpointOrigTri \ {.fRcanvas.can itemconfig current -fill "#ffffff"} .fRcanvas.can bind TAGpointOrigTri \ {.fRcanvas.can itemconfig current -fill $COLORPOINThex} ##+####################################################################### ## If the 'outward' radiobutton is clicked, ## clear the canvas and redraw according to the current ## setting of the 'outward' and 'inward' buttons. ##+####################################################################### bind .fRbuttons.radbuttOUTER {reset} ##+####################################################################### ## If the 'inward' radiobutton is clicked, ## clear the canvas and redraw according to the current ## setting of the 'outward' and 'inward' radiobuttons. ##+####################################################################### bind .fRbuttons.radbuttINNER {reset} ##+####################################################################### ## If the 'both' radiobutton is clicked, ## clear the canvas and redraw according to the current ## setting of the 'outward' and 'inward' radiobuttons. ##+####################################################################### bind .fRbuttons.radbuttBOTH {reset} ##+################################################################## ##+################################################################## ## PROCS SECTION: ## ## 'initDraw' - This proc is called in the 'Additional GUI ## Initialization' section at the bottom of this ## script to put an initial drawing of the 'original' ## triangle --- and the requested 3 or 6 'base' ## equilateral triangles, ## and the 'outer' or 'inner' triangle that ## connects the centers of the 'base' triangles ## --- on the canvas. ## Also called in the 'reset' proc. ## ## 'reset' - This proc clears the canvas and runs 'initDraw'. ## Called by the 'Reset' button and some bindings. ## ## The following 3 procs handle moving an 'original' triangle vertex point ## --- any of the 3 points called A,B,C. ## ## 'pointSelect' - called by a button1-press binding on an 'OrigTri'-point-tag of the canvas. ## 'pointMove' - called by a button1-motion binding on the canvas. ## 'pointMoveEnd' - called by a button1-release binding on an 'OrigTri'-point-tag of the canvas. ## ## The following 3 procs handle redrawing the various triangles, points, and text ## --- for a move of point A, B, or C. ## ## 'redraw4movedA' - called by proc 'pointMoveEnd', to delete and redraw the points, ## lines, and text affected by moving 'original-triangle' point A. ## 'redraw4movedB' - called by proc 'pointMoveEnd', to delete and redraw the points, ## lines, and text affected by moving 'original-triangle' point B. ## 'redraw4movedC' - called by proc 'pointMoveEnd', to delete and redraw the points, ## lines, and text affected by moving 'original-triangle' point C. ## ## 'show_state' - reports on the state of the current image: ## - the coordinates of the 3 'original-triangle' vertex points - A,B,C ## - the coordinates of the 3 'peak' vertex points of the 3 ## 'base' equilateral triangles - points AB,BC,CA - ## 'outward' or 'inward', ## - the lengths of the 3 sides/line-segments of the 'original triangle' ## - the lengths of the 6 other sides of the 'base' equilateral ## triangles --- 'outward' or 'inward' ## - the coordinates of the 3 centers of the 3 'base' equilateral ## triangles --- 'outward' or 'inward' ## - the lengths of the 3 lines/sides connecting the 3 centers of the ## 3 'base' equilateral triangles --- 'outer' or 'inner' triangles ## - the area of the 'outer-centers' triangle, if drawn ## - the area of the 'inner-centers' triangle, if drawn ## - the difference of the 2 areas, if both the 'outer-centers' and ## the 'inner-centers' triangle are drawn. ## Called by the 'ShowState' button. ## ## 'area_triangle_3points' - returns the area of a triangle for coordinates of 3 vertices. ## Called by the 'show_state' proc. ## ## Other utility procs: ## ## 'set_background_color' - Sets the color for the canvas (background). ## Called by the 'BackgroundColor' button. ## ## 'set_line_color' - Sets the color for the circle on the canvas. ## Called by the 'LineColor' button. ## ## 'set_point_color' - Sets the color for the inscribed polygon. ## Called by the 'PointColor' button. ## ## 'update_button_colors' - Sets the color of the 4 color buttons. ## Called by the 'set_*_color' procs. ## ## 'advise_user' - Used by various procs to put a message for ## the user on a message line of the GUI. ## ## 'popup_msgVarWithScroll' - called by 'Help' button to show HELPtext var. ## ##+################################################################# ##+######################################################################## ## PROC 'initDraw' ##+######################################################################## ## PURPOSE: Puts an initial drawing of the 'original' triangle with vertex ## points A,B,C --- and the 3 'outward' or 'inward' 'base' ## equilateral triangles, and their 'outer' or 'inner' triangle ## that connects the centers of the 3 outward or inward 'base' ## equilateral triangles --- on the canvas. ## ## CALLED BY: the 'Additional GUI Initialization' section at the ## bottom of this Tk script. ##+######################################################################## proc initDraw {} { ## FOR TESTING: (to dummy out this proc) # return ## INPUT globals: global lineWidthPx COLORLINEhex COLORPOINThex curFONTspecs curFONTSMALLspecs \ dashPatternOrig dashPatternPeakOut dashPatternPeakIn \ dashPatternNapOut dashPatternNapIn \ pointRADIUSpx pointOUTLINEWIDTHpx pointOUTLINECOLORhex \ VARradbuttsOUTorIN sqrt3 sqrt3over3 ## OUTPUT globals: global AxPx AyPx BxPx ByPx CxPx CyPx \ peakABout_xPx peakABout_yPx peakBCout_xPx peakBCout_yPx peakCAout_xPx peakCAout_yPx \ centABout_xPx centABout_yPx centBCout_xPx centBCout_yPx centCAout_xPx centCAout_yPx \ peakABin_xPx peakABin_yPx peakBCin_xPx peakBCin_yPx peakCAin_xPx peakCAin_yPx \ centABin_xPx centABin_yPx centBCin_xPx centBCin_yPx centCAin_xPx centCAin_yPx # global PrevImgWidthPx PrevImgHeightPx ############################################################ ## Use a 'wm geometry' command to get the window to resize ## according to the Tk 'pack' window-geometry manager --- ## for example, after the user has manually resized the ## top window. ## ## Reference: wiki.tcl.tk/10720 and wiki.tcl.tk/44 ## and page 237 of Ousterhout's book 'Tcl and the Tk Toolkit': ## "If you would like to restore a window to its natural ## size, you can invoke 'wm geometry' with an empty ## geometry string." ############################################################ # wm geometry . {} ################################################################## ## Use 'update' to make sure the 'pack' geometry manager has ## set the width and height of the canvas widget. ################################################################## update ################################################################ ## Get the current width & height of the image area that we ## are going to use --- the dimensions of the canvas widget. ################################################################ set CurImgWidthPx [winfo width .fRcanvas.can] set CurImgHeightPx [winfo height .fRcanvas.can] ## FOR TESTING: if {0} { puts "" puts "proc 'initDraw':" puts "CurImgWidthPx: $CurImgWidthPx CurImgHeightPx: $CurImgHeightPx" } ################################################################ ## Store the current width & height in 'Prev' variables --- for ## use in other draw procs to check if the mapping between ## world-coordinates and pixel-coordinates needs to be changed. ################################################################ # set PrevImgWidthPx $CurImgWidthPx # set PrevImgHeightPx $CurImgHeightPx ############################################################ ## Set the 'scrollregion' of the canvas according to the ## requested canvas size. (A simple 'update' does not work.) ## COMMENTED. ## We will use this if we put scrollbars on the canvas. ############################################################ # .fRcanvas.can configure -scrollregion "0 0 $CurImgWidthPx $CurImgHeightPx" ##+################################################## ## Set the initial coordinates of the 3 vertices --- ## A,B,C --- of the 'original' triangle. ## ## We keep the x and y (pixel) coordinates between ## of the current width and height of the canvas. ## ## If OUTWARD (or BOTH) 'base' triangles are requested, ## we put points A,B,C near the center of the canvas. ## ## If INWARD 'base' triangles are requested, ## we put points A,B,C nearer the edges of the canvas. ##+################################################## if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { set AxPx [expr {0.4 * $CurImgWidthPx}] set AyPx [expr {0.4 * $CurImgHeightPx}] set BxPx [expr {0.3 * $CurImgWidthPx}] set ByPx [expr {0.6 * $CurImgHeightPx}] set CxPx [expr {0.5 * $CurImgWidthPx}] set CyPx [expr {0.5 * $CurImgHeightPx}] } if {"$VARradbuttsOUTorIN" == "in"} { set AxPx [expr {0.25 * $CurImgWidthPx}] set AyPx [expr {0.25 * $CurImgHeightPx}] set BxPx [expr {0.3 * $CurImgWidthPx}] set ByPx [expr {0.7 * $CurImgHeightPx}] set CxPx [expr {0.5 * $CurImgWidthPx}] set CyPx [expr {0.75 * $CurImgHeightPx}] } ############################################### ## Draw the line from A to B. ############################################### .fRcanvas.can create line \ $AxPx $AyPx $BxPx $ByPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrigTri TAGlineAB} ############################################### ## Draw the line from B to C. ############################################### .fRcanvas.can create line \ $BxPx $ByPx $CxPx $CyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrigTri TAGlineBC} ############################################### ## Draw the line from C to A. ############################################### .fRcanvas.can create line \ $CxPx $CyPx $AxPx $AyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrigTri TAGlineCA} ############################################### ## Calculate the midpoints of lines AB,BC,CA. ############################################### set midABxPx [expr {($AxPx + $BxPx)/2.0}] set midAByPx [expr {($AyPx + $ByPx)/2.0}] set midBCxPx [expr {($BxPx + $CxPx)/2.0}] set midBCyPx [expr {($ByPx + $CyPx)/2.0}] set midCAxPx [expr {($CxPx + $AxPx)/2.0}] set midCAyPx [expr {($CyPx + $AyPx)/2.0}] ######################################################## ## If 'outward' equilateral triangles are requested, ## calculate the 3 'peak' points of the 3 'outward-base' ## equilateral triangles. ## Also calculate the center points of the ## the 3 'outward-base' equilateral triangles. ## ## Then draw the 3 'outward-base' equilateral triangles. ## And draw the 'outer' Napoleon triangle that ## connects the 3 center points. ######################################################## if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side AB. ############################################################ ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'outward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set peakABout_xPx [expr {$midABxPx - ($dy*$sqrt3)}] set peakABout_yPx [expr {$midAByPx + ($dx*$sqrt3)}] .fRcanvas.can create line \ $AxPx $AyPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} ########################################################### ## Draw text characters 'AB' near the 'peak' vertex (point) ## of the 'base' triangle on side AB. ########################################################### .fRcanvas.can create text \ $peakABout_xPx [expr {$peakABout_yPx + (1.5 * $pointRADIUSpx)}] \ -anchor se \ -fill $COLORPOINThex -font "$curFONTSMALLspecs" \ -text "AB" -tags {TAGtext TAGtextABpeak} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side BC. ############################################################ ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'outward' --- in a section at top of this script. set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set peakBCout_xPx [expr {$midBCxPx - ($dy*$sqrt3)}] set peakBCout_yPx [expr {$midBCyPx + ($dx*$sqrt3)}] .fRcanvas.can create line \ $BxPx $ByPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} .fRcanvas.can create line \ $CxPx $CyPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} ########################################################### ## Draw text characters 'BC' near the 'peak' vertex (point) ## of the 'base' triangle on side BC. ########################################################### .fRcanvas.can create text \ $peakBCout_xPx [expr {$peakBCout_yPx + (1.5 * $pointRADIUSpx)}] \ -anchor ne \ -fill $COLORPOINThex -font "$curFONTSMALLspecs" \ -text "BC" -tags {TAGtext TAGtextBCpeak} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side CA. ############################################################ ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'outward' --- in a section at top of this script. set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set peakCAout_xPx [expr {$midCAxPx - ($dy*$sqrt3)}] set peakCAout_yPx [expr {$midCAyPx + ($dx*$sqrt3)}] .fRcanvas.can create line \ $CxPx $CyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} .fRcanvas.can create line \ $AxPx $AyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} ########################################################### ## Draw text characters 'CA' near the 'peak' vertex (point) ## of the 'base' triangle on side CA. ########################################################### .fRcanvas.can create text \ $peakCAout_xPx [expr {$peakCAout_yPx + (1.5 * $pointRADIUSpx)}] \ -anchor sw \ -fill $COLORPOINThex -font "$curFONTSMALLspecs" \ -text "CA" -tags {TAGtext TAGtextCApeak} ##################################################### ## Draw the 3 sides of the 'outer' Napoleon triangle. ##################################################### set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set centABout_xPx [expr {$midABxPx - ($dy*$sqrt3over3)}] set centABout_yPx [expr {$midAByPx + ($dx*$sqrt3over3)}] set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set centBCout_xPx [expr {$midBCxPx - ($dy*$sqrt3over3)}] set centBCout_yPx [expr {$midBCyPx + ($dx*$sqrt3over3)}] set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set centCAout_xPx [expr {$midCAxPx - ($dy*$sqrt3over3)}] set centCAout_yPx [expr {$midCAyPx + ($dx*$sqrt3over3)}] .fRcanvas.can create line \ $centABout_xPx $centABout_yPx $centBCout_xPx $centBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutAB2BC} .fRcanvas.can create line \ $centBCout_xPx $centBCout_yPx $centCAout_xPx $centCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutBC2CA} .fRcanvas.can create line \ $centCAout_xPx $centCAout_yPx $centABout_xPx $centABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutCA2AB} } ## END OF if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} ####################################################### ## If 'inward' equilateral triangles are requested, ## calculate the 3 'peak' points of the 3 'inward-base' ## equilateral triangles. ## Also calculate the center points of the ## the 3 'inward-base' equilateral triangles. ## ## Then draw the 3 'inward-base' equilateral triangles. ## And draw the 'inner' Napoleon triangle that ## connects the 3 center points. ####################################################### if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} { ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side AB. ############################################################ ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'inward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set peakABin_xPx [expr {$midABxPx + ($dy*$sqrt3)}] set peakABin_yPx [expr {$midAByPx - ($dx*$sqrt3)}] .fRcanvas.can create line \ $AxPx $AyPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} ########################################################### ## Draw text characters 'AB' near the 'peak' vertex (point) ## of the 'base' triangle on side AB. ########################################################### .fRcanvas.can create text \ $peakABin_xPx [expr {$peakABin_yPx + (1.5 * $pointRADIUSpx)}] \ -anchor w \ -fill $COLORPOINThex -font "$curFONTSMALLspecs" \ -text "AB" -tags {TAGtext TAGtextABpeak} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side BC. ############################################################ set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set peakBCin_xPx [expr {$midBCxPx + ($dy*$sqrt3)}] set peakBCin_yPx [expr {$midBCyPx - ($dx*$sqrt3)}] .fRcanvas.can create line \ $BxPx $ByPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} .fRcanvas.can create line \ $CxPx $CyPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} ########################################################### ## Draw text characters 'BC' near the 'peak' vertex (point) ## of the 'base' triangle on side BC. ########################################################### .fRcanvas.can create text \ $peakBCin_xPx [expr {$peakBCin_yPx - (1.5 * $pointRADIUSpx)}] \ -anchor s \ -fill $COLORPOINThex -font "$curFONTSMALLspecs" \ -text "BC" -tags {TAGtext TAGtextBCpeak} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side CA. ############################################################ ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'inward' --- in a section at top of this script. set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set peakCAin_xPx [expr {$midCAxPx + ($dy*$sqrt3)}] set peakCAin_yPx [expr {$midCAyPx - ($dx*$sqrt3)}] .fRcanvas.can create line \ $CxPx $CyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} .fRcanvas.can create line \ $AxPx $AyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} ########################################################### ## Draw text characters 'CA' near the 'peak' vertex (point) ## of the 'base' triangle on side CA. ########################################################### .fRcanvas.can create text \ $peakCAin_xPx [expr {$peakCAin_yPx - (1.5 * $pointRADIUSpx)}] \ -anchor e \ -fill $COLORPOINThex -font "$curFONTSMALLspecs" \ -text "CA" -tags {TAGtext TAGtextCApeak} ##################################################### ## Draw the 3 sides of the 'inner' Napoleon triangle. ##################################################### ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'inward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set centABin_xPx [expr {$midABxPx + ($dy*$sqrt3over3)}] set centABin_yPx [expr {$midAByPx - ($dx*$sqrt3over3)}] set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set centBCin_xPx [expr {$midBCxPx + ($dy*$sqrt3over3)}] set centBCin_yPx [expr {$midBCyPx - ($dx*$sqrt3over3)}] set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set centCAin_xPx [expr {$midCAxPx + ($dy*$sqrt3over3)}] set centCAin_yPx [expr {$midCAyPx - ($dx*$sqrt3over3)}] ## Instead of drawing 3 lines for the 'inner' Napoleon triangle, ## we draw a filled polygon (triangle). if {0} { .fRcanvas.can create line \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInAB2BC} .fRcanvas.can create line \ $centBCin_xPx $centBCin_yPx $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInBC2CA} .fRcanvas.can create line \ $centCAin_xPx $centCAin_yPx $centABin_xPx $centABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInCA2AB} } .fRcanvas.can create poly \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex \ -outline $COLORLINEhex -width $lineWidthPx \ -tags {TAGlinesNapIn} } ## END OF if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} #################################################### ## Draw circles representing the 3 vertices (points) ## of the 'original' triangle --- A,B,C. #################################################### set ulXpx [expr {$AxPx - $pointRADIUSpx}] set ulYpx [expr {$AyPx - $pointRADIUSpx}] set lrXpx [expr {$AxPx + $pointRADIUSpx}] set lrYpx [expr {$AyPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointA} set ulXpx [expr {$BxPx - $pointRADIUSpx}] set ulYpx [expr {$ByPx - $pointRADIUSpx}] set lrXpx [expr {$BxPx + $pointRADIUSpx}] set lrYpx [expr {$ByPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointB} set ulXpx [expr {$CxPx - $pointRADIUSpx}] set ulYpx [expr {$CyPx - $pointRADIUSpx}] set lrXpx [expr {$CxPx + $pointRADIUSpx}] set lrYpx [expr {$CyPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointC} #################################################### ## Draw a text character near the 3 vertices (points) ## of the 'original' triangle --- A,B,C. #################################################### .fRcanvas.can create text $AxPx [expr {$AyPx - (1.5 * $pointRADIUSpx)}] \ -anchor s \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "A" -tags {TAGtext TAGtextA} .fRcanvas.can create text [expr {$BxPx - (1.5 * $pointRADIUSpx)}] $ByPx \ -anchor e \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "B" -tags {TAGtext TAGtextB} .fRcanvas.can create text [expr {$CxPx + (1.5 * $pointRADIUSpx)}] $CyPx \ -anchor w \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "C" -tags {TAGtext TAGtextC} } ## END OF PROC 'initDraw' ##+######################################################################## ## PROC 'reset' ##+######################################################################## ## PURPOSE: Clears the canvas and calls proc 'initDraw'. ## ## CALLED BY: the 'Reset' button ##+######################################################################## proc reset {} { .fRcanvas.can delete all initDraw } ## END OF PROC 'reset' ##+######################################################### ## PROC: 'pointSelect' ##+######################################################### ## PURPOSE: Determines an object-ID to move. ## Gets the ID of the 'current' selected object ## on the canvas, at the button-press location. ## ## Sets the current x,y in vars prevXpx and prevYpx ## --- for use in the 'pointMove' proc. ## ## CALLED BY: a button1-PRESS binding on the canvas, namely ## .fRcanvas.can bind TAGpointOrigTri ... ##+######################################################## proc pointSelect {Xpx Ypx} { ## FOR TESTING: (to dummy out this proc) # return ## OUTPUT globals: global moveID prevXpx prevYpx ################################################################## ## Map from view coordinates to canvas coordinates, per ## page 559 of 4th edition of 'Practical Programming in Tcl & Tk'. ## ## (This may only be needed if we put scrollbars on the canvas.) ################################################################## # set Xpx [.fRcanvas.can canvasx $Xpx] # set Ypx [.fRcanvas.can canvasy $Ypx] ######################################################################## ## Tag the 'current' canvas (point) object with tag 'TAGselected'. ######################################################################## ## Reference: plot.tcl of the Tcl-Tk demos. See BINDINGS section above. ######################################################################## .fRcanvas.can dtag TAGselected .fRcanvas.can addtag TAGselected withtag current .fRcanvas.can raise TAGselected ####################################################################### ## Get the ID of the 'current' (selected) item. ####################################################################### set moveID [.fRcanvas.can find withtag TAGselected] ## FOR TESTING: if {0} { puts "" puts "PROC 'pointSelect' selected canvas object:" puts " moveID = $moveID" } ############################################## ## Put a status message in the status frame. ## ## COMMENTED. This causes the canvas to resize ## --- narrower. ############################################## # advise_user "Point ID $moveID selected." # update #################################################################### ## Hold these coordinates for use in the other 2 'pointMove' procs ## --- 'pointMove' and 'pointMoveEnd'. #################################################################### set prevXpx $Xpx set prevYpx $Ypx ############################################################## ## We COULD delete the 2 lines attached to this point now, ## and the 2 affected mid-points, and the line connecting those ## mid-points. ## Then we could re-draw them in proc 'pointMoveEnd'. ## OR ## We could delete the lines-and-points AND redraw them ## in proc 'pointMoveEnd'. ## ## We will do both the delete and the redraw in proc 'pointMoveEnd'. ## ## If that is too confusing to the user, we could do the delete here. ## ## What would probably be least confusing to the user is to ## 'rubber band' the 4 lines in the 'pointMove' proc. But that ## is extra processing (and code). We avoid that for now. ################################################################## ## FOR TESTING: if {0} { puts "" puts "PROC 'pointSelect' detected" puts "moveID: $moveID" puts "pixel coordinates Xpx: $Xpx Ypx: $Ypx" set TAGS_for_moveID [.fRcanvas.can gettags $moveID] puts "TAGS_for_moveID: $TAGS_for_moveID" } } ## END OF PROC 'pointSelect' ##+############################################################# ## proc 'pointMove' ##+############################################################# ## PURPOSE: Moves a selected point, whose ID is in var 'moveID', ## according to the current x,y pixel coordinates. ## ## CALLED BY: bind .fRcanvas.can ##+######################################################### proc pointMove {Xpx Ypx} { ## FOR TESTING: (to dummy out this proc) # return ## INPUT globals: global moveID ## INPUT AND OUTPUT globals: global prevXpx prevYpx #################################################### ## If a point is not currently selected, exit. #################################################### if {![info exists moveID]} {return} if {"$moveID" == ""} {return} ################################################################## ## Map from view coordinates to canvas coordinates, per ## page 559 of 4th edition of 'Practical Programming in Tcl & Tk'. ## ## (This may only be needed if we put scrollbars on the canvas.) ################################################################## # set Xpx [.fRcanvas.can canvasx $Xpx] # set Ypx [.fRcanvas.can canvasy $Ypx] ######################################################## ## Reset the location of object $moveID on the canvas, ## by the 'delta' from the previous location. ######################################################## .fRcanvas.can move $moveID [expr {$Xpx - $prevXpx}] [expr {$Ypx - $prevYpx}] ######################################################################## ## Alternatively: Move the item with tag 'TAGselected'. ######################################################################## ## Reference: plot.tcl of the Tcl-Tk demos. See BINDINGS section above. ######################################################################## # .fRcanvas.can move TAGselected [expr {$Xpx - $prevXpx}] [expr {$Ypx - $prevYpx}] ############################################################# ## Save the new position for use in these 'pointMove' procs. ############################################################# set prevXpx $Xpx set prevYpx $Ypx ## FOR TESTING: if {0} { puts "" puts "PROC 'pointMove' > Moved object $moveID to $Xpx $Ypx" set TAGS_for_moveID [.fRcanvas.can gettags $moveID] puts "TAGS_for_moveID: $TAGS_for_moveID" } } ## END OF PROC 'pointMove' ##+############################################################## ## PROC: 'pointMoveEnd' ##+############################################################## ## PURPOSE: Get the new x,y pixel coordinates of the moving point, ## whose canvas ID is in var 'moveID'. ## ## Redraw the triangles configuration, according to ## whether point A, B, or C, is being moved. ## ## CALLED BY: a button1-release binding on the canvas, namely ## fRcanvas.can bind TAGpointOrigTri ... ##+############################################################## proc pointMoveEnd {Xpx Ypx} { ## FOR TESTING: (to dummy out this proc) # return ## INPUT globals: global moveID prevXpx prevYpx aRtext #################################################### ## If a point is not currently selected, exit. #################################################### if {![info exists moveID]} {return} if {"$moveID" == ""} {return} ################################################################## ## Map from view coordinates to canvas coordinates, per ## page 559 of 4th edition of 'Practical Programming in Tcl & Tk'. ## ## (This may only be needed if we put scrollbars on the canvas.) ################################################################## # set Xpx [.fRcanvas.can canvasx $Xpx] # set Ypx [.fRcanvas.can canvasy $Ypx] ############################################################# ## Reset the location of the point $moveID on the canvas, ## according to the 'delta' from the previous positon. ############################################################# .fRcanvas.can move $moveID [expr {$Xpx - $prevXpx}] [expr {$Ypx - $prevYpx}] ####################################################### ## Determine which of points A,B,C,D is being moved. ####################################################### set TAGS_for_moveID [.fRcanvas.can gettags $moveID] set moveLETTER "" if {[lsearch -exact $TAGS_for_moveID TAGpointA] != -1} { set moveLETTER "A" } elseif {[lsearch -exact $TAGS_for_moveID TAGpointB] != -1} { set moveLETTER "B" } elseif {[lsearch -exact $TAGS_for_moveID TAGpointC] != -1} { set moveLETTER "C" } ## FOR TESTING: if {0} { puts "" puts "PROC 'pointMoveEnd' > Moved object $moveID to $Xpx $Ypx" puts "moveLETTER: $moveLETTER" } ############################################## ## Put a message in the message frame. ############################################## advise_user "Point $moveLETTER was moved to $Xpx,$Ypx pixel coordinates. $aRtext(labelDRAG)" update ############################################## ## For the indicated point (A, B, or C), ## perform the appropriate redraw processing. ############################################## if {"$moveLETTER" == "A"} { redraw4movedA $Xpx $Ypx } elseif {"$moveLETTER" == "B"} { redraw4movedB $Xpx $Ypx } elseif {"$moveLETTER" == "C"} { redraw4movedC $Xpx $Ypx } ################################################################ ## We are done with this move. ## Let us blank out var 'moveID' to make sure we do not move ## this point anymore until a new select (button-press) event. ################################################################ set moveID "" ############################################################# ## Remove the tag 'TAGselected'. ######################################################################## ## Reference: plot.tcl of the Tcl-Tk demos. See BINDINGS section above. ######################################################################## .fRcanvas.can dtag TAGselected } ## END OF PROC 'pointMoveEnd' ##+############################################################# ## PROC 'redraw4movedA' ##+############################################################# ## PURPOSE: When point A of the 'original' triangle is moved, ## this proc is called to delete and redraw ## - a point and 2 lines of the 'original' triangle ## - 2 sides of two of the 'outward' or 'inward' ## equilateral triangles that are based on the ## 2 sides of the original triangle that were redrawn. ## - the 'outer' or 'inner' Napoleon triangle. ## ## CALLED BY: proc 'pointMoveEnd' ##+############################################################# proc redraw4movedA {Xpx Ypx} { ## FOR TESTING: (dummy out this routine) # return ## INPUT globals: global CxPx CyPx BxPx ByPx sqrt3 sqrt3over3 VARradbuttsOUTorIN \ peakBCout_xPx peakBCout_yPx \ centBCout_xPx centBCout_yPx \ peakBCin_xPx peakBCin_yPx \ centBCin_xPx centBCin_yPx \ lineWidthPx dashPatternOrig dashPatternPeakOut dashPatternPeakIn \ dashPatternNapOut dashPatternNapIn \ COLORLINEhex COLORPOINThex curFONTspecs curFONTSMALLspecs \ pointRADIUSpx pointOUTLINEWIDTHpx pointOUTLINECOLORhex ## OUTPUT globals: global AxPx AyPx \ peakABout_xPx peakABout_yPx peakCAout_xPx peakCAout_yPx \ centABout_xPx centABout_yPx centCAout_xPx centCAout_yPx \ peakABin_xPx peakABin_yPx peakCAin_xPx peakCAin_yPx \ centABin_xPx centABin_yPx centCAin_xPx centCAin_yPx ################################################################## ## Delete point A and associated lines and text, namely: ## - the text for point A ## - lines AB and CA ## - the 4 sides of the 2 'outward-base' equilateral triangles ## based on lines AB and CA ## - the 4 sides of the 2 'inward-base' equilateral triangles ## based on lines AB and CA ## - the 3 sides of the 'outer' Napoleon triangle ## - the 3 sides of the 'inner' Napoleon triangle ## In total, delete as many as 18 objects. ################################################################## .fRcanvas.can delete TAGpointA .fRcanvas.can delete TAGtextA .fRcanvas.can delete TAGlineAB .fRcanvas.can delete TAGlineCA .fRcanvas.can delete TAGlinesPeakOutAB .fRcanvas.can delete TAGlinesPeakOutCA .fRcanvas.can delete TAGlinesPeakInAB .fRcanvas.can delete TAGlinesPeakInCA .fRcanvas.can delete TAGtextABpeak .fRcanvas.can delete TAGtextCApeak .fRcanvas.can delete TAGlinesNapOut .fRcanvas.can delete TAGlinesNapIn ################################################################ ## Reset the coordinates of point A. ################################################################ set AxPx $Xpx set AyPx $Ypx ################################################################ ## ReDraw lines AB and CA of the 'original' triangle. ################################################################ .fRcanvas.can create line \ $AxPx $AyPx $BxPx $ByPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineAB} .fRcanvas.can create line \ $CxPx $CyPx $AxPx $AyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineCA} ################################################################ ## Recalculate the midpoints on lines AB and CA. ################################################################ set midABxPx [expr {($AxPx + $BxPx)/2.0}] set midAByPx [expr {($AyPx + $ByPx)/2.0}] set midCAxPx [expr {($AxPx + $CxPx)/2.0}] set midCAyPx [expr {($AyPx + $CyPx)/2.0}] ######################################################## ## If 'outward' equilateral triangles are requested, ## recalculate the 2 'peak' points of the 2 'outward-base' ## equilateral triangles on AB and CA. ## Also calculate the center points of these two ## 'outward-base' equilateral triangles. ## ## Then draw the sides of the 2 'outward-base' equilateral ## triangles on AB and CA. ## And draw the 'outer' Napoleon triangle that ## connects the 3 center points. ######################################################## if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'outward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set peakABout_xPx [expr {$midABxPx - ($dy*$sqrt3)}] set peakABout_yPx [expr {$midAByPx + ($dx*$sqrt3)}] set centABout_xPx [expr {$midABxPx - ($dy*$sqrt3over3)}] set centABout_yPx [expr {$midAByPx + ($dx*$sqrt3over3)}] set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set peakCAout_xPx [expr {$midCAxPx - ($dy*$sqrt3)}] set peakCAout_yPx [expr {$midCAyPx + ($dx*$sqrt3)}] set centCAout_xPx [expr {$midCAxPx - ($dy*$sqrt3over3)}] set centCAout_yPx [expr {$midCAyPx + ($dx*$sqrt3over3)}] ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side AB. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side CA. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} .fRcanvas.can create line \ $AxPx $AyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} ##################################################### ## Draw the 3 sides of the 'outer' Napoleon triangle. ##################################################### .fRcanvas.can create line \ $centABout_xPx $centABout_yPx $centBCout_xPx $centBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutAB2BC} .fRcanvas.can create line \ $centBCout_xPx $centBCout_yPx $centCAout_xPx $centCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutBC2CA} .fRcanvas.can create line \ $centCAout_xPx $centCAout_yPx $centABout_xPx $centABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutCA2AB} } ## END OF if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} ####################################################### ## If 'inward' equilateral triangles are requested, ## calculate the 2 'peak' points of the 2 'inward-base' ## equilateral triangles on sides AB and CA. ## Also calculate the center points of these two ## 'inward-base' equilateral triangles. ## ## Then draw the 2 'inward-base' equilateral triangles. ## And draw the 'inner' Napoleon triangle that ## connects the 3 center points. ####################################################### if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} { ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'inward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set peakABin_xPx [expr {$midABxPx + ($dy*$sqrt3)}] set peakABin_yPx [expr {$midAByPx - ($dx*$sqrt3)}] set centABin_xPx [expr {$midABxPx + ($dy*$sqrt3over3)}] set centABin_yPx [expr {$midAByPx - ($dx*$sqrt3over3)}] set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set peakCAin_xPx [expr {$midCAxPx + ($dy*$sqrt3)}] set peakCAin_yPx [expr {$midCAyPx - ($dx*$sqrt3)}] set centCAin_xPx [expr {$midCAxPx + ($dy*$sqrt3over3)}] set centCAin_yPx [expr {$midCAyPx - ($dx*$sqrt3over3)}] ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side AB. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side CA. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} .fRcanvas.can create line \ $AxPx $AyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} ##################################################### ## Draw the 3 sides of the 'inner' Napoleon triangle. ##################################################### ## Instead of drawing 3 lines for the 'inner' Napoleon triangle, ## we draw a filled polygon (triangle). if {0} { .fRcanvas.can create line \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInAB2BC} .fRcanvas.can create line \ $centBCin_xPx $centBCin_yPx $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInBC2CA} .fRcanvas.can create line \ $centCAin_xPx $centCAin_yPx $centABin_xPx $centABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInCA2AB} } ## END OF 'if {0}' comment .fRcanvas.can create poly \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex \ -outline $COLORLINEhex -width $lineWidthPx \ -tags {TAGlinesNapIn} } ## END OF if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} ################################################################ ## ReDraw the point A. ################################################################ set ulXpx [expr {$AxPx - $pointRADIUSpx}] set ulYpx [expr {$AyPx - $pointRADIUSpx}] set lrXpx [expr {$AxPx + $pointRADIUSpx}] set lrYpx [expr {$AyPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointA} ################################################################ ## Raise points B and C --- so that they cover ends of lines. ################################################################ .fRcanvas.can raise TAGpointB .fRcanvas.can raise TAGpointC #################################################### ## Redraw a text character near vertex A. #################################################### .fRcanvas.can create text $AxPx [expr {$AyPx + (1.5 * $pointRADIUSpx)}] \ -anchor ne \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "A" -tags {TAGtext TAGtextA} } ## END OF PROC 'redraw4movedA' ##+############################################################# ## PROC 'redraw4movedB' ##+############################################################# ## PURPOSE: When point B of the 'original' triangle is moved, ## this proc is called to delete and redraw ## - a point and 2 lines of the 'original' triangle ## - 2 sides of two of the 'outward' or 'inward' ## equilateral triangles that are based on the ## 2 sides of the original triangle that were redrawn. ## - the 'outer' or 'inner' Napoleon triangle. ## ## CALLED BY: proc 'pointMoveEnd' ##+############################################################# proc redraw4movedB {Xpx Ypx} { ## FOR TESTING: (dummy out this routine) # return ## INPUT globals: global AxPx AyPx CxPx CyPx sqrt3 sqrt3over3 VARradbuttsOUTorIN \ peakCAout_xPx peakCAout_yPx \ centCAout_xPx centCAout_yPx \ peakCAin_xPx peakCAin_yPx \ centCAin_xPx centCAin_yPx \ lineWidthPx dashPatternOrig dashPatternPeakOut dashPatternPeakIn \ dashPatternNapOut dashPatternNapIn \ COLORLINEhex COLORPOINThex curFONTspecs curFONTSMALLspecs \ pointRADIUSpx pointOUTLINEWIDTHpx pointOUTLINECOLORhex ## OUTPUT globals: global BxPx ByPx \ peakABout_xPx peakABout_yPx peakBCout_xPx peakBCout_yPx \ centABout_xPx centABout_yPx centBCout_xPx centBCout_yPx \ peakABin_xPx peakABin_yPx peakBCin_xPx peakBCin_yPx \ centABin_xPx centABin_yPx centBCin_xPx centBCin_yPx ################################################################## ## Delete point B and associated lines and text, namely: ## - the text for point B ## - lines AB and BC ## - the 4 sides of the 2 'outward-base' equilateral triangles ## based on lines AB and BC ## - the 4 sides of the 2 'inward-base' equilateral triangles ## based on lines AB and BC ## - the 3 sides of the 'outer' Napoleon triangle ## - the 3 sides of the 'inner' Napoleon triangle ## In total, delete as many as 18 objects. ################################################################## .fRcanvas.can delete TAGpointB .fRcanvas.can delete TAGtextB .fRcanvas.can delete TAGlineAB .fRcanvas.can delete TAGlineBC .fRcanvas.can delete TAGlinesPeakOutAB .fRcanvas.can delete TAGlinesPeakOutBC .fRcanvas.can delete TAGlinesPeakInAB .fRcanvas.can delete TAGlinesPeakInBC .fRcanvas.can delete TAGtextABpeak .fRcanvas.can delete TAGtextBCpeak .fRcanvas.can delete TAGlinesNapOut .fRcanvas.can delete TAGlinesNapIn ################################################################ ## Reset the coordinates of point B. ################################################################ set BxPx $Xpx set ByPx $Ypx ################################################################ ## ReDraw lines AB and BC of the 'original' triangle. ################################################################ .fRcanvas.can create line \ $AxPx $AyPx $BxPx $ByPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineAB} .fRcanvas.can create line \ $BxPx $ByPx $CxPx $CyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineBC} ################################################################ ## Recalculate the midpoints on lines AB and BC. ################################################################ set midABxPx [expr {($AxPx + $BxPx)/2.0}] set midAByPx [expr {($AyPx + $ByPx)/2.0}] set midBCxPx [expr {($BxPx + $CxPx)/2.0}] set midBCyPx [expr {($ByPx + $CyPx)/2.0}] ######################################################## ## If 'outward' equilateral triangles are requested, ## recalculate the 2 'peak' points of the 2 'outward-base' ## equilateral triangles on AB and BC. ## Also calculate the center points of these two ## 'outward-base' equilateral triangles. ## ## Then draw the sides of the 2 'outward-base' equilateral ## triangles on AB and BC. ## And draw the 'outer' Napoleon triangle that ## connects the 3 center points. ######################################################## if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'outward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set peakABout_xPx [expr {$midABxPx - ($dy*$sqrt3)}] set peakABout_yPx [expr {$midAByPx + ($dx*$sqrt3)}] set centABout_xPx [expr {$midABxPx - ($dy*$sqrt3over3)}] set centABout_yPx [expr {$midAByPx + ($dx*$sqrt3over3)}] set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set peakBCout_xPx [expr {$midBCxPx - ($dy*$sqrt3)}] set peakBCout_yPx [expr {$midBCyPx + ($dx*$sqrt3)}] set centBCout_xPx [expr {$midBCxPx - ($dy*$sqrt3over3)}] set centBCout_yPx [expr {$midBCyPx + ($dx*$sqrt3over3)}] ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side AB. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side BC. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} .fRcanvas.can create line \ $BxPx $ByPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} ##################################################### ## Draw the 3 sides of the 'outer' Napoleon triangle. ##################################################### .fRcanvas.can create line \ $centABout_xPx $centABout_yPx $centBCout_xPx $centBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutAB2BC} .fRcanvas.can create line \ $centBCout_xPx $centBCout_yPx $centCAout_xPx $centCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutBC2CA} .fRcanvas.can create line \ $centCAout_xPx $centCAout_yPx $centABout_xPx $centABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutCA2AB} } ## END OF if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} ####################################################### ## If 'inward' equilateral triangles are requested, ## calculate the 2 'peak' points of the 2 'inward-base' ## equilateral triangles on sides AB and BC. ## Also calculate the center points of these two ## 'inward-base' equilateral triangles. ## ## Then draw the 2 'inward-base' equilateral triangles. ## And draw the 'inner' Napoleon triangle that ## connects the 3 center points. ####################################################### if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} { ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'inward' --- in a section at top of this script. set dx [expr {$BxPx - $midABxPx}] set dy [expr {$ByPx - $midAByPx}] set peakABin_xPx [expr {$midABxPx + ($dy*$sqrt3)}] set peakABin_yPx [expr {$midAByPx - ($dx*$sqrt3)}] set centABin_xPx [expr {$midABxPx + ($dy*$sqrt3over3)}] set centABin_yPx [expr {$midAByPx - ($dx*$sqrt3over3)}] set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set peakBCin_xPx [expr {$midBCxPx + ($dy*$sqrt3)}] set peakBCin_yPx [expr {$midBCyPx - ($dx*$sqrt3)}] set centBCin_xPx [expr {$midBCxPx + ($dy*$sqrt3over3)}] set centBCin_yPx [expr {$midBCyPx - ($dx*$sqrt3over3)}] ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side AB. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side BC. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} .fRcanvas.can create line \ $BxPx $ByPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} ##################################################### ## Draw the 3 sides of the 'inner' Napoleon triangle. ##################################################### ## Instead of drawing 3 lines for the 'inner' Napoleon triangle, ## we draw a filled polygon (triangle). if {0} { .fRcanvas.can create line \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInAB2BC} .fRcanvas.can create line \ $centBCin_xPx $centBCin_yPx $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInBC2CA} .fRcanvas.can create line \ $centCAin_xPx $centCAin_yPx $centABin_xPx $centABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInCA2AB} } ## END OF 'if {0}' comment .fRcanvas.can create poly \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex \ -outline $COLORLINEhex -width $lineWidthPx \ -tags {TAGlinesNapIn} } ## END OF if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} ################################################################ ## ReDraw the point B. ################################################################ set ulXpx [expr {$BxPx - $pointRADIUSpx}] set ulYpx [expr {$ByPx - $pointRADIUSpx}] set lrXpx [expr {$BxPx + $pointRADIUSpx}] set lrYpx [expr {$ByPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointB} ################################################################ ## Raise points A and C --- so that they cover ends of lines. ################################################################ .fRcanvas.can raise TAGpointA .fRcanvas.can raise TAGpointC #################################################### ## Redraw a text character near vertex B. #################################################### .fRcanvas.can create text $BxPx [expr {$ByPx - (1.5 * $pointRADIUSpx)}] \ -anchor se \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "B" -tags {TAGtext TAGtextB} } ## END OF PROC 'redraw4movedB' ##+############################################################# ## PROC 'redraw4movedC' ##+############################################################# ## PURPOSE: When point C of the 'original' triangle is moved, ## this proc is called to delete and redraw ## - a point and 2 lines of the 'original' triangle ## - 2 sides of two of the 'outward' or 'inward' ## equilateral triangles that are based on the ## 2 sides of the original triangle that were redrawn. ## - the 'outer' or 'inner' Napoleon triangle. ## ## CALLED BY: proc 'pointMoveEnd' ##+############################################################# proc redraw4movedC {Xpx Ypx} { ## FOR TESTING: (dummy out this routine) # return ## INPUT globals: global BxPx ByPx AxPx AyPx sqrt3 sqrt3over3 VARradbuttsOUTorIN \ peakABout_xPx peakABout_yPx \ centABout_xPx centABout_yPx \ peakABin_xPx peakABin_yPx \ centABin_xPx centABin_yPx \ lineWidthPx dashPatternOrig dashPatternPeakOut dashPatternPeakIn \ dashPatternNapOut dashPatternNapIn \ COLORLINEhex COLORPOINThex curFONTspecs curFONTSMALLspecs \ pointRADIUSpx pointOUTLINEWIDTHpx pointOUTLINECOLORhex ## OUTPUT globals: global CxPx CyPx \ peakCAout_xPx peakCAout_yPx peakBCout_xPx peakBCout_yPx \ centCAout_xPx centCAout_yPx centBCout_xPx centBCout_yPx \ peakCAin_xPx peakCAin_yPx peakBCin_xPx peakBCin_yPx \ centCAin_xPx centCAin_yPx centBCin_xPx centBCin_yPx ################################################################## ## Delete point C and associated lines and text, namely: ## - the text for point C ## - lines BC and CA ## - the 4 sides of the 2 'outward-base' equilateral triangles ## based on lines CA and BC ## - the 4 sides of the 2 'inward-base' equilateral triangles ## based on lines CA and BC ## - the 3 sides of the 'outer' Napoleon triangle ## - the 3 sides of the 'inner' Napoleon triangle ## In total, delete as many as 18 objects. ################################################################## .fRcanvas.can delete TAGpointC .fRcanvas.can delete TAGtextC .fRcanvas.can delete TAGlineBC .fRcanvas.can delete TAGlineCA .fRcanvas.can delete TAGlinesPeakOutCA .fRcanvas.can delete TAGlinesPeakOutBC .fRcanvas.can delete TAGlinesPeakInCA .fRcanvas.can delete TAGlinesPeakInBC .fRcanvas.can delete TAGtextCApeak .fRcanvas.can delete TAGtextBCpeak .fRcanvas.can delete TAGlinesNapOut .fRcanvas.can delete TAGlinesNapIn ################################################################ ## Reset the coordinates of point C. ################################################################ set CxPx $Xpx set CyPx $Ypx ################################################################ ## ReDraw lines BC and CA of the 'original' triangle. ################################################################ .fRcanvas.can create line \ $BxPx $ByPx $CxPx $CyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineBC} .fRcanvas.can create line \ $CxPx $CyPx $AxPx $AyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineCA} ################################################################ ## Recalculate the midpoints on lines BC and CA. ################################################################ set midBCxPx [expr {($BxPx + $CxPx)/2.0}] set midBCyPx [expr {($ByPx + $CyPx)/2.0}] set midCAxPx [expr {($CxPx + $AxPx)/2.0}] set midCAyPx [expr {($CyPx + $AyPx)/2.0}] ######################################################## ## If 'outward' equilateral triangles are requested, ## recalculate the 2 'peak' points of the 2 'outward-base' ## equilateral triangles on CA and BC. ## Also calculate the center points of these two ## 'outward-base' equilateral triangles. ## ## Then draw the sides of the 2 'outward-base' equilateral ## triangles on CA and BC. ## And draw the 'outer' Napoleon triangle that ## connects the 3 center points. ######################################################## if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'outward' --- in a section at top of this script. set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set peakCAout_xPx [expr {$midCAxPx - ($dy*$sqrt3)}] set peakCAout_yPx [expr {$midCAyPx + ($dx*$sqrt3)}] set centCAout_xPx [expr {$midCAxPx - ($dy*$sqrt3over3)}] set centCAout_yPx [expr {$midCAyPx + ($dx*$sqrt3over3)}] set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set peakBCout_xPx [expr {$midBCxPx - ($dy*$sqrt3)}] set peakBCout_yPx [expr {$midBCyPx + ($dx*$sqrt3)}] set centBCout_xPx [expr {$midBCxPx - ($dy*$sqrt3over3)}] set centBCout_yPx [expr {$midBCyPx + ($dx*$sqrt3over3)}] ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side CA. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} .fRcanvas.can create line \ $CxPx $CyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side BC. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} .fRcanvas.can create line \ $BxPx $ByPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} ##################################################### ## Draw the 3 sides of the 'outer' Napoleon triangle. ##################################################### .fRcanvas.can create line \ $centABout_xPx $centABout_yPx $centBCout_xPx $centBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutAB2BC} .fRcanvas.can create line \ $centBCout_xPx $centBCout_yPx $centCAout_xPx $centCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutBC2CA} .fRcanvas.can create line \ $centCAout_xPx $centCAout_yPx $centABout_xPx $centABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutCA2AB} } ## END OF if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} ####################################################### ## If 'inward' equilateral triangles are requested, ## calculate the 2 'peak' points of the 2 'inward-base' ## equilateral triangles on sides CA and BC. ## Also calculate the center points of these two ## 'inward-base' equilateral triangles. ## ## Then draw the 2 'inward-base' equilateral triangles. ## And draw the 'inner' Napoleon triangle that ## connects the 3 center points. ####################################################### if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} { ## Set the discussion of computing coords of 'peak' and 'cent' ## points --- 'inward' --- in a section at top of this script. set dx [expr {$AxPx - $midCAxPx}] set dy [expr {$AyPx - $midCAyPx}] set peakCAin_xPx [expr {$midCAxPx + ($dy*$sqrt3)}] set peakCAin_yPx [expr {$midCAyPx - ($dx*$sqrt3)}] set centCAin_xPx [expr {$midCAxPx + ($dy*$sqrt3over3)}] set centCAin_yPx [expr {$midCAyPx - ($dx*$sqrt3over3)}] set dx [expr {$CxPx - $midBCxPx}] set dy [expr {$CyPx - $midBCyPx}] set peakBCin_xPx [expr {$midBCxPx + ($dy*$sqrt3)}] set peakBCin_yPx [expr {$midBCyPx - ($dx*$sqrt3)}] set centBCin_xPx [expr {$midBCxPx + ($dy*$sqrt3over3)}] set centBCin_yPx [expr {$midBCyPx - ($dx*$sqrt3over3)}] ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side CA. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} .fRcanvas.can create line \ $CxPx $CyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side BC. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} .fRcanvas.can create line \ $BxPx $ByPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} ##################################################### ## Draw the 3 sides of the 'inner' Napoleon triangle. ##################################################### ## Instead of drawing 3 lines for the 'inner' Napoleon triangle, ## we draw a filled polygon (triangle). if {0} { .fRcanvas.can create line \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInAB2BC} .fRcanvas.can create line \ $centBCin_xPx $centBCin_yPx $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInBC2CA} .fRcanvas.can create line \ $centCAin_xPx $centCAin_yPx $centABin_xPx $centABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInCA2AB} } ## END OF 'if {0}' comment .fRcanvas.can create poly \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex \ -outline $COLORLINEhex -width $lineWidthPx \ -tags {TAGlinesNapIn} } ## END OF if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} ################################################################ ## ReDraw the point C. ################################################################ set ulXpx [expr {$CxPx - $pointRADIUSpx}] set ulYpx [expr {$CyPx - $pointRADIUSpx}] set lrXpx [expr {$CxPx + $pointRADIUSpx}] set lrYpx [expr {$CyPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointC} ################################################################ ## Raise points B and A --- so that they cover ends of lines. ################################################################ .fRcanvas.can raise TAGpointB .fRcanvas.can raise TAGpointA #################################################### ## Redraw a text character near vertex C. #################################################### .fRcanvas.can create text $CxPx [expr {$CyPx - (1.5 * $pointRADIUSpx)}] \ -anchor sw \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "C" -tags {TAGtext TAGtextC} } ## END OF PROC 'redraw4movedC' ##+##################################################################### ## PROC 'show_state' ##+##################################################################### ## PURPOSE: To report on the state of the current configuration of ## the 'original' triangle and the 'outer' and 'inner' triangles: ## ## - the coordinates of their vertex points ## - the lengths of their line segments (sides) ## ## CALLED BY: the 'ShowState' button ##+##################################################################### proc show_state {} { ## FOR TESTING: (dummy out this routine) # return global AxPx AyPx BxPx ByPx CxPx CyPx VARradbuttsOUTorIN \ peakABout_xPx peakABout_yPx peakCAout_xPx peakCAout_yPx \ peakBCout_xPx peakBCout_yPx \ centABout_xPx centABout_yPx centCAout_xPx centCAout_yPx \ centBCout_xPx centBCout_yPx \ peakABin_xPx peakABin_yPx peakCAin_xPx peakCAin_yPx \ peakBCin_xPx peakBCin_yPx \ centABin_xPx centABin_yPx centCAin_xPx centCAin_yPx \ centBCin_xPx centBCin_yPx ################################################################### ## Calculate the lengths of the sides of the 'original' triangle. ################################################################### set lenAB [expr {hypot($BxPx - $AxPx,$ByPx - $AyPx)}] set lenBC [expr {hypot($CxPx - $BxPx,$CyPx - $ByPx)}] set lenCA [expr {hypot($AxPx - $CxPx,$AyPx - $CyPx)}] ############################################################# ## Compute the area of the 'original' triangle here. ############################################################# ###################################################### ## Create the heading for the state listing along with ## the 'state' of the 'original' triangle. ###################################################### set VARlist \ "tkNapoleonsTheorem - Centers of Equilateral Triangles on ANY Triangle Yield an Equilateral Triangle The following coordinates are 'pixel' coordinates on the canvas. The x-coordinates are measured from the left of the canvas. The y-coordinates are measured from the top of the canvas. STATE OF THE CURRENT CONFIGURATION OF THE 'ORIGINAL' TRIANGLE: Current Coordinates of points A,B,C of the 'original' triangle: Ax,Ay: [format "%-10.4f" $AxPx] , [format "%-10.4f" $AyPx] Bx,By: [format "%-10.4f" $BxPx] , [format "%-10.4f" $ByPx] Cx,Cy: [format "%-10.4f" $CxPx] , [format "%-10.4f" $CyPx] Lengths of the sides of the 'original' triangle: Length of side AB: [format "%-10.4f" $lenAB] Length of side BC: [format "%-10.4f" $lenBC] Length of side CA: [format "%-10.4f" $lenCA] " ######################################################### ## If 'outward' triangles were requested, ## add the 'state' of the 'outward' equilateral triangles ## and the 'outer' Napoleon triangle. ######################################################### if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { ################################################################### ## Calculate the lengths of the sides of the 'outward' ## equilateral triangle on side AB of the 'original' triangle. ################################################################### set lenAB [expr {hypot($BxPx - $AxPx,$ByPx - $AyPx)}] set lenAtoABpeak [expr {hypot($AxPx - $peakABout_xPx,$AyPx - $peakABout_yPx)}] set lenBtoABpeak [expr {hypot($BxPx - $peakABout_xPx,$ByPx - $peakABout_yPx)}] ################################################################### ## Calculate the lengths of the sides of the 'outward' ## equilateral triangle on side BC of the 'original' triangle. ################################################################### set lenBC [expr {hypot($CxPx - $BxPx,$CyPx - $ByPx)}] set lenCtoBCpeak [expr {hypot($CxPx - $peakBCout_xPx,$CyPx - $peakBCout_yPx)}] set lenBtoBCpeak [expr {hypot($BxPx - $peakBCout_xPx,$ByPx - $peakBCout_yPx)}] ################################################################### ## Calculate the lengths of the sides of the 'outward' ## equilateral triangle on side CA of the 'original' triangle. ################################################################### set lenCA [expr {hypot($AxPx - $CxPx,$AyPx - $CyPx)}] set lenAtoCApeak [expr {hypot($AxPx - $peakCAout_xPx,$AyPx - $peakCAout_yPx)}] set lenCtoCApeak [expr {hypot($CxPx - $peakCAout_xPx,$CyPx - $peakCAout_yPx)}] ################################################################### ## Calculate the lengths of the sides of the 'outer' Napoleon ## triangle --- to confirm that it is an equilateral triangle. ################################################################### set lenNapOut_centAB2BC [expr {hypot($centABout_xPx - $centBCout_xPx,$centABout_yPx - $centBCout_yPx)}] set lenNapOut_centBC2CA [expr {hypot($centBCout_xPx - $centCAout_xPx,$centBCout_yPx - $centCAout_yPx)}] set lenNapOut_centCA2AB [expr {hypot($centCAout_xPx - $centBCout_xPx,$centCAout_yPx - $centBCout_yPx)}] ############################################################# ## Compute the area of the 'outer' Napoleon triangle here. ############################################################# set VARlist \ "$VARlist -------------------------------------------------------------- STATE OF THE 'OUTWARD' EQUILATERAL TRIANGLES: Current Coordinates of points of the 'outward' equilateral triangle on side AB of the 'original' triangle: Ax,Ay: [format "%-10.4f" $AxPx] , [format "%-10.4f" $AyPx] Bx,By: [format "%-10.4f" $BxPx] , [format "%-10.4f" $ByPx] peakABout_x,peakABout_y: [format "%-10.4f" $peakABout_xPx] , [format "%-10.4f" $peakABout_yPx] Lengths of the sides of the 'outward' equilateral triangle on side AB of the 'original' triangle: Length of side AB: [format "%-10.4f" $lenAB] Length of side A-to-ABpeak: [format "%-10.4f" $lenAtoABpeak] Length of side B-to-ABpeak: [format "%-10.4f" $lenBtoABpeak] ------------------------------------------------------------------- Current Coordinates of points of the 'outward' equilateral triangle on side BC of the 'original' triangle: Bx,By: [format "%-10.4f" $BxPx] , [format "%-10.4f" $ByPx] Cx,Cy: [format "%-10.4f" $CxPx] , [format "%-10.4f" $CyPx] peakBCout_x,peakBCout_y: [format "%-10.4f" $peakBCout_xPx] , [format "%-10.4f" $peakBCout_yPx] Lengths of the sides of the 'outward' equilateral triangle on side BC of the 'original' triangle: Length of side BC: [format "%-10.4f" $lenBC] Length of side B-to-BCpeak: [format "%-10.4f" $lenBtoBCpeak] Length of side C-to-BCpeak: [format "%-10.4f" $lenCtoBCpeak] ------------------------------------------------------------------- Current Coordinates of points of the 'outward' equilateral triangle on side CA of the 'original' triangle: Cx,Cy: [format "%-10.4f" $CxPx] , [format "%-10.4f" $CyPx] Ax,Ay: [format "%-10.4f" $AxPx] , [format "%-10.4f" $AyPx] peakCAout_x,peakCAout_y: [format "%-10.4f" $peakCAout_xPx] , [format "%-10.4f" $peakCAout_yPx] Lengths of the sides of the 'outward' equilateral triangle on side CA of the 'original' triangle: Length of side CA: [format "%-10.4f" $lenCA] Length of side A-to-CApeak: [format "%-10.4f" $lenAtoCApeak] Length of side C-to-CApeak: [format "%-10.4f" $lenCtoCApeak] ********************************************************************** Current Coordinates of points of the 'OUTER' NAPOLEON TRIANGLE which are center-points of the 3 'outward' equilateral triangles above: ********************************************************************** Center of equilateral triangle on side AB: [format "%-10.4f" $centABout_xPx] , [format "%-10.4f" $centABout_yPx] Center of equilateral triangle on side BC: [format "%-10.4f" $centBCout_xPx] , [format "%-10.4f" $centBCout_yPx] Center of equilateral triangle on side CA: [format "%-10.4f" $centCAout_xPx] , [format "%-10.4f" $centCAout_yPx] Lengths of the sides of the 'outer' Napoleon triangle which connect the center-points of the 3 'outward' equilateral triangles above: Length of side from centers over AB and BC: [format "%-10.4f" $lenNapOut_centAB2BC] Length of side from centers over BC and CA: [format "%-10.4f" $lenNapOut_centBC2CA] Length of side from centers over CA and AB: [format "%-10.4f" $lenNapOut_centCA2AB] NOTE: The 3 sides of the 'outer' Napoleon triangle have the same length. This confirms that THE 'OUTER' NAPLOLEON TRIANGLE IS AN EQUILATERAL TRIANGLE. " } ## END OF if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} ######################################################### ## If 'inward' triangles were requested, ## add the 'state' of the 'inward' equilateral triangles ## and the 'inner' Napoleon triangle. ######################################################### if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} { ################################################################### ## Calculate the lengths of the sides of the 'inward' ## equilateral triangle on side AB of the 'original' triangle. ################################################################### set lenAB [expr {hypot($BxPx - $AxPx,$ByPx - $AyPx)}] set lenAtoABpeak [expr {hypot($AxPx - $peakABin_xPx,$AyPx - $peakABin_yPx)}] set lenBtoABpeak [expr {hypot($BxPx - $peakABin_xPx,$ByPx - $peakABin_yPx)}] ################################################################### ## Calculate the lengths of the sides of the 'inward' ## equilateral triangle on side BC of the 'original' triangle. ################################################################### set lenBC [expr {hypot($CxPx - $BxPx,$CyPx - $ByPx)}] set lenCtoBCpeak [expr {hypot($CxPx - $peakBCin_xPx,$CyPx - $peakBCin_yPx)}] set lenBtoBCpeak [expr {hypot($BxPx - $peakBCin_xPx,$ByPx - $peakBCin_yPx)}] ################################################################### ## Calculate the lengths of the sides of the 'inward' ## equilateral triangle on side CA of the 'original' triangle. ################################################################### set lenCA [expr {hypot($AxPx - $CxPx,$AyPx - $CyPx)}] set lenAtoCApeak [expr {hypot($AxPx - $peakCAin_xPx,$AyPx - $peakCAin_yPx)}] set lenCtoCApeak [expr {hypot($CxPx - $peakCAin_xPx,$CyPx - $peakCAin_yPx)}] ################################################################### ## Calculate the lengths of the sides of the 'inner' Napoleon ## triangle --- to confirm that it is an equilateral triangle. ################################################################### set lenNapIn_centAB2BC [expr {hypot($centABin_xPx - $centBCin_xPx,$centABin_yPx - $centBCin_yPx)}] set lenNapIn_centBC2CA [expr {hypot($centBCin_xPx - $centCAin_xPx,$centBCin_yPx - $centCAin_yPx)}] set lenNapIn_centCA2AB [expr {hypot($centCAin_xPx - $centBCin_xPx,$centCAin_yPx - $centBCin_yPx)}] ############################################################# ## Compute the area of the 'inner' Napoleon triangle here. ############################################################# set VARlist \ "$VARlist -------------------------------------------------------------- STATE OF THE 'INWARD' EQUILATERAL TRIANGLES: Current Coordinates of points of the 'inward' equilateral triangle on side AB of the 'original' triangle: Ax,Ay: [format "%-10.4f" $AxPx] , [format "%-10.4f" $AyPx] Bx,By: [format "%-10.4f" $BxPx] , [format "%-10.4f" $ByPx] peakABin_x,peakABin_y: [format "%-10.4f" $peakABin_xPx] , [format "%-10.4f" $peakABin_yPx] Lengths of the sides of the 'inward' equilateral triangle on side AB of the 'original' triangle: Length of side AB: [format "%-10.4f" $lenAB] Length of side A-to-ABpeak: [format "%-10.4f" $lenAtoABpeak] Length of side B-to-ABpeak: [format "%-10.4f" $lenBtoABpeak] ------------------------------------------------------------------ Current Coordinates of points of the 'inward' equilateral triangle on side BC of the 'original' triangle: Bx,By: [format "%-10.4f" $BxPx] , [format "%-10.4f" $ByPx] Cx,Cy: [format "%-10.4f" $CxPx] , [format "%-10.4f" $CyPx] peakBCin_x,peakBCin_y: [format "%-10.4f" $peakBCin_xPx] , [format "%-10.4f" $peakBCin_yPx] Lengths of the sides of the 'inward' equilateral triangle on side BC of the 'original' triangle: Length of side BC: [format "%-10.4f" $lenBC] Length of side B-to-BCpeak: [format "%-10.4f" $lenBtoBCpeak] Length of side C-to-BCpeak: [format "%-10.4f" $lenCtoBCpeak] ------------------------------------------------------------------ Current Coordinates of points of the 'inward' equilateral triangle on side CA of the 'original' triangle: Cx,Cy: [format "%-10.4f" $CxPx] , [format "%-10.4f" $CyPx] Ax,Ay: [format "%-10.4f" $AxPx] , [format "%-10.4f" $AyPx] peakCAin_x,peakCAin_y: [format "%-10.4f" $peakCAin_xPx] , [format "%-10.4f" $peakCAin_yPx] Lengths of the sides of the 'inward' equilateral triangle on side CA of the 'original' triangle: Length of side CA: [format "%-10.4f" $lenCA] Length of side C-to-CApeak: [format "%-10.4f" $lenCtoCApeak] Length of side A-to-CApeak: [format "%-10.4f" $lenAtoCApeak] ********************************************************************* Current Coordinates of points of the 'INNER' NAPOLEON TRIANGLE which are center-points of the 3 'inward' equilateral triangles above: ********************************************************************* Center of equilateral triangle on side AB: [format "%-10.4f" $centABin_xPx] , [format "%-10.4f" $centABin_yPx] Center of equilateral triangle on side BC: [format "%-10.4f" $centBCin_xPx] , [format "%-10.4f" $centBCin_yPx] Center of equilateral triangle on side CA: [format "%-10.4f" $centCAin_xPx] , [format "%-10.4f" $centCAin_yPx] Lengths of the sides of the 'inner' Napoleon triangle which connect the center-points of the 3 'inward' equilateral triangles above: Length of side from centers over AB and BC: [format "%-10.4f" $lenNapIn_centAB2BC] Length of side from centers over BC and CA: [format "%-10.4f" $lenNapIn_centBC2CA] Length of side from centers over CA and AB: [format "%-10.4f" $lenNapIn_centCA2AB] NOTE: The 3 sides of the 'inner' Napoleon triangle have the same length. This confirms that the 'INNER' NAPLOLEON TRIANGLE IS AN EQUILATERAL TRIANGLE. " } ## END OF if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} ######################################################### ## If BOTH triangles were requested, ## add the areas of the 'outer' and 'inner' ## Napoleon triangles to the report. ######################################################### if {"$VARradbuttsOUTorIN" == "outANDin"} { ################################################################### ## Calculate the area of the 'original' triangle, ABC. ################################################################### set areaORIG [area_triangle_3points $AxPx $AyPx $BxPx $ByPx $CxPx $CyPx] ################################################################### ## Calculate the area of the 'outer' Napoleon triangle. ################################################################### set areaOUTER [area_triangle_3points \ $centABout_xPx $centABout_yPx \ $centBCout_xPx $centBCout_yPx \ $centCAout_xPx $centCAout_yPx] ################################################################### ## Calculate the area of the 'inner' Napoleon triangle. ################################################################### set areaINNER [area_triangle_3points \ $centABin_xPx $centABin_yPx \ $centBCin_xPx $centBCin_yPx \ $centCAin_xPx $centCAin_yPx] ################################################################### ## Calculate the difference in areas of the 'outer' and 'inner' ## Napoleon triangles. ################################################################### set diffOUTandIN [expr {$areaOUTER - $areaINNER}] set VARlist \ "$VARlist ----------------------------------------------------------------- AREAS OF THE ORIGINAL TRIANGLE and the 'OUTER' AND 'INNER NAPOLEON (EQUILATERAL) TRIANGLES: AREA of the 'original' triangle, ABC: [format "%-10.4f" $areaORIG] AREA of the 'outer' Napoleon (equilateral) triangle: [format "%-10.4f" $areaOUTER] AREA of the 'inner' Napoleon (equilateral) triangle: [format "%-10.4f" $areaINNER] DIFFERENCE between the 'outer' and 'inner' areas: [format "%-10.4f" $diffOUTandIN] NOTE: The difference in area of the 'outer' and 'inner' two Napoleon triangles EQUALS the area of the 'original' triangle. " } ## END OF if {"$VARradbuttsOUTorIN" == "outANDin"} ############################## ## Show the list. ############################## popup_msgVarWithScroll .topList "$VARlist" +20+30 } ## END OF proc 'show_state' ##+##################################################################### ## PROC 'area_triangle_3points' ##+##################################################################### ## PURPOSE: ## ## This procedure is invoked to calculate the area of a triangle ## given the coordinates of its 3 vertex points. ## ## Calculated using Heron's formula. ## ## CALLED BY: the 'show_state' proc ##+##################################################################### proc area_triangle_3points {x1 y1 x2 y2 x3 y3} { set len12 [expr {hypot($x1 - $x2 , $y1 - $y2)}] set len23 [expr {hypot($x2 - $x3 , $y2 - $y3)}] set len31 [expr {hypot($x3 - $x1 , $y3 - $y1)}] set s [expr {($len12 + $len23 + $len31)/2.0}] set s12 [expr {$s - $len12}] set s23 [expr {$s - $len23}] set s31 [expr {$s - $len31}] set area [expr {sqrt($s * $s12 * $s23 * $s31)}] return $area } ## END OF proc 'area_triangle_3points' ##+##################################################################### ## 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 (background) color of the canvas --- ## on which all the geometry is to be drawn. ## ## Arguments: none ## ## CALLED BY: .fRbuttons.buttCOLORbkgd button ##+##################################################################### proc set_background_color {} { global COLORBKGDr COLORBKGDg COLORBKGDb COLORBKGDhex ColorSelectorScript ## FOR TESTING: # puts "COLORBKGDr: $COLORBKGDr" # puts "COLORBKGDg: $COLORBKGDb" # puts "COLORBKGDb: $COLORBKGDb" set TEMPrgb [ exec $ColorSelectorScript $COLORBKGDr $COLORBKGDg $COLORBKGDb] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLORBKGDhex "#$hexRGB" set COLORBKGDr $r255 set COLORBKGDg $g255 set COLORBKGDb $b255 ## Set color of background-color button. update_button_colors ## Set the color of the canvas. .fRcanvas.can config -bg $COLORBKGDhex } ## END OF PROC 'set_background_color' #+##################################################################### ## PROC 'set_line_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 circle to be ## drawn on the canvas. ## ## Arguments: none (global variables are used) ## ## CALLED BY: .fRbuttons.buttCOLORline button ##+##################################################################### proc set_line_color {} { global COLORLINEr COLORLINEg COLORLINEb COLORLINEhex ColorSelectorScript ## FOR TESTING: # puts "COLORLINEr: $COLORLINEr" # puts "COLORLINEg: $COLORLINEb" # puts "COLORLINEb: $COLORLINEb" set TEMPrgb [ exec $ColorSelectorScript $COLORLINEr $COLORLINEg $COLORLINEb] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLORLINEhex "#$hexRGB" set COLORLINEr $r255 set COLORLINEg $g255 set COLORLINEb $b255 ## Set color of the draw-color button. update_button_colors ## Redraw the lines. redraw_lines } ## END OF PROC 'set_line_color' ##+##################################################################### ## PROC 'redraw_lines' ##+##################################################################### ## PURPOSE: Redraw the lines of the triangles --- using a new line color. ## ## CALLED BY: the 'set_line_color' proc ##+##################################################################### proc redraw_lines {} { ## FOR TESTING: (dummy out this routine) # return global lineWidthPx COLORLINEhex dashPatternOrig \ dashPatternPeakOut dashPatternPeakIn \ dashPatternNapOut dashPatternNapIn \ AxPx AyPx BxPx ByPx CxPx CyPx \ peakABout_xPx peakABout_yPx peakBCout_xPx peakBCout_yPx peakCAout_xPx peakCAout_yPx \ centABout_xPx centABout_yPx centBCout_xPx centBCout_yPx centCAout_xPx centCAout_yPx \ peakABin_xPx peakABin_yPx peakBCin_xPx peakBCin_yPx peakCAin_xPx peakCAin_yPx \ centABin_xPx centABin_yPx centBCin_xPx centBCin_yPx centCAin_xPx centCAin_yPx \ VARradbuttsOUTorIN ############################################### ## Delete lines AB,BC,CA --- in preparation for ## redrawing the 'original' triangle A,B,C. ############################################### .fRcanvas.can delete TAGlineAB .fRcanvas.can delete TAGlineBC .fRcanvas.can delete TAGlineCA ############################################### ## Draw the line from A to B. ############################################### .fRcanvas.can create line \ $AxPx $AyPx $BxPx $ByPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineAB} ############################################### ## Draw the line from B to C. ############################################### .fRcanvas.can create line \ $BxPx $ByPx $CxPx $CyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineBC} ############################################### ## Draw the line from C to A. ############################################### .fRcanvas.can create line \ $CxPx $CyPx $AxPx $AyPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternOrig -tags {TAGlinesOrig TAGlineCA} ################################################### ## Delete the sides of the 'outward-base' triangles ## on sides AB,BC, and CA --- and delete the sides of ## the 'outer' Napoleon triangle. Then redraw ## those sides. ################################################### if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} { .fRcanvas.can delete TAGlinesPeakOut .fRcanvas.can delete TAGlinesNapOut ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side AB. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABout_xPx $peakABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutAB} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side BC. ############################################################ .fRcanvas.can create line \ $BxPx $ByPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} .fRcanvas.can create line \ $CxPx $CyPx $peakBCout_xPx $peakBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutBC} ############################################################ ## Draw 2 'peak' sides of the 'outward' equilateral triangle ## based on side CA. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} .fRcanvas.can create line \ $AxPx $AyPx $peakCAout_xPx $peakCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakOut -tags {TAGlinesPeakOut TAGlinesPeakOutCA} ##################################################### ## Draw the 3 sides of the 'outer' Napoleon triangle. ##################################################### .fRcanvas.can create line \ $centABout_xPx $centABout_yPx $centBCout_xPx $centBCout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutAB2BC} .fRcanvas.can create line \ $centBCout_xPx $centBCout_yPx $centCAout_xPx $centCAout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutBC2CA} .fRcanvas.can create line \ $centCAout_xPx $centCAout_yPx $centABout_xPx $centABout_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapOut -tags {TAGlinesNapOut TAGlineNapOutCA2AB} } ## END OF if {"$VARradbuttsOUTorIN" == "out" || "$VARradbuttsOUTorIN" == "outANDin"} ####################################################### ## If 'inward' equilateral triangles are requested, ## calculate the 3 'peak' points of the 3 'inward-base' ## equilateral triangles. ## Also calculate the center points of the ## the 3 'inward-base' equilateral triangles. ## ## Then draw the 3 'inward-base' equilateral triangles. ## And draw the 'inner' Napoleon triangle that ## connects the 3 center points. ####################################################### if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} { ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side AB. ############################################################ .fRcanvas.can create line \ $AxPx $AyPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} .fRcanvas.can create line \ $BxPx $ByPx $peakABin_xPx $peakABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInAB} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side BC. ############################################################ .fRcanvas.can create line \ $BxPx $ByPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} .fRcanvas.can create line \ $CxPx $CyPx $peakBCin_xPx $peakBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInBC} ############################################################ ## Draw 2 'peak' sides of the 'inward' equilateral triangle ## based on side CA. ############################################################ .fRcanvas.can create line \ $CxPx $CyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} .fRcanvas.can create line \ $AxPx $AyPx $peakCAin_xPx $peakCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternPeakIn -tags {TAGlinesPeakIn TAGlinesPeakInCA} ##################################################### ## Draw the 3 sides of the 'inner' Napoleon triangle. ##################################################### .fRcanvas.can create line \ $centABin_xPx $centABin_yPx $centBCin_xPx $centBCin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInAB2BC} .fRcanvas.can create line \ $centBCin_xPx $centBCin_yPx $centCAin_xPx $centCAin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInBC2CA} .fRcanvas.can create line \ $centCAin_xPx $centCAin_yPx $centABin_xPx $centABin_yPx \ -fill $COLORLINEhex -width $lineWidthPx \ -dash $dashPatternNapIn -tags {TAGlinesNapIn TAGlineNapInCA2AB} } ## END OF if {"$VARradbuttsOUTorIN" == "in" || "$VARradbuttsOUTorIN" == "outANDin"} ##################################################### ## Raise the point objects of the 'original' triangle ## above the line objects. ##################################################### .fRcanvas.can raise TAGpointA .fRcanvas.can raise TAGpointB .fRcanvas.can raise TAGpointC } ## END OF proc 'redraw_lines' #+##################################################################### ## PROC 'set_point_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 inscribed polygon ## drawn on the canvas. ## ## Arguments: none (global variables are used) ## ## CALLED BY: .fRbuttons.buttCOLORpoint button ##+##################################################################### proc set_point_color {} { global COLORPOINTr COLORPOINTg COLORPOINTb COLORPOINThex ColorSelectorScript ## FOR TESTING: # puts "COLORPOINTr: $COLORPOINTr" # puts "COLORPOINTg: $COLORPOINTb" # puts "COLORPOINTb: $COLORPOINTb" set TEMPrgb [ exec $ColorSelectorScript $COLORPOINTr $COLORPOINTg $COLORPOINTb] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLORPOINThex "#$hexRGB" set COLORPOINTr $r255 set COLORPOINTg $g255 set COLORPOINTb $b255 ## Set color of the draw-color button. update_button_colors ## Redraw the points. redraw_points } ## END OF PROC 'set_point_color' ##+##################################################################### ## PROC 'redraw_points' ##+##################################################################### ## PURPOSE: Redraw the 8 points --- using a new point color. ## ## CALLED BY: the 'set_point_color' proc ##+##################################################################### proc redraw_points {} { ## FOR TESTING: (dummy out this routine) # return global COLORPOINThex pointRADIUSpx pointOUTLINEWIDTHpx \ pointOUTLINECOLORhex curFONTspecs curFONTSMALLspecs \ AxPx AyPx BxPx ByPx CxPx CyPx #################################################### ## Delete the 3 points A,B,C. #################################################### .fRcanvas.can delete TAGpointA .fRcanvas.can delete TAGpointB .fRcanvas.can delete TAGpointC #################################################### ## Draw circles representing the 3 vertices (points) ## of the 'original' triangle --- A,B,C. #################################################### set ulXpx [expr {$AxPx - $pointRADIUSpx}] set ulYpx [expr {$AyPx - $pointRADIUSpx}] set lrXpx [expr {$AxPx + $pointRADIUSpx}] set lrYpx [expr {$AyPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointA} set ulXpx [expr {$BxPx - $pointRADIUSpx}] set ulYpx [expr {$ByPx - $pointRADIUSpx}] set lrXpx [expr {$BxPx + $pointRADIUSpx}] set lrYpx [expr {$ByPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointB} set ulXpx [expr {$CxPx - $pointRADIUSpx}] set ulYpx [expr {$CyPx - $pointRADIUSpx}] set lrXpx [expr {$CxPx + $pointRADIUSpx}] set lrYpx [expr {$CyPx + $pointRADIUSpx}] .fRcanvas.can create oval \ $ulXpx $ulYpx $lrXpx $lrYpx \ -width $pointOUTLINEWIDTHpx -outline $pointOUTLINECOLORhex \ -fill $COLORPOINThex -tags {TAGpointOrigTri TAGpointC} #################################################### ## Delete the 3 text labels -- for points A,B,C. #################################################### .fRcanvas.can delete TAGtextA .fRcanvas.can delete TAGtextB .fRcanvas.can delete TAGtextC #################################################### ## Draw a text character near the 3 vertices (points) ## of the 'original' triangle --- A,B,C. #################################################### .fRcanvas.can create text $AxPx $AyPx -anchor ne \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "A" -tags {TAGtext TAGtextA} .fRcanvas.can create text $BxPx $ByPx -anchor se \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "B" -tags {TAGtext TAGtextB} .fRcanvas.can create text $CxPx $CyPx -anchor sw \ -fill $COLORPOINThex -font "$curFONTspecs" \ -text "C" -tags {TAGtext TAGtextC} } ## END OF proc 'redraw_points' ##+##################################################################### ## PROC 'update_button_colors' ##+##################################################################### ## PURPOSE: ## This procedure is invoked to set the background color of each of ## 3 color buttons to its current color --- and sets foreground color, ## for text on the 3 buttons, to a suitable(?) black or white color, ## so that the label text is readable. ## ## (We might need to weight the RGB colors differently when summing ## them, to get a better choice of black or white for the wide ## range of colors that are possible on these color buttons.) ## ## Arguments: global color vars ## ## CALLED BY: 3 colors procs: ## 'set_background_color' 'set_line_color' ## 'set_point_color' ## and ## in the additional-GUI-initialization section at ## the bottom of this script to initialize the color of ## the buttons. ##+##################################################################### proc update_button_colors {} { global COLORBKGDr COLORBKGDg COLORBKGDb COLORBKGDhex \ COLORLINEr COLORLINEg COLORLINEb COLORLINEhex \ COLORPOINTr COLORPOINTg COLORPOINTb COLORPOINThex # set colorBREAK 300 set colorBREAK 375 .fRbuttons.buttCOLORbkgd configure -bg $COLORBKGDhex set sumCOLOR [expr {$COLORBKGDr + $COLORBKGDg + $COLORBKGDb}] if {$sumCOLOR > $colorBREAK} { .fRbuttons.buttCOLORbkgd configure -fg "#000000" } else { .fRbuttons.buttCOLORbkgd configure -fg "#f0f0f0" } .fRbuttons.buttCOLORline configure -bg $COLORLINEhex set sumCOLOR [expr {$COLORLINEr + $COLORLINEg + $COLORLINEb}] if {$sumCOLOR > $colorBREAK} { .fRbuttons.buttCOLORline configure -fg "#000000" } else { .fRbuttons.buttCOLORline configure -fg "#f0f0f0" } .fRbuttons.buttCOLORpoint configure -bg $COLORPOINThex set sumCOLOR [expr {$COLORPOINTr + $COLORPOINTg + $COLORPOINTb}] if {$sumCOLOR > $colorBREAK} { .fRbuttons.buttCOLORpoint configure -fg "#000000" } else { .fRbuttons.buttCOLORpoint configure -fg "#f0f0f0" } } ## END OF PROC 'update_button_colors' ##+##################################################################### ## PROC 'advise_user' ##+##################################################################### ## PURPOSE: Puts a message to the user on the GUI. ## ## CALLED BY: in the additional-GUI-initialization section at ## the bottom of this script ## and in some procs. ##+##################################################################### proc advise_user {text} { .fRmsg.labelMSG configure -text "$text" ## Make sure the text is displayed on the GUI. update ## Alternatively, we could put the message in the title-bar ## of the GUI window. (But it is easy for the user to ## fail to see the message there. Besides, we have more ## options in displaying the message by putting it on a ## Tk widget in the GUI.) ## # wm title . "$text" } ## END OF PROC 'advise_user' ##+######################################################################## ## PROC 'popup_msgVarWithScroll' ##+######################################################################## ## PURPOSE: Report help or error conditions to the user. ## ## We do not use focus,grab,tkwait in this proc, ## because we use it to show help when the GUI is idle, ## and we may want the user to be able to keep the Help ## window open while doing some other things with the GUI ## such as putting a filename in the filename entry field ## or clicking on a radiobutton. ## ## For a similar proc with focus-grab-tkwait added, ## see the proc 'popup_msgVarWithScroll_wait' in a ## 3DterrainGeneratorExaminer Tk script. ## ## REFERENCE: page 602 of 'Practical Programming in Tcl and Tk', ## 4th edition, by Welch, Jones, Hobbs. ## ## ARGUMENTS: A toplevel frame name (such as .fRhelp or .fRerrmsg) ## and a variable holding text (many lines, if needed). ## ## CALLED BY: 'help' button ##+######################################################################## ## To have more control over the formatting of the message (esp. ## words per line), we use this 'toplevel-text' method, ## rather than the 'tk_dialog' method -- like on page 574 of the book ## by Hattie Schroeder & Mike Doyel,'Interactive Web Applications ## with Tcl/Tk', Appendix A "ED, the Tcl Code Editor". ##+######################################################################## proc popup_msgVarWithScroll { toplevName VARtext ULloc} { ## global fontTEMP_varwidth #; Not needed. 'wish' makes this global. ## global env # bell # bell ################################################# ## Set VARwidth & VARheight from $VARtext. ################################################# ## To get VARheight, ## split at '\n' (newlines) and count 'lines'. ################################################# set VARlist [ split $VARtext "\n" ] ## For testing: # puts "VARlist: $VARlist" set VARheight [ llength $VARlist ] ## For testing: # puts "VARheight: $VARheight" ################################################# ## To get VARwidth, ## loop through the 'lines' getting length ## of each; save max. ################################################# set VARwidth 0 ############################################# ## LOOK AT EACH LINE IN THE LIST. ############################################# foreach line $VARlist { ############################################# ## Get the length of the line. ############################################# set LINEwidth [ string length $line ] if { $LINEwidth > $VARwidth } { set VARwidth $LINEwidth } } ## END OF foreach line $VARlist ## For testing: # puts "VARwidth: $VARwidth" ############################################################### ## NOTE: VARwidth works for a fixed-width font used for the ## text widget ... BUT the programmer may need to be ## careful that the contents of VARtext are all ## countable characters by the 'string length' command. ############################################################### ##################################### ## SETUP 'TOP LEVEL' HELP WINDOW. ##################################### catch {destroy $toplevName} toplevel $toplevName # wm geometry $toplevName 600x400+100+50 # wm geometry $toplevName +100+50 wm geometry $toplevName $ULloc wm title $toplevName "Note" # wm title $toplevName "Note to $env(USER)" wm iconname $toplevName "Note" ##################################### ## In the frame '$toplevName' - ## DEFINE THE TEXT WIDGET and ## its two scrollbars --- and ## DEFINE an OK BUTTON widget. ##################################### if {$VARheight > 10} { text $toplevName.text \ -wrap none \ -font fontTEMP_varwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 \ -yscrollcommand "$toplevName.scrolly set" \ -xscrollcommand "$toplevName.scrollx set" scrollbar $toplevName.scrolly \ -orient vertical \ -command "$toplevName.text yview" scrollbar $toplevName.scrollx \ -orient horizontal \ -command "$toplevName.text xview" } else { text $toplevName.text \ -wrap none \ -font fontTEMP_varwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 } button $toplevName.butt \ -text "OK" \ -font fontTEMP_varwidth \ -command "destroy $toplevName" ############################################### ## PACK *ALL* the widgets in frame '$toplevName'. ############################################### ## Pack the bottom button BEFORE the ## bottom x-scrollbar widget, pack $toplevName.butt \ -side bottom \ -anchor center \ -fill none \ -expand 0 if {$VARheight > 10} { ## Pack the scrollbars BEFORE the text widget, ## so that the text does not monopolize the space. pack $toplevName.scrolly \ -side right \ -anchor center \ -fill y \ -expand 0 ## DO NOT USE '-expand 1' HERE on the Y-scrollbar. ## THAT ALLOWS Y-SCROLLBAR TO EXPAND AND PUTS ## BLANK SPACE BETWEEN Y-SCROLLBAR & THE TEXT AREA. pack $toplevName.scrollx \ -side bottom \ -anchor center \ -fill x \ -expand 0 ## DO NOT USE '-expand 1' HERE on the X-scrollbar. ## THAT KEEPS THE TEXT AREA FROM EXPANDING. pack $toplevName.text \ -side top \ -anchor center \ -fill both \ -expand 1 } else { pack $toplevName.text \ -side top \ -anchor center \ -fill both \ -expand 1 } ################################################ ## Set some 'event' bindings to allow for ## easy scrolling through huge listings. ## is a press of the Page-Down key. ## is a press of the Page-Up key. ## is a press of the Home key ## to go to the top of the listing. ## is a press of the End key ## to go to the bottom of the listing. ## is a press of the Up-arrow key. ## is a press of the Down-arrow key. ################################################ bind $toplevName "$toplevName.text yview scroll +1 page" bind $toplevName "$toplevName.text yview scroll -1 page" bind $toplevName "$toplevName.text see 1.0" bind $toplevName "$toplevName.text see end" bind $toplevName "$toplevName.text yview scroll -1 unit" bind $toplevName "$toplevName.text yview scroll +1 unit" ##################################### ## LOAD MSG INTO TEXT WIDGET. ##################################### ## $toplevName.text delete 1.0 end $toplevName.text insert end $VARtext $toplevName.text configure -state disabled } ## END OF PROC 'popup_msgVarWithScroll' ##+######################## ## END of PROC definitions. ##+######################## ##+######################## ## Set the 'HELPtext' var. ##+######################## set HELPtext "\ \ \ ** HELP for this 'tkNapoleonsTheorem' App ** This Tk script is meant to demonstrate Napoleon's Theorem : If 3 EQUILATERAL triangles are constructed on the sides of ANY triangle --- either ALL 3 OUTWARD or ALL 3 INWARD --- the centers of those 3 equilateral triangles themselves form an EQUILATERAL triangle. The triangle thus formed is called the 'outer' or 'inner' 'Napoleon' triangle. In addition, it turns out: The difference in area between the 'outer' and 'inner' two Napoleon triangles equals the area of the 'original' triangle. This script is meant to 'dynamically' demonstrate these facts by allowing the user to 'drag' any point of the 'original' triangle to form a new triangle. In all, the figure involves up to 1+4+4 = 9 triangles, depending on whether 'outward', 'inward', or both are requested: a) the 'original', arbitrary triangle, b) the 3 'outward' equilateral triangles based on the 3 sides of the 'original' triangle, which we will call 'outer-base' triangles, and the 'outer' equilateral 'Napoleon' triangle --- whose 3 sides connect the centers of the 3 'outer-base' equilateral triangles, c) the 3 'inward' equilateral triangles based on the 3 sides of the 'original' triangle, which we will call 'inner-base' triangles, and the 'inner' equilateral 'Napoleon' triangle --- whose 3 sides connect the centers of the 3 'inner-base' equilateral triangles. When the user finishes the 'drag' (releases the mouse-button): 1) The moved point of the 'original' triangle is deleted and redrawn in its new position. 2) The 2 affected sides (line-segments) of the 'original', arbitrary triangle are deleted and redrawn. Also, if 'outward' or 'inward' or both are requested: 3) Two of three 'outer/inner-base' equilateral triangles are redrawn, by deleting and redrawing the 2 sides of the 2 outer/inner equilateral triangles that are 'based' on the 2 redrawn sides of the 'original' triangle. 4) Two of the 3 centers of the 3 'outer/inner-base' equilateral triangles are recalculated. 5) The three sides of the 'outer' or 'inner' equilateral 'Napoleon' triangle that connect the centers are deleted and redrawn --- yielding a new 'outer' or 'inner' equilateral 'Napoleon' triangle. These operations may be done in a different order. For example, some deletions may be grouped together, and some re-draws may be grouped together. But the operations proceed so quickly that the order of the operations will ordinarily not be noticed. We 'tag' the 3 points of the 'original', arbitrary triangle with names like A,B,C. ************ GUI FEATURES: ************ This GUI uses a Tk 'canvas' widget to show the up-to-9 triangles. The line segments of the triangles are drawn with 'create line' commands on the canvas. The 3 points of the 'original' triangle are indicated by color-filled circles that are drawn with 'create oval' commands. We use a rectangular drawing area (the Tk 'canvas' widget), and we allow the user to control the size (in pixels) of that drawing area by the user resizing the entire GUI window --- which results in the canvas being automatically resized by the Tk 'pack' geometry manager. The delete-and-redraw operations are automatically triggered when the user releases the mouse button after moving one of the 3 points of the 'original' triangle. (The 3 vertices/points of the 'original' triangle are the only objects on the canvas that are moveable by the user. All other objects --- such as line-segments and text items --- are redrawn automatically for the user.) Three 'Color' buttons on the GUI allow the user to specify - background color of the Tk canvas widget - color of the line segments of the up-to-9 triangles - color of the vertex points of triangles, at least the 3 vertex points of the 'original' triangle. Because the drawing gets so 'busy' when both 'outer' and 'inner' equilateral triangles are requested, the 'inner' Napoleon triangle is drawn as a filled polygon (triangle) --- so that it stands out from the lines of the other eight triangles. A 'ShowState' button on the GUI may be used to report on the state of the current image, such as: - coordinates of the various triangle vertex points --- of the 'original' triangle and the 'outer' and/or 'inner' equilateral triangles, - lengths of the line-segments (sides) of triangles --- for the 'original' triangle and the 'outer' and/or 'inner' equilateral triangles. And if 'both' was requested, the 'ShowState' report shows - the area of the 'original' triangle, ABC - the areas of the 'outer' or 'inner' Napoleon (equilateral) triangles. - the difference of the 'outer' and 'inner' areas --- which always turns out to equal the area of the original triangle. (The lengths of the sides of each of the 8 equilateral triangles should be equal --- the 3 'base' 'outward' and 'inward' equilateral triangles and the one 'outer' and the one 'inner' 'Napoleon' equilateral triangle. In particular, the lengths of the sides of the 'outer' and 'inner' triangles being equal confirms that those two 'Napoleon' triangles are indeed equilateral triangles --- as the theorem declares.) A 'Help' button on the GUI show this help text. ******************************** CAPTURING THE GUI IMAGE: ******************************** A screen/window capture utility (like 'gnome-screenshot' on Linux) can be used to capture the GUI image in a 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 smaller image suitable for use in a web page or an email. ******************************** HISTORICAL NOTE: ******************************** It is not known whether Napoleon really did notice that connecting the centers of the 3 equilateral triangles (on an arbitrary triangle) would always form a new equilateral triangle. That fact may have been discovered by a mathematician who served Napoleon and his armies. For example, Napoleon had mathematicians with him on a campaign in Egypt. But it is quite possible that he considered configurations like these. Note that the jutting-outward triangles on an original, inner triangle are similar to the triangles that appear on vertex points of pentagonal forts --- and the pentagonal forts were not always equal-sided in shape. Those outward triangles were intended to give strategic advantage in protecting the fort. " ##+################################################################ ##+################################################################ ## ADDITIONAL GUI INITIALIZATION SECTION: Mainly to ## - Draw an initial circle and polygon(s) on the canvas. ##+################################################################ ##+################################################################ ##+##################################################### ## Set the full-name of the RGB color-selector Tk script ## that is used in several procs above. ##+##################################################### ## FOR TESTING: # puts "argv0: $argv0" set DIRthisScript "[file dirname $argv0]" ## For ease of testing in a Linux/Unix terminal and located at the ## directory containing this Tk script. Set the full directory name. if {"$DIRthisScript" == "."} { set DIRthisScript "[pwd]" } set DIRupOne "[file dirname "$DIRthisScript"]" set DIRupTwo "[file dirname "$DIRupOne"]" set ColorSelectorScript "$DIRupTwo/SELECTORtools/tkRGBselector/sho_colorvals_via_sliders3rgb.tk" ## Alternatively: Put the RGB color-selector Tk script in the ## same directory as this Tk script and uncomment the following. # set ColorSelectorScript "$DIRthisScript/sho_colorvals_via_sliders3rgb.tk" ##+############################################################ ## Initialize the 3 drawing colors --- for background, ## line-segments, and points. ##+############################################################ set COLORBKGDr 90 set COLORBKGDg 90 set COLORBKGDb 255 set COLORBKGDhex [format "#%02X%02X%02X" $COLORBKGDr $COLORBKGDg $COLORBKGDb] set COLORLINEr 255 set COLORLINEg 255 set COLORLINEb 255 set COLORLINEhex [format "#%02X%02X%02X" $COLORLINEr $COLORLINEg $COLORLINEb] set COLORPOINTr 255 set COLORPOINTg 0 set COLORPOINTb 0 set COLORPOINThex [format "#%02X%02X%02X" $COLORPOINTr $COLORPOINTg $COLORPOINTb] ##+################################### ## Set the color of the color buttons. ##+################################### update_button_colors ##+############################################################ ## We need following command because the 'initDraw' proc ## (called below) does not (re)set the background/canvas color. ## Only the background-color button-proc sets the canvas color. ##+############################################################ .fRcanvas.can config -bg $COLORBKGDhex ##+################################################ ## Set a width for line-segments. ##+################################################ # set lineWidthPx 1 set lineWidthPx 2 ##+################################################# ## Set a constants to use in 'format' statements ## used to display the coordinate values and line ## lengths. ##+################################################ # set decimalDIGITS 6 set decimalDIGITS 8 ##+################################################### ## Set dash-patterns for the lines (sides) of the ## various triangles. ## ## Each pattern is a list of integers. ## Each element represents the number of pixels of a line segment. ## Only the odd segments are drawn using the "outline" color. ## The other segments are drawn transparent. ##+################################################### set dashPatternOrig {} set dashPatternPeakOut {6 3} set dashPatternNapOut {12 3} set dashPatternPeakIn {2 4} set dashPatternNapIn {4 4} ##+################################################### ## Set a radius (in pixels) for the circles that ## represent the vertices of triangles. ##+################################################### set pointRADIUSpx 5 ##+################################################### ## Set a color for the outline of the circles that ## represent the vertices of triangles. ##+################################################### set pointOUTLINECOLORhex "#ffffff" ##+###################################################### ## Set a width (in pixels) for the outline of the circles ## that represent the vertices of triangles. ##+###################################################### set pointOUTLINEWIDTHpx 1 ##+##################################################### ## Initialize var 'curFONTspecs' and 'curFONTSMALLspecs', ## used to specify the font for the text drawn on the ## canvas widget. ## See the font-section near the top of the code ## for some other font family names, such as ## { new century schoolbook } ##+##################################################### set curFONTspecs [list -family {Liberation Mono} -size -34 \ -weight bold -slant roman -underline 0 -overstrike 0] set curFONTSMALLspecs [list -family {Liberation Mono} -size -14 \ -weight bold -slant roman -underline 0 -overstrike 0] ##+###################################################### ## Display an initial 'how-to' message to the user. ## ## This should be performed before the call to 'initDraw', ## because this may determine the width of the window --- ## and thus the width of the expandable canvas. ## This helps center the initial figure in the canvas area. ##+###################################################### advise_user "$aRtext(labelINIT)" ##+################################################# ## Set a variable to hold the square root of 3 ## --- and one-third of the square root of 3, which ## equals the reciprocal of the square root of 3. ##+################################################# set sqrt3 [expr {sqrt(3.0)}] set sqrt3over3 [expr {$sqrt3 / 3.0}] ##+################################################# ## Initialize setting of the radiobutton variable. ##+################################################# set VARradbuttsOUTorIN "out" # set VARradbuttsOUTorIN "in" ##+################################################# ## Draw the initial configuration of triangles. ##+################################################# initDraw