[Arjen Markus] (29 september 2009) on the comp.lang.tcl newsgroup Stuart asked for a script to plot wind roses. As I had some time on my hands, I did a first implementation of such a diagram using Plotchart. The result is below. ---- ====== # windrose.tcl -- # Add a wind rose diagram to Plotchart # # package -- # Register the new plot type # package require Plotchart namespace eval ::Plotchart { set methodProc(windrose,plot) DrawWindRoseData set methodProc(windrose,saveplot) SavePlot set methodProc(windrose,title) DrawTitle } # createWindRose -- # Create a new command for plotting a windrose # # Arguments: # w Name of the canvas # radius_data Maximum radius and step # sectors Number of sectors (default: 16) # Result: # Name of a new command # Note: # The entire canvas will be dedicated to the windrose # Possible additional arguments (optional): nautical/mathematical # step in phi # proc ::Plotchart::createWindRose { w radius_data {sectors 16}} { variable data_series foreach s [array names data_series "$w,*"] { unset data_series($s) } set newchart "windrose_$w" interp alias {} $newchart {} ::Plotchart::PlotHandler windrose $w set rad_max [lindex $radius_data 0] set rad_step [lindex $radius_data 1] if { $rad_step <= 0.0 } { return -code error "Step size can not be zero or negative" } if { $rad_max <= 0.0 } { return -code error "Maximum radius can not be zero or negative" } foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break} viewPort $w $pxmin $pymin $pxmax $pymax polarCoordinates $w $rad_max DrawRoseAxes $w $rad_max $rad_step set data_series($w,radius) {} for { set i 0 } { $i < $sectors } { incr i } { lappend data_series($w,cumulative_radius) 0.0 } set data_series($w,start_angle) [expr {90.0 - 360.0/(4.0*$sectors)}] set data_series($w,d_angle) [expr {360.0/(2.0*$sectors)}] set data_series($w,increment_angle) [expr {360.0/$sectors}] set data_series($w,count_data) 0 return $newchart } # DrawRoseAxes -- # Draw the axes to support a wind rose # Arguments: # w Name of the canvas # rad_max Maximum radius # rad_step Step in radius # Result: # None # Side effects: # Axes drawn in canvas # proc ::Plotchart::DrawRoseAxes { w rad_max rad_step } { # # Draw the spikes # set angle 0.0 foreach {xcentre ycentre} [polarToPixel $w 0.0 0.0] {break} foreach {angle text dir} { 90 North s 180 West e 270 South n 0 East w } { foreach {xcrd ycrd} [polarToPixel $w $rad_max $angle] {break} foreach {xtxt ytxt} [polarToPixel $w [expr {1.05*$rad_max}] $angle] {break} $w create line $xcentre $ycentre $xcrd $ycrd $w create text $xtxt $ytxt -text $text -anchor $dir } # # Draw the concentric circles # set rad $rad_step while { $rad < $rad_max+0.5*$rad_step } { foreach {xtxt ytxt} [polarToPixel $w $rad 45.0] {break} foreach {xright ycrd} [polarToPixel $w $rad 0.0] {break} foreach {xleft ycrd} [polarToPixel $w $rad 180.0] {break} foreach {xcrd ytop} [polarToPixel $w $rad 90.0] {break} foreach {xcrd ybottom} [polarToPixel $w $rad 270.0] {break} $w create oval $xleft $ytop $xright $ybottom $w create text $xtxt [expr {$ytxt+3}] -text $rad -anchor s set rad [expr {$rad+$rad_step}] } } # DrawWindRoseData -- # Draw the data for each sector # Arguments: # w Name of the canvas # data List of "sectors" data # colour Colour to use # Result: # None # Side effects: # Data added to the wind rose # proc ::Plotchart::DrawWindRoseData { w data colour } { variable data_series set start_angle $data_series($w,start_angle) set increment $data_series($w,increment_angle) set width_sector $data_series($w,d_angle) set new_cumulative {} foreach value $data cumulative_radius $data_series($w,cumulative_radius) { console show ; puts $start_angle set radius [expr {$value + $cumulative_radius}] foreach {xright ytop} [polarToPixel $w [expr {$radius*sqrt(2.0)}] 45.0] {break} foreach {xleft ybottom} [polarToPixel $w [expr {$radius*sqrt(2.0)}] 225.0] {break} $w create arc $xleft $ytop $xright $ybottom -style pie -fill $colour \ -tag data_$data_series($w,count_data) -start $start_angle -extent $width_sector lappend new_cumulative $radius set start_angle [expr {$start_angle - $increment}] } $w lower data_$data_series($w,count_data) set data_series($w,cumulative_radius) $new_cumulative incr data_series($w,count_data) } # main -- # Testing the wind rose diagram # pack [canvas .c -bg white] set p [::Plotchart::createWindRose .c {30 6} 4] $p plot {5 10 0 3} red $p plot {10 10 10 3} blue $p title "Simple wind rose - margins need to be corrected ..." ====== ---- <>Category Graphics