[Keith Vetter] 2003-03-24 : as I was writing [TkGoldberg], I found it difficult dealing with complex canvas objects that were composed of arcs and polygons. These objects were hard to fill with a color, especially if the arc is a concave part of the object. Also, arcs don't rotate well (see [Canvas Rotation]). I realize now that if I could have decomposed the complex object into one polygon then both of my problems would have been solved. But to do that I would need to convert arc into a vertex list. The code below does just that. It is a generalization of [Regular polygons] in that it takes "-start", "-extent" and "-sides" as optional addition paramters. ---- ''[escargo] 24 Mar 2003'' - There's a little glitch that appears on a seven-sided figure. If start is set to zero, the glitch appears on the far right-hand side.... [KPV] oops, step size should have been a double, not an int. ---- proc rp2 {x0 y0 x1 y1 args} { array set V {-sides 0 -start 90 -extent 360} ;# Default values foreach {a value} $args { if {! [info exists V($a)]} {error "unknown option $a"} if {$value == {}} {error "value of \"$a\" missing"} set V($a) $value } if {$V(-extent) == 0} {return {}} set xm [expr {($x0+$x1)/2.}] set ym [expr {($y0+$y1)/2.}] set rx [expr {$xm-$x0}] set ry [expr {$ym-$y0}] set n $V(-sides) if {$n == 0} { ;# 0 sides => circle set n [expr {round(($rx+$ry)*0.5)}] if {$n < 2} {set n 4} } set dir [expr {$V(-extent) < 0 ? -1 : 1}] ;# Extent can be negative if {abs($V(-extent)) > 360} { set V(-extent) [expr {$dir * (abs($V(-extent)) % 360)}] } set step [expr {$dir * 360.0 / $n}] set numsteps [expr {1 + double($V(-extent)) / $step}] set xy {} set DEG2RAD [expr {4*atan(1)*2/360}] for {set i 0} {$i < int($numsteps)} {incr i} { set rad [expr {($V(-start) - $i * $step) * $DEG2RAD}] set x [expr {$rx*cos($rad)}] set y [expr {$ry*sin($rad)}] lappend xy [expr {$xm + $x}] [expr {$ym - $y}] } # Figure out where last segment should end if {$numsteps != int($numsteps)} { # Vecter V1 is last drawn vertext (x,y) from above # Vector V2 is the edge of the polygon set rad2 [expr {($V(-start) - int($numsteps) * $step) * $DEG2RAD}] set x2 [expr {$rx*cos($rad2) - $x}] set y2 [expr {$ry*sin($rad2) - $y}] # Vector V3 is unit vector in direction we end at set rad3 [expr {($V(-start) - $V(-extent)) * $DEG2RAD}] set x3 [expr {cos($rad3)}] set y3 [expr {sin($rad3)}] # Find where V3 crosses V1+V2 => find j s.t. V1 + kV2 = jV3 set j [expr {($x*$y2 - $x2*$y) / ($x3*$y2 - $x2*$y3)}] lappend xy [expr {$xm + $j * $x3}] [expr {$ym - $j * $y3}] } return $xy } # Now for code to demonstrate and test it proc DrawIt {args} { global S foreach {x0 y0 x1 y1} [.c cget -scrollregion] break set bbox [list 20 20 [incr x1 -20] [incr y1 -20]] .c delete poly set xy [eval rp2 $bbox -sides $S(sides) -start $S(start) -extent 360] .c create poly $xy -fill {} -outline black -width 2 -dash - -tag poly set xy [eval rp2 $bbox -sides $S(sides) -start $S(start) -extent $S(extent)] .c create poly $xy -fill red -outline {} -tag poly .c create line $xy -fill red -fill black -width 3 -tag poly } pack [frame .bottom] -side bottom -fill x pack [canvas .c -width 500 -height 500 -bd 2 -relief raised] -fill both -expand 1 bind .c {%W config -scrollregion [list 0 0 %w %h] ; DrawIt} scale .sides -variable S(sides) -orient h -from 0 -to 10 -label Sides -relief ridge scale .start -variable S(start) -orient h -from 0 -to 360 -label Start -relief ridge scale .extent -variable S(extent) -orient h -from -360 -to 360 -label Extent -relief ridge pack .sides .start .extent -side left -in .bottom array set S {extent 135 sides 4 start 0} trace variable S w DrawIt ---- [Category Graphics]