source: branches/blt4_trunk/gui/scripts/transferfunctioneditor.tcl @ 6351

Last change on this file since 6351 was 6351, checked in by dkearney, 8 years ago

merging r6288 through r6350 from trunk to blt4trunk branch

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