Attachment "plotchart.tcl" to
ticket [1891251fff]
added by
relaxmike
2008-02-11 23:24:32.
# plotchart.tcl --
# Facilities to draw simple plots in a dedicated canvas
#
# Note:
# This source file contains the public functions.
# The others are contained in "plotpriv.tcl"
#
package require Tcl 8.3
package require Tk
# Plotchart --
# Namespace to hold the procedures and the private data
#
namespace eval ::Plotchart {
variable settings
variable legend
variable scaling
variable methodProc
variable data_series
namespace export worldCoordinates viewPort coordsToPixel \
polarCoordinates setZoomPan \
world3DCoordinates coordsToPixel \
coords3DToPixel polarToPixel \
pixelToCoords pixelToIndex determineScale \
createXYPlot createPolarPlot createPiechart \
createBarchart createHorizontalBarchart \
createTimechart createStripchart \
createIsometricPlot create3DPlot \
createGanttChart createHistogram colorMap \
create3DBars createRadialchart \
createTXPlot createRightAxis \
create3DRibbonChart
#
# Array linking procedures with methods
#
set methodProc(xyplot,title) DrawTitle
set methodProc(xyplot,xtext) DrawXtext
set methodProc(xyplot,ytext) DrawYtext
set methodProc(xyplot,plot) DrawData
set methodProc(xyplot,dot) DrawDot
set methodProc(xyplot,dotconfig) DotConfigure
set methodProc(xyplot,interval) DrawInterval
set methodProc(xyplot,trend) DrawTrendLine
set methodProc(xyplot,vector) DrawVector
set methodProc(xyplot,vectorconfig) VectorConfigure
set methodProc(xyplot,rchart) DrawRchart
set methodProc(xyplot,grid) DrawGrid
set methodProc(xyplot,contourlines) DrawIsolines
set methodProc(xyplot,contourfill) DrawShades
set methodProc(xyplot,contourbox) DrawBox
set methodProc(xyplot,saveplot) SavePlot
set methodProc(xyplot,dataconfig) DataConfig
set methodProc(xyplot,xconfig) XConfig
set methodProc(xyplot,yconfig) YConfig
set methodProc(xyplot,xticklines) DrawXTicklines
set methodProc(xyplot,yticklines) DrawYTicklines
set methodProc(xyplot,background) BackgroundColour
set methodProc(xyplot,legendconfig) LegendConfigure
set methodProc(xyplot,legend) DrawLegend
set methodProc(xyplot,balloon) DrawBalloon
set methodProc(xyplot,balloonconfig) ConfigBalloon
set methodProc(xyplot,plaintext) DrawPlainText
set methodProc(piechart,title) DrawTitle
set methodProc(piechart,plot) DrawPie
set methodProc(piechart,saveplot) SavePlot
set methodProc(piechart,balloon) DrawBalloon
set methodProc(piechart,balloonconfig) ConfigBalloon
set methodProc(piechart,plaintext) DrawPlainText
set methodProc(polarplot,title) DrawTitle
set methodProc(polarplot,plot) DrawPolarData
set methodProc(polarplot,saveplot) SavePlot
set methodProc(polarplot,dataconfig) DataConfig
set methodProc(polarplot,background) BackgroundColour
set methodProc(polarplot,legendconfig) LegendConfigure
set methodProc(polarplot,legend) DrawLegend
set methodProc(polarplot,balloon) DrawBalloon
set methodProc(polarplot,balloonconfig) ConfigBalloon
set methodProc(polarplot,plaintext) DrawPlainText
set methodProc(histogram,title) DrawTitle
set methodProc(histogram,xtext) DrawXtext
set methodProc(histogram,ytext) DrawYtext
set methodProc(histogram,plot) DrawHistogramData
set methodProc(histogram,saveplot) SavePlot
set methodProc(histogram,dataconfig) DataConfig
set methodProc(histogram,xconfig) XConfig
set methodProc(histogram,yconfig) YConfig
set methodProc(histogram,yticklines) DrawYTicklines
set methodProc(histogram,background) BackgroundColour
set methodProc(histogram,legendconfig) LegendConfigure
set methodProc(histogram,legend) DrawLegend
set methodProc(histogram,balloon) DrawBalloon
set methodProc(histogram,balloonconfig) ConfigBalloon
set methodProc(histogram,plaintext) DrawPlainText
set methodProc(horizbars,title) DrawTitle
set methodProc(horizbars,xtext) DrawXtext
set methodProc(horizbars,ytext) DrawYtext
set methodProc(horizbars,plot) DrawHorizBarData
set methodProc(horizbars,xticklines) DrawXTicklines
set methodProc(horizbars,background) BackgroundColour
set methodProc(horizbars,saveplot) SavePlot
set methodProc(horizbars,colours) SetColours
set methodProc(horizbars,colors) SetColours
set methodProc(horizbars,xconfig) XConfig
set methodProc(horizbars,legendconfig) LegendConfigure
set methodProc(horizbars,legend) DrawLegend
set methodProc(horizbars,balloon) DrawBalloon
set methodProc(horizbars,balloonconfig) ConfigBalloon
set methodProc(horizbars,plaintext) DrawPlainText
set methodProc(vertbars,title) DrawTitle
set methodProc(vertbars,xtext) DrawXtext
set methodProc(vertbars,ytext) DrawYtext
set methodProc(vertbars,plot) DrawVertBarData
set methodProc(vertbars,background) BackgroundColour
set methodProc(vertbars,yticklines) DrawYTicklines
set methodProc(vertbars,saveplot) SavePlot
set methodProc(vertbars,colours) SetColours
set methodProc(vertbars,colors) SetColours
set methodProc(vertbars,yconfig) YConfig
set methodProc(vertbars,legendconfig) LegendConfigure
set methodProc(vertbars,legend) DrawLegend
set methodProc(vertbars,balloon) DrawBalloon
set methodProc(vertbars,balloonconfig) ConfigBalloon
set methodProc(vertbars,plaintext) DrawPlainText
set methodProc(timechart,title) DrawTitle
set methodProc(timechart,period) DrawTimePeriod
set methodProc(timechart,milestone) DrawTimeMilestone
set methodProc(timechart,vertline) DrawTimeVertLine
set methodProc(timechart,saveplot) SavePlot
set methodProc(timechart,background) BackgroundColour
set methodProc(timechart,balloon) DrawBalloon
set methodProc(timechart,balloonconfig) ConfigBalloon
set methodProc(timechart,plaintext) DrawPlainText
set methodProc(ganttchart,title) DrawTitle
set methodProc(ganttchart,period) DrawGanttPeriod
set methodProc(ganttchart,task) DrawGanttPeriod
set methodProc(ganttchart,milestone) DrawGanttMilestone
set methodProc(ganttchart,vertline) DrawGanttVertLine
set methodProc(ganttchart,saveplot) SavePlot
set methodProc(ganttchart,color) GanttColor
set methodProc(ganttchart,colour) GanttColor
set methodProc(ganttchart,font) GanttFont
set methodProc(ganttchart,connect) DrawGanttConnect
set methodProc(ganttchart,summary) DrawGanttSummary
set methodProc(ganttchart,background) BackgroundColour
set methodProc(ganttchart,balloon) DrawBalloon
set methodProc(ganttchart,balloonconfig) ConfigBalloon
set methodProc(ganttchart,plaintext) DrawPlainText
set methodProc(stripchart,title) DrawTitle
set methodProc(stripchart,xtext) DrawXtext
set methodProc(stripchart,ytext) DrawYtext
set methodProc(stripchart,plot) DrawStripData
set methodProc(stripchart,saveplot) SavePlot
set methodProc(stripchart,dataconfig) DataConfig
set methodProc(stripchart,xconfig) XConfig
set methodProc(stripchart,yconfig) YConfig
set methodProc(stripchart,yticklines) DrawYTicklines
set methodProc(stripchart,background) BackgroundColour
set methodProc(stripchart,legendconfig) LegendConfigure
set methodProc(stripchart,legend) DrawLegend
set methodProc(stripchart,balloon) DrawBalloon
set methodProc(stripchart,balloonconfig) ConfigBalloon
set methodProc(stripchart,plaintext) DrawPlainText
set methodProc(isometric,title) DrawTitle
set methodProc(isometric,xtext) DrawXtext
set methodProc(isometric,ytext) DrawYtext
set methodProc(isometric,plot) DrawIsometricData
set methodProc(isometric,saveplot) SavePlot
set methodProc(isometric,background) BackgroundColour
set methodProc(isometric,balloon) DrawBalloon
set methodProc(isometric,balloonconfig) ConfigBalloon
set methodProc(isometric,plaintext) DrawPlainText
set methodProc(3dplot,title) DrawTitle
set methodProc(3dplot,plotfunc) Draw3DFunction
set methodProc(3dplot,plotdata) Draw3DData
set methodProc(3dplot,plotline) Draw3DLineFrom3Dcoordinates
set methodProc(3dplot,gridsize) GridSize3D
set methodProc(3dplot,saveplot) SavePlot
set methodProc(3dplot,colour) SetColours
set methodProc(3dplot,color) SetColours
set methodProc(3dplot,xconfig) XConfig
set methodProc(3dplot,yconfig) YConfig
set methodProc(3dplot,zconfig) ZConfig
set methodProc(3dplot,plotfuncont) Draw3DFunctionContour
set methodProc(3dplot,background) BackgroundColour
set methodProc(3dbars,title) DrawTitle
set methodProc(3dbars,plot) Draw3DBar
set methodProc(3dbars,yconfig) YConfig
set methodProc(3dbars,saveplot) SavePlot
set methodProc(3dbars,config) Config3DBars
set methodProc(3dbars,balloon) DrawBalloon
set methodProc(3dbars,balloonconfig) ConfigBalloon
set methodProc(3dbars,plaintext) DrawPlainText
set methodProc(radialchart,title) DrawTitle
set methodProc(radialchart,plot) DrawRadial
set methodProc(radialchart,saveplot) SavePlot
set methodProc(radialchart,balloon) DrawBalloon
set methodProc(radialchart,plaintext) DrawPlainText
set methodProc(txplot,title) DrawTitle
set methodProc(txplot,xtext) DrawXtext
set methodProc(txplot,ytext) DrawYtext
set methodProc(txplot,plot) DrawTimeData
set methodProc(txplot,interval) DrawInterval
set methodProc(txplot,saveplot) SavePlot
set methodProc(txplot,dataconfig) DataConfig
set methodProc(txplot,xconfig) XConfig
set methodProc(txplot,yconfig) YConfig
set methodProc(txplot,xticklines) DrawXTicklines
set methodProc(txplot,yticklines) DrawYTicklines
set methodProc(txplot,background) BackgroundColour
set methodProc(txplot,legendconfig) LegendConfigure
set methodProc(txplot,legend) DrawLegend
set methodProc(txplot,balloon) DrawBalloon
set methodProc(txplot,balloonconfig) ConfigBalloon
set methodProc(txplot,plaintext) DrawPlainText
set methodProc(3dribbon,title) DrawTitle
set methodProc(3dribbon,saveplot) SavePlot
set methodProc(3dribbon,line) Draw3DLine
set methodProc(3dribbon,area) Draw3DArea
set methodProc(3dribbon,background) BackgroundColour
#
# Auxiliary parameters
#
variable torad
set torad [expr {3.1415926/180.0}]
variable options
variable option_keys
variable option_values
set options {-colour -color -symbol -type -filled -fillcolour}
set option_keys {-colour -colour -symbol -type -filled -fillcolour}
set option_values {-colour {...}
-symbol {plus cross circle up down dot upfilled downfilled}
-type {line symbol both}
-filled {no up down}
-fillcolour {...}
}
variable axis_options
variable axis_option_clear
variable axis_option_values
set axis_options {-format -ticklength -ticklines -scale}
set axis_option_clear { 0 0 0 1 }
set axis_option_values {-format {...}
-ticklength {...}
-ticklines {0 1}
-scale {...}
}
variable contour_options
}
# setZoomPan --
# Set up the bindings for zooming and panning
# Arguments:
# w Name of the canvas window
# Result:
# None
# Side effect:
# Bindings set up
#
proc ::Plotchart::setZoomPan { w } {
set sqrt2 [expr {sqrt(2.0)}]
set sqrt05 [expr {sqrt(0.5)}]
bind $w <Control-Button-1> [list ::Plotchart::ScaleItems $w %x %y $sqrt2]
bind $w <Control-Prior> [list ::Plotchart::ScaleItems $w %x %y $sqrt2]
bind $w <Control-Button-2> [list ::Plotchart::ScaleItems $w %x %y $sqrt05]
bind $w <Control-Button-3> [list ::Plotchart::ScaleItems $w %x %y $sqrt05]
bind $w <Control-Next> [list ::Plotchart::ScaleItems $w %x %y $sqrt05]
bind $w <Control-Up> [list ::Plotchart::MoveItems $w 0 -40]
bind $w <Control-Down> [list ::Plotchart::MoveItems $w 0 40]
bind $w <Control-Left> [list ::Plotchart::MoveItems $w -40 0]
bind $w <Control-Right> [list ::Plotchart::MoveItems $w 40 0]
focus $w
}
# viewPort --
# Set the pixel extremes for the graph
# Arguments:
# w Name of the canvas window
# pxmin Minimum X-coordinate
# pymin Minimum Y-coordinate
# pxmax Maximum X-coordinate
# pymax Maximum Y-coordinate
# Result:
# None
# Side effect:
# Array scaling filled
#
proc ::Plotchart::viewPort { w pxmin pymin pxmax pymax } {
variable scaling
if { $pxmin >= $pxmax || $pymin >= $pymax } {
return -code error "Inconsistent bounds for viewport"
}
# <MB>
set scaling($w,pxmin) $pxmin
set scaling($w,pymin) $pymin
set scaling($w,pxmax) $pxmax
set scaling($w,pymax) $pymax
set scaling($w,new) 1
}
# worldCoordinates --
# Set the extremes for the world coordinates
# Arguments:
# w Name of the canvas window
# xmin Minimum X-coordinate
# ymin Minimum Y-coordinate
# xmax Maximum X-coordinate
# ymax Maximum Y-coordinate
# Result:
# None
# Side effect:
# Array scaling filled
#
proc ::Plotchart::worldCoordinates { w xmin ymin xmax ymax } {
variable scaling
if { $xmin == $xmax || $ymin == $ymax } {
return -code error "Minimum and maximum must differ for world coordinates"
}
set scaling($w,xmin) [expr {double($xmin)}]
set scaling($w,ymin) [expr {double($ymin)}]
set scaling($w,xmax) [expr {double($xmax)}]
set scaling($w,ymax) [expr {double($ymax)}]
set scaling($w,new) 1
}
# polarCoordinates --
# Set the extremes for the polar coordinates
# Arguments:
# w Name of the canvas window
# radmax Maximum radius
# Result:
# None
# Side effect:
# Array scaling filled
#
proc ::Plotchart::polarCoordinates { w radmax } {
variable scaling
if { $radmax <= 0.0 } {
return -code error "Maximum radius must be positive"
}
set scaling($w,xmin) [expr {-double($radmax)}]
set scaling($w,ymin) [expr {-double($radmax)}]
set scaling($w,xmax) [expr {double($radmax)}]
set scaling($w,ymax) [expr {double($radmax)}]
set scaling($w,new) 1
}
# world3DCoordinates --
# Set the extremes for the world coordinates in 3D plots
# Arguments:
# w Name of the canvas window
# xmin Minimum X-coordinate
# ymin Minimum Y-coordinate
# zmin Minimum Z-coordinate
# xmax Maximum X-coordinate
# ymax Maximum Y-coordinate
# zmax Maximum Z-coordinate
# Result:
# None
# Side effect:
# Array scaling filled
#
proc ::Plotchart::world3DCoordinates { w xmin ymin zmin xmax ymax zmax } {
variable scaling
if { $xmin == $xmax || $ymin == $ymax || $zmin == $zmax } {
return -code error "Minimum and maximum must differ for world coordinates"
}
set scaling($w,xmin) [expr {double($xmin)}]
set scaling($w,ymin) [expr {double($ymin)}]
set scaling($w,zmin) [expr {double($zmin)}]
set scaling($w,xmax) [expr {double($xmax)}]
set scaling($w,ymax) [expr {double($ymax)}]
set scaling($w,zmax) [expr {double($zmax)}]
set scaling($w,new) 1
}
# coordsToPixel --
# Convert world coordinates to pixel coordinates
# Arguments:
# w Name of the canvas
# xcrd X-coordinate
# ycrd Y-coordinate
# Result:
# List of two elements, x- and y-coordinates in pixels
#
proc ::Plotchart::coordsToPixel { w xcrd ycrd } {
variable scaling
if { $scaling($w,new) == 1 } {
set scaling($w,new) 0
set width [expr {$scaling($w,pxmax)-$scaling($w,pxmin)}]
set height [expr {$scaling($w,pymax)-$scaling($w,pymin)}]
set dx [expr {$scaling($w,xmax)-$scaling($w,xmin)}]
set dy [expr {$scaling($w,ymax)-$scaling($w,ymin)}]
set scaling($w,xfactor) [expr {$width/$dx}]
set scaling($w,yfactor) [expr {$height/$dy}]
}
set xpix [expr {$scaling($w,pxmin)+($xcrd-$scaling($w,xmin))*$scaling($w,xfactor)}]
set ypix [expr {$scaling($w,pymin)+($scaling($w,ymax)-$ycrd)*$scaling($w,yfactor)}]
return [list $xpix $ypix]
}
# coords3DToPixel --
# Convert world coordinates to pixel coordinates (3D plots)
# Arguments:
# w Name of the canvas
# xcrd X-coordinate
# ycrd Y-coordinate
# zcrd Z-coordinate
# Result:
# List of two elements, x- and y-coordinates in pixels
#
proc ::Plotchart::coords3DToPixel { w xcrd ycrd zcrd } {
variable scaling
if { $scaling($w,new) == 1 } {
set scaling($w,new) 0
set width [expr {$scaling($w,pxmax)-$scaling($w,pxmin)}]
set height [expr {$scaling($w,pymax)-$scaling($w,pymin)}]
set dx [expr {$scaling($w,xmax)-$scaling($w,xmin)}]
set dy [expr {$scaling($w,ymax)-$scaling($w,ymin)}]
set dz [expr {$scaling($w,zmax)-$scaling($w,zmin)}]
set scaling($w,xyfactor) [expr {$scaling($w,yfract)*$width/$dx}]
set scaling($w,xzfactor) [expr {$scaling($w,zfract)*$height/$dx}]
set scaling($w,yfactor) [expr {$width/$dy}]
set scaling($w,zfactor) [expr {$height/$dz}]
}
#
# The values for xcrd = xmax
#
set xpix [expr {$scaling($w,pxmin)+($ycrd-$scaling($w,ymin))*$scaling($w,yfactor)}]
set ypix [expr {$scaling($w,pymin)+($scaling($w,zmax)-$zcrd)*$scaling($w,zfactor)}]
#
# Add the shift due to xcrd-xmax
#
set xpix [expr {$xpix + $scaling($w,xyfactor)*($xcrd-$scaling($w,xmax))}]
set ypix [expr {$ypix - $scaling($w,xzfactor)*($xcrd-$scaling($w,xmax))}]
return [list $xpix $ypix]
}
# pixelToCoords --
# Convert pixel coordinates to world coordinates
# Arguments:
# w Name of the canvas
# xpix X-coordinate (pixel)
# ypix Y-coordinate (pixel)
# Result:
# List of two elements, x- and y-coordinates in world coordinate system
#
proc ::Plotchart::pixelToCoords { w xpix ypix } {
variable scaling
if { $scaling($w,new) == 1 } {
set scaling($w,new) 0
set width [expr {$scaling($w,pxmax)-$scaling($w,pxmin)}]
set height [expr {$scaling($w,pymax)-$scaling($w,pymin)}]
set dx [expr {$scaling($w,xmax)-$scaling($w,xmin)}]
set dy [expr {$scaling($w,ymax)-$scaling($w,ymin)}]
set scaling($w,xfactor) [expr {$width/$dx}]
set scaling($w,yfactor) [expr {$height/$dy}]
}
set xcrd [expr {$scaling($w,xmin)+($xpix-$scaling($w,pxmin))/$scaling($w,xfactor)}]
set ycrd [expr {$scaling($w,ymax)-($ypix-$scaling($w,pymin))/$scaling($w,yfactor)}]
return [list $xcrd $ycrd]
}
# pixelToIndex --
# Convert pixel coordinates to elements list index
# Arguments:
# w Name of the canvas
# xpix X-coordinate (pixel)
# ypix Y-coordinate (pixel)
# Result:
# Elements list index
#
proc ::Plotchart::pixelToIndex { w xpix ypix } {
variable scaling
variable torad
set idx -1
set radius [expr {($scaling(${w},pxmax) - $scaling(${w},pxmin)) / 2}]
set xrel [expr {${xpix} - $scaling(${w},pxmin) - ${radius}}]
set yrel [expr {-${ypix} + $scaling(${w},pymin) + ${radius}}]
if {[expr {pow(${radius},2) < (pow(${xrel},2) + pow(${yrel},2))}]} {
# do nothing out of pie chart
} elseif {[info exists scaling(${w},angles)]} {
set xy_angle [expr {(360 + round(atan2(${yrel},${xrel})/${torad})) % 360}]
foreach angle $scaling(${w},angles) {
if {${xy_angle} <= ${angle}} {
break
}
incr idx
}
}
return ${idx}
}
# polarToPixel --
# Convert polar coordinates to pixel coordinates
# Arguments:
# w Name of the canvas
# rad Radius of the point
# phi Angle of the point (degrees)
# Result:
# List of two elements, x- and y-coordinates in pixels
#
proc ::Plotchart::polarToPixel { w rad phi } {
variable torad
set xcrd [expr {$rad*cos($phi*$torad)}]
set ycrd [expr {$rad*sin($phi*$torad)}]
coordsToPixel $w $xcrd $ycrd
}
# createXYPlot --
# Create a command for drawing an XY plot
# Arguments:
# w Name of the canvas
# xscale Minimum, maximum and step for x-axis (initial)
# yscale Minimum, maximum and step for y-axis
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the XY plot.
# The plot will be drawn with axes
#
proc ::Plotchart::createXYPlot { w xscale yscale } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "xyplot_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler xyplot $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
foreach {xmin xmax xdelt} $xscale {break}
foreach {ymin ymax ydelt} $yscale {break}
if { $xdelt == 0.0 || $ydelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($xmax-$xmin)*$xdelt < 0.0 } {
set xdelt [expr {-$xdelt}]
}
if { ($ymax-$ymin)*$ydelt < 0.0 } {
set ydelt [expr {-$ydelt}]
}
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
DrawYaxis $w $ymin $ymax $ydelt
DrawXaxis $w $xmin $xmax $xdelt
DrawMask $w
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createStripchart --
# Create a command for drawing a strip chart
# Arguments:
# w Name of the canvas
# xscale Minimum, maximum and step for x-axis (initial)
# yscale Minimum, maximum and step for y-axis
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the stripchart.
# The stripchart will be drawn with axes
#
proc ::Plotchart::createStripchart { w xscale yscale } {
variable data_series
set newchart [createXYPlot $w $xscale $yscale]
interp alias {} $newchart {}
set newchart "stripchart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler stripchart $w
return $newchart
}
# createIsometricPlot --
# Create a command for drawing an "isometric" plot
# Arguments:
# w Name of the canvas
# xscale Minimum and maximum for x-axis
# yscale Minimum and maximum for y-axis
# stepsize Step size for numbers on the axes or "noaxes"
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the plot
# The plot will be drawn with or without axes
#
proc ::Plotchart::createIsometricPlot { w xscale yscale stepsize } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "isometric_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler isometric $w
if { $stepsize != "noaxes" } {
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
} else {
set pxmin 0
set pymin 0
#set pxmax [$w cget -width]
#set pymax [$w cget -height]
set pxmax [WidthCanvas $w]
set pymax [HeightCanvas $w]
}
foreach {xmin xmax} $xscale {break}
foreach {ymin ymax} $yscale {break}
if { $xmin == $xmax || $ymin == $ymax } {
return -code error "Extremes for axes must be different"
}
viewPort $w $pxmin $pymin $pxmax $pymax
ScaleIsometric $w $xmin $ymin $xmax $ymax
if { $stepsize != "noaxes" } {
DrawYaxis $w $ymin $ymax $ydelt
DrawXaxis $w $xmin $xmax $xdelt
DrawMask $w
}
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createHistogram --
# Create a command for drawing a histogram
# Arguments:
# w Name of the canvas
# xscale Minimum, maximum and step for x-axis (initial)
# yscale Minimum, maximum and step for y-axis
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the histogram.
# The plot will be drawn with axes
# This is almost the same code as for an XY plot
#
proc ::Plotchart::createHistogram { w xscale yscale } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "histogram_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler histogram $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
foreach {xmin xmax xdelt} $xscale {break}
foreach {ymin ymax ydelt} $yscale {break}
if { $xdelt == 0.0 || $ydelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($xmax-$xmin)*$xdelt < 0.0 } {
set xdelt [expr {-$xdelt}]
}
if { ($ymax-$ymin)*$ydelt < 0.0 } {
set ydelt [expr {-$ydelt}]
}
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
DrawYaxis $w $ymin $ymax $ydelt
DrawXaxis $w $xmin $xmax $xdelt
DrawMask $w
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createPiechart --
# Create a command for drawing a pie chart
# Arguments:
# w Name of the canvas
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the pie chart.
#
proc ::Plotchart::createPiechart { w } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "piechart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler piechart $w
foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}
viewPort $w $pxmin $pymin $pxmax $pymax
$w create oval $pxmin $pymin $pxmax $pymax
SetColours $w blue lightblue green yellow orange red magenta brown
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createPolarplot --
# Create a command for drawing a polar plot
# Arguments:
# w Name of the canvas
# radius_data Maximum radius and step
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the polar plot
# Possible additional arguments (optional): nautical/mathematical
# step in phi
#
proc ::Plotchart::createPolarplot { w radius_data } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "polarplot_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler polarplot $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
DrawPolarAxes $w $rad_max $rad_step
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createBarchart --
# Create a command for drawing a barchart with vertical bars
# Arguments:
# w Name of the canvas
# xlabels List of labels for x-axis
# yscale Minimum, maximum and step for y-axis
# noseries Number of series or the keyword "stacked"
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the barchart.
#
proc ::Plotchart::createBarchart { w xlabels yscale noseries } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "barchart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler vertbars $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
set xmin 0.0
set xmax [expr {[llength $xlabels] + 0.1}]
foreach {ymin ymax ydelt} $yscale {break}
if { $ydelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($ymax-$ymin)*$ydelt < 0.0 } {
set ydelt [expr {-$ydelt}]
}
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
DrawYaxis $w $ymin $ymax $ydelt
DrawXlabels $w $xlabels $noseries
DrawMask $w
DefaultLegend $w
set data_series($w,legendtype) "rectangle"
DefaultBalloon $w
SetColours $w blue lightblue green yellow orange red magenta brown
return $newchart
}
# createHorizontalBarchart --
# Create a command for drawing a barchart with horizontal bars
# Arguments:
# w Name of the canvas
# xscale Minimum, maximum and step for x-axis
# ylabels List of labels for y-axis
# noseries Number of series or the keyword "stacked"
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the barchart.
#
proc ::Plotchart::createHorizontalBarchart { w xscale ylabels noseries } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "hbarchart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler horizbars $w
set notext 2.0
set text_width 8
#
# Compute the maximum width of the labels
# <MB>
#
label .invisibleLabel
set fontname [.invisibleLabel cget -font]
destroy .invisibleLabel
set xspacemax 0
foreach ylab $ylabels {
set xspace [font measure $fontname $ylab]
if {$xspace> $xspacemax} then {
set xspacemax $xspace
}
}
set text_width [expr {int ( $xspacemax / 10.) + 1}]
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w $notext $text_width] {break}
set ymin 0.0
set ymax [expr {[llength $ylabels] + 0.1}]
foreach {xmin xmax xdelt} $xscale {break}
if { $xdelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($xmax-$xmin)*$xdelt < 0.0 } {
set xdelt [expr {-$xdelt}]
}
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
DrawXaxis $w $xmin $xmax $xdelt
DrawYlabels $w $ylabels $noseries
DrawMask $w
DefaultLegend $w
set data_series($w,legendtype) "rectangle"
DefaultBalloon $w
SetColours $w blue lightblue green yellow orange red magenta brown
return $newchart
}
# createTimechart --
# Create a command for drawing a simple timechart
# Arguments:
# w Name of the canvas
# time_begin Start time (in the form of a date/time)
# time_end End time (in the form of a date/time)
# noitems Number of items to be shown (determines spacing)
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the timechart.
#
proc ::Plotchart::createTimechart { w time_begin time_end noitems } {
variable data_series
variable scaling
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "timechart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler timechart $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w 3] {break}
set ymin 0.0
set ymax $noitems
set xmin [expr {1.0*[clock scan $time_begin]}]
set xmax [expr {1.0*[clock scan $time_end]}]
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
set scaling($w,current) $ymax
set scaling($w,dy) -0.7
return $newchart
}
# createGanttchart --
# Create a command for drawing a Gantt (planning) chart
# Arguments:
# w Name of the canvas
# time_begin Start time (in the form of a date/time)
# time_end End time (in the form of a date/time)
# noitems Number of items to be shown (determines spacing)
# text_width Estimated maximum length of text (default: 20)
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the Gantt chart.
# Most commands taken from time charts.
#
proc ::Plotchart::createGanttchart { w time_begin time_end noitems
{text_width 20} } {
variable data_series
variable scaling
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "ganttchart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler ganttchart $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w 3 $text_width] {break}
set ymin 0.0
set ymax $noitems
set xmin [expr {1.0*[clock scan $time_begin]}]
set xmax [expr {1.0*[clock scan $time_end]}]
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
set scaling($w,current) $ymax
set scaling($w,dy) -0.7
#
# Draw the backgrounds (both in the text part and the
# graphical part; the text part has the "special" tag
# "Edit" to enable a GUI to change things)
#
set yend 0.0
for { set i 0 } { $i < $noitems } { incr i } {
set ybegin $yend
set yend [expr {$ybegin+1.0}]
foreach {x1 y1} [coordsToPixel $w $xmin $ybegin] {break}
foreach {x2 y2} [coordsToPixel $w $xmax $yend ] {break}
if { $i%2 == 0 } {
set tag odd
} else {
set tag even
}
$w create rectangle 0 $y1 $x1 $y2 -fill white -tag Edit -outline white
$w create rectangle $x1 $y1 $x2 $y2 -fill white -tag $tag -outline white
}
#
# Default colours and fonts
#
GanttColor $w description black
GanttColor $w completed lightblue
GanttColor $w left white
GanttColor $w odd white
GanttColor $w even lightgrey
GanttColor $w summary black
GanttColor $w summarybar black
GanttFont $w description "times 10"
GanttFont $w summary "times 10 bold"
GanttFont $w scale "times 7"
DefaultBalloon $w
return $newchart
}
# create3DPlot --
# Create a simple 3D plot
# Arguments:
# w Name of the canvas
# xscale Minimum, maximum and step for x-axis (initial)
# yscale Minimum, maximum and step for y-axis
# zscale Minimum, maximum and step for z-axis
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the 3D plot
#
proc ::Plotchart::create3DPlot { w xscale yscale zscale } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "3dplot_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler 3dplot $w
foreach {pxmin pymin pxmax pymax} [Margins3DPlot $w] {break}
foreach {xmin xmax xstep} $xscale {break}
foreach {ymin ymax ystep} $yscale {break}
foreach {zmin zmax zstep} $zscale {break}
viewPort $w $pxmin $pymin $pxmax $pymax
world3DCoordinates $w $xmin $ymin $zmin $xmax $ymax $zmax
Draw3DAxes $w $xmin $ymin $zmin $xmax $ymax $zmax \
$xstep $ystep $zstep
DefaultLegend $w
DefaultBalloon $w
SetColours $w grey black
return $newchart
}
# create3DBarchart --
# Create a command for drawing a barchart with vertical 3D bars
# Arguments:
# w Name of the canvas
# yscale Minimum, maximum and step for y-axis
# nobars Number of bars to be drawn
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the barchart.
#
proc ::Plotchart::create3DBarchart { w yscale nobars } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "3dbarchart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler 3dbars $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w 4] {break}
set xmin 0.0
set xmax [expr {$nobars + 0.1}]
foreach {ymin ymax ydelt} $yscale {break}
if { $ydelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($ymax-$ymin)*$ydelt < 0.0 } {
set ydelt [expr {-$ydelt}]
}
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
DrawYaxis $w $ymin $ymax $ydelt
#DrawMask $w -- none!
Draw3DBarchart $w $yscale $nobars
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createRadialchart --
# Create a command for drawing a radial chart
# Arguments:
# w Name of the canvas
# names Names of the spokes
# scale Scale factor for the data
# style (Optional) style of the chart (lines, cumulative or filled)
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the radial chart.
#
proc ::Plotchart::createRadialchart { w names scale {style lines} } {
variable settings
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "radialchart_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler radialchart $w
foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}
viewPort $w $pxmin $pymin $pxmax $pymax
$w create oval $pxmin $pymin $pxmax $pymax
set settings($w,scale) [expr {double($scale)}]
set settings($w,style) $style
set settings($w,number) [llength $names]
DrawRadialSpokes $w $names
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createTXPlot --
# Create a command for drawing a TX plot (x versus date/time)
# Arguments:
# w Name of the canvas
# tscale Minimum, maximum and step for date/time-axis (initial)
# (values must be valid dates and the step is in days)
# xscale Minimum, maximum and step for vertical axis
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the TX plot.
# The plot will be drawn with axes
#
proc ::Plotchart::createTXPlot { w tscale xscale } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "txplot_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler txplot $w
foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
foreach {tmin tmax tdelt} $tscale {break}
set xmin [clock scan $tmin]
set xmax [clock scan $tmax]
set xdelt [expr {86400*$tdelt}]
foreach {ymin ymax ydelt} $xscale {break}
if { $xdelt == 0.0 || $ydelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($xmax-$xmin)*$xdelt < 0.0 } {
set xdelt [expr {-$xdelt}]
}
if { ($ymax-$ymin)*$ydelt < 0.0 } {
set ydelt [expr {-$ydelt}]
}
viewPort $w $pxmin $pymin $pxmax $pymax
worldCoordinates $w $xmin $ymin $xmax $ymax
DrawYaxis $w $ymin $ymax $ydelt
DrawTimeaxis $w $tmin $tmax $tdelt
DrawMask $w
DefaultLegend $w
DefaultBalloon $w
return $newchart
}
# createRightAxis --
# Create a command for drawing a plot with a right axis
# Arguments:
# w Name of the canvas
# yscale Minimum, maximum and step for vertical axis
# Result:
# Name of a new command
# Note:
# This command requires that another plot command has been
# created prior to this one. Some of the properties from that
# command serve for this one too.
#
proc ::Plotchart::createRightAxis { w yscale } {
variable data_series
variable scaling
set newchart "right_$w"
#
# Check if there is an appropriate plot already defined - there
# should be only one!
#
if { [llength [info command "*_$w" ]] == 0 } {
return -code error "There should be a plot with a left axis already defined"
}
if { [llength [info command "*_$w" ]] != 1 } {
return -code error "There should be only one plot command for this widget ($w)"
}
set type [lindex [interp alias {} [info command "*_$w"]] 1]
interp alias {} $newchart {} ::Plotchart::PlotHandler $type r$w
interp alias {} r$w {} $w
set xmin $scaling($w,xmin)
set xmax $scaling($w,xmax)
set pxmin $scaling($w,pxmin)
set pxmax $scaling($w,pxmax)
set pymin $scaling($w,pymin)
set pymax $scaling($w,pymax)
foreach {ymin ymax ydelt} $yscale {break}
if { $ydelt == 0.0 } {
return -code error "Step size can not be zero"
}
if { ($ymax-$ymin)*$ydelt < 0.0 } {
set ydelt [expr {-$ydelt}]
}
viewPort r$w $pxmin $pymin $pxmax $pymax
worldCoordinates r$w $xmin $ymin $xmax $ymax
DrawRightaxis r$w $ymin $ymax $ydelt
return $newchart
}
# create3DRibbonChart --
# Create a chart that can display 3D lines and areas
# Arguments:
# w Name of the canvas
# names Labels along the x-axis
# yscale Minimum, maximum and step for y-axis
# zscale Minimum, maximum and step for z-axis
# Result:
# Name of a new command
# Note:
# The entire canvas will be dedicated to the 3D chart
#
proc ::Plotchart::create3DRibbonChart { w names yscale zscale } {
variable data_series
foreach s [array names data_series "$w,*"] {
unset data_series($s)
}
set newchart "3dribbon_$w"
interp alias {} $newchart {} ::Plotchart::PlotHandler 3dribbon $w
foreach {pxmin pymin pxmax pymax} [Margins3DPlot $w] {break}
foreach {xmin xmax xstep} {0.0 1.0 0.0} {break}
foreach {ymin ymax ystep} $yscale {break}
foreach {zmin zmax zstep} $zscale {break}
set xstep [expr {1.0/[llength $names]}]
set data_series($w,xbase) [expr {1.0-0.15*$xstep}]
set data_series($w,xstep) $xstep
set data_series($w,xwidth) [expr {0.7*$xstep}]
viewPort $w $pxmin $pymin $pxmax $pymax
world3DCoordinates $w $xmin $ymin $zmin $xmax $ymax $zmax
Draw3DAxes $w $xmin $ymin $zmin $xmax $ymax $zmax \
$xstep $ystep $zstep $names
DefaultLegend $w
DefaultBalloon $w
SetColours $w grey black
return $newchart
}
# Load the private procedures
#
source [file join [file dirname [info script]] "plotpriv.tcl"]
source [file join [file dirname [info script]] "plotaxis.tcl"]
source [file join [file dirname [info script]] "plot3d.tcl"]
source [file join [file dirname [info script]] "scaling.tcl"]
source [file join [file dirname [info script]] "plotcontour.tcl"]
source [file join [file dirname [info script]] "plotgantt.tcl"]
source [file join [file dirname [info script]] "plotbusiness.tcl"]
source [file join [file dirname [info script]] "plotannot.tcl"]
# Announce our presence
#
package provide Plotchart 1.3.2