source: trunk/gui/scripts/transferfunctioneditor.tcl @ 3984

Last change on this file since 3984 was 3984, checked in by gah, 11 years ago

fix for new markers (immediately send new transfer function, don't create new marker is close to an existing marker).

File size: 10.9 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2
3# ----------------------------------------------------------------------
4#  COMPONENT: transferfunctioneditor - Rudimentary editor for 3D volume
5#                                      transfer functions
6#
7#  This class is used to modify transfer functions used in volume rendering
8#  on 3D scalar/vector datasets.
9#
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require Itk
18package require BLT
19package require Img
20
21itcl::class Rappture::TransferFunctionEditor {
22    private variable _nextId 0;         # Used to create unique marker names
23    private variable _values;           # Relative values for each marker.
24    private variable _limits;           # Over limits of transfer function.
25    private variable _labels;           # Label id for each marker.
26    private variable _ticks;            # Tick id for each marker.
27    private variable _canvas    ""
28    private variable _name "";          # Name of transfer function.
29    private variable _activeMotion   0
30    private variable _activePress    0
31    private variable _id2name
32    private common   _normalIcon [Rappture::icon nvlegendmark]
33    private common   _activeIcon [Rappture::icon nvlegendmark2]
34    public variable command ""
35
36    private method SetAbsoluteValue { name x }
37    private method GetAbsoluteValue { name }
38    private method ContinueDrag { name x y }
39    private method EnterTick { name }
40    private method GetOverlappingMarkers { x y }
41    private method GetScreenPosition { name }
42    private method LeaveTick { name }
43    private method NewMarker { x y state }
44    private method SetRelativeValue  { name x }
45    private method GetRelativeValue  { name }
46    private method RemoveDuplicateMarkers {name x y}
47    private method SetScreenPosition { name }
48    private method SetVisibility { name bool }
49    private method StartDrag { name x y }
50    private method StopDrag { name x y }
51    private method Activate { name }
52    private method Deactivate { name }
53    private method UpdateViewer {}
54
55    constructor {c name args} {}
56    destructor {}
57    public method limits { min max }
58    public method names {}
59    public method name {}
60    public method values {}
61    public method absoluteValues {}
62    public method removeMarkers { list }
63    public method addMarkers { values }
64    public method hideMarkers { {list {}} }
65    public method showMarkers { {limits {}} }
66}
67
68itcl::body Rappture::TransferFunctionEditor::constructor {c name args} {
69    set _canvas $c
70    set _name $name
71    set _limits [list 0.0 1.0]
72    $c bind transfunc <ButtonRelease-1> \
73        [itcl::code $this NewMarker %x %y normal]
74    eval configure $args
75}
76
77itcl::body Rappture::TransferFunctionEditor::limits { min max } {
78    set _limits [list $min $max]
79}
80
81itcl::body Rappture::TransferFunctionEditor::names {} {
82    return [lsort [array names _values]]
83}
84
85itcl::body Rappture::TransferFunctionEditor::values {} {
86    set list {}
87    foreach name [array names _ticks] {
88        lappend list [GetRelativeValue $name]
89    }
90    return [lsort -real $list]
91}
92
93itcl::body Rappture::TransferFunctionEditor::absoluteValues {} {
94    set list {}
95    foreach name [array names _values] {
96        lappend list [GetAbsoluteValue $name]
97    }
98    return $list
99}
100
101itcl::body Rappture::TransferFunctionEditor::NewMarker { x y state } {
102    foreach id [$_canvas find overlapping \
103                    [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5]] {
104        if { [info exists _id2name($id)] } {
105            puts stderr "Too close to existing marker"
106            return;                     # Too close to existing marker
107        }
108    }
109    set name "tick[incr _nextId]"
110    set w [winfo width $_canvas]
111    set h [winfo height $_canvas]
112
113    set _ticks($name) [$_canvas create image 0 $h \
114                           -image $_normalIcon -anchor s \
115                           -tags "tick $_name $this" -state $state]
116    set _labels($name) [$_canvas create text 0 $h \
117                            -anchor n -fill white -font "Helvetica 8" \
118                            -tags "$this $_name" -state $state]
119    set _id2name($_ticks($name)) $name
120    $_canvas bind $_ticks($name) <Enter> [itcl::code $this EnterTick $name]
121    $_canvas bind $_ticks($name) <Leave> [itcl::code $this LeaveTick $name]
122    $_canvas bind $_ticks($name) <ButtonPress-1> \
123        [itcl::code $this StartDrag $name %x %y]
124    $_canvas bind $_ticks($name) <B1-Motion> \
125        [itcl::code $this ContinueDrag $name %x %y]
126    $_canvas bind $_ticks($name) <ButtonRelease-1> \
127        [itcl::code $this StopDrag $name %x %y]
128
129    SetRelativeValue $name [expr {double($x-10)/($w-20)}]
130    if { $state == "normal" } {
131        UpdateViewer
132    }
133    return $name
134}
135
136itcl::body Rappture::TransferFunctionEditor::destructor {} {
137    $_canvas delete $_name
138}
139
140itcl::body Rappture::TransferFunctionEditor::name {} {
141    return $_name
142}
143
144itcl::body Rappture::TransferFunctionEditor::Activate { name } {
145    if  { $_activePress || $_activeMotion } {
146        $_canvas itemconfigure $_labels($name) -state normal
147        $_canvas itemconfigure $_ticks($name) -image $_activeIcon
148        $_canvas itemconfigure title -state hidden
149    }
150}
151
152itcl::body Rappture::TransferFunctionEditor::Deactivate { name } {
153    if  { $_activePress || $_activeMotion } {
154        #puts stderr "do nothing for Deactivate"
155    } else {
156        $_canvas itemconfigure $_labels($name) -state hidden
157        $_canvas itemconfigure $_ticks($name) -image $_normalIcon
158        $_canvas itemconfigure title -state normal
159    }
160}
161
162itcl::body Rappture::TransferFunctionEditor::SetVisibility { name bool } {
163    if { $bool } {
164        $_canvas itemconfigure $_ticks($name) -state normal
165        $_canvas raise $_ticks($name)
166    } else {
167        $_canvas itemconfigure $_ticks($name) -state hidden
168    }
169}
170
171itcl::body Rappture::TransferFunctionEditor::GetScreenPosition { name } {
172    set x [GetRelativeValue $name]
173    if { $x < 0.0 } {
174        set x 0.0
175    } elseif { $x > 1.0 } {
176        set x 1.0
177    }
178    set low 10
179    set w [winfo width $_canvas]
180    set high [expr {$w  - 10}]
181    set x [expr {round($x*($high - $low) + $low)}]
182    return $x
183}
184
185itcl::body Rappture::TransferFunctionEditor::SetScreenPosition { name } {
186    set value $_values($name)
187    set x [GetScreenPosition $name]
188    set absval [GetAbsoluteValue $name]
189    set y 31
190    $_canvas itemconfigure $_labels($name) -text [format %.2g $absval]
191    $_canvas coords $_ticks($name) $x [expr {$y+3}]
192    $_canvas coords $_labels($name) $x [expr {$y+5}]
193}
194
195itcl::body Rappture::TransferFunctionEditor::GetAbsoluteValue { name } {
196    foreach {min max} $_limits break
197    return [expr {($_values($name) * ($max - $min)) + $min}]
198}
199
200itcl::body Rappture::TransferFunctionEditor::SetAbsoluteValue { name value } {
201    foreach {min max} $_limits break
202    set absval $value
203    set relval [expr {($absval - $min) / ($max - $min)}]
204    set _values($name) $relval
205    set y 31
206    $_canvas itemconfigure $_label -text [format %.2g $absval]
207    set x [GetScreenPosition $name]
208    $_canvas coords $_ticks($name) $x [expr {$y+3}]
209    $_canvas coords $_labels($name) $x [expr {$y+5}]
210    return $absval
211}
212
213itcl::body Rappture::TransferFunctionEditor::GetRelativeValue  { name } {
214    return $_values($name)
215}
216
217itcl::body Rappture::TransferFunctionEditor::SetRelativeValue  { name value } {
218    set _values($name) $value
219    set x [GetScreenPosition $name]
220    set y 31
221    set absval [GetAbsoluteValue $name]
222    $_canvas itemconfigure $_labels($name) -text [format %.2g $absval]
223    $_canvas coords $_ticks($name) $x [expr {$y+3}]
224    $_canvas coords $_labels($name) $x [expr {$y+5}]
225}
226
227itcl::body Rappture::TransferFunctionEditor::EnterTick { name } {
228    set _activeMotion 1
229    Activate $name
230    $_canvas raise $_ticks($name)
231}
232
233itcl::body Rappture::TransferFunctionEditor::LeaveTick { name } {
234    set _activeMotion 0
235    Deactivate $name
236}
237
238itcl::body Rappture::TransferFunctionEditor::StartDrag { name x y } {
239    $_canvas raise $_ticks($name)
240    set _activePress 1
241    Activate $name
242    $_canvas itemconfigure limits -state hidden
243    $_canvas itemconfigure title -state hidden
244}
245
246itcl::body Rappture::TransferFunctionEditor::StopDrag { name x y } {
247    ContinueDrag $name $x $y
248    RemoveDuplicateMarkers $name $x $y
249    set _activePress 0
250    Deactivate $name
251    $_canvas itemconfigure limits -state normal
252    $_canvas itemconfigure title -state normal
253}
254
255itcl::body Rappture::TransferFunctionEditor::ContinueDrag { name x y } {
256    set w [winfo width $_canvas]
257    SetRelativeValue $name [expr {double($x-10)/($w-20)}]
258    UpdateViewer
259    $_canvas raise $_ticks($name)
260    set _activePress 1
261    Activate $name
262    $_canvas itemconfigure limits -state hidden
263    $_canvas itemconfigure title -state hidden
264}
265
266itcl::body Rappture::TransferFunctionEditor::GetOverlappingMarkers { x y } {
267    set list {}
268    foreach id [$_canvas find overlapping $x $y $x $y] {
269        if { [info exists _id2name($id)] } {
270            lappend list $_id2name($id)
271        }
272    }
273    return $list
274}
275
276itcl::body Rappture::TransferFunctionEditor::hideMarkers { {list {}} } {
277    if { $list == "" } {
278        set list [array names _values]
279    }
280    foreach name $list {
281        SetVisibility $name 0
282    }
283}
284
285itcl::body Rappture::TransferFunctionEditor::showMarkers { {limits {}} } {
286    if { $limits != "" } {
287        set _limits $limits
288        foreach name [array names _values] {
289            SetScreenPosition $name
290        }
291    }
292    foreach name [array names _values] {
293        SetVisibility $name 1
294    }
295}
296
297itcl::body Rappture::TransferFunctionEditor::RemoveDuplicateMarkers {name x y} {
298    foreach marker [GetOverlappingMarkers $x $y] {
299        if { $marker != $name } {
300            Activate $marker
301            set markerx [GetScreenPosition $marker]
302            if { ($x < ($markerx-3)) || ($x > ($markerx+3)) } {
303                continue
304            }
305            $_canvas delete $_ticks($marker)
306            $_canvas delete $_labels($marker)
307            array unset _ticks $marker
308            array unset _labels $marker
309            array unset _values $marker
310            bell
311        }
312    }
313}
314
315itcl::body Rappture::TransferFunctionEditor::addMarkers { values } {
316    foreach value $values {
317        set name [NewMarker 0 0 hidden]
318        SetRelativeValue $name $value
319    }
320}
321
322itcl::body Rappture::TransferFunctionEditor::removeMarkers { names } {
323    if { $names == "" } {
324        set names [array names _values]
325    }
326    foreach name $names {
327        $_canvas delete $_ticks($name)
328        $_canvas delete $_labels($name)
329        array unset _ticks $name
330        array unset _labels $name
331        array unset _values $name
332    }
333    UpdateViewer
334}
335
336itcl::body Rappture::TransferFunctionEditor::UpdateViewer {} {
337    # Tell the nanovis/flowvis client to update its transfer functions
338    # now that a marker position has changed.
339    if { $command != "" } {
340        eval uplevel \#0 $command
341    }
342}
Note: See TracBrowser for help on using the repository browser.