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.
AM (22 october 2009) I have added this to Plotchart, along with some new plot methods.
# 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"
}
lassign [MarginsCircle $w] pxmin pymin pxmax pymax
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
lassign [polarToPixel $w 0.0 0.0] xcentre ycentre
foreach {angle text dir} {
90 North s
180 West e
270 South n
0 East w } {
lassign [polarToPixel $w $rad_max $angle] xcrd ycrd
lassign [polarToPixel $w [expr {1.05*$rad_max}] $angle] xtxt ytxt
$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 } {
lassign [polarToPixel $w $rad 45.0] xtxt ytxt
lassign [polarToPixel $w $rad 0.0] xright ycrd
lassign [polarToPixel $w $rad 180.0] xleft ycrd
lassign [polarToPixel $w $rad 90.0] xcrd ytop
lassign [polarToPixel $w $rad 270.0] xcrd ybottom
$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}]
lassign [polarToPixel $w [expr {$radius*sqrt(2.0)}] 45.0] xright ytop
lassign [polarToPixel $w [expr {$radius*sqrt(2.0)}] 225.0] xleft ybottom
$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 ..."
(06.08.2023) Bug Only works with older Plotchart. :from tklib 0.6, Plotchart2.0.1
arjen - 2023-08-07 06:12:48
Hm, I will have to look into this bug!
(2023-08-08 07:28)
for Plotchart2.0.1 in ::Plotchart::createWindRose missing :
variable scaling set scaling($w,coordSystem) 0 CopyConfig windrose $w
and and ticket for newer Ticket
arjen - 2023-08-13 11:40:54
Thanks - I repaired this in version 2.6.1. See the ticket for more information.