[Richard Suchenwirth] - In the weekend fun project for [Describing and rendering flags in Tcl], some geometrical shapes were required: sun (Taiwan style: 12 triangles arranged around a circle), moon (crescent), and stars. Since these involve quite some arithmetics on coordinates, the tasks were delegated to a separate ''geom'' package, whose procedures give and take coordinates, but don't know about canvases or colors. A five-point star is described as a polygon of ten points: five are the corners of a regular pentagon, the others are the crossing points of every pair of lines between the pentagon edges. Maybe this code can be reused in other ways, too - feel free to grab it! namespace eval geom { variable p360 [expr atan(1.)*8/360] proc crosspoint {xa ya xb yb xc yc xd yd} { # compute crossing between two straight lines ("" if parallel) if {$xa==$xb} { set xres $xa ;# vertical - couldn't divide by deltax } else { set a [expr double($yb-$ya)/($xb-$xa)] set b [expr $yb-($a*$xb)] } if {$xc==$xd} { set xres $xc ;# vertical - couldn't divide by deltax } else { set c [expr double($yd-$yc)/($xd-$xc)] set d [expr $yd-($c*$xd)] } if {[info exists a] && [info exists c] && $a==$c} {return ""} if {![info exists a] && ![info exists c]} {return ""} if ![info exists xres] { set xres [expr double($d-$b)/($a-$c)] } if [info exists a] { set yres [expr $a*$xres+$b] } else { set yres [expr $c*$xres+$d] } list $xres $yres } proc star5 {x y r {skew 0}} { # compute coordinates for a five-point star variable p360 foreach {p angle} {A 0 B 72 C 144 D 216 E 288} { set rad [expr ($angle-$skew)*$p360] set $p [list [expr $x+$r*sin($rad)] [expr $y-$r*cos($rad)]] } set F [eval crosspoint $A $C $B $E] set G [eval crosspoint $B $D $A $C] set H [eval crosspoint $C $E $B $D] set I [eval crosspoint $D $A $C $E] set J [eval crosspoint $E $B $A $D] concat $A $F $B $G $C $H $D $I $E $J } proc sunrays {x y r {n 12}} { # rotated triangles around a circle variable p360 for {set i 0} {$i<$n} {incr i} { set rad [expr ($i*360./$n)*$p360] set rad1 [expr ($i*360./$n-170./$n)*$p360] set rad2 [expr ($i*360./$n+170./$n)*$p360] lappend res [list \ [expr $x+$r*sin($rad)] [expr $y-$r*cos($rad)] \ [expr $x+$r*0.67*sin($rad1)] [expr $y-$r*0.67*cos($rad1)] \ [expr $x+$r*0.67*sin($rad2)] [expr $y-$r*0.67*cos($rad2)] \ ] } set res } } NB. This code contains no "moon". It is supposed to come here, but in the hurry I was in I put it directly into [Describing and rendering flags in Tcl] - it's just the superimposition of two circles anyway. ---- Here's a slicker routine for drawing a star (by Keith Vetter on c.l.t): [KPV] - some explanation behind this code. My first version simply drew the five lines of a star which looked okay, but when I added a binding to it, it only "took" when clicking outside the central pentagon. It seems the code to determine what's ''inside'' (the winding rule) differs between the drawing code and the binding code. The math behind this code is as follows: the angle to each of the 10 points is obvious, the distance to the outer points is given (''delta''), so we just need the distance of the inner points (''delta2''). My flash of insight came when I realized the Y value of the first inner point equals that of the next outer point. So to compute delta2, I just scaled the unit vector to that inner point until the Y value is what we know it should be, yielding the X value and then delta2. proc MakeStar {x y delta} { set pi [expr {atan(1) * 4}] # Compute delta to inner corner set x1 [expr {$delta * cos(54 * $pi/180)}] ;# Vector to inner point set y1 [expr {$delta * sin(54 * $pi/180)}] set XY [expr {sqrt($x1*$x1 + $y1*$y1)}] ;# Unit vector set y2 [expr {$delta * sin(18 * $pi/180)}] ;# Y value to match set delta2 [expr {$XY * $y2 / $y1}] # Now get all coordinates of the 5 outer and 5 inner points for {set i 0} {$i < 10} {incr i} { set d [expr {($i % 2) == 0 ? $delta : $delta2}] set theta [expr {(90 + 36 * $i) * $pi / 180}] set x1 [expr {$x + $d * cos($theta)}] set y1 [expr {$y - $d * sin($theta)}] lappend coords $x1 $y1 } return $coords } ---- [Arts and crafts of Tcl-Tk programming]