Version 0 of Sun, moon, and stars

Updated 2001-02-12 15:15:33

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.


Arts and crafts of Tcl-Tk programming