1# plotchart.tcl --
2#    Facilities to draw simple plots in a dedicated canvas
3#
4# Note:
5#    This source file contains the public functions.
6#    The private functions are contained in the files "sourced"
7#    at the end.
8#
9package require Tcl 8.4
10package require Tk
11
12# Plotchart --
13#    Namespace to hold the procedures and the private data
14#
15namespace eval ::Plotchart {
16   variable settings
17   variable legend
18   variable scaling
19   variable methodProc
20   variable data_series
21
22   namespace export worldCoordinates viewPort coordsToPixel \
23                    polarCoordinates setZoomPan \
24                    world3DCoordinates coordsToPixel \
25                    coords3DToPixel polarToPixel \
26                    pixelToCoords pixelToIndex \
27                    determineScale determineScaleFromList \
28                    createXYPlot createPolarplot createPiechart \
29                    createBarchart createHorizontalBarchart \
30                    createTimechart createStripchart \
31                    createIsometricPlot create3DPlot \
32                    createGanttChart createHistogram colorMap \
33                    create3DBars createRadialchart \
34                    createTXPlot createRightAxis \
35                    create3DRibbonChart create3DRibbonPlot \
36                    createXLogYPlot createLogXYPlot createLogXLogYPlot \
37                    createWindrose createTargetDiagram createPerformanceProfile \
38                    plotconfig plotpack plotmethod
39
40   #
41   # Array linking procedures with methods
42   #
43   set methodProc(xyplot,title)             DrawTitle
44   set methodProc(xyplot,xtext)             DrawXtext
45   set methodProc(xyplot,ytext)             DrawYtext
46   set methodProc(xyplot,vtext)             DrawVtext
47   set methodProc(xyplot,plot)              DrawData
48   set methodProc(xyplot,dot)               DrawDot
49   set methodProc(xyplot,dotconfig)         DotConfigure
50   set methodProc(xyplot,interval)          DrawInterval
51   set methodProc(xyplot,trend)             DrawTrendLine
52   set methodProc(xyplot,vector)            DrawVector
53   set methodProc(xyplot,vectorconfig)      VectorConfigure
54   set methodProc(xyplot,rchart)            DrawRchart
55   set methodProc(xyplot,grid)              DrawGrid
56   set methodProc(xyplot,contourlines)      DrawIsolines
57   set methodProc(xyplot,contourfill)       DrawShades
58   set methodProc(xyplot,contourbox)        DrawBox
59   set methodProc(xyplot,saveplot)          SavePlot
60   set methodProc(xyplot,dataconfig)        DataConfig
61   set methodProc(xyplot,xconfig)           XConfig
62   set methodProc(xyplot,yconfig)           YConfig
63   set methodProc(xyplot,xticklines)        DrawXTicklines
64   set methodProc(xyplot,yticklines)        DrawYTicklines
65   set methodProc(xyplot,background)        BackgroundColour
66   set methodProc(xyplot,legendconfig)      LegendConfigure
67   set methodProc(xyplot,legend)            DrawLegend
68   set methodProc(xyplot,balloon)           DrawBalloon
69   set methodProc(xyplot,balloonconfig)     ConfigBalloon
70   set methodProc(xyplot,plaintext)         DrawPlainText
71   set methodProc(xyplot,plaintextconfig)   ConfigPlainText
72   set methodProc(xyplot,bindvar)           BindVar
73   set methodProc(xyplot,bindcmd)           BindCmd
74   set methodProc(xyplot,rescale)           RescalePlot
75   set methodProc(xyplot,box-and-whiskers)  DrawBoxWhiskers
76   set methodProc(xyplot,xband)             DrawXband
77   set methodProc(xyplot,yband)             DrawYband
78   set methodProc(xyplot,labeldot)          DrawLabelDot
79   set methodProc(xyplot,bindplot)          BindPlot
80   set methodProc(xyplot,bindlast)          BindLast
81   set methodProc(xyplot,contourlinesfunctionvalues)      DrawIsolinesFunctionValues
82   set methodProc(xyplot,contourlinesfunctionpoints)      DrawIsolinesFunctionPoints
83   set methodProc(xyplot,plotfunc)          DrawFunction
84   set methodProc(xlogyplot,title)          DrawTitle
85   set methodProc(xlogyplot,xtext)          DrawXtext
86   set methodProc(xlogyplot,ytext)          DrawYtext
87   set methodProc(xlogyplot,vtext)          DrawVtext
88   set methodProc(xlogyplot,plot)           DrawLogYData
89   set methodProc(xlogyplot,dot)            DrawLogDot
90   set methodProc(xlogyplot,dotconfig)      DotConfigure
91   set methodProc(xlogyplot,interval)       DrawLogInterval
92   set methodProc(xlogyplot,trend)          DrawLogTrendLine
93   set methodProc(xlogyplot,saveplot)       SavePlot
94   set methodProc(xlogyplot,dataconfig)     DataConfig
95   set methodProc(xlogyplot,xconfig)        XConfig
96   set methodProc(xlogyplot,yconfig)        YConfig
97   set methodProc(xlogyplot,xticklines)     DrawXTicklines
98   set methodProc(xlogyplot,yticklines)     DrawYTicklines
99   set methodProc(xlogyplot,background)     BackgroundColour
100   set methodProc(xlogyplot,legendconfig)   LegendConfigure
101   set methodProc(xlogyplot,legend)         DrawLegend
102   set methodProc(xlogyplot,balloon)        DrawBalloon
103   set methodProc(xlogyplot,balloonconfig)  ConfigBalloon
104   set methodProc(xlogyplot,plaintext)      DrawPlainText
105   set methodProc(xlogyplot,plaintextconfig) ConfigPlainText
106   set methodProc(logxyplot,title)          DrawTitle
107   set methodProc(logxyplot,xtext)          DrawXtext
108   set methodProc(logxyplot,ytext)          DrawYtext
109   set methodProc(logxyplot,vtext)          DrawVtext
110   set methodProc(logxyplot,plot)           DrawLogXData
111   set methodProc(logxyplot,dot)            DrawLogDot
112   set methodProc(logxyplot,dotconfig)      DotConfigure
113   set methodProc(logxyplot,interval)       DrawLogInterval
114   set methodProc(logxyplot,trend)          DrawLogTrendLine
115   set methodProc(logxyplot,saveplot)       SavePlot
116   set methodProc(logxyplot,dataconfig)     DataConfig
117   set methodProc(logxyplot,xconfig)        XConfig
118   set methodProc(logxyplot,yconfig)        YConfig
119   set methodProc(logxyplot,xticklines)     DrawXTicklines
120   set methodProc(logxyplot,yticklines)     DrawYTicklines
121   set methodProc(logxyplot,background)     BackgroundColour
122   set methodProc(logxyplot,legendconfig)   LegendConfigure
123   set methodProc(logxyplot,legend)         DrawLegend
124   set methodProc(logxyplot,balloon)        DrawBalloon
125   set methodProc(logxyplot,balloonconfig)  ConfigBalloon
126   set methodProc(logxyplot,plaintext)      DrawPlainText
127   set methodProc(logxyplot,plaintextconfig)   ConfigPlainText
128   set methodProc(logxlogyplot,title)          DrawTitle
129   set methodProc(logxlogyplot,xtext)          DrawXtext
130   set methodProc(logxlogyplot,ytext)          DrawYtext
131   set methodProc(logxlogyplot,vtext)          DrawVtext
132   set methodProc(logxlogyplot,plot)           DrawLogXLogYData
133   set methodProc(logxlogyplot,dot)            DrawLogDot
134   set methodProc(logxlogyplot,dotconfig)      DotConfigure
135   set methodProc(logxlogyplot,interval)       DrawLogInterval
136   set methodProc(logxlogyplot,trend)          DrawLogTrendLine
137   set methodProc(logxlogyplot,saveplot)       SavePlot
138   set methodProc(logxlogyplot,dataconfig)     DataConfig
139   set methodProc(logxlogyplot,xconfig)        XConfig
140   set methodProc(logxlogyplot,yconfig)        YConfig
141   set methodProc(logxlogyplot,xticklines)     DrawXTicklines
142   set methodProc(logxlogyplot,yticklines)     DrawYTicklines
143   set methodProc(logxlogyplot,background)     BackgroundColour
144   set methodProc(logxlogyplot,legendconfig)   LegendConfigure
145   set methodProc(logxlogyplot,legend)         DrawLegend
146   set methodProc(logxlogyplot,balloon)        DrawBalloon
147   set methodProc(logxlogyplot,balloonconfig)  ConfigBalloon
148   set methodProc(logxlogyplot,plaintext)      DrawPlainText
149   set methodProc(logxlogyplot,plaintextconfig) ConfigPlainText
150   set methodProc(piechart,title)              DrawTitle
151   set methodProc(piechart,plot)               DrawPie
152   set methodProc(piechart,saveplot)           SavePlot
153   set methodProc(piechart,balloon)            DrawBalloon
154   set methodProc(piechart,balloonconfig)      ConfigBalloon
155   set methodProc(piechart,explode)            PieExplodeSegment
156   set methodProc(piechart,plaintext)          DrawPlainText
157   set methodProc(piechart,plaintextconfig)    ConfigPlainText
158   set methodProc(polarplot,title)             DrawTitle
159   set methodProc(polarplot,plot)              DrawPolarData
160   set methodProc(polarplot,saveplot)          SavePlot
161   set methodProc(polarplot,dataconfig)        DataConfig
162   set methodProc(polarplot,background)        BackgroundColour
163   set methodProc(polarplot,legendconfig)      LegendConfigure
164   set methodProc(polarplot,legend)            DrawLegend
165   set methodProc(polarplot,balloon)           DrawBalloon
166   set methodProc(polarplot,balloonconfig)     ConfigBalloon
167   set methodProc(polarplot,plaintext)         DrawPlainText
168   set methodProc(polarplot,plaintextconfig)   ConfigPlainText
169   set methodProc(polarplot,labeldot)          DrawLabelDotPolar
170   set methodProc(histogram,title)             DrawTitle
171   set methodProc(histogram,xtext)             DrawXtext
172   set methodProc(histogram,ytext)             DrawYtext
173   set methodProc(histogram,vtext)             DrawVtext
174   set methodProc(histogram,plot)              DrawHistogramData
175   set methodProc(histogram,saveplot)          SavePlot
176   set methodProc(histogram,dataconfig)        DataConfig
177   set methodProc(histogram,xconfig)           XConfig
178   set methodProc(histogram,yconfig)           YConfig
179   set methodProc(histogram,yticklines)        DrawYTicklines
180   set methodProc(histogram,background)        BackgroundColour
181   set methodProc(histogram,legendconfig)      LegendConfigure
182   set methodProc(histogram,legend)            DrawLegend
183   set methodProc(histogram,balloon)           DrawBalloon
184   set methodProc(histogram,balloonconfig)     ConfigBalloon
185   set methodProc(histogram,plaintext)         DrawPlainText
186   set methodProc(histogram,plaintextconfig)   ConfigPlainText
187   set methodProc(horizbars,title)             DrawTitle
188   set methodProc(horizbars,xtext)             DrawXtext
189   set methodProc(horizbars,ytext)             DrawYtext
190   set methodProc(horizbars,vtext)             DrawVtext
191   set methodProc(horizbars,plot)              DrawHorizBarData
192   set methodProc(horizbars,xticklines)        DrawXTicklines
193   set methodProc(horizbars,background)        BackgroundColour
194   set methodProc(horizbars,saveplot)          SavePlot
195   set methodProc(horizbars,colours)           SetColours
196   set methodProc(horizbars,colors)            SetColours
197   set methodProc(horizbars,xconfig)           XConfig
198   set methodProc(horizbars,config)            ConfigBar
199   set methodProc(horizbars,legendconfig)      LegendConfigure
200   set methodProc(horizbars,legend)            DrawLegend
201   set methodProc(horizbars,balloon)           DrawBalloon
202   set methodProc(horizbars,balloonconfig)     ConfigBalloon
203   set methodProc(horizbars,plaintext)         DrawPlainText
204   set methodProc(horizbars,plaintextconfig)   ConfigPlainText
205   set methodProc(vertbars,title)              DrawTitle
206   set methodProc(vertbars,xtext)              DrawXtext
207   set methodProc(vertbars,ytext)              DrawYtext
208   set methodProc(vertbars,vtext)              DrawVtext
209   set methodProc(vertbars,plot)               DrawVertBarData
210   set methodProc(vertbars,background)         BackgroundColour
211   set methodProc(vertbars,yticklines)         DrawYTicklines
212   set methodProc(vertbars,saveplot)           SavePlot
213   set methodProc(vertbars,colours)            SetColours
214   set methodProc(vertbars,colors)             SetColours
215   set methodProc(vertbars,yconfig)            YConfig
216   set methodProc(vertbars,config)             ConfigBar
217   set methodProc(vertbars,legendconfig)       LegendConfigure
218   set methodProc(vertbars,legend)             DrawLegend
219   set methodProc(vertbars,balloon)            DrawBalloon
220   set methodProc(vertbars,balloonconfig)      ConfigBalloon
221   set methodProc(vertbars,plaintext)          DrawPlainText
222   set methodProc(vertbars,plaintextconfig)    ConfigPlainText
223   set methodProc(timechart,title)             DrawTitle
224   set methodProc(timechart,period)            DrawTimePeriod
225   set methodProc(timechart,milestone)         DrawTimeMilestone
226   set methodProc(timechart,vertline)          DrawTimeVertLine
227   set methodProc(timechart,saveplot)          SavePlot
228   set methodProc(timechart,background)        BackgroundColour
229   set methodProc(timechart,balloon)           DrawBalloon
230   set methodProc(timechart,balloonconfig)     ConfigBalloon
231   set methodProc(timechart,plaintext)         DrawPlainText
232   set methodProc(timechart,plaintextconfig)   ConfigPlainText
233   set methodProc(timechart,hscroll)           ConnectHorizScrollbar
234   set methodProc(timechart,vscroll)           ConnectVertScrollbar
235   set methodProc(ganttchart,title)            DrawTitle
236   set methodProc(ganttchart,period)           DrawGanttPeriod
237   set methodProc(ganttchart,task)             DrawGanttPeriod
238   set methodProc(ganttchart,milestone)        DrawGanttMilestone
239   set methodProc(ganttchart,vertline)         DrawGanttVertLine
240   set methodProc(ganttchart,saveplot)         SavePlot
241   set methodProc(ganttchart,color)            GanttColor
242   set methodProc(ganttchart,colour)           GanttColor
243   set methodProc(ganttchart,font)             GanttFont
244   set methodProc(ganttchart,connect)          DrawGanttConnect
245   set methodProc(ganttchart,summary)          DrawGanttSummary
246   set methodProc(ganttchart,background)       BackgroundColour
247   set methodProc(ganttchart,balloon)          DrawBalloon
248   set methodProc(ganttchart,balloonconfig)    ConfigBalloon
249   set methodProc(ganttchart,plaintext)        DrawPlainText
250   set methodProc(ganttchart,plaintextconfig)  ConfigPlainText
251   set methodProc(ganttchart,hscroll)          ConnectHorizScrollbar
252   set methodProc(ganttchart,vscroll)          ConnectVertScrollbar
253   set methodProc(stripchart,title)            DrawTitle
254   set methodProc(stripchart,xtext)            DrawXtext
255   set methodProc(stripchart,ytext)            DrawYtext
256   set methodProc(stripchart,vtext)            DrawVtext
257   set methodProc(stripchart,plot)             DrawStripData
258   set methodProc(stripchart,saveplot)         SavePlot
259   set methodProc(stripchart,dataconfig)       DataConfig
260   set methodProc(stripchart,xconfig)          XConfig
261   set methodProc(stripchart,yconfig)          YConfig
262   set methodProc(stripchart,yticklines)       DrawYTicklines
263   set methodProc(stripchart,background)       BackgroundColour
264   set methodProc(stripchart,legendconfig)     LegendConfigure
265   set methodProc(stripchart,legend)           DrawLegend
266   set methodProc(stripchart,balloon)          DrawBalloon
267   set methodProc(stripchart,balloonconfig)    ConfigBalloon
268   set methodProc(stripchart,plaintext)        DrawPlainText
269   set methodProc(stripchart,plaintextconfig)  ConfigPlainText
270   set methodProc(isometric,title)             DrawTitle
271   set methodProc(isometric,xtext)             DrawXtext
272   set methodProc(isometric,ytext)             DrawYtext
273   set methodProc(isometric,vtext)             DrawVtext
274   set methodProc(isometric,plot)              DrawIsometricData
275   set methodProc(isometric,saveplot)          SavePlot
276   set methodProc(isometric,background)        BackgroundColour
277   set methodProc(isometric,balloon)           DrawBalloon
278   set methodProc(isometric,balloonconfig)     ConfigBalloon
279   set methodProc(isometric,plaintext)         DrawPlainText
280   set methodProc(isometric,plaintextconfig)   ConfigPlainText
281   set methodProc(3dplot,title)                DrawTitle
282   set methodProc(3dplot,plotfunc)             Draw3DFunction
283   set methodProc(3dplot,plotdata)             Draw3DData
284   set methodProc(3dplot,plotline)             Draw3DLineFrom3Dcoordinates
285   set methodProc(3dplot,gridsize)             GridSize3D
286   set methodProc(3dplot,ribbon)               Draw3DRibbon
287   set methodProc(3dplot,saveplot)             SavePlot
288   set methodProc(3dplot,colour)               SetColours
289   set methodProc(3dplot,color)                SetColours
290   set methodProc(3dplot,xconfig)              XConfig
291   set methodProc(3dplot,yconfig)              YConfig
292   set methodProc(3dplot,zconfig)              ZConfig
293   set methodProc(3dplot,plotfuncont)          Draw3DFunctionContour
294   set methodProc(3dplot,background)           BackgroundColour
295   set methodProc(3dbars,title)                DrawTitle
296   set methodProc(3dbars,plot)                 Draw3DBar
297   set methodProc(3dbars,yconfig)              YConfig
298   set methodProc(3dbars,saveplot)             SavePlot
299   set methodProc(3dbars,config)               Config3DBar
300   set methodProc(3dbars,balloon)              DrawBalloon
301   set methodProc(3dbars,balloonconfig)        ConfigBalloon
302   set methodProc(3dbars,plaintext)            DrawPlainText
303   set methodProc(3dbars,plaintextconfig)      ConfigPlainText
304   set methodProc(radialchart,title)           DrawTitle
305   set methodProc(radialchart,plot)            DrawRadial
306   set methodProc(radialchart,saveplot)        SavePlot
307   set methodProc(radialchart,balloon)         DrawBalloon
308   set methodProc(radialchart,plaintext)       DrawPlainText
309   set methodProc(radialchart,plaintextconfig) ConfigPlainText
310   set methodProc(txplot,title)                DrawTitle
311   set methodProc(txplot,xtext)                DrawXtext
312   set methodProc(txplot,ytext)                DrawYtext
313   set methodProc(txplot,vtext)                DrawVtext
314   set methodProc(txplot,plot)                 DrawTimeData
315   set methodProc(txplot,interval)             DrawInterval
316   set methodProc(txplot,saveplot)             SavePlot
317   set methodProc(txplot,dataconfig)           DataConfig
318   set methodProc(txplot,xconfig)              XConfig
319   set methodProc(txplot,yconfig)              YConfig
320   set methodProc(txplot,xticklines)           DrawXTicklines
321   set methodProc(txplot,yticklines)           DrawYTicklines
322   set methodProc(txplot,background)           BackgroundColour
323   set methodProc(txplot,legendconfig)         LegendConfigure
324   set methodProc(txplot,legend)               DrawLegend
325   set methodProc(txplot,balloon)              DrawBalloon
326   set methodProc(txplot,balloonconfig)        ConfigBalloon
327   set methodProc(txplot,plaintext)            DrawPlainText
328   set methodProc(txplot,plaintextconfig)      ConfigPlainText
329   set methodProc(3dribbon,title)              DrawTitle
330   set methodProc(3dribbon,saveplot)           SavePlot
331   set methodProc(3dribbon,line)               Draw3DLine
332   set methodProc(3dribbon,area)               Draw3DArea
333   set methodProc(3dribbon,background)         BackgroundColour
334   set methodProc(boxplot,title)               DrawTitle
335   set methodProc(boxplot,xtext)               DrawXtext
336   set methodProc(boxplot,ytext)               DrawYtext
337   set methodProc(boxplot,vtext)               DrawVtext
338   set methodProc(boxplot,plot)                DrawBoxData
339   set methodProc(boxplot,saveplot)            SavePlot
340   set methodProc(boxplot,dataconfig)          DataConfig
341   set methodProc(boxplot,xconfig)             XConfig
342   set methodProc(boxplot,yconfig)             YConfig
343   set methodProc(boxplot,xticklines)          DrawXTicklines
344   set methodProc(boxplot,yticklines)          DrawYTicklines
345   set methodProc(boxplot,background)          BackgroundColour
346   set methodProc(boxplot,legendconfig)        LegendConfigure
347   set methodProc(boxplot,legend)              DrawLegend
348   set methodProc(boxplot,balloon)             DrawBalloon
349   set methodProc(boxplot,balloonconfig)       ConfigBalloon
350   set methodProc(boxplot,plaintext)           DrawPlainText
351   set methodProc(boxplot,plaintextconfig)     ConfigPlainText
352   set methodProc(windrose,plot)               DrawWindRoseData
353   set methodProc(windrose,saveplot)           SavePlot
354   set methodProc(windrose,title)              DrawTitle
355   set methodProc(targetdiagram,title)         DrawTitle
356   set methodProc(targetdiagram,xtext)         DrawXtext
357   set methodProc(targetdiagram,ytext)         DrawYtext
358   set methodProc(targetdiagram,vtext)         DrawVtext
359   set methodProc(targetdiagram,plot)          DrawTargetData
360   set methodProc(targetdiagram,saveplot)      SavePlot
361   set methodProc(targetdiagram,background)    BackgroundColour
362   set methodProc(targetdiagram,legendconfig)  LegendConfigure
363   set methodProc(targetdiagram,legend)        DrawLegend
364   set methodProc(targetdiagram,balloon)       DrawBalloon
365   set methodProc(targetdiagram,balloonconfig) ConfigBalloon
366   set methodProc(targetdiagram,plaintext)     DrawPlainText
367   set methodProc(targetdiagram,plaintextconfig) ConfigPlainText
368   set methodProc(targetdiagram,dataconfig)    DataConfig
369   set methodProc(3dribbonplot,title)          DrawTitle
370   set methodProc(3dribbonplot,plot)           Draw3DRibbon
371   set methodProc(3dribbonplot,saveplot)       SavePlot
372   set methodProc(3dribbonplot,xconfig)        XConfig
373   set methodProc(3dribbonplot,yconfig)        YConfig
374   set methodProc(3dribbonplot,zconfig)        ZConfig
375   set methodProc(3dribbonplot,background)     BackgroundColour
376   set methodProc(performance,title)           DrawTitle
377   set methodProc(performance,xtext)           DrawXtext
378   set methodProc(performance,ytext)           DrawYtext
379   set methodProc(performance,vtext)           DrawVtext
380   set methodProc(performance,plot)            DrawPerformanceData
381   set methodProc(performance,dot)             DrawDot
382   set methodProc(performance,saveplot)        SavePlot
383   set methodProc(performance,dataconfig)      DataConfig
384   set methodProc(performance,xconfig)         XConfig
385   set methodProc(performance,yconfig)         YConfig
386   set methodProc(performance,xticklines)      DrawXTicklines
387   set methodProc(performance,yticklines)      DrawYTicklines
388   set methodProc(performance,background)      BackgroundColour
389   set methodProc(performance,legendconfig)    LegendConfigure
390   set methodProc(performance,legend)          DrawLegend
391   set methodProc(performance,balloon)         DrawBalloon
392   set methodProc(performance,balloonconfig)   ConfigBalloon
393   set methodProc(performance,plaintext)       DrawPlainText
394   set methodProc(performance,plaintextconfig) ConfigPlainText
395
396   #
397   # Auxiliary parameters
398   #
399   variable torad
400   set torad [expr {3.1415926/180.0}]
401
402   variable options
403   variable option_keys
404   variable option_values
405   set options       {-colour -color  -symbol -type -filled -fillcolour -boxwidth -width}
406   set option_keys   {-colour -colour -symbol -type -filled -fillcolour -boxwidth -width}
407   set option_values {-colour {...}
408                      -symbol {plus cross circle up down dot upfilled downfilled}
409                      -type {line symbol both}
410                      -filled {no up down}
411                      -fillcolour {...}
412                      -boxwidth   {...}
413                      -width      {...}
414                     }
415
416   variable axis_options
417   variable axis_option_clear
418   variable axis_option_values
419   set axis_options       {-format -ticklength -ticklines -scale -minorticks -labeloffset -axisoffset}
420   set axis_option_clear  { 0       0           0          1      0           0            0         }
421   set axis_option_config { 0       1           0          0      1           1            1         }
422   set axis_option_values {-format      {...}
423                           -ticklength  {...}
424                           -ticklines   {0 1}
425                           -scale       {...}
426                           -minorticks  {...}
427                           -labeloffset {...}
428                           -axisoffset  {...}
429                          }
430   variable contour_options
431}
432
433# setZoomPan --
434#    Set up the bindings for zooming and panning
435# Arguments:
436#    w           Name of the canvas window
437# Result:
438#    None
439# Side effect:
440#    Bindings set up
441#
442proc ::Plotchart::setZoomPan { w } {
443   set sqrt2  [expr {sqrt(2.0)}]
444   set sqrt05 [expr {sqrt(0.5)}]
445
446   bind $w <Control-Button-1> [list ::Plotchart::ScaleItems $w %x %y $sqrt2]
447   bind $w <Control-Prior>    [list ::Plotchart::ScaleItems $w %x %y $sqrt2]
448   bind $w <Control-Button-2> [list ::Plotchart::ScaleItems $w %x %y $sqrt05]
449   bind $w <Control-Button-3> [list ::Plotchart::ScaleItems $w %x %y $sqrt05]
450   bind $w <Control-Next>     [list ::Plotchart::ScaleItems $w %x %y $sqrt05]
451   bind $w <Control-Up>       [list ::Plotchart::MoveItems  $w   0 -40]
452   bind $w <Control-Down>     [list ::Plotchart::MoveItems  $w   0  40]
453   bind $w <Control-Left>     [list ::Plotchart::MoveItems  $w -40   0]
454   bind $w <Control-Right>    [list ::Plotchart::MoveItems  $w  40   0]
455   focus $w
456}
457
458# viewPort --
459#    Set the pixel extremes for the graph
460# Arguments:
461#    w           Name of the canvas window
462#    pxmin       Minimum X-coordinate
463#    pymin       Minimum Y-coordinate
464#    pxmax       Maximum X-coordinate
465#    pymax       Maximum Y-coordinate
466# Result:
467#    None
468# Side effect:
469#    Array scaling filled
470#
471proc ::Plotchart::viewPort { w pxmin pymin pxmax pymax } {
472   variable scaling
473
474   if { $pxmin >= $pxmax || $pymin >= $pymax } {
475      return -code error "Inconsistent bounds for viewport - increase canvas size or decrease margins"
476   }
477
478   set scaling($w,pxmin)    $pxmin
479   set scaling($w,pymin)    $pymin
480   set scaling($w,pxmax)    $pxmax
481   set scaling($w,pymax)    $pymax
482   set scaling($w,new)      1
483}
484
485# worldCoordinates --
486#    Set the extremes for the world coordinates
487# Arguments:
488#    w           Name of the canvas window
489#    xmin        Minimum X-coordinate
490#    ymin        Minimum Y-coordinate
491#    xmax        Maximum X-coordinate
492#    ymax        Maximum Y-coordinate
493# Result:
494#    None
495# Side effect:
496#    Array scaling filled
497#
498proc ::Plotchart::worldCoordinates { w xmin ymin xmax ymax } {
499   variable scaling
500
501   if { $xmin == $xmax || $ymin == $ymax } {
502      return -code error "Minimum and maximum must differ for world coordinates"
503   }
504
505   set scaling($w,xmin)    [expr {double($xmin)}]
506   set scaling($w,ymin)    [expr {double($ymin)}]
507   set scaling($w,xmax)    [expr {double($xmax)}]
508   set scaling($w,ymax)    [expr {double($ymax)}]
509
510   set scaling($w,new)     1
511}
512
513# polarCoordinates --
514#    Set the extremes for the polar coordinates
515# Arguments:
516#    w           Name of the canvas window
517#    radmax      Maximum radius
518# Result:
519#    None
520# Side effect:
521#    Array scaling filled
522#
523proc ::Plotchart::polarCoordinates { w radmax } {
524   variable scaling
525
526   if { $radmax <= 0.0 } {
527      return -code error "Maximum radius must be positive"
528   }
529
530   set scaling($w,xmin)    [expr {-double($radmax)}]
531   set scaling($w,ymin)    [expr {-double($radmax)}]
532   set scaling($w,xmax)    [expr {double($radmax)}]
533   set scaling($w,ymax)    [expr {double($radmax)}]
534
535   set scaling($w,new)     1
536}
537
538# world3DCoordinates --
539#    Set the extremes for the world coordinates in 3D plots
540# Arguments:
541#    w           Name of the canvas window
542#    xmin        Minimum X-coordinate
543#    ymin        Minimum Y-coordinate
544#    zmin        Minimum Z-coordinate
545#    xmax        Maximum X-coordinate
546#    ymax        Maximum Y-coordinate
547#    zmax        Maximum Z-coordinate
548# Result:
549#    None
550# Side effect:
551#    Array scaling filled
552#
553proc ::Plotchart::world3DCoordinates { w xmin ymin zmin xmax ymax zmax } {
554   variable scaling
555
556   if { $xmin == $xmax || $ymin == $ymax || $zmin == $zmax } {
557      return -code error "Minimum and maximum must differ for world coordinates"
558   }
559
560   set scaling($w,xmin)    [expr {double($xmin)}]
561   set scaling($w,ymin)    [expr {double($ymin)}]
562   set scaling($w,zmin)    [expr {double($zmin)}]
563   set scaling($w,xmax)    [expr {double($xmax)}]
564   set scaling($w,ymax)    [expr {double($ymax)}]
565   set scaling($w,zmax)    [expr {double($zmax)}]
566
567   set scaling($w,new)     1
568}
569
570# coordsToPixel --
571#    Convert world coordinates to pixel coordinates
572# Arguments:
573#    w           Name of the canvas
574#    xcrd        X-coordinate
575#    ycrd        Y-coordinate
576# Result:
577#    List of two elements, x- and y-coordinates in pixels
578#
579proc ::Plotchart::coordsToPixel { w xcrd ycrd } {
580   variable scaling
581
582   if { $scaling($w,new) == 1 } {
583      set scaling($w,new)     0
584      set width               [expr {$scaling($w,pxmax)-$scaling($w,pxmin)}]
585      set height              [expr {$scaling($w,pymax)-$scaling($w,pymin)}]
586
587      set dx                  [expr {$scaling($w,xmax)-$scaling($w,xmin)}]
588      set dy                  [expr {$scaling($w,ymax)-$scaling($w,ymin)}]
589      set scaling($w,xfactor) [expr {$width/$dx}]
590      set scaling($w,yfactor) [expr {$height/$dy}]
591   }
592
593   set xpix [expr {$scaling($w,pxmin)+($xcrd-$scaling($w,xmin))*$scaling($w,xfactor)}]
594   set ypix [expr {$scaling($w,pymin)+($scaling($w,ymax)-$ycrd)*$scaling($w,yfactor)}]
595   return [list $xpix $ypix]
596}
597
598# coords3DToPixel --
599#    Convert world coordinates to pixel coordinates (3D plots)
600# Arguments:
601#    w           Name of the canvas
602#    xcrd        X-coordinate
603#    ycrd        Y-coordinate
604#    zcrd        Z-coordinate
605# Result:
606#    List of two elements, x- and y-coordinates in pixels
607#
608proc ::Plotchart::coords3DToPixel { w xcrd ycrd zcrd } {
609   variable scaling
610
611   if { $scaling($w,new) == 1 } {
612      set scaling($w,new)      0
613      set width                [expr {$scaling($w,pxmax)-$scaling($w,pxmin)}]
614      set height               [expr {$scaling($w,pymax)-$scaling($w,pymin)}]
615
616      set dx                   [expr {$scaling($w,xmax)-$scaling($w,xmin)}]
617      set dy                   [expr {$scaling($w,ymax)-$scaling($w,ymin)}]
618      set dz                   [expr {$scaling($w,zmax)-$scaling($w,zmin)}]
619      set scaling($w,xyfactor) [expr {$scaling($w,yfract)*$width/$dx}]
620      set scaling($w,xzfactor) [expr {$scaling($w,zfract)*$height/$dx}]
621      set scaling($w,yfactor)  [expr {$width/$dy}]
622      set scaling($w,zfactor)  [expr {$height/$dz}]
623   }
624
625   #
626   # The values for xcrd = xmax
627   #
628   set xpix [expr {$scaling($w,pxmin)+($ycrd-$scaling($w,ymin))*$scaling($w,yfactor)}]
629   set ypix [expr {$scaling($w,pymin)+($scaling($w,zmax)-$zcrd)*$scaling($w,zfactor)}]
630
631   #
632   # Add the shift due to xcrd-xmax
633   #
634   set xpix [expr {$xpix + $scaling($w,xyfactor)*($xcrd-$scaling($w,xmax))}]
635   set ypix [expr {$ypix - $scaling($w,xzfactor)*($xcrd-$scaling($w,xmax))}]
636
637   return [list $xpix $ypix]
638}
639
640# pixelToCoords --
641#    Convert pixel coordinates to world coordinates
642# Arguments:
643#    w           Name of the canvas
644#    xpix        X-coordinate (pixel)
645#    ypix        Y-coordinate (pixel)
646# Result:
647#    List of two elements, x- and y-coordinates in world coordinate system
648#
649proc ::Plotchart::pixelToCoords { w xpix ypix } {
650   variable scaling
651
652   if { $scaling($w,new) == 1 } {
653      set scaling($w,new)     0
654      set width               [expr {$scaling($w,pxmax)-$scaling($w,pxmin)}]
655      set height              [expr {$scaling($w,pymax)-$scaling($w,pymin)}]
656
657      set dx                  [expr {$scaling($w,xmax)-$scaling($w,xmin)}]
658      set dy                  [expr {$scaling($w,ymax)-$scaling($w,ymin)}]
659      set scaling($w,xfactor) [expr {$width/$dx}]
660      set scaling($w,yfactor) [expr {$height/$dy}]
661   }
662
663   set xcrd [expr {$scaling($w,xmin)+($xpix-$scaling($w,pxmin))/$scaling($w,xfactor)}]
664   set ycrd [expr {$scaling($w,ymax)-($ypix-$scaling($w,pymin))/$scaling($w,yfactor)}]
665   return [list $xcrd $ycrd]
666}
667
668# pixelToIndex --
669#    Convert pixel coordinates to elements list index
670# Arguments:
671#    w           Name of the canvas
672#    xpix        X-coordinate (pixel)
673#    ypix        Y-coordinate (pixel)
674# Result:
675#    Elements list index
676#
677proc ::Plotchart::pixelToIndex { w xpix ypix } {
678   variable scaling
679   variable torad
680
681   set idx -1
682   set radius [expr {($scaling(${w},pxmax) - $scaling(${w},pxmin)) / 2}]
683   set xrel [expr {${xpix} - $scaling(${w},pxmin) - ${radius}}]
684   set yrel [expr {-${ypix} + $scaling(${w},pymin) + ${radius}}]
685   if {[expr {pow(${radius},2) < (pow(${xrel},2) + pow(${yrel},2))}]} {
686       # do nothing out of pie chart
687   } elseif {[info exists scaling(${w},angles)]} {
688       set xy_angle [expr {(360 + round(atan2(${yrel},${xrel})/${torad})) % 360}]
689       foreach angle $scaling(${w},angles) {
690       if {${xy_angle} <= ${angle}} {
691           break
692       }
693       incr idx
694       }
695   }
696   return ${idx}
697}
698
699# polarToPixel --
700#    Convert polar coordinates to pixel coordinates
701# Arguments:
702#    w           Name of the canvas
703#    rad         Radius of the point
704#    phi         Angle of the point (degrees)
705# Result:
706#    List of two elements, x- and y-coordinates in pixels
707#
708proc ::Plotchart::polarToPixel { w rad phi } {
709   variable torad
710
711   set xcrd [expr {$rad*cos($phi*$torad)}]
712   set ycrd [expr {$rad*sin($phi*$torad)}]
713
714   coordsToPixel $w $xcrd $ycrd
715}
716
717# createXYPlot --
718#    Create a command for drawing an XY plot
719# Arguments:
720#    w           Name of the canvas
721#    xscale      Minimum, maximum and step for x-axis (initial)
722#    yscale      Minimum, maximum and step for y-axis
723#    args        Options (currently: "-xlabels list" and "-ylabels list")
724# Result:
725#    Name of a new command
726# Note:
727#    The entire canvas will be dedicated to the XY plot.
728#    The plot will be drawn with axes
729#
730proc ::Plotchart::createXYPlot { w xscale yscale args} {
731   variable scaling
732   variable data_series
733
734   foreach s [array names data_series "$w,*"] {
735      unset data_series($s)
736   }
737
738   set newchart "xyplot_$w"
739   interp alias {} $newchart {} ::Plotchart::PlotHandler xyplot $w
740   CopyConfig xyplot $w
741   set scaling($w,eventobj) ""
742
743   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
744
745   foreach {xmin xmax xdelt} $xscale {break}
746   foreach {ymin ymax ydelt} $yscale {break}
747
748   if { $xdelt == 0.0 || $ydelt == 0.0 } {
749      return -code error "Step size can not be zero"
750   }
751
752   if { $xdelt ne {} && ($xmax-$xmin)*$xdelt < 0.0 } {
753      set xdelt [expr {-$xdelt}]
754   }
755   if { $ydelt ne {} && ($ymax-$ymin)*$ydelt < 0.0 } {
756      set ydelt [expr {-$ydelt}]
757   }
758
759   viewPort         $w $pxmin $pymin $pxmax $pymax
760   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
761
762   if { $xdelt eq {} } {
763       foreach {arg val} $args {
764           switch -exact -- $arg {
765               -xlabels {
766                   DrawXaxis $w $xmin  $xmax  $xdelt $arg $val
767               }
768               -ylabels {
769                   # Ignore
770               }
771               default {
772                   error "Argument $arg not recognized"
773               }
774           }
775       }
776   } else {
777       DrawXaxis   $w $xmin  $xmax  $xdelt
778   }
779   if { $ydelt eq {} } {
780       foreach {arg val} $args {
781           switch -exact -- $arg {
782               -ylabels {
783                   DrawYaxis $w $ymin  $ymax  $ydelt $arg $val
784               }
785               -xlabels {
786                   # Ignore
787               }
788               default {
789                   error "Argument $arg not recognized"
790               }
791           }
792       }
793   } else {
794       DrawYaxis        $w $ymin  $ymax  $ydelt
795   }
796   DrawMask         $w
797   DefaultLegend    $w
798   DefaultBalloon   $w
799
800   $newchart dataconfig labeldot -colour red -type symbol -symbol dot
801
802   return $newchart
803}
804
805# createStripchart --
806#    Create a command for drawing a strip chart
807# Arguments:
808#    w           Name of the canvas
809#    xscale      Minimum, maximum and step for x-axis (initial)
810#    yscale      Minimum, maximum and step for y-axis
811# Result:
812#    Name of a new command
813# Note:
814#    The entire canvas will be dedicated to the stripchart.
815#    The stripchart will be drawn with axes
816#
817proc ::Plotchart::createStripchart { w xscale yscale } {
818   variable data_series
819
820   set newchart [createXYPlot $w $xscale $yscale]
821
822   interp alias {} $newchart {}
823
824   set newchart "stripchart_$w"
825   interp alias {} $newchart {} ::Plotchart::PlotHandler stripchart $w
826   CopyConfig stripchart $w
827
828   return $newchart
829}
830
831# createIsometricPlot --
832#    Create a command for drawing an "isometric" plot
833# Arguments:
834#    w           Name of the canvas
835#    xscale      Minimum and maximum for x-axis
836#    yscale      Minimum and maximum for y-axis
837#    stepsize    Step size for numbers on the axes or "noaxes"
838# Result:
839#    Name of a new command
840# Note:
841#    The entire canvas will be dedicated to the plot
842#    The plot will be drawn with or without axes
843#
844proc ::Plotchart::createIsometricPlot { w xscale yscale stepsize } {
845   variable data_series
846
847   foreach s [array names data_series "$w,*"] {
848      unset data_series($s)
849   }
850
851   set newchart "isometric_$w"
852   interp alias {} $newchart {} ::Plotchart::PlotHandler isometric $w
853   CopyConfig isometric $w
854
855   if { $stepsize != "noaxes" } {
856      foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
857   } else {
858      set pxmin 0
859      set pymin 0
860      #set pxmax [$w cget -width]
861      #set pymax [$w cget -height]
862      set pxmax [WidthCanvas $w]
863      set pymax [HeightCanvas $w]
864   }
865
866   foreach {xmin xmax xdelt} $xscale {break}
867   foreach {ymin ymax ydelt} $yscale {break}
868
869   if { $xmin == $xmax || $ymin == $ymax } {
870      return -code error "Extremes for axes must be different"
871   }
872
873   viewPort         $w $pxmin $pymin $pxmax $pymax
874   ScaleIsometric   $w $xmin  $ymin  $xmax  $ymax
875
876   if { $stepsize != "noaxes" } {
877      DrawYaxis        $w $ymin  $ymax  $stepsize
878      DrawXaxis        $w $xmin  $xmax  $stepsize
879      DrawMask         $w
880   }
881   DefaultLegend  $w
882   DefaultBalloon $w
883
884   return $newchart
885}
886
887# createXLogYPlot --
888#    Create a command for drawing an XY plot (with a vertical logarithmic axis)
889# Arguments:
890#    w           Name of the canvas
891#    xscale      Minimum, maximum and step for x-axis (initial)
892#    yscale      Minimum, maximum and step for y-axis (step is ignored!)
893# Result:
894#    Name of a new command
895# Note:
896#    The entire canvas will be dedicated to the XY plot.
897#    The plot will be drawn with axes
898#
899proc ::Plotchart::createXLogYPlot { w xscale yscale } {
900   variable data_series
901
902   foreach s [array names data_series "$w,*"] {
903      unset data_series($s)
904   }
905
906   set newchart "xlogyplot_$w"
907   interp alias {} $newchart {} ::Plotchart::PlotHandler xlogyplot $w
908   CopyConfig xlogyplot $w
909
910   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
911
912   foreach {xmin xmax xdelt} $xscale {break}
913   foreach {ymin ymax ydelt} $yscale {break}
914
915   if { $xdelt == 0.0 || $ydelt == 0.0 } {
916      return -code error "Step size can not be zero"
917   }
918
919   if { $ymin <= 0.0 || $ymax <= 0.0 } {
920      return -code error "Minimum and maximum for y-axis must be positive"
921   }
922
923   #
924   # TODO: reversed log plot
925   #
926
927   viewPort         $w $pxmin $pymin $pxmax $pymax
928   worldCoordinates $w $xmin  [expr {log10($ymin)}]  $xmax [expr {log10($ymax)}]
929
930   DrawLogYaxis     $w $ymin  $ymax  $ydelt
931   DrawXaxis        $w $xmin  $xmax  $xdelt
932   DrawMask         $w
933   DefaultLegend    $w
934   DefaultBalloon   $w
935
936   return $newchart
937}
938
939# createLogXYPlot --
940#    Create a command for drawing an XY plot (with a horizontal logarithmic axis)
941# Arguments:
942#    w           Name of the canvas
943#    xscale      Minimum, maximum and step for x-axis (step is ignored!)
944#    yscale      Minimum, maximum and step for y-axis (initial)
945# Result:
946#    Name of a new command
947# Note:
948#    The entire canvas will be dedicated to the XY plot.
949#    The plot will be drawn with axes
950#
951proc ::Plotchart::createLogXYPlot { w xscale yscale } {
952   variable data_series
953
954   foreach s [array names data_series "$w,*"] {
955      unset data_series($s)
956   }
957
958   set newchart "logxyplot_$w"
959   interp alias {} $newchart {} ::Plotchart::PlotHandler logxyplot $w
960   CopyConfig logxyplot $w
961
962   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
963
964   foreach {xmin xmax xdelt} $xscale {break}
965   foreach {ymin ymax ydelt} $yscale {break}
966
967   if { $xmin <= 0.0 || $xmax <= 0.0 } {
968      return -code error "Minimum and maximum for x-axis must be positive"
969   }
970
971   if { $ydelt == 0.0 } {
972      return -code error "Step size can not be zero"
973   }
974
975   #
976   # TODO: reversed log plot
977   #
978
979   viewPort         $w $pxmin $pymin $pxmax $pymax
980   worldCoordinates $w [expr {log10($xmin)}] $ymin [expr {log10($xmax)}] $ymax
981   DrawYaxis        $w $ymin  $ymax  $ydelt
982   DrawLogXaxis     $w $xmin  $xmax  $xdelt
983   DrawMask         $w
984   DefaultLegend    $w
985   DefaultBalloon   $w
986
987   return $newchart
988}
989
990# createLogXLogYPlot --
991#    Create a command for drawing an XY plot (with a both logarithmic axis)
992# Arguments:
993#    w           Name of the canvas
994#    xscale      Minimum, maximum and step for x-axis (step is ignored!)
995#    yscale      Minimum, maximum and step for y-axis (step is ignored!)
996# Result:
997#    Name of a new command
998# Note:
999#    The entire canvas will be dedicated to the XY plot.
1000#    The plot will be drawn with axes
1001#
1002proc ::Plotchart::createLogXLogYPlot { w xscale yscale } {
1003   variable data_series
1004
1005   foreach s [array names data_series "$w,*"] {
1006      unset data_series($s)
1007   }
1008
1009   set newchart "logxlogyplot_$w"
1010   interp alias {} $newchart {} ::Plotchart::PlotHandler logxlogyplot $w
1011   CopyConfig logxlogyplot $w
1012
1013   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
1014
1015   foreach {xmin xmax xdelt} $xscale {break}
1016   foreach {ymin ymax ydelt} $yscale {break}
1017
1018   if { $xmin <= 0.0 || $xmax <= 0.0 } {
1019      return -code error "Minimum and maximum for x-axis must be positive"
1020   }
1021
1022   if { $ymin <= 0.0 || $ymax <= 0.0 } {
1023      return -code error "Minimum and maximum for y-axis must be positive"
1024   }
1025
1026   #
1027   # TODO: reversed log plot
1028   #
1029
1030   viewPort         $w $pxmin $pymin $pxmax $pymax
1031   worldCoordinates $w [expr {log10($xmin)}] [expr {log10($ymin)}] [expr {log10($xmax)}] [expr {log10($ymax)}]
1032   DrawLogYaxis     $w $ymin  $ymax  $ydelt
1033   DrawLogXaxis     $w $xmin  $xmax  $xdelt
1034   DrawMask         $w
1035   DefaultLegend    $w
1036   DefaultBalloon   $w
1037
1038   return $newchart
1039}
1040
1041# createHistogram --
1042#    Create a command for drawing a histogram
1043# Arguments:
1044#    w           Name of the canvas
1045#    xscale      Minimum, maximum and step for x-axis (initial)
1046#    yscale      Minimum, maximum and step for y-axis
1047# Result:
1048#    Name of a new command
1049# Note:
1050#    The entire canvas will be dedicated to the histogram.
1051#    The plot will be drawn with axes
1052#    This is almost the same code as for an XY plot
1053#
1054proc ::Plotchart::createHistogram { w xscale yscale } {
1055   variable data_series
1056
1057   foreach s [array names data_series "$w,*"] {
1058      unset data_series($s)
1059   }
1060
1061   set newchart "histogram_$w"
1062   interp alias {} $newchart {} ::Plotchart::PlotHandler histogram $w
1063   CopyConfig histogram $w
1064
1065   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
1066
1067   foreach {xmin xmax xdelt} $xscale {break}
1068   foreach {ymin ymax ydelt} $yscale {break}
1069
1070   if { $xdelt == 0.0 || $ydelt == 0.0 } {
1071      return -code error "Step size can not be zero"
1072   }
1073
1074   if { ($xmax-$xmin)*$xdelt < 0.0 } {
1075      set xdelt [expr {-$xdelt}]
1076   }
1077   if { ($ymax-$ymin)*$ydelt < 0.0 } {
1078      set ydelt [expr {-$ydelt}]
1079   }
1080
1081   viewPort         $w $pxmin $pymin $pxmax $pymax
1082   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1083
1084   DrawYaxis        $w $ymin  $ymax  $ydelt
1085   DrawXaxis        $w $xmin  $xmax  $xdelt
1086   DrawMask         $w
1087   DefaultLegend    $w
1088   DefaultBalloon   $w
1089
1090   return $newchart
1091}
1092
1093# createPiechart --
1094#    Create a command for drawing a pie chart
1095# Arguments:
1096#    w           Name of the canvas
1097# Result:
1098#    Name of a new command
1099# Note:
1100#    The entire canvas will be dedicated to the pie chart.
1101#
1102proc ::Plotchart::createPiechart { w } {
1103   variable data_series
1104   variable scaling
1105
1106   foreach s [array names data_series "$w,*"] {
1107      unset data_series($s)
1108   }
1109
1110   set newchart "piechart_$w"
1111   interp alias {} $newchart {} ::Plotchart::PlotHandler piechart $w
1112   CopyConfig piechart $w
1113
1114   foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}
1115
1116   viewPort $w $pxmin $pymin $pxmax $pymax
1117  #$w create oval $pxmin $pymin $pxmax $pymax
1118
1119   SetColours $w blue lightblue green yellow orange red magenta brown
1120   DefaultLegend  $w
1121   DefaultBalloon $w
1122
1123   set scaling($w,auto)      0
1124   set scaling($w,exploded) -1
1125
1126   return $newchart
1127}
1128
1129# createPolarplot --
1130#    Create a command for drawing a polar plot
1131# Arguments:
1132#    w             Name of the canvas
1133#    radius_data   Maximum radius and step
1134# Result:
1135#    Name of a new command
1136# Note:
1137#    The entire canvas will be dedicated to the polar plot
1138#    Possible additional arguments (optional): nautical/mathematical
1139#    step in phi
1140#
1141proc ::Plotchart::createPolarplot { w radius_data } {
1142   variable data_series
1143
1144   foreach s [array names data_series "$w,*"] {
1145      unset data_series($s)
1146   }
1147
1148   set newchart "polarplot_$w"
1149   interp alias {} $newchart {} ::Plotchart::PlotHandler polarplot $w
1150   CopyConfig polarplot $w
1151
1152   set rad_max   [lindex $radius_data 0]
1153   set rad_step  [lindex $radius_data 1]
1154
1155   if { $rad_step <= 0.0 } {
1156      return -code error "Step size can not be zero or negative"
1157   }
1158   if { $rad_max <= 0.0 } {
1159      return -code error "Maximum radius can not be zero or negative"
1160   }
1161
1162   foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}
1163
1164   viewPort         $w $pxmin     $pymin     $pxmax   $pymax
1165   polarCoordinates $w $rad_max
1166   DrawPolarAxes    $w $rad_max   $rad_step
1167   DefaultLegend    $w
1168   DefaultBalloon   $w
1169
1170   $newchart dataconfig labeldot -colour red -type symbol -symbol dot
1171
1172   return $newchart
1173}
1174
1175# createBarchart --
1176#    Create a command for drawing a barchart with vertical bars
1177# Arguments:
1178#    w           Name of the canvas
1179#    xlabels     List of labels for x-axis
1180#    yscale      Minimum, maximum and step for y-axis
1181#    noseries    Number of series or the keyword "stacked"
1182# Result:
1183#    Name of a new command
1184# Note:
1185#    The entire canvas will be dedicated to the barchart.
1186#
1187proc ::Plotchart::createBarchart { w xlabels yscale noseries } {
1188   variable data_series
1189   variable settings
1190
1191   foreach s [array names data_series "$w,*"] {
1192      unset data_series($s)
1193   }
1194
1195   set newchart "barchart_$w"
1196   interp alias {} $newchart {} ::Plotchart::PlotHandler vertbars $w
1197   CopyConfig vertbars $w
1198
1199   set settings($w,showvalues)   0
1200   set settings($w,valuefont)    ""
1201   set settings($w,valuecolour)  black
1202   set settings($w,valueformat)  %s
1203
1204   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
1205
1206   set xmin  0.0
1207   set xmax  [expr {[llength $xlabels] + 0.1}]
1208
1209   foreach {ymin ymax ydelt} $yscale {break}
1210
1211   if { $ydelt == 0.0 } {
1212      return -code error "Step size can not be zero"
1213   }
1214
1215   if { ($ymax-$ymin)*$ydelt < 0.0 } {
1216      set ydelt [expr {-$ydelt}]
1217   }
1218
1219   viewPort         $w $pxmin $pymin $pxmax $pymax
1220   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1221
1222   DrawYaxis        $w $ymin  $ymax  $ydelt
1223   DrawXlabels      $w $xlabels $noseries
1224   DrawMask         $w
1225   DefaultLegend    $w
1226   set data_series($w,legendtype) "rectangle"
1227   DefaultBalloon   $w
1228
1229   SetColours $w blue lightblue green yellow orange red magenta brown
1230
1231   return $newchart
1232}
1233
1234# createHorizontalBarchart --
1235#    Create a command for drawing a barchart with horizontal bars
1236# Arguments:
1237#    w           Name of the canvas
1238#    xscale      Minimum, maximum and step for x-axis
1239#    ylabels     List of labels for y-axis
1240#    noseries    Number of series or the keyword "stacked"
1241# Result:
1242#    Name of a new command
1243# Note:
1244#    The entire canvas will be dedicated to the barchart.
1245#
1246proc ::Plotchart::createHorizontalBarchart { w xscale ylabels noseries } {
1247   variable data_series
1248   variable config
1249   variable settings
1250
1251   foreach s [array names data_series "$w,*"] {
1252      unset data_series($s)
1253   }
1254
1255   set newchart "hbarchart_$w"
1256   interp alias {} $newchart {} ::Plotchart::PlotHandler horizbars $w
1257   CopyConfig horizbars $w
1258
1259   set settings($w,showvalues)   0
1260   set settings($w,valuefont)    ""
1261   set settings($w,valuecolour)  black
1262   set settings($w,valueformat)  %s
1263
1264   set font      $config($w,leftaxis,font)
1265   set xspacemax 0
1266   foreach ylabel $ylabels {
1267       set xspace [font measure $font $ylabel]
1268       if { $xspace > $xspacemax } {
1269           set xspacemax $xspace
1270       }
1271   }
1272   set config($w,margin,left) [expr {$xspacemax+5}] ;# Slightly more space required!
1273
1274   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
1275
1276   set ymin  0.0
1277   set ymax  [expr {[llength $ylabels] + 0.1}]
1278
1279   foreach {xmin xmax xdelt} $xscale {break}
1280
1281   if { $xdelt == 0.0 } {
1282      return -code error "Step size can not be zero"
1283   }
1284
1285   if { ($xmax-$xmin)*$xdelt < 0.0 } {
1286      set xdelt [expr {-$xdelt}]
1287   }
1288
1289   viewPort         $w $pxmin $pymin $pxmax $pymax
1290   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1291
1292   DrawXaxis        $w $xmin  $xmax  $xdelt
1293   DrawYlabels      $w $ylabels $noseries
1294   DrawMask         $w
1295   DefaultLegend    $w
1296   set data_series($w,legendtype) "rectangle"
1297   DefaultBalloon   $w
1298
1299   SetColours $w blue lightblue green yellow orange red magenta brown
1300
1301   return $newchart
1302}
1303
1304# createBoxplot --
1305#    Create a command for drawing a plot with box-and-whiskers
1306# Arguments:
1307#    w           Name of the canvas
1308#    xscale      Minimum, maximum and step for x-axis
1309#    ylabels     List of labels for y-axis
1310# Result:
1311#    Name of a new command
1312# Note:
1313#    The entire canvas will be dedicated to the boxplot.
1314#
1315proc ::Plotchart::createBoxplot { w xscale ylabels } {
1316   variable data_series
1317   variable config
1318
1319   foreach s [array names data_series "$w,*"] {
1320      unset data_series($s)
1321   }
1322
1323   set newchart "boxplot_$w"
1324   interp alias {} $newchart {} ::Plotchart::PlotHandler boxplot $w
1325   CopyConfig boxplot $w
1326
1327   set font      $config($w,leftaxis,font)
1328   set xspacemax 0
1329   foreach ylabel $ylabels {
1330       set xspace [font measure $font $ylabel]
1331       if { $xspace > $xspacemax } {
1332           set xspacemax $xspace
1333       }
1334   }
1335   set config($w,margin,left) [expr {$xspacemax+5}] ;# Slightly more space required!
1336   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
1337
1338   set ymin  0.0
1339   set ymax  [expr {[llength $ylabels] + 0.1}]
1340
1341   foreach {xmin xmax xdelt} $xscale {break}
1342
1343   if { $xdelt == 0.0 } {
1344      return -code error "Step size can not be zero"
1345   }
1346
1347   if { ($xmax-$xmin)*$xdelt < 0.0 } {
1348      set xdelt [expr {-$xdelt}]
1349   }
1350
1351   viewPort         $w $pxmin $pymin $pxmax $pymax
1352   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1353
1354   DrawXaxis        $w $xmin  $xmax  $xdelt
1355   DrawYlabels      $w $ylabels 1
1356   DrawMask         $w
1357   DefaultLegend    $w
1358   set data_series($w,legendtype) "rectangle"
1359   DefaultBalloon   $w
1360
1361   set config($w,axisnames) $ylabels
1362
1363   return $newchart
1364}
1365
1366# createTimechart --
1367#    Create a command for drawing a simple timechart
1368# Arguments:
1369#    w           Name of the canvas
1370#    time_begin  Start time (in the form of a date/time)
1371#    time_end    End time (in the form of a date/time)
1372#    args        Number of items to be shown (determines spacing)
1373#                or one or more options (-barheight pixels, -ylabelwidth pixels)
1374# Result:
1375#    Name of a new command
1376# Note:
1377#    The entire canvas will be dedicated to the timechart.
1378#
1379proc ::Plotchart::createTimechart { w time_begin time_end args} {
1380   variable data_series
1381   variable scaling
1382
1383   foreach s [array names data_series "$w,*"] {
1384      unset data_series($s)
1385   }
1386
1387   set newchart "timechart_$w"
1388   interp alias {} $newchart {} ::Plotchart::PlotHandler timechart $w
1389   CopyConfig timechart $w
1390
1391   #
1392   # Handle the arguments
1393   #
1394   set barheight    0
1395   set noitems      [lindex $args 0]
1396   set ylabelwidth  8
1397
1398   if { [string is integer -strict $noitems] } {
1399       set args [lrange $args 1 end]
1400   }
1401   foreach {keyword value} $args {
1402       switch -- $keyword {
1403           "-barheight" {
1404                set barheight $value
1405           }
1406           "-ylabelwidth" {
1407                set ylabelwidth [expr {$value/10.0}] ;# Pixels to characters
1408           }
1409           default {
1410                # Ignore
1411           }
1412       }
1413   }
1414
1415   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w 3 $ylabelwidth] {break}
1416
1417   if { $barheight != 0 } {
1418       set noitems [expr {($pxmax-$pxmin)/double($barheight)}]
1419   }
1420   set scaling($w,barheight) $barheight
1421
1422   set ymin  0.0
1423   set ymax  $noitems
1424
1425   set xmin  [expr {1.0*[clock scan $time_begin]}]
1426   set xmax  [expr {1.0*[clock scan $time_end]}]
1427
1428   viewPort         $w $pxmin $pymin $pxmax $pymax
1429   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1430
1431   set scaling($w,current) $ymax
1432   set scaling($w,dy)      -0.7
1433
1434   DrawScrollMask $w
1435   set scaling($w,curpos)  0
1436   set scaling($w,curhpos) 0
1437
1438   return $newchart
1439}
1440
1441# createGanttchart --
1442#    Create a command for drawing a Gantt (planning) chart
1443# Arguments:
1444#    w           Name of the canvas
1445#    time_begin  Start time (in the form of a date/time)
1446#    time_end    End time (in the form of a date/time)
1447#    args        (First integer) Number of items to be shown (determines spacing)
1448#                (Second integer) Estimated maximum length of text (default: 20)
1449#                Or keyword-value pairs
1450# Result:
1451#    Name of a new command
1452# Note:
1453#    The entire canvas will be dedicated to the Gantt chart.
1454#    Most commands taken from time charts.
1455#
1456proc ::Plotchart::createGanttchart { w time_begin time_end args} {
1457
1458   variable data_series
1459   variable scaling
1460
1461   foreach s [array names data_series "$w,*"] {
1462      unset data_series($s)
1463   }
1464
1465   set newchart "ganttchart_$w"
1466   interp alias {} $newchart {} ::Plotchart::PlotHandler ganttchart $w
1467   CopyConfig ganttchart $w
1468
1469   #
1470   # Handle the arguments
1471   #
1472   set barheight    0
1473   set noitems      [lindex $args 0]
1474
1475   if { [string is integer -strict $noitems] } {
1476       set args        [lrange $args 1 end]
1477       set ylabelwidth [lindex $args 0]
1478       if { [string is integer -strict $ylabelwidth] } {
1479           set args [lrange $args 1 end]
1480       } else {
1481           set ylabelwidth 20
1482       }
1483   } else {
1484       set ylabelwidth 20
1485   }
1486
1487   foreach {keyword value} $args {
1488       switch -- $keyword {
1489           "-barheight" {
1490                set barheight $value
1491           }
1492           "-ylabelwidth" {
1493                set ylabelwidth [expr {$value/10.0}] ;# Pixels to characters
1494           }
1495           default {
1496                # Ignore
1497           }
1498       }
1499   }
1500
1501   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w 3 $ylabelwidth] {break}
1502
1503   if { $barheight != 0 } {
1504       set noitems [expr {($pxmax-$pxmin)/double($barheight)}]
1505   }
1506   set scaling($w,barheight) $barheight
1507
1508   set ymin  0.0
1509   set ymax  $noitems
1510
1511   set xmin  [expr {1.0*[clock scan $time_begin]}]
1512   set xmax  [expr {1.0*[clock scan $time_end]}]
1513
1514   viewPort         $w $pxmin $pymin $pxmax $pymax
1515   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1516
1517   set scaling($w,current) $ymax
1518   set scaling($w,dy)      -0.7
1519
1520   #
1521   # Draw the backgrounds (both in the text part and the
1522   # graphical part; the text part has the "special" tag
1523   # "Edit" to enable a GUI to change things)
1524   #
1525   set yend 0.0
1526   for { set i 0 } { $i < $noitems } { incr i } {
1527       set ybegin $yend
1528       set yend   [expr {$ybegin+1.0}]
1529       foreach {x1 y1} [coordsToPixel $w $xmin $ybegin] {break}
1530       foreach {x2 y2} [coordsToPixel $w $xmax $yend  ] {break}
1531
1532       if { $i%2 == 0 } {
1533           set tag odd
1534       } else {
1535           set tag even
1536       }
1537       $w create rectangle 0   $y1 $x1 $y2 -fill white \
1538           -tag {Edit vertscroll lowest} -outline white
1539       $w create rectangle $x1 $y1 $x2 $y2 -fill white \
1540           -tag [list $tag vertscroll lowest] -outline white
1541   }
1542
1543   #
1544   # Default colours and fonts
1545   #
1546   GanttColor $w description black
1547   GanttColor $w completed   lightblue
1548   GanttColor $w left        white
1549   GanttColor $w odd         white
1550   GanttColor $w even        lightgrey
1551   GanttColor $w summary     black
1552   GanttColor $w summarybar  black
1553   GanttFont  $w description "times 10"
1554   GanttFont  $w summary     "times 10 bold"
1555   GanttFont  $w scale       "times 7"
1556   DefaultBalloon $w
1557
1558   DrawScrollMask $w
1559   set scaling($w,curpos)  0
1560   set scaling($w,curhpos) 0
1561
1562   return $newchart
1563}
1564
1565# create3DPlot --
1566#    Create a simple 3D plot
1567# Arguments:
1568#    w           Name of the canvas
1569#    xscale      Minimum, maximum and step for x-axis (initial)
1570#    yscale      Minimum, maximum and step for y-axis
1571#    zscale      Minimum, maximum and step for z-axis
1572# Result:
1573#    Name of a new command
1574# Note:
1575#    The entire canvas will be dedicated to the 3D plot
1576#
1577proc ::Plotchart::create3DPlot { w xscale yscale zscale } {
1578   variable data_series
1579
1580   foreach s [array names data_series "$w,*"] {
1581      unset data_series($s)
1582   }
1583
1584   set newchart "3dplot_$w"
1585   interp alias {} $newchart {} ::Plotchart::PlotHandler 3dplot $w
1586   CopyConfig 3dplot $w
1587
1588   foreach {pxmin pymin pxmax pymax} [Margins3DPlot $w] {break}
1589
1590   foreach {xmin xmax xstep} $xscale {break}
1591   foreach {ymin ymax ystep} $yscale {break}
1592   foreach {zmin zmax zstep} $zscale {break}
1593
1594   viewPort           $w $pxmin $pymin $pxmax $pymax
1595   world3DCoordinates $w $xmin  $ymin  $zmin  $xmax  $ymax $zmax
1596
1597   Draw3DAxes         $w $xmin  $ymin  $zmin  $xmax  $ymax $zmax \
1598                         $xstep $ystep $zstep
1599   DefaultLegend      $w
1600   DefaultBalloon     $w
1601
1602   SetColours $w grey black
1603
1604   return $newchart
1605}
1606
1607# create3DRibbonPlot --
1608#    Create a simple 3D plot that allows for ribbons
1609# Arguments:
1610#    w           Name of the canvas
1611#    yscale      Minimum, maximum and step for y-axis
1612#    zscale      Minimum, maximum and step for z-axis
1613# Result:
1614#    Name of a new command
1615# Note:
1616#    The entire canvas will be dedicated to the 3D plot
1617#
1618proc ::Plotchart::create3DRibbonPlot { w yscale zscale } {
1619   variable data_series
1620
1621   foreach s [array names data_series "$w,*"] {
1622      unset data_series($s)
1623   }
1624
1625   set newchart "3dribbonplot_$w"
1626   interp alias {} $newchart {} ::Plotchart::PlotHandler 3dribbonplot $w
1627   CopyConfig 3dplot $w
1628
1629   foreach {pxmin pymin pxmax pymax} [Margins3DPlot $w] {break}
1630
1631   foreach {xmin xmax xstep} {0.0 1.0 0.0} {break}
1632   foreach {ymin ymax ystep} $yscale {break}
1633   foreach {zmin zmax zstep} $zscale {break}
1634
1635   viewPort           $w $pxmin $pymin $pxmax $pymax
1636   world3DCoordinates $w $xmin  $ymin  $zmin  $xmax  $ymax $zmax
1637
1638   Draw3DAxes         $w $xmin  $ymin  $zmin  $xmin  $ymax $zmax \
1639                         $xstep $ystep $zstep
1640   DefaultLegend      $w
1641   DefaultBalloon     $w
1642
1643   SetColours $w grey black
1644
1645   return $newchart
1646}
1647
1648# create3DBarchart --
1649#    Create a command for drawing a barchart with vertical 3D bars
1650# Arguments:
1651#    w           Name of the canvas
1652#    yscale      Minimum, maximum and step for y-axis
1653#    nobars      Number of bars to be drawn
1654# Result:
1655#    Name of a new command
1656# Note:
1657#    The entire canvas will be dedicated to the barchart.
1658#
1659proc ::Plotchart::create3DBarchart { w yscale nobars } {
1660   variable data_series
1661
1662   foreach s [array names data_series "$w,*"] {
1663      unset data_series($s)
1664   }
1665
1666   set newchart "3dbarchart_$w"
1667   interp alias {} $newchart {} ::Plotchart::PlotHandler 3dbars $w
1668   CopyConfig 3dbars $w
1669
1670   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w 4] {break}
1671
1672   set xmin  0.0
1673   set xmax  [expr {$nobars + 0.1}]
1674
1675   foreach {ymin ymax ydelt} $yscale {break}
1676
1677   if { $ydelt == 0.0 } {
1678      return -code error "Step size can not be zero"
1679   }
1680
1681   if { ($ymax-$ymin)*$ydelt < 0.0 } {
1682      set ydelt [expr {-$ydelt}]
1683   }
1684
1685   viewPort         $w $pxmin $pymin $pxmax $pymax
1686   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1687
1688   DrawYaxis        $w $ymin  $ymax  $ydelt
1689  #DrawMask         $w -- none!
1690   Draw3DBarchart   $w $yscale $nobars
1691   DefaultLegend    $w
1692   DefaultBalloon   $w
1693
1694   return $newchart
1695}
1696
1697# createRadialchart --
1698#    Create a command for drawing a radial chart
1699# Arguments:
1700#    w           Name of the canvas
1701#    names       Names of the spokes
1702#    scale       Scale factor for the data
1703#    style       (Optional) style of the chart (lines, cumulative or filled)
1704# Result:
1705#    Name of a new command
1706# Note:
1707#    The entire canvas will be dedicated to the radial chart.
1708#
1709proc ::Plotchart::createRadialchart { w names scale {style lines} } {
1710   variable settings
1711   variable data_series
1712
1713   foreach s [array names data_series "$w,*"] {
1714      unset data_series($s)
1715   }
1716
1717   set newchart "radialchart_$w"
1718   interp alias {} $newchart {} ::Plotchart::PlotHandler radialchart $w
1719   CopyConfig radialchart $w
1720
1721   foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}
1722
1723   viewPort $w $pxmin $pymin $pxmax $pymax
1724   $w create oval $pxmin $pymin $pxmax $pymax
1725
1726   set settings($w,scale)  [expr {double($scale)}]
1727   set settings($w,style)  $style
1728   set settings($w,number) [llength $names]
1729
1730   DrawRadialSpokes $w $names
1731   DefaultLegend  $w
1732   DefaultBalloon $w
1733
1734   return $newchart
1735}
1736
1737# createTXPlot --
1738#    Create a command for drawing a TX plot (x versus date/time)
1739# Arguments:
1740#    w           Name of the canvas
1741#    tscale      Minimum, maximum and step for date/time-axis (initial)
1742#                (values must be valid dates and the step is in days)
1743#    xscale      Minimum, maximum and step for vertical axis
1744# Result:
1745#    Name of a new command
1746# Note:
1747#    The entire canvas will be dedicated to the TX plot.
1748#    The plot will be drawn with axes
1749#
1750proc ::Plotchart::createTXPlot { w tscale xscale } {
1751   variable data_series
1752
1753   foreach s [array names data_series "$w,*"] {
1754      unset data_series($s)
1755   }
1756
1757   set newchart "txplot_$w"
1758   interp alias {} $newchart {} ::Plotchart::PlotHandler txplot $w
1759   CopyConfig txplot $w
1760
1761   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
1762
1763   foreach {tmin tmax tdelt} $tscale {break}
1764
1765   set xmin  [clock scan $tmin]
1766   set xmax  [clock scan $tmax]
1767   set xdelt [expr {86400*$tdelt}]
1768
1769   foreach {ymin ymax ydelt} $xscale {break}
1770
1771   if { $xdelt == 0.0 || $ydelt == 0.0 } {
1772      return -code error "Step size can not be zero"
1773   }
1774
1775   if { ($xmax-$xmin)*$xdelt < 0.0 } {
1776      set xdelt [expr {-$xdelt}]
1777   }
1778   if { ($ymax-$ymin)*$ydelt < 0.0 } {
1779      set ydelt [expr {-$ydelt}]
1780   }
1781
1782   viewPort         $w $pxmin $pymin $pxmax $pymax
1783   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
1784
1785   DrawYaxis        $w $ymin  $ymax  $ydelt
1786   DrawTimeaxis     $w $tmin  $tmax  $tdelt
1787   DrawMask         $w
1788   DefaultLegend    $w
1789   DefaultBalloon   $w
1790
1791   return $newchart
1792}
1793
1794# createRightAxis --
1795#    Create a command for drawing a plot with a right axis
1796# Arguments:
1797#    w           Name of the canvas
1798#    yscale      Minimum, maximum and step for vertical axis
1799# Result:
1800#    Name of a new command
1801# Note:
1802#    This command requires that another plot command has been
1803#    created prior to this one. Some of the properties from that
1804#    command serve for this one too.
1805#
1806proc ::Plotchart::createRightAxis { w yscale } {
1807   variable data_series
1808   variable scaling
1809   variable config
1810
1811   set newchart "right_$w"
1812
1813   #
1814   # Check if there is an appropriate plot already defined - there
1815   # should be only one!
1816   #
1817   if { [llength [info command "*_$w" ]] == 0 } {
1818       return -code error "There should be a plot with a left axis already defined"
1819   }
1820   if { [llength [info command "*_$w" ]] >= 2 } {
1821       if { [llength [info command "right_$w"]] == 0 } {
1822           return -code error "There should be only one plot command for this widget ($w)"
1823       } else {
1824           catch {
1825               interp alias {} $newchart {}
1826           }
1827       }
1828   }
1829
1830   foreach s [array names data_series "r$w,*"] {
1831      unset data_series($s)
1832   }
1833
1834   set type [lindex [interp alias {} [info command "*_$w"]] 1]
1835
1836   interp alias {} $newchart {} ::Plotchart::PlotHandler $type r$w
1837   interp alias {} r$w       {} $w
1838   CopyConfig $type r$w
1839
1840   set config(r$w,font,char_width)  $config($w,font,char_width)
1841   set config(r$w,font,char_height) $config($w,font,char_height)
1842
1843   set xmin $scaling($w,xmin)
1844   set xmax $scaling($w,xmax)
1845
1846   set pxmin $scaling($w,pxmin)
1847   set pxmax $scaling($w,pxmax)
1848   set pymin $scaling($w,pymin)
1849   set pymax $scaling($w,pymax)
1850
1851   foreach {ymin ymax ydelt} $yscale {break}
1852
1853   if { $ydelt == 0.0 } {
1854      return -code error "Step size can not be zero"
1855   }
1856
1857   if { ($ymax-$ymin)*$ydelt < 0.0 } {
1858      set ydelt [expr {-$ydelt}]
1859   }
1860
1861   viewPort         r$w $pxmin $pymin $pxmax $pymax
1862   worldCoordinates r$w $xmin  $ymin  $xmax  $ymax
1863
1864   DrawRightaxis    r$w $ymin  $ymax  $ydelt
1865
1866   #DefaultLegend    r$w
1867   #DefaultBalloon   r$w
1868
1869   return $newchart
1870}
1871
1872# create3DRibbonChart --
1873#    Create a chart that can display 3D lines and areas
1874# Arguments:
1875#    w           Name of the canvas
1876#    names       Labels along the x-axis
1877#    yscale      Minimum, maximum and step for y-axis
1878#    zscale      Minimum, maximum and step for z-axis
1879# Result:
1880#    Name of a new command
1881# Note:
1882#    The entire canvas will be dedicated to the 3D chart
1883#
1884proc ::Plotchart::create3DRibbonChart { w names yscale zscale } {
1885   variable data_series
1886
1887   foreach s [array names data_series "$w,*"] {
1888      unset data_series($s)
1889   }
1890
1891   set newchart "3dribbon_$w"
1892   interp alias {} $newchart {} ::Plotchart::PlotHandler 3dribbon $w
1893   CopyConfig 3dribbon $w
1894
1895   foreach {pxmin pymin pxmax pymax} [Margins3DPlot $w] {break}
1896
1897   foreach {xmin xmax xstep} {0.0 1.0 0.0} {break}
1898   foreach {ymin ymax ystep} $yscale {break}
1899   foreach {zmin zmax zstep} $zscale {break}
1900
1901   set xstep [expr {1.0/[llength $names]}]
1902   set data_series($w,xbase)  [expr {1.0-0.15*$xstep}]
1903   set data_series($w,xstep)  $xstep
1904   set data_series($w,xwidth) [expr {0.7*$xstep}]
1905
1906   viewPort           $w $pxmin $pymin $pxmax $pymax
1907   world3DCoordinates $w $xmin  $ymin  $zmin  $xmax  $ymax $zmax
1908
1909   Draw3DAxes         $w $xmin  $ymin  $zmin  $xmax  $ymax $zmax \
1910                         $xstep $ystep $zstep $names
1911   DefaultLegend      $w
1912   DefaultBalloon     $w
1913
1914   SetColours $w grey black
1915
1916   return $newchart
1917}
1918
1919# createWindRose --
1920#     Create a new command for plotting a windrose
1921#
1922# Arguments:
1923#    w             Name of the canvas
1924#    radius_data   Maximum radius and step
1925#    sectors       Number of sectors (default: 16)
1926# Result:
1927#    Name of a new command
1928# Note:
1929#    The entire canvas will be dedicated to the windrose
1930#    Possible additional arguments (optional): nautical/mathematical
1931#    step in phi
1932#
1933proc ::Plotchart::createWindRose { w radius_data {sectors 16}} {
1934    variable data_series
1935
1936    foreach s [array names data_series "$w,*"] {
1937        unset data_series($s)
1938    }
1939
1940    set newchart "windrose_$w"
1941    interp alias {} $newchart {} ::Plotchart::PlotHandler windrose $w
1942    CopyConfig windrose $w
1943
1944    set rad_max   [lindex $radius_data 0]
1945    set rad_step  [lindex $radius_data 1]
1946
1947    if { $rad_step <= 0.0 } {
1948        return -code error "Step size can not be zero or negative"
1949    }
1950    if { $rad_max <= 0.0 } {
1951        return -code error "Maximum radius can not be zero or negative"
1952    }
1953
1954    foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}
1955
1956    viewPort         $w $pxmin     $pymin     $pxmax   $pymax
1957    polarCoordinates $w $rad_max
1958    DrawRoseAxes     $w $rad_max   $rad_step
1959
1960
1961    set data_series($w,radius) {}
1962    for { set i 0 } { $i < $sectors } { incr i } {
1963        lappend data_series($w,cumulative_radius) 0.0
1964    }
1965
1966    set data_series($w,start_angle)     [expr {90.0 - 360.0/(4.0*$sectors)}]
1967    set data_series($w,d_angle)         [expr {360.0/(2.0*$sectors)}]
1968    set data_series($w,increment_angle) [expr {360.0/$sectors}]
1969    set data_series($w,count_data)      0
1970
1971
1972    return $newchart
1973}
1974
1975# createTargetDiagram --
1976#    Create a command for drawing a target diagram
1977# Arguments:
1978#    w           Name of the canvas
1979#    bounds      List of radii to indicate bounds for the skill
1980#    scale       Scale of the axes - defaults to 1
1981# Result:
1982#    Name of a new command
1983# Note:
1984#    The entire canvas will be dedicated to the XY plot.
1985#    The plot will be drawn with axes
1986#
1987proc ::Plotchart::createTargetDiagram { w bounds {scale 1.0}} {
1988    variable scaling
1989    variable data_series
1990    variable config
1991
1992    foreach s [array names data_series "$w,*"] {
1993        unset data_series($s)
1994    }
1995
1996    set newchart "targetdiagram_$w"
1997    interp alias {} $newchart {} ::Plotchart::PlotHandler targetdiagram $w
1998    CopyConfig targetdiagram $w
1999
2000    foreach {pxmin pymin pxmax pymax} [MarginsSquare $w] {break}
2001
2002    set extremes [determineScale [expr {-$scale}] $scale]
2003    foreach {xmin xmax xdelt} $extremes {break}
2004    foreach {ymin ymax ydelt} $extremes {break}
2005
2006    if { $xdelt == 0.0 || $ydelt == 0.0 } {
2007        return -code error "Step size can not be zero"
2008    }
2009
2010    if { $xdelt ne {} && ($xmax-$xmin)*$xdelt < 0.0 } {
2011        set xdelt [expr {-$xdelt}]
2012    }
2013    if { ($ymax-$ymin)*$ydelt < 0.0 } {
2014        set ydelt [expr {-$ydelt}]
2015    }
2016
2017    viewPort         $w $pxmin $pymin $pxmax $pymax
2018    worldCoordinates $w $xmin  $ymin  $xmax  $ymax
2019
2020    DrawYaxis        $w $ymin  $ymax  $ydelt
2021    DrawXaxis        $w $xmin  $xmax  $xdelt
2022
2023    DrawMask         $w
2024    DefaultLegend    $w
2025    DefaultBalloon   $w
2026
2027    foreach {pxcent pycent} [coordsToPixel $w 0.0 0.0] {break}
2028
2029    $w create line $pxmin  $pycent $pxmax  $pycent -fill $config($w,limits,color) -tag limits
2030    $w create line $pxcent $pymin  $pxcent $pymax  -fill $config($w,limits,color) -tag limits
2031
2032    foreach r $bounds {
2033        foreach {pxmin pymin} [coordsToPixel $w [expr {-$r}] [expr {-$r}]] {break}
2034        foreach {pxmax pymax} [coordsToPixel $w $r $r] {break}
2035
2036        $w create oval $pxmin $pymin $pxmax $pymax -outline $config($w,limits,color) -tag limits
2037    }
2038
2039
2040    return $newchart
2041}
2042
2043# createPerformanceProfile --
2044#    Create a command for drawing a performance profile
2045# Arguments:
2046#    w           Name of the canvas
2047#    scale       Maximum value for the x-axis
2048# Result:
2049#    Name of a new command
2050# Note:
2051#    The entire canvas will be dedicated to the XY plot.
2052#    The plot will be drawn with axes
2053#
2054proc ::Plotchart::createPerformanceProfile { w scale } {
2055   variable scaling
2056   variable data_series
2057
2058   foreach s [array names data_series "$w,*"] {
2059      unset data_series($s)
2060   }
2061
2062   set newchart "performance_$w"
2063   interp alias {} $newchart {} ::Plotchart::PlotHandler performance $w
2064   CopyConfig performance $w
2065   set scaling($w,eventobj) ""
2066
2067   foreach {pxmin pymin pxmax pymax} [MarginsRectangle $w] {break}
2068
2069   foreach {xmin xmax xdelt} [determineScale 1.0 $scale] {break}
2070   foreach {ymin ymax ydelt} {0.0 1.1 0.25} {break}
2071
2072   viewPort         $w $pxmin $pymin $pxmax $pymax
2073   worldCoordinates $w $xmin  $ymin  $xmax  $ymax
2074
2075   DrawYaxis        $w $ymin  $ymax  $ydelt
2076   DrawXaxis        $w $xmin  $xmax  $xdelt
2077
2078   DrawMask         $w
2079   DefaultLegend    $w
2080   LegendConfigure  $w -position bottom-right
2081   DefaultBalloon   $w
2082
2083
2084   return $newchart
2085}
2086
2087# Load the private procedures
2088#
2089source [file join [file dirname [info script]] "plotpriv.tcl"]
2090source [file join [file dirname [info script]] "plotaxis.tcl"]
2091source [file join [file dirname [info script]] "plot3d.tcl"]
2092source [file join [file dirname [info script]] "scaling.tcl"]
2093source [file join [file dirname [info script]] "plotcontour.tcl"]
2094source [file join [file dirname [info script]] "plotgantt.tcl"]
2095source [file join [file dirname [info script]] "plotbusiness.tcl"]
2096source [file join [file dirname [info script]] "plotannot.tcl"]
2097source [file join [file dirname [info script]] "plotconfig.tcl"]
2098source [file join [file dirname [info script]] "plotpack.tcl"]
2099source [file join [file dirname [info script]] "plotbind.tcl"]
2100source [file join [file dirname [info script]] "plotspecial.tcl"]
2101
2102# Announce our presence
2103#
2104package provide Plotchart 1.9.2
2105