File: editgraph.tcl

package info (click to toggle)
tklib 0.6%2B20190108-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 15,008 kB
  • sloc: tcl: 75,757; sh: 5,789; ansic: 792; pascal: 359; makefile: 70; sed: 53; exp: 21
file content (176 lines) | stat: -rwxr-xr-x 3,734 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env tclsh
## -*- tcl -*-

package require Tk

# editgraph.tcl --
#     Widget to edit data series graphically
#
#     Note:
#     Not as elegant as could be with bindings via Plotchart itself
#
package require Plotchart

namespace eval ::Editgraph {

    variable graph
    variable endedit
}

# editSeries --
#     Procedure to edit a series of data graphically
#
# Arguments:
#     xrange          Range for the x values
#     yrange          Range for the y values
#     number          Number of data points
#
# Result:
#     List of x,y values representing the data series
#
# Note:
#     The widget allows setting new y values for given x values only
#
proc ::Editgraph::editSeries {xrange yrange number} {

    variable graph
    variable endedit

    toplevel .graph
    wm title .graph "Editing series"
    canvas   .graph.c -width 400 -height 300
    button   .graph.ok     -text OK     -width 10 -command {::Editgraph::SaveSeries}
    button   .graph.cancel -text Cancel -width 10 -command {::Editgraph::CancelSeries}
    grid     .graph.c -
    grid     .graph.ok .graph.cancel

    #
    # Initialise the series
    #
    foreach {xmin xmax} $xrange {break}
    foreach {ymin ymax} $yrange {break}

    if { $ymin <= 0.0 && $ymax >= 0.0 } {
        set y 0.0
    } else {
        set y $ymin
    }

    set delx [expr {($xmax-$xmin)/double($number-1)}]

    set graph(xy) {}
    set x         $xmin
    while { $x < $xmax+0.5*$delx } {
        lappend graph(xy) $x $y
        set x [expr {$x + $delx}]
        if { abs($x) < 0.5 *$delx } {
            set x 0.0
        }
    }
    set graph(xmin)   $xmin
    set graph(xmax)   $xmax
    set graph(delx)   $delx
    set graph(number) $number

    set graph(plot) [::Plotchart::createXYPlot .graph.c \
                        [::Plotchart::determineScale $xmin $xmax] \
                        [::Plotchart::determineScale $ymin $ymax]]

    $graph(plot) dataconfig data -colour blue
    set graph(widget) .graph.c

    foreach {x y} $graph(xy) {
        $graph(plot) plot data $x $y
    }

    #
    # Set the bindings
    #
    bind .graph.c <Button-1> {::Editgraph::EditPoint %W %x %y}

    vwait ::Editgraph::endedit
    puts "$endedit"

    if { $endedit == 1 } {
        return $graph(xy)
    } else {
        return {}
    }
}

# SaveSeries, CancelSeries --
#     Callback procedure for the widget
#
# Arguments:
#     None
#
# Result:
#     None
#
# Side effects:
#     The widget is closed
#
proc ::Editgraph::SaveSeries {} {
    set ::Editgraph::endedit 1
    destroy .graph
}

proc ::Editgraph::CancelSeries {} {
    set ::Editgraph::endedit 0
    destroy .graph
}

# EditPoint --
#     Callback procedure for setting the new data point
#
# Arguments:
#     w             Widget
#     x             X-coordinate of selected point (pixel)
#     y             Y-coordinate of selected point (pixel)
#
# Result:
#     None
#
# Side effects:
#     The data points are updated and the graph redrawn
#

proc ::Editgraph::EditPoint {w x y} {
    variable graph

    foreach {xc yc} [::Plotchart::pixelToCoords $graph(widget) $x $y] {break}

    set xp [expr {int(0.5+($xc-$graph(xmin))/$graph(delx))}]

    if { $xp < 0 } { set xp 0 }
    if { $xp > $graph(number) } { set xp $graph(number) }

    lset graph(xy) [expr {2*$xp+1}] $yc

    #
    # Reset the plotted data
    #
    $graph(widget) delete data
    $graph(plot) plot data "" ""

    #
    # Redraw the data
    #
    foreach {x y} $graph(xy) {
        $graph(plot) plot data $x $y
    }

}

# main --
#     Make it all work

catch {
    console show
}
set xyseries [::Editgraph::editSeries {0 100} {-50 50} 10]

puts "Series:"
foreach {x y} $xyseries {
    puts [format "%10.4f %10.4f" $x $y]
}