source: trunk/gui/scripts/vtkstreamlinesviewer.tcl @ 2623

Last change on this file since 2623 was 2623, checked in by gah, 13 years ago

bug in delete method, don't touch dataobj

File size: 84.8 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: vtkviewer - Vtk drawing object viewer
4#
5#  It connects to the Vtk server running on a rendering farm,
6#  transmits data, and displays the results.
7# ======================================================================
8#  AUTHOR:  Michael McLennan, Purdue University
9#  Copyright (c) 2004-2005  Purdue Research Foundation
10#
11#  See the file "license.terms" for information on usage and
12#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13# ======================================================================
14package require Itk
15package require BLT
16#package require Img
17package require vtk
18
19option add *VtkStreamlinesViewer.width 4i widgetDefault
20option add *VtkStreamlinesViewer*cursor crosshair widgetDefault
21option add *VtkStreamlinesViewer.height 4i widgetDefault
22option add *VtkStreamlinesViewer.foreground black widgetDefault
23option add *VtkStreamlinesViewer.controlBackground gray widgetDefault
24option add *VtkStreamlinesViewer.controlDarkBackground #999999 widgetDefault
25option add *VtkStreamlinesViewer.plotBackground black widgetDefault
26option add *VtkStreamlinesViewer.plotForeground white widgetDefault
27option add *VtkStreamlinesViewer.font \
28    -*-helvetica-medium-r-normal-*-12-* widgetDefault
29
30# must use this name -- plugs into Rappture::resources::load
31proc VtkStreamlinesViewer_init_resources {} {
32    Rappture::resources::register \
33        vtkvis_server Rappture::VtkStreamlinesViewer::SetServerList
34}
35
36itcl::class Rappture::VtkStreamlinesViewer {
37    inherit Rappture::VisViewer
38
39    itk_option define -plotforeground plotForeground Foreground ""
40    itk_option define -plotbackground plotBackground Background ""
41
42    constructor { hostlist args } {
43        Rappture::VisViewer::constructor $hostlist
44    } {
45        # defined below
46    }
47    destructor {
48        # defined below
49    }
50    public proc SetServerList { namelist } {
51        Rappture::VisViewer::SetServerList "vtkvis" $namelist
52    }
53    public method add {dataobj {settings ""}}
54    public method camera {option args}
55    public method delete {args}
56    public method disconnect {}
57    public method download {option args}
58    public method get {args}
59    public method isconnected {}
60    public method limits { colormap }
61    public method sendto { string }
62    public method parameters {title args} {
63        # do nothing
64    }
65    public method scale {args}
66
67    protected method Connect {}
68    protected method CurrentDatasets {args}
69    protected method Disconnect {}
70    protected method DoResize {}
71    protected method DoReseed {}
72    protected method DoRotate {}
73    protected method AdjustSetting {what {value ""}}
74    protected method InitSettings { args  }
75    protected method Pan {option x y}
76    protected method Pick {x y}
77    protected method Rebuild {}
78    protected method ReceiveDataset { args }
79    protected method ReceiveImage { args }
80    protected method ReceiveLegend { colormap title vmin vmax size }
81    protected method Rotate {option x y}
82    protected method SendCmd {string}
83    protected method Zoom {option}
84
85    # The following methods are only used by this class.
86    private method BuildAxisTab {}
87    private method BuildCameraTab {}
88    private method BuildColormap { name colors }
89    private method BuildCutplaneTab {}
90    private method BuildDownloadPopup { widget command }
91    private method BuildStreamsTab {}
92    private method BuildVolumeTab {}
93    private method ConvertToVtkData { dataobj comp }
94    private method DrawLegend { title }
95    private method EnterLegend { x y }
96    private method EventuallyResize { w h }
97    private method EventuallyReseed { numPoints }
98    private method EventuallyRotate { q }
99    private method EventuallySetCutplane { axis args }
100    private method GetImage { args }
101    private method GetVtkData { args }
102    private method IsValidObject { dataobj }
103    private method LeaveLegend {}
104    private method MotionLegend { x y }
105    private method PanCamera {}
106    private method RequestLegend {}
107    private method SetColormap { dataobj comp }
108    private method ChangeColormap { dataobj comp color }
109    private method ColorsToColormap { color }
110    private method SetLegendTip { x y }
111    private method SetObjectStyle { dataobj comp }
112    private method Slice {option args}
113
114    private variable _arcball ""
115    private variable _outbuf       ;    # buffer for outgoing commands
116
117    private variable _dlist ""     ;    # list of data objects
118    private variable _obj2datasets
119    private variable _obj2ovride   ;    # maps dataobj => style override
120    private variable _datasets     ;    # contains all the dataobj-component
121                                   ;    # datasets in the server
122    private variable _colormaps    ;    # contains all the colormaps
123                                   ;    # in the server.
124    private variable _dataset2style    ;# maps dataobj-component to transfunc
125
126    private variable _click        ;    # info used for rotate operations
127    private variable _limits       ;    # autoscale min/max for all axes
128    private variable _view         ;    # view params for 3D view
129    private variable _settings
130    private variable _style;            # Array of current component styles.
131    private variable _initialStyle;     # Array of initial component styles.
132    private variable _reset 1;          # indicates if camera needs to be reset
133                                        # to starting position.
134
135    private variable _first ""     ;    # This is the topmost dataset.
136    private variable _start 0
137    private variable _buffering 0
138    private variable _title ""
139    private variable _seeds
140
141    common _downloadPopup;              # download options from popup
142    private common _hardcopy
143    private variable _width 0
144    private variable _height 0
145    private variable _resizePending 0
146    private variable _reseedPending 0
147    private variable _rotatePending 0
148    private variable _cutplanePending 0
149    private variable _outline
150    private variable _vectorFields
151    private variable _scalarFields
152    private variable _fields
153    private variable _currentField ""
154    private variable _numSeeds 200
155    private variable _colorMode "vmag";#  Mode of colormap (vmag or scalar)
156}
157
158itk::usual VtkStreamlinesViewer {
159    keep -background -foreground -cursor -font
160    keep -plotbackground -plotforeground
161}
162
163# ----------------------------------------------------------------------
164# CONSTRUCTOR
165# ----------------------------------------------------------------------
166itcl::body Rappture::VtkStreamlinesViewer::constructor {hostlist args} {
167    # Rebuild event
168    $_dispatcher register !rebuild
169    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
170
171    # Resize event
172    $_dispatcher register !resize
173    $_dispatcher dispatch $this !resize "[itcl::code $this DoResize]; list"
174
175    # Reseed event
176    $_dispatcher register !reseed
177    $_dispatcher dispatch $this !reseed "[itcl::code $this DoReseed]; list"
178
179    # Rotate event
180    $_dispatcher register !rotate
181    $_dispatcher dispatch $this !rotate "[itcl::code $this DoRotate]; list"
182
183    # X-Cutplane event
184    $_dispatcher register !xcutplane
185    $_dispatcher dispatch $this !xcutplane \
186        "[itcl::code $this AdjustSetting cutplane-xposition]; list"
187
188    # Y-Cutplane event
189    $_dispatcher register !ycutplane
190    $_dispatcher dispatch $this !ycutplane \
191        "[itcl::code $this AdjustSetting cutplane-yposition]; list"
192
193    # Z-Cutplane event
194    $_dispatcher register !zcutplane
195    $_dispatcher dispatch $this !zcutplane \
196        "[itcl::code $this AdjustSetting cutplane-zposition]; list"
197
198    #
199    # Populate parser with commands handle incoming requests
200    #
201    $_parser alias image [itcl::code $this ReceiveImage]
202    $_parser alias dataset [itcl::code $this ReceiveDataset]
203    $_parser alias legend [itcl::code $this ReceiveLegend]
204
205    array set _outline {
206        id -1
207        afterId -1
208        x1 -1
209        y1 -1
210        x2 -1
211        y2 -1
212    }
213    # Initialize the view to some default parameters.
214    array set _view {
215        qw              1
216        qx              0
217        qy              0
218        qz              0
219        zoom            1.0
220        xpan            0
221        ypan            0
222        ortho           0
223    }
224    set _arcball [blt::arcball create 100 100]
225    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
226    $_arcball quaternion $q
227
228    set _limits(zmin) 0.0
229    set _limits(zmax) 1.0
230
231    array set _settings [subst {
232        axis-xgrid              0
233        axis-ygrid              0
234        axis-zgrid              0
235        axis-xcutplane          0
236        axis-ycutplane          0
237        axis-zcutplane          0
238        axis-xposition          0
239        axis-yposition          0
240        axis-zposition          0
241        axis-visible            1
242        axis-labels             1
243        cutplane-edges          0
244        cutplane-xvisible       0
245        cutplane-yvisible       0
246        cutplane-zvisible       0
247        cutplane-xposition      50
248        cutplane-yposition      50
249        cutplane-zposition      50
250        cutplane-visible        1
251        cutplane-wireframe      0
252        cutplane-opacity        100
253        volume-edges            0
254        volume-lighting         1
255        volume-opacity          40
256        volume-visible          1
257        volume-wireframe        0
258        streamlines-seeds       0
259        streamlines-visible     1
260        streamlines-opacity     100
261        streamlines-numpoints   200
262        streamlines-lighting    1
263        streamlines-scale       1
264        legend-visible          1
265    }]
266
267    itk_component add view {
268        canvas $itk_component(plotarea).view \
269            -highlightthickness 0 -borderwidth 0
270    } {
271        usual
272        ignore -highlightthickness -borderwidth  -background
273    }
274
275    set c $itk_component(view)
276    bind $c <Configure> [itcl::code $this EventuallyResize %w %h]
277    bind $c <4> [itcl::code $this Zoom in 0.25]
278    bind $c <5> [itcl::code $this Zoom out 0.25]
279    bind $c <KeyPress-Left>  [list %W xview scroll 10 units]
280    bind $c <KeyPress-Right> [list %W xview scroll -10 units]
281    bind $c <KeyPress-Up>    [list %W yview scroll 10 units]
282    bind $c <KeyPress-Down>  [list %W yview scroll -10 units]
283    bind $c <Enter> "focus %W"
284
285    # Fix the scrollregion in case we go off screen
286    $c configure -scrollregion [$c bbox all]
287
288    set _map(id) [$c create image 0 0 -anchor nw -image $_image(plot)]
289    set _map(cwidth) -1
290    set _map(cheight) -1
291    set _map(zoom) 1.0
292    set _map(original) ""
293
294    set f [$itk_component(main) component controls]
295    itk_component add reset {
296        button $f.reset -borderwidth 1 -padx 1 -pady 1 \
297            -highlightthickness 0 \
298            -image [Rappture::icon reset-view] \
299            -command [itcl::code $this Zoom reset]
300    } {
301        usual
302        ignore -highlightthickness
303    }
304    pack $itk_component(reset) -side top -padx 2 -pady 2
305    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
306
307    itk_component add zoomin {
308        button $f.zin -borderwidth 1 -padx 1 -pady 1 \
309            -highlightthickness 0 \
310            -image [Rappture::icon zoom-in] \
311            -command [itcl::code $this Zoom in]
312    } {
313        usual
314        ignore -highlightthickness
315    }
316    pack $itk_component(zoomin) -side top -padx 2 -pady 2
317    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
318
319    itk_component add zoomout {
320        button $f.zout -borderwidth 1 -padx 1 -pady 1 \
321            -highlightthickness 0 \
322            -image [Rappture::icon zoom-out] \
323            -command [itcl::code $this Zoom out]
324    } {
325        usual
326        ignore -highlightthickness
327    }
328    pack $itk_component(zoomout) -side top -padx 2 -pady 2
329    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
330
331    itk_component add volume {
332        Rappture::PushButton $f.volume \
333            -onimage [Rappture::icon volume-on] \
334            -offimage [Rappture::icon volume-off] \
335            -variable [itcl::scope _settings(volume-visible)] \
336            -command [itcl::code $this AdjustSetting volume-visible]
337    }
338    $itk_component(volume) select
339    Rappture::Tooltip::for $itk_component(volume) \
340        "Don't display the volume"
341    pack $itk_component(volume) -padx 2 -pady 2
342
343    itk_component add streamlines {
344        Rappture::PushButton $f.streamlines \
345            -onimage [Rappture::icon streamlines-on] \
346            -offimage [Rappture::icon streamlines-off] \
347            -variable [itcl::scope _settings(streamlines-visible)] \
348            -command [itcl::code $this AdjustSetting streamlines-visible] \
349    }
350    $itk_component(streamlines) select
351    Rappture::Tooltip::for $itk_component(streamlines) \
352        "Toggle the streamlines on/off"
353    pack $itk_component(streamlines) -padx 2 -pady 2
354
355    itk_component add cutplane {
356        Rappture::PushButton $f.cutplane \
357            -onimage [Rappture::icon cutbutton] \
358            -offimage [Rappture::icon cutbutton] \
359            -variable [itcl::scope _settings(cutplane-visible)] \
360            -command [itcl::code $this AdjustSetting cutplane-visible]
361    }
362    $itk_component(cutplane) select
363    Rappture::Tooltip::for $itk_component(cutplane) \
364        "Show/Hide cutplanes"
365    pack $itk_component(cutplane) -padx 2 -pady 2
366
367
368    if { [catch {
369        BuildVolumeTab
370        BuildStreamsTab
371        BuildCutplaneTab
372        BuildAxisTab
373        BuildCameraTab
374    } errs] != 0 } {
375        puts stderr errs=$errs
376    }
377    # Legend
378
379    set _image(legend) [image create photo]
380    itk_component add legend {
381        canvas $itk_component(plotarea).legend -width 50 -highlightthickness 0
382    } {
383        usual
384        ignore -highlightthickness
385        rename -background -plotbackground plotBackground Background
386    }
387
388    # Hack around the Tk panewindow.  The problem is that the requested
389    # size of the 3d view isn't set until an image is retrieved from
390    # the server.  So the panewindow uses the tiny size.
391    set w 10000
392    pack forget $itk_component(view)
393    blt::table $itk_component(plotarea) \
394        0,0 $itk_component(view) -fill both -reqwidth $w
395    blt::table configure $itk_component(plotarea) c1 -resize none
396
397    # Bindings for rotation via mouse
398    bind $itk_component(view) <ButtonPress-1> \
399        [itcl::code $this Rotate click %x %y]
400    bind $itk_component(view) <B1-Motion> \
401        [itcl::code $this Rotate drag %x %y]
402    bind $itk_component(view) <ButtonRelease-1> \
403        [itcl::code $this Rotate release %x %y]
404    bind $itk_component(view) <Configure> \
405        [itcl::code $this EventuallyResize %w %h]
406
407    if 0 {
408    bind $itk_component(view) <Configure> \
409        [itcl::code $this EventuallyResize %w %h]
410    }
411    # Bindings for panning via mouse
412    bind $itk_component(view) <ButtonPress-2> \
413        [itcl::code $this Pan click %x %y]
414    bind $itk_component(view) <B2-Motion> \
415        [itcl::code $this Pan drag %x %y]
416    bind $itk_component(view) <ButtonRelease-2> \
417        [itcl::code $this Pan release %x %y]
418
419    bind $itk_component(view) <ButtonRelease-3> \
420        [itcl::code $this Pick %x %y]
421
422    # Bindings for panning via keyboard
423    bind $itk_component(view) <KeyPress-Left> \
424        [itcl::code $this Pan set -10 0]
425    bind $itk_component(view) <KeyPress-Right> \
426        [itcl::code $this Pan set 10 0]
427    bind $itk_component(view) <KeyPress-Up> \
428        [itcl::code $this Pan set 0 -10]
429    bind $itk_component(view) <KeyPress-Down> \
430        [itcl::code $this Pan set 0 10]
431    bind $itk_component(view) <Shift-KeyPress-Left> \
432        [itcl::code $this Pan set -2 0]
433    bind $itk_component(view) <Shift-KeyPress-Right> \
434        [itcl::code $this Pan set 2 0]
435    bind $itk_component(view) <Shift-KeyPress-Up> \
436        [itcl::code $this Pan set 0 -2]
437    bind $itk_component(view) <Shift-KeyPress-Down> \
438        [itcl::code $this Pan set 0 2]
439
440    # Bindings for zoom via keyboard
441    bind $itk_component(view) <KeyPress-Prior> \
442        [itcl::code $this Zoom out]
443    bind $itk_component(view) <KeyPress-Next> \
444        [itcl::code $this Zoom in]
445
446    bind $itk_component(view) <Enter> "focus $itk_component(view)"
447
448    if {[string equal "x11" [tk windowingsystem]]} {
449        # Bindings for zoom via mouse
450        bind $itk_component(view) <4> [itcl::code $this Zoom out]
451        bind $itk_component(view) <5> [itcl::code $this Zoom in]
452    }
453
454    set _image(download) [image create photo]
455
456    eval itk_initialize $args
457    Connect
458    update
459}
460
461# ----------------------------------------------------------------------
462# DESTRUCTOR
463# ----------------------------------------------------------------------
464itcl::body Rappture::VtkStreamlinesViewer::destructor {} {
465    Disconnect
466    $_dispatcher cancel !rebuild
467    $_dispatcher cancel !resize
468    $_dispatcher cancel !reseed
469    $_dispatcher cancel !rotate
470    $_dispatcher cancel !xcutplane
471    $_dispatcher cancel !ycutplane
472    $_dispatcher cancel !zcutplane
473    image delete $_image(plot)
474    image delete $_image(download)
475    catch { blt::arcball destroy $_arcball }
476}
477
478itcl::body Rappture::VtkStreamlinesViewer::DoResize {} {
479    if { $_width < 2 } {
480        set _width 500
481    }
482    if { $_height < 2 } {
483        set _height 500
484    }
485    set _start [clock clicks -milliseconds]
486    SendCmd "screen size $_width $_height"
487    RequestLegend
488
489    #SendCmd "imgflush"
490
491    # Must reset camera to have object scaling to take effect.
492    #SendCmd "camera reset"
493    #SendCmd "camera zoom $_view(zoom)"
494    set _resizePending 0
495}
496
497itcl::body Rappture::VtkStreamlinesViewer::DoRotate {} {
498    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
499    SendCmd "camera orient $q"
500    set _rotatePending 0
501}
502
503itcl::body Rappture::VtkStreamlinesViewer::DoReseed {} {
504    foreach dataset [CurrentDatasets -visible] {
505        foreach {dataobj comp} [split $dataset -] break
506        # This command works for either random or fmesh seeds
507        SendCmd "streamlines seed numpts $_numSeeds $dataset"
508    }
509    set _reseedPending 0
510}
511
512itcl::body Rappture::VtkStreamlinesViewer::EventuallyResize { w h } {
513    set _width $w
514    set _height $h
515    $_arcball resize $w $h
516    if { !$_resizePending } {
517        set _resizePending 1
518        $_dispatcher event -after 400 !resize
519    }
520}
521
522itcl::body Rappture::VtkStreamlinesViewer::EventuallyReseed { numPoints } {
523    set _numSeeds $numPoints
524    if { !$_reseedPending } {
525        set _reseedPending 1
526        $_dispatcher event -after 600 !reseed
527    }
528}
529
530set rotate_delay 100
531
532itcl::body Rappture::VtkStreamlinesViewer::EventuallyRotate { q } {
533    foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
534    if { !$_rotatePending } {
535        set _rotatePending 1
536        global rotate_delay
537        $_dispatcher event -after $rotate_delay !rotate
538    }
539}
540
541itcl::body Rappture::VtkStreamlinesViewer::EventuallySetCutplane { axis args } {
542    if { !$_cutplanePending } {
543        set _cutplanePending 1
544        $_dispatcher event -after 100 !${axis}cutplane
545    }
546}
547
548# ----------------------------------------------------------------------
549# USAGE: add <dataobj> ?<settings>?
550#
551# Clients use this to add a data object to the plot.  The optional
552# <settings> are used to configure the plot.  Allowed settings are
553# -color, -brightness, -width, -linestyle, and -raise.
554# ----------------------------------------------------------------------
555itcl::body Rappture::VtkStreamlinesViewer::add {dataobj {settings ""}} {
556    array set params {
557        -color auto
558        -width 1
559        -linestyle solid
560        -brightness 0
561        -raise 0
562        -description ""
563        -param ""
564        -type ""
565    }
566    array set params $settings
567    set params(-description) ""
568    set params(-param) ""
569    foreach {opt val} $settings {
570        if {![info exists params($opt)]} {
571            error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
572        }
573        set params($opt) $val
574    }
575    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
576        # can't handle -autocolors yet
577        set params(-color) black
578    }
579    set pos [lsearch -exact $dataobj $_dlist]
580    if {$pos < 0} {
581        lappend _dlist $dataobj
582    }
583    set _obj2ovride($dataobj-color) $params(-color)
584    set _obj2ovride($dataobj-width) $params(-width)
585    set _obj2ovride($dataobj-raise) $params(-raise)
586    $_dispatcher event -idle !rebuild
587}
588
589
590# ----------------------------------------------------------------------
591# USAGE: delete ?<dataobj1> <dataobj2> ...?
592#
593#       Clients use this to delete a dataobj from the plot.  If no dataobjs
594#       are specified, then all dataobjs are deleted.  No data objects are
595#       deleted.  They are only removed from the display list.
596#
597# ----------------------------------------------------------------------
598itcl::body Rappture::VtkStreamlinesViewer::delete {args} {
599    if { [llength $args] == 0} {
600        set args $_dlist
601    }
602    # Delete all specified dataobjs
603    set changed 0
604    foreach dataobj $args {
605        set pos [lsearch -exact $_dlist $dataobj]
606        if { $pos < 0 } {
607            continue;                   # Don't know anything about it.
608        }
609        # Remove it from the dataobj list.
610        set _dlist [lreplace $_dlist $pos $pos]
611        SendCmd "dataset visible 0"
612        array unset _obj2ovride $dataobj-*
613        array unset _settings $dataobj-*
614        # Append to the end of the dataobj list.
615        lappend _dlist $dataobj
616        set changed 1
617    }
618    # If anything changed, then rebuild the plot
619    if { $changed } {
620        $_dispatcher event -idle !rebuild
621    }
622}
623
624# ----------------------------------------------------------------------
625# USAGE: get ?-objects?
626# USAGE: get ?-visible?
627# USAGE: get ?-image view?
628#
629# Clients use this to query the list of objects being plotted, in
630# order from bottom to top of this result.  The optional "-image"
631# flag can also request the internal images being shown.
632# ----------------------------------------------------------------------
633itcl::body Rappture::VtkStreamlinesViewer::get {args} {
634    if {[llength $args] == 0} {
635        set args "-objects"
636    }
637
638    set op [lindex $args 0]
639    switch -- $op {
640        "-objects" {
641            # put the dataobj list in order according to -raise options
642            set dlist {}
643            foreach dataobj $_dlist {
644                if { ![IsValidObject $dataobj] } {
645                    continue
646                }
647                if {[info exists _obj2ovride($dataobj-raise)] &&
648                    $_obj2ovride($dataobj-raise)} {
649                    set dlist [linsert $dlist 0 $dataobj]
650                } else {
651                    lappend dlist $dataobj
652                }
653            }
654            return $dlist
655        }
656        "-visible" {
657            set dlist {}
658            foreach dataobj $_dlist {
659                if { ![IsValidObject $dataobj] } {
660                    continue
661                }
662                if { ![info exists _obj2ovride($dataobj-raise)] } {
663                    # No setting indicates that the object isn't visible.
664                    continue
665                }
666                # Otherwise use the -raise parameter to put the object to
667                # the front of the list.
668                if { $_obj2ovride($dataobj-raise) } {
669                    set dlist [linsert $dlist 0 $dataobj]
670                } else {
671                    lappend dlist $dataobj
672                }
673            }
674            return $dlist
675        }           
676        -image {
677            if {[llength $args] != 2} {
678                error "wrong # args: should be \"get -image view\""
679            }
680            switch -- [lindex $args end] {
681                view {
682                    return $_image(plot)
683                }
684                default {
685                    error "bad image name \"[lindex $args end]\": should be view"
686                }
687            }
688        }
689        default {
690            error "bad option \"$op\": should be -objects or -image"
691        }
692    }
693}
694
695# ----------------------------------------------------------------------
696# USAGE: scale ?<data1> <data2> ...?
697#
698# Sets the default limits for the overall plot according to the
699# limits of the data for all of the given <data> objects.  This
700# accounts for all objects--even those not showing on the screen.
701# Because of this, the limits are appropriate for all objects as
702# the user scans through data in the ResultSet viewer.
703# ----------------------------------------------------------------------
704itcl::body Rappture::VtkStreamlinesViewer::scale {args} {
705    array unset _limits
706    foreach dataobj $args {
707        set string [limits $dataobj]
708        if { $string == "" } {
709            continue
710        }
711        array set bounds $string
712        if {![info exists _limits(xmin)] || $_limits(xmin) > $bounds(xmin)} {
713            set _limits(xmin) $bounds(xmin)
714        }
715        if {![info exists _limits(xmax)] || $_limits(xmax) < $bounds(xmax)} {
716            set _limits(xmax) $bounds(xmax)
717        }
718
719        if {![info exists _limits(ymin)] || $_limits(ymin) > $bounds(ymin)} {
720            set _limits(ymin) $bounds(ymin)
721        }
722        if {![info exists _limits(ymax)] || $_limits(ymax) < $bounds(ymax)} {
723            set _limits(ymax) $bounds(ymax)
724        }
725
726        if {![info exists _limits(zmin)] || $_limits(zmin) > $bounds(zmin)} {
727            set _limits(zmin) $bounds(zmin)
728        }
729        if {![info exists _limits(zmax)] || $_limits(zmax) < $bounds(zmax)} {
730            set _limits(zmax) $bounds(zmax)
731        }
732    }
733}
734
735# ----------------------------------------------------------------------
736# USAGE: download coming
737# USAGE: download controls <downloadCommand>
738# USAGE: download now
739#
740# Clients use this method to create a downloadable representation
741# of the plot.  Returns a list of the form {ext string}, where
742# "ext" is the file extension (indicating the type of data) and
743# "string" is the data itself.
744# ----------------------------------------------------------------------
745itcl::body Rappture::VtkStreamlinesViewer::download {option args} {
746    switch $option {
747        coming {
748            if {[catch {
749                blt::winop snap $itk_component(plotarea) $_image(download)
750            }]} {
751                $_image(download) configure -width 1 -height 1
752                $_image(download) put #000000
753            }
754        }
755        controls {
756            set popup .vtkviewerdownload
757            if { ![winfo exists .vtkviewerdownload] } {
758                set inner [BuildDownloadPopup $popup [lindex $args 0]]
759            } else {
760                set inner [$popup component inner]
761            }
762            set _downloadPopup(image_controls) $inner.image_frame
763            set num [llength [get]]
764            set num [expr {($num == 1) ? "1 result" : "$num results"}]
765            set word [Rappture::filexfer::label downloadWord]
766            $inner.summary configure -text "$word $num in the following format:"
767            update idletasks            ;# Fix initial sizes
768            return $popup
769        }
770        now {
771            set popup .vtkviewerdownload
772            if {[winfo exists .vtkviewerdownload]} {
773                $popup deactivate
774            }
775            switch -- $_downloadPopup(format) {
776                "image" {
777                    return [$this GetImage [lindex $args 0]]
778                }
779                "vtk" {
780                    return [$this GetVtkData [lindex $args 0]]
781                }
782            }
783            return ""
784        }
785        default {
786            error "bad option \"$option\": should be coming, controls, now"
787        }
788    }
789}
790
791# ----------------------------------------------------------------------
792# USAGE: Connect ?<host:port>,<host:port>...?
793#
794# Clients use this method to establish a connection to a new
795# server, or to reestablish a connection to the previous server.
796# Any existing connection is automatically closed.
797# ----------------------------------------------------------------------
798itcl::body Rappture::VtkStreamlinesViewer::Connect {} {
799    set _hosts [GetServerList "vtkvis"]
800    if { "" == $_hosts } {
801        return 0
802    }
803    set result [VisViewer::Connect $_hosts]
804    if { $result } {
805        set w [winfo width $itk_component(view)]
806        set h [winfo height $itk_component(view)]
807        EventuallyResize $w $h
808    }
809    return $result
810}
811
812#
813# isconnected --
814#
815#       Indicates if we are currently connected to the visualization server.
816#
817itcl::body Rappture::VtkStreamlinesViewer::isconnected {} {
818    return [VisViewer::IsConnected]
819}
820
821#
822# disconnect --
823#
824itcl::body Rappture::VtkStreamlinesViewer::disconnect {} {
825    Disconnect
826    set _reset 1
827}
828
829#
830# Disconnect --
831#
832#       Clients use this method to disconnect from the current rendering
833#       server.
834#
835itcl::body Rappture::VtkStreamlinesViewer::Disconnect {} {
836    VisViewer::Disconnect
837
838    # disconnected -- no more data sitting on server
839    set _outbuf ""
840    array unset _datasets
841    array unset _data
842    array unset _colormaps
843    array unset _seeds
844    array unset _dataset2style
845    array unset _obj2datasets
846}
847
848#
849# sendto --
850#
851itcl::body Rappture::VtkStreamlinesViewer::sendto { bytes } {
852    SendBytes "$bytes\n"
853}
854
855#
856# SendCmd
857#
858#       Send commands off to the rendering server.  If we're currently
859#       sending data objects to the server, buffer the commands to be
860#       sent later.
861#
862itcl::body Rappture::VtkStreamlinesViewer::SendCmd {string} {
863    if { $_buffering } {
864        append _outbuf $string "\n"
865    } else {
866        SendBytes "$string\n"
867    }
868}
869
870# ----------------------------------------------------------------------
871# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
872#
873# Invoked automatically whenever the "image" command comes in from
874# the rendering server.  Indicates that binary image data with the
875# specified <size> will follow.
876# ----------------------------------------------------------------------
877itcl::body Rappture::VtkStreamlinesViewer::ReceiveImage { args } {
878    array set info {
879        -token "???"
880        -bytes 0
881        -type image
882    }
883    array set info $args
884    set bytes [ReceiveBytes $info(-bytes)]
885    if { $info(-type) == "image" } {
886        if 0 {
887            set f [open "last.ppm" "w"]
888            puts $f $bytes
889            close $f
890        }
891        $_image(plot) configure -data $bytes
892        set time [clock seconds]
893        set date [clock format $time]
894        #puts stderr "$date: received image [image width $_image(plot)]x[image height $_image(plot)] image>"       
895        if { $_start > 0 } {
896            set finish [clock clicks -milliseconds]
897            #puts stderr "round trip time [expr $finish -$_start] milliseconds"
898            set _start 0
899        }
900    } elseif { $info(type) == "print" } {
901        set tag $this-print-$info(-token)
902        set _hardcopy($tag) $bytes
903    }
904}
905
906#
907# ReceiveDataset --
908#
909itcl::body Rappture::VtkStreamlinesViewer::ReceiveDataset { args } {
910    if { ![isconnected] } {
911        return
912    }
913    set option [lindex $args 0]
914    switch -- $option {
915        "scalar" {
916            set option [lindex $args 1]
917            switch -- $option {
918                "world" {
919                    foreach { x y z value tag } [lrange $args 2 end] break
920                }
921                "pixel" {
922                    foreach { x y value tag } [lrange $args 2 end] break
923                }
924            }
925        }
926        "vector" {
927            set option [lindex $args 1]
928            switch -- $option {
929                "world" {
930                    foreach { x y z vx vy vz tag } [lrange $args 2 end] break
931                }
932                "pixel" {
933                    foreach { x y vx vy vz tag } [lrange $args 2 end] break
934                }
935            }
936        }
937        "names" {
938            foreach { name } [lindex $args 1] {
939                #puts stderr "Dataset: $name"
940            }
941        }
942        default {
943            error "unknown dataset option \"$option\" from server"
944        }
945    }
946}
947
948# ----------------------------------------------------------------------
949# USAGE: Rebuild
950#
951# Called automatically whenever something changes that affects the
952# data in the widget.  Clears any existing data and rebuilds the
953# widget to display new data.
954# ----------------------------------------------------------------------
955itcl::body Rappture::VtkStreamlinesViewer::Rebuild {} {
956    update
957    set w [winfo width $itk_component(view)]
958    set h [winfo height $itk_component(view)]
959    if { $w < 2 || $h < 2 } {
960        $_dispatcher event -idle !rebuild
961        return
962    }
963
964    # Turn on buffering of commands to the server.  We don't want to
965    # be preempted by a server disconnect/reconnect (which automatically
966    # generates a new call to Rebuild).   
967    set _buffering 1
968
969    set _width $w
970    set _height $h
971    $_arcball resize $w $h
972    DoResize
973    #
974    # Reset the camera and other view parameters
975    #
976    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
977    $_arcball quaternion $q
978    if {$_view(ortho)} {
979        SendCmd "camera mode ortho"
980    } else {
981        SendCmd "camera mode persp"
982    }
983    DoRotate
984    PanCamera
985    set _first ""
986    InitSettings axis-xgrid axis-ygrid axis-zgrid axis-mode \
987        axis-visible axis-labels cutplane-visible \
988        cutplane-xposition cutplane-yposition cutplane-zposition \
989        cutplane-xvisible cutplane-yvisible cutplane-zvisible
990
991    SendCmd "imgflush"
992
993    set _limits(zmin) ""
994    set _limits(zmax) ""
995    set _first ""
996    foreach dataobj [get -objects] {
997        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
998            set _first $dataobj
999        }
1000        set _obj2datasets($dataobj) ""
1001        foreach comp [$dataobj components] {
1002            set tag $dataobj-$comp
1003            if { ![info exists _datasets($tag)] } {
1004                set bytes [$dataobj blob $comp]
1005                set length [string length $bytes]
1006                append _outbuf "dataset add $tag data follows $length\n"
1007                append _outbuf $bytes
1008                set _datasets($tag) 1
1009                SetObjectStyle $dataobj $comp
1010            }
1011            lappend _obj2datasets($dataobj) $tag
1012            if { [info exists _obj2ovride($dataobj-raise)] } {
1013                SendCmd "dataset visible 1 $tag"
1014            } else {
1015                SendCmd "dataset visible 0 $tag"
1016            }
1017        }
1018    }
1019    if {"" != $_first} {
1020        set location [$_first hints camera]
1021        if { $location != "" } {
1022            array set view $location
1023        }
1024
1025        foreach axis { x y z } {
1026            set label [$_first hints ${axis}label]
1027            if { $label != "" } {
1028                SendCmd "axis name $axis $label"
1029            }
1030            set units [$_first hints ${axis}units]
1031            if { $units != "" } {
1032                SendCmd "axis units $axis $units"
1033            }
1034        }
1035        array unset _scalarFields
1036        array unset _vectorFields
1037        set _currentField [$_first hints default]
1038        $itk_component(field) choices delete 0 end
1039        array unset _fields
1040        foreach { name title units } [$_first hints vectors] {
1041            set _vectorFields($title) $name
1042            $itk_component(field) choices insert end "$name" "$title"
1043            set _fields($name) [list $title $units]
1044        }
1045        foreach { name title units } [$_first hints scalars] {
1046            set _scalarFields($title) $name
1047            $itk_component(field) choices insert end "$name" "$title"
1048            set _fields($name) [list $title $units]
1049        }
1050        $itk_component(field) value $_currentField
1051    }
1052
1053    InitSettings streamlines-visible streamlines-palette volume-visible
1054
1055    if { $_reset } {
1056        InitSettings streamlines-seeds streamlines-opacity \
1057            streamlines-numpoints streamlines-lighting \
1058            streamlines-palette streamlines-field \
1059            volume-edges volume-lighting volume-opacity volume-wireframe
1060        Zoom reset
1061        set _reset 0
1062    }
1063       
1064    set _buffering 0;                        # Turn off buffering.
1065
1066    # Actually write the commands to the server socket.  If it fails, we don't
1067    # care.  We're finished here.
1068    blt::busy hold $itk_component(hull)
1069    SendBytes $_outbuf;                       
1070    blt::busy release $itk_component(hull)
1071    set _outbuf "";                        # Clear the buffer.               
1072}
1073
1074# ----------------------------------------------------------------------
1075# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
1076#
1077# Returns a list of server IDs for the current datasets being displayed.  This
1078# is normally a single ID, but it might be a list of IDs if the current data
1079# object has multiple components.
1080# ----------------------------------------------------------------------
1081itcl::body Rappture::VtkStreamlinesViewer::CurrentDatasets {args} {
1082    set flag [lindex $args 0]
1083    switch -- $flag {
1084        "-all" {
1085            if { [llength $args] > 1 } {
1086                error "CurrentDatasets: can't specify dataobj after \"-all\""
1087            }
1088            set dlist [get -objects]
1089        }
1090        "-visible" {
1091            if { [llength $args] > 1 } {
1092                set dlist {}
1093                set args [lrange $args 1 end]
1094                foreach dataobj $args {
1095                    if { [info exists _obj2ovride($dataobj-raise)] } {
1096                        lappend dlist $dataobj
1097                    }
1098                }
1099            } else {
1100                set dlist [get -visible]
1101            }
1102        }           
1103        default {
1104            set dlist $args
1105        }
1106    }
1107    set rlist ""
1108    foreach dataobj $dlist {
1109        foreach comp [$dataobj components] {
1110            set tag $dataobj-$comp
1111            if { [info exists _datasets($tag)] && $_datasets($tag) } {
1112                lappend rlist $tag
1113            }
1114        }
1115    }
1116    return $rlist
1117}
1118
1119# ----------------------------------------------------------------------
1120# USAGE: Zoom in
1121# USAGE: Zoom out
1122# USAGE: Zoom reset
1123#
1124# Called automatically when the user clicks on one of the zoom
1125# controls for this widget.  Changes the zoom for the current view.
1126# ----------------------------------------------------------------------
1127itcl::body Rappture::VtkStreamlinesViewer::Zoom {option} {
1128    switch -- $option {
1129        "in" {
1130            set _view(zoom) [expr {$_view(zoom)*1.25}]
1131            SendCmd "camera zoom $_view(zoom)"
1132        }
1133        "out" {
1134            set _view(zoom) [expr {$_view(zoom)*0.8}]
1135            SendCmd "camera zoom $_view(zoom)"
1136        }
1137        "reset" {
1138            array set _view {
1139                qw      1
1140                qx      0
1141                qy      0
1142                qz      0
1143                zoom    1.0
1144                xpan   0
1145                ypan   0
1146            }
1147            SendCmd "camera reset all"
1148            if { $_first != "" } {
1149                set location [$_first hints camera]
1150                if { $location != "" } {
1151                    array set _view $location
1152                }
1153            }
1154            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1155            $_arcball quaternion $q
1156            DoRotate
1157        }
1158    }
1159}
1160
1161itcl::body Rappture::VtkStreamlinesViewer::PanCamera {} {
1162    set x $_view(xpan)
1163    set y $_view(ypan)
1164    SendCmd "camera pan $x $y"
1165}
1166
1167
1168# ----------------------------------------------------------------------
1169# USAGE: Rotate click <x> <y>
1170# USAGE: Rotate drag <x> <y>
1171# USAGE: Rotate release <x> <y>
1172#
1173# Called automatically when the user clicks/drags/releases in the
1174# plot area.  Moves the plot according to the user's actions.
1175# ----------------------------------------------------------------------
1176itcl::body Rappture::VtkStreamlinesViewer::Rotate {option x y} {
1177    switch -- $option {
1178        "click" {
1179            $itk_component(view) configure -cursor fleur
1180            set _click(x) $x
1181            set _click(y) $y
1182        }
1183        "drag" {
1184            if {[array size _click] == 0} {
1185                Rotate click $x $y
1186            } else {
1187                set w [winfo width $itk_component(view)]
1188                set h [winfo height $itk_component(view)]
1189                if {$w <= 0 || $h <= 0} {
1190                    return
1191                }
1192
1193                if {[catch {
1194                    # this fails sometimes for no apparent reason
1195                    set dx [expr {double($x-$_click(x))/$w}]
1196                    set dy [expr {double($y-$_click(y))/$h}]
1197                }]} {
1198                    return
1199                }
1200                if { $dx == 0 && $dy == 0 } {
1201                    return
1202                }
1203                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1204                EventuallyRotate $q
1205                set _click(x) $x
1206                set _click(y) $y
1207            }
1208        }
1209        "release" {
1210            Rotate drag $x $y
1211            $itk_component(view) configure -cursor ""
1212            catch {unset _click}
1213        }
1214        default {
1215            error "bad option \"$option\": should be click, drag, release"
1216        }
1217    }
1218}
1219
1220itcl::body Rappture::VtkStreamlinesViewer::Pick {x y} {
1221    foreach tag [CurrentDatasets -visible] {
1222        SendCmd "dataset getscalar pixel $x $y $tag"
1223    }
1224}
1225
1226# ----------------------------------------------------------------------
1227# USAGE: $this Pan click x y
1228#        $this Pan drag x y
1229#        $this Pan release x y
1230#
1231# Called automatically when the user clicks on one of the zoom
1232# controls for this widget.  Changes the zoom for the current view.
1233# ----------------------------------------------------------------------
1234itcl::body Rappture::VtkStreamlinesViewer::Pan {option x y} {
1235    switch -- $option {
1236        "set" {
1237            set w [winfo width $itk_component(view)]
1238            set h [winfo height $itk_component(view)]
1239            set x [expr $x / double($w)]
1240            set y [expr $y / double($h)]
1241            set _view(xpan) [expr $_view(xpan) + $x]
1242            set _view(ypan) [expr $_view(ypan) + $y]
1243            PanCamera
1244            return
1245        }
1246        "click" {
1247            set _click(x) $x
1248            set _click(y) $y
1249            $itk_component(view) configure -cursor hand1
1250        }
1251        "drag" {
1252            if { ![info exists _click(x)] } {
1253                set _click(x) $x
1254            }
1255            if { ![info exists _click(y)] } {
1256                set _click(y) $y
1257            }
1258            set w [winfo width $itk_component(view)]
1259            set h [winfo height $itk_component(view)]
1260            set dx [expr ($_click(x) - $x)/double($w)]
1261            set dy [expr ($_click(y) - $y)/double($h)]
1262            set _click(x) $x
1263            set _click(y) $y
1264            set _view(xpan) [expr $_view(xpan) - $dx]
1265            set _view(ypan) [expr $_view(ypan) - $dy]
1266            PanCamera
1267        }
1268        "release" {
1269            Pan drag $x $y
1270            $itk_component(view) configure -cursor ""
1271        }
1272        default {
1273            error "unknown option \"$option\": should set, click, drag, or release"
1274        }
1275    }
1276}
1277
1278# ----------------------------------------------------------------------
1279# USAGE: InitSettings <what> ?<value>?
1280#
1281# Used internally to update rendering settings whenever parameters
1282# change in the popup settings panel.  Sends the new settings off
1283# to the back end.
1284# ----------------------------------------------------------------------
1285itcl::body Rappture::VtkStreamlinesViewer::InitSettings { args } {
1286    foreach spec $args {
1287        if { [info exists _settings($_first-$spec)] } {
1288            # Reset global setting with dataobj specific setting
1289            set _settings($spec) $_settings($_first-$spec)
1290        }
1291        AdjustSetting $spec
1292    }
1293}
1294
1295#
1296# AdjustSetting --
1297#
1298#       Changes/updates a specific setting in the widget.  There are
1299#       usually user-setable option.  Commands are sent to the render
1300#       server.
1301#
1302itcl::body Rappture::VtkStreamlinesViewer::AdjustSetting {what {value ""}} {
1303    if { ![isconnected] } {
1304        return
1305    }
1306    switch -- $what {
1307        "volume-opacity" {
1308            set val $_settings(volume-opacity)
1309            set sval [expr { 0.01 * double($val) }]
1310            foreach dataset [CurrentDatasets -visible] {
1311                SendCmd "polydata opacity $sval $dataset"
1312            }
1313        }
1314        "volume-wireframe" {
1315            set bool $_settings(volume-wireframe)
1316            foreach dataset [CurrentDatasets -visible] {
1317                SendCmd "polydata wireframe $bool $dataset"
1318            }
1319        }
1320        "volume-visible" {
1321            set bool $_settings(volume-visible)
1322            foreach dataset [CurrentDatasets -visible] {
1323                SendCmd "polydata visible $bool $dataset"
1324            }
1325            if { $bool } {
1326                Rappture::Tooltip::for $itk_component(volume) \
1327                    "Hide the volume"
1328            } else {
1329                Rappture::Tooltip::for $itk_component(volume) \
1330                    "Show the volume"
1331            }
1332        }
1333        "volume-lighting" {
1334            set bool $_settings(volume-lighting)
1335            foreach dataset [CurrentDatasets -visible] {
1336                SendCmd "polydata lighting $bool $dataset"
1337            }
1338        }
1339        "volume-edges" {
1340            set bool $_settings(volume-edges)
1341            foreach dataset [CurrentDatasets -visible] {
1342                SendCmd "polydata edges $bool $dataset"
1343            }
1344        }
1345        "axis-visible" {
1346            set bool $_settings(axis-visible)
1347            SendCmd "axis visible all $bool"
1348        }
1349        "axis-labels" {
1350            set bool $_settings(axis-labels)
1351            SendCmd "axis labels all $bool"
1352        }
1353        "axis-xgrid" - "axis-ygrid" - "axis-zgrid" {
1354            set axis [string range $what 5 5]
1355            set bool $_settings($what)
1356            SendCmd "axis grid $axis $bool"
1357        }
1358        "axis-mode" {
1359            set mode [$itk_component(axismode) value]
1360            set mode [$itk_component(axismode) translate $mode]
1361            set _settings($what) $mode
1362            SendCmd "axis flymode $mode"
1363        }
1364        "cutplane-edges" {
1365            set bool $_settings($what)
1366            foreach dataset [CurrentDatasets -visible] {
1367                SendCmd "cutplane edges $bool $dataset"
1368            }
1369        }
1370        "cutplane-visible" {
1371            set bool $_settings($what)
1372            foreach dataset [CurrentDatasets -visible] {
1373                SendCmd "cutplane visible $bool $dataset"
1374            }
1375        }
1376        "cutplane-wireframe" {
1377            set bool $_settings($what)
1378            foreach dataset [CurrentDatasets -visible] {
1379                SendCmd "cutplane wireframe $bool $dataset"
1380            }
1381        }
1382        "cutplane-lighting" {
1383            set bool $_settings($what)
1384            foreach dataset [CurrentDatasets -visible] {
1385                SendCmd "cutplane lighting $bool $dataset"
1386            }
1387        }
1388        "cutplane-opacity" {
1389            set val $_settings($what)
1390            set sval [expr { 0.01 * double($val) }]
1391            foreach dataset [CurrentDatasets -visible] {
1392                SendCmd "cutplane opacity $sval $dataset"
1393            }
1394        }
1395        "cutplane-xvisible" - "cutplane-yvisible" - "cutplane-zvisible" {
1396            set axis [string range $what 9 9]
1397            set bool $_settings($what)
1398            if { $bool } {
1399                $itk_component(${axis}CutScale) configure -state normal \
1400                    -troughcolor white
1401            } else {
1402                $itk_component(${axis}CutScale) configure -state disabled \
1403                    -troughcolor grey82
1404            }
1405            SendCmd "cutplane axis $axis $bool"
1406        }
1407        "cutplane-xposition" - "cutplane-yposition" - "cutplane-zposition" {
1408            set axis [string range $what 9 9]
1409            set pos [expr $_settings($what) * 0.01]
1410            SendCmd "cutplane slice ${axis} ${pos}"
1411            set _cutplanePending 0
1412        }
1413        "streamlines-seeds" {
1414            set bool $_settings($what)
1415            foreach dataset [CurrentDatasets -visible] {
1416                SendCmd "streamlines seed visible $bool $dataset"
1417            }
1418        }
1419        "streamlines-numpoints" {
1420            set density $_settings($what)
1421            EventuallyReseed $density
1422        }
1423        "streamlines-visible" {
1424            set bool $_settings($what)
1425            foreach dataset [CurrentDatasets -visible] {
1426                SendCmd "streamlines visible $bool $dataset"
1427            }
1428            if { $bool } {
1429                Rappture::Tooltip::for $itk_component(streamlines) \
1430                    "Hide the streamlines"
1431            } else {
1432                Rappture::Tooltip::for $itk_component(streamlines) \
1433                    "Show the streamlines"
1434            }
1435        }
1436        "streamlines-mode" {
1437            set mode [$itk_component(streammode) value]
1438            set _settings(streamlines-mode) $mode
1439            foreach dataset [CurrentDatasets -visible] {
1440                switch -- $mode {
1441                    "lines" {
1442                        SendCmd "streamlines lines $dataset"
1443                    }
1444                    "ribbons" {
1445                        SendCmd "streamlines ribbons 3 0 $dataset"
1446                    }
1447                    "tubes" {
1448                        SendCmd "streamlines tubes 5 3 $dataset"
1449                    }
1450                }
1451            }
1452        }
1453        "streamlines-palette" {
1454            set palette [$itk_component(palette) value]
1455            set _settings(streamlines-palette) $palette
1456            foreach dataset [CurrentDatasets -visible $_first] {
1457                foreach {dataobj comp} [split $dataset -] break
1458                ChangeColormap $dataobj $comp $palette
1459            }
1460            RequestLegend
1461        }
1462        "streamlines-opacity" {
1463            set val $_settings(streamlines-opacity)
1464            set sval [expr { 0.01 * double($val) }]
1465            foreach dataset [CurrentDatasets -visible $_first] {
1466                SendCmd "streamlines opacity $sval $dataset"
1467            }
1468        }
1469        "streamlines-scale" {
1470            set val $_settings(streamlines-scale)
1471            set sval [expr { 0.01 * double($val) }]
1472            foreach dataset [CurrentDatasets -visible $_first] {
1473                SendCmd "streamlines scale $sval $sval $sval $dataset"
1474            }
1475        }
1476        "streamlines-lighting" {
1477            set bool $_settings(streamlines-lighting)
1478            foreach dataset [CurrentDatasets -visible $_first] {
1479                SendCmd "streamlines lighting $bool $dataset"
1480            }
1481        }
1482        "streamlines-field" {
1483            set new [$itk_component(field) value]
1484            set value [$itk_component(field) translate $new]
1485            set _settings(streamlines-field) $value
1486            if { [info exists _scalarFields($new)] } {
1487                set name $_scalarFields($new)
1488                set _colorMode scalar
1489                set fieldType scalar
1490                set _currentField $new
1491            } elseif { [info exists _vectorFields($new)] } {
1492                set name $_vectorFields($new)
1493                set _colorMode vmag
1494                set fieldType vector
1495                set _currentField $new
1496            } else {
1497                puts stderr "unknown field \"$new\""
1498                return
1499            }
1500            foreach dataset [CurrentDatasets -visible] {
1501                SendCmd "streamlines colormode $_colorMode ${name} $dataset"
1502                SendCmd "cutplane colormode $_colorMode ${name} $dataset"
1503            }
1504            RequestLegend
1505        }
1506        default {
1507            error "don't know how to fix $what"
1508        }
1509    }
1510}
1511
1512#
1513# RequestLegend --
1514#
1515#       Request a new legend from the server.  The size of the legend
1516#       is determined from the height of the canvas.  It will be rotated
1517#       to be vertical when drawn.
1518#
1519itcl::body Rappture::VtkStreamlinesViewer::RequestLegend {} {
1520    set font "Arial 8"
1521    set lineht [font metrics $font -linespace]
1522    set c $itk_component(legend)
1523    set w 12
1524    set h [expr {$_height - 3 * ($lineht + 2)}]
1525    if { $h < 1} {
1526        return
1527    }
1528    if { [info exists _scalarFields($_currentField)] } {
1529        set name $_scalarFields($_currentField)
1530    } elseif { [info exists _vectorFields($_currentField)] } {
1531        set name $_vectorFields($_currentField)
1532    } else {
1533        return
1534    }
1535    # Set the legend on the first streamlines dataset.
1536    foreach dataset [CurrentDatasets -visible $_first] {
1537        foreach {dataobj comp} [split $dataset -] break
1538        if { [info exists _dataset2style($dataset)] } {
1539            SendCmd "legend $_dataset2style($dataset) $_colorMode $name {} $w $h 0"
1540            break;
1541        }
1542    }
1543}
1544
1545#
1546# ChangeColormap --
1547#
1548itcl::body Rappture::VtkStreamlinesViewer::ChangeColormap {dataobj comp color} {
1549    set tag $dataobj-$comp
1550    if { ![info exist _style($tag)] } {
1551        error "no initial colormap"
1552    }
1553    array set style $_style($tag)
1554    set style(-color) $color
1555    set _style($tag) [array get style]
1556    SetColormap $dataobj $comp
1557}
1558
1559#
1560# SetColormap --
1561#
1562itcl::body Rappture::VtkStreamlinesViewer::SetColormap { dataobj comp } {
1563    array set style {
1564        -color BGYOR
1565        -levels 6
1566        -opacity 1.0
1567    }
1568    set tag $dataobj-$comp
1569    if { ![info exists _initialStyle($tag)] } {
1570        # Save the initial component style.
1571        set _initialStyle($tag) [$dataobj style $comp]
1572    }
1573
1574    # Override defaults with initial style defined in xml.
1575    array set style $_initialStyle($tag)
1576
1577    if { ![info exists _style($tag)] } {
1578        set _style($tag) [array get style]
1579    }
1580    # Override initial style with current style.
1581    array set style $_style($tag)
1582
1583    set name "$style(-color):$style(-levels):$style(-opacity)"
1584    if { ![info exists _colormaps($name)] } {
1585        BuildColormap $name [array get style]
1586        set _colormaps($name) 1
1587    }
1588    if { ![info exists _dataset2style($tag)] ||
1589         $_dataset2style($tag) != $name } {
1590        SendCmd "streamlines colormap $name $tag"
1591        SendCmd "cutplane colormap $name $tag"
1592        set _dataset2style($tag) $name
1593    }
1594}
1595
1596itcl::body Rappture::VtkStreamlinesViewer::ColorsToColormap { colors } {
1597    switch -- $colors {
1598        "grey-to-blue" {
1599            return {
1600                0.0                      0.200 0.200 0.200
1601                0.14285714285714285      0.400 0.400 0.400
1602                0.2857142857142857       0.600 0.600 0.600
1603                0.42857142857142855      0.900 0.900 0.900
1604                0.5714285714285714       0.800 1.000 1.000
1605                0.7142857142857143       0.600 1.000 1.000
1606                0.8571428571428571       0.400 0.900 1.000
1607                1.0                      0.000 0.600 0.800
1608            }
1609        }
1610        "blue-to-grey" {
1611            return {
1612                0.0                     0.000 0.600 0.800
1613                0.14285714285714285     0.400 0.900 1.000
1614                0.2857142857142857      0.600 1.000 1.000
1615                0.42857142857142855     0.800 1.000 1.000
1616                0.5714285714285714      0.900 0.900 0.900
1617                0.7142857142857143      0.600 0.600 0.600
1618                0.8571428571428571      0.400 0.400 0.400
1619                1.0                     0.200 0.200 0.200
1620            }
1621        }
1622        "blue" {
1623            return {
1624                0.0                     0.900 1.000 1.000
1625                0.1111111111111111      0.800 0.983 1.000
1626                0.2222222222222222      0.700 0.950 1.000
1627                0.3333333333333333      0.600 0.900 1.000
1628                0.4444444444444444      0.500 0.833 1.000
1629                0.5555555555555556      0.400 0.750 1.000
1630                0.6666666666666666      0.300 0.650 1.000
1631                0.7777777777777778      0.200 0.533 1.000
1632                0.8888888888888888      0.100 0.400 1.000
1633                1.0                     0.000 0.250 1.000
1634            }
1635        }
1636        "brown-to-blue" {
1637            return {
1638                0.0                             0.200   0.100   0.000
1639                0.09090909090909091             0.400   0.187   0.000
1640                0.18181818181818182             0.600   0.379   0.210
1641                0.2727272727272727              0.800   0.608   0.480
1642                0.36363636363636365             0.850   0.688   0.595
1643                0.45454545454545453             0.950   0.855   0.808
1644                0.5454545454545454              0.800   0.993   1.000
1645                0.6363636363636364              0.600   0.973   1.000
1646                0.7272727272727273              0.400   0.940   1.000
1647                0.8181818181818182              0.200   0.893   1.000
1648                0.9090909090909091              0.000   0.667   0.800
1649                1.0                             0.000   0.480   0.600
1650            }
1651        }
1652        "blue-to-brown" {
1653            return {
1654                0.0                             0.000   0.480   0.600
1655                0.09090909090909091             0.000   0.667   0.800
1656                0.18181818181818182             0.200   0.893   1.000
1657                0.2727272727272727              0.400   0.940   1.000
1658                0.36363636363636365             0.600   0.973   1.000
1659                0.45454545454545453             0.800   0.993   1.000
1660                0.5454545454545454              0.950   0.855   0.808
1661                0.6363636363636364              0.850   0.688   0.595
1662                0.7272727272727273              0.800   0.608   0.480
1663                0.8181818181818182              0.600   0.379   0.210
1664                0.9090909090909091              0.400   0.187   0.000
1665                1.0                             0.200   0.100   0.000
1666            }
1667        }
1668        "blue-to-orange" {
1669            return {
1670                0.0                             0.000   0.167   1.000
1671                0.09090909090909091             0.100   0.400   1.000
1672                0.18181818181818182             0.200   0.600   1.000
1673                0.2727272727272727              0.400   0.800   1.000
1674                0.36363636363636365             0.600   0.933   1.000
1675                0.45454545454545453             0.800   1.000   1.000
1676                0.5454545454545454              1.000   1.000   0.800
1677                0.6363636363636364              1.000   0.933   0.600
1678                0.7272727272727273              1.000   0.800   0.400
1679                0.8181818181818182              1.000   0.600   0.200
1680                0.9090909090909091              1.000   0.400   0.100
1681                1.0                             1.000   0.167   0.000
1682            }
1683        }
1684        "orange-to-blue" {
1685            return {
1686                0.0                             1.000   0.167   0.000
1687                0.09090909090909091             1.000   0.400   0.100
1688                0.18181818181818182             1.000   0.600   0.200
1689                0.2727272727272727              1.000   0.800   0.400
1690                0.36363636363636365             1.000   0.933   0.600
1691                0.45454545454545453             1.000   1.000   0.800
1692                0.5454545454545454              0.800   1.000   1.000
1693                0.6363636363636364              0.600   0.933   1.000
1694                0.7272727272727273              0.400   0.800   1.000
1695                0.8181818181818182              0.200   0.600   1.000
1696                0.9090909090909091              0.100   0.400   1.000
1697                1.0                             0.000   0.167   1.000
1698            }
1699        }
1700        "rainbow" {
1701            set clist {
1702                "#EE82EE"
1703                "#4B0082"
1704                "blue"
1705                "#008000"
1706                "yellow"
1707                "#FFA500"
1708                "red"
1709            }
1710        }
1711        "BGYOR" {
1712            set clist {
1713                "blue"
1714                "#008000"
1715                "yellow"
1716                "#FFA500"
1717                "red"
1718            }
1719        }
1720        "ROYGB" {
1721            set clist {
1722                "red"
1723                "#FFA500"
1724                "yellow"
1725                "#008000"
1726                "blue"
1727            }
1728        }
1729        "RYGCB" {
1730            set clist {
1731                "red"
1732                "yellow"
1733                "green"
1734                "cyan"
1735                "blue"
1736            }
1737        }
1738        "BCGYR" {
1739            set clist {
1740                "blue"
1741                "cyan"
1742                "green"
1743                "yellow"
1744                "red"
1745            }
1746        }
1747        "spectral" {
1748            return {
1749                0.0 0.150 0.300 1.000
1750                0.1 0.250 0.630 1.000
1751                0.2 0.450 0.850 1.000
1752                0.3 0.670 0.970 1.000
1753                0.4 0.880 1.000 1.000
1754                0.5 1.000 1.000 0.750
1755                0.6 1.000 0.880 0.600
1756                0.7 1.000 0.680 0.450
1757                0.8 0.970 0.430 0.370
1758                0.9 0.850 0.150 0.196
1759                1.0 0.650 0.000 0.130
1760            }
1761        }
1762        "green-to-magenta" {
1763            return {
1764                0.0 0.000 0.316 0.000
1765                0.06666666666666667 0.000 0.526 0.000
1766                0.13333333333333333 0.000 0.737 0.000
1767                0.2 0.000 0.947 0.000
1768                0.26666666666666666 0.316 1.000 0.316
1769                0.3333333333333333 0.526 1.000 0.526
1770                0.4 0.737 1.000 0.737
1771                0.4666666666666667 1.000 1.000 1.000
1772                0.5333333333333333 1.000 0.947 1.000
1773                0.6 1.000 0.737 1.000
1774                0.6666666666666666 1.000 0.526 1.000
1775                0.7333333333333333 1.000 0.316 1.000
1776                0.8 0.947 0.000 0.947
1777                0.8666666666666667 0.737 0.000 0.737
1778                0.9333333333333333 0.526 0.000 0.526
1779                1.0 0.316 0.000 0.316
1780            }
1781        }
1782        "greyscale" {
1783            return {
1784                0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
1785            }
1786        }
1787        "nanohub" {
1788            set clist "white yellow green cyan blue magenta"
1789        }
1790        default {
1791            set clist $colors
1792        }
1793    }
1794    set cmap {}
1795    for {set i 0} {$i < [llength $clist]} {incr i} {
1796        set x [expr {double($i)/([llength $clist]-1)}]
1797        set color [lindex $clist $i]
1798        append cmap "$x [Color2RGB $color] "
1799    }
1800    return $cmap
1801}
1802
1803#
1804# BuildColormap --
1805#
1806itcl::body Rappture::VtkStreamlinesViewer::BuildColormap { name styles } {
1807    array set style $styles
1808    set cmap [ColorsToColormap $style(-color)]
1809    if { [llength $cmap] == 0 } {
1810        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1811    }
1812    if { ![info exists _settings(volume-opacity)] } {
1813        set _settings(volume-opacity) $style(-opacity)
1814    }
1815    set max $_settings(volume-opacity)
1816
1817    set wmap "0.0 1.0 1.0 1.0"
1818    SendCmd "colormap add $name { $cmap } { $wmap }"
1819}
1820
1821# ----------------------------------------------------------------------
1822# CONFIGURATION OPTION: -plotbackground
1823# ----------------------------------------------------------------------
1824itcl::configbody Rappture::VtkStreamlinesViewer::plotbackground {
1825    if { [isconnected] } {
1826        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1827        SendCmd "screen bgcolor $r $g $b"
1828    }
1829}
1830
1831# ----------------------------------------------------------------------
1832# CONFIGURATION OPTION: -plotforeground
1833# ----------------------------------------------------------------------
1834itcl::configbody Rappture::VtkStreamlinesViewer::plotforeground {
1835    if { [isconnected] } {
1836        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1837        #fix this!
1838        #SendCmd "color background $r $g $b"
1839    }
1840}
1841
1842itcl::body Rappture::VtkStreamlinesViewer::limits { dataobj } {
1843    return
1844    array unset _limits $dataobj-*
1845    foreach comp [$dataobj components] {
1846        set tag $dataobj-$comp
1847        if { ![info exists _limits($tag)] } {
1848            set data [$dataobj blob $comp]
1849            set tmpfile file[pid].vtk
1850            set f [open "$tmpfile" "w"]
1851            fconfigure $f -translation binary
1852            puts $f $data
1853            close $f
1854            set reader [vtkDataSetReader $tag-xvtkDataSetReader]
1855            $reader SetFileName $tmpfile
1856            $reader ReadAllScalarsOn
1857            $reader ReadAllVectorsOn
1858            $reader ReadAllFieldsOn
1859            $reader Update
1860            set output [$reader GetOutput]
1861            set _limits($tag) [$output GetBounds]
1862            set pointData [$output GetPointData]
1863            puts stderr "\#scalars=[$reader GetNumberOfScalarsInFile]"
1864            puts stderr "\#fielddata=[$reader GetNumberOfFieldDataInFile]"
1865            puts stderr "fielddataname=[$reader GetFieldDataNameInFile 0]"
1866            set fieldData [$output GetFieldData]
1867            set pointData [$output GetPointData]
1868            puts stderr "field \#arrays=[$fieldData GetNumberOfArrays]"
1869            for { set i 0 } { $i < [$fieldData GetNumberOfArrays] } { incr i } {
1870                puts stderr [$fieldData GetArrayName $i]
1871            }
1872            puts stderr "point \#arrays=[$pointData GetNumberOfArrays]"
1873            for { set i 0 } { $i < [$pointData GetNumberOfArrays] } { incr i } {
1874                set name [$pointData GetArrayName $i]
1875                if { ![info exists _fields($name)] } {
1876                    $itk_component(field) choices insert end "$name" "$name"
1877                    set _fields($name) 1
1878                }
1879            }
1880            puts stderr "field \#components=[$fieldData GetNumberOfComponents]"
1881            puts stderr "point \#components=[$pointData GetNumberOfComponents]"
1882            puts stderr "field \#tuples=[$fieldData GetNumberOfTuples]"
1883            puts stderr "point \#tuples=[$pointData GetNumberOfTuples]"
1884            puts stderr "point \#scalars=[$pointData GetScalars]"
1885            puts stderr vectors=[$pointData GetVectors]
1886            rename $output ""
1887            rename $reader ""
1888            file delete $tmpfile
1889        }
1890        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1891        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1892            set limits(xmin) $xMin
1893        }
1894        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1895            set limits(xmax) $xMax
1896        }
1897        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1898            set limits(ymin) $xMin
1899        }
1900        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1901            set limits(ymax) $yMax
1902        }
1903        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1904            set limits(zmin) $zMin
1905        }
1906        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1907            set limits(zmax) $zMax
1908        }
1909    }
1910    return [array get limits]
1911}
1912
1913itcl::body Rappture::VtkStreamlinesViewer::BuildVolumeTab {} {
1914
1915    set fg [option get $itk_component(hull) font Font]
1916    #set bfg [option get $itk_component(hull) boldFont Font]
1917
1918    set inner [$itk_component(main) insert end \
1919        -title "Volume Settings" \
1920        -icon [Rappture::icon volume-on]]
1921    $inner configure -borderwidth 4
1922
1923    checkbutton $inner.volume \
1924        -text "Show Volume" \
1925        -variable [itcl::scope _settings(volume-visible)] \
1926        -command [itcl::code $this AdjustSetting volume-visible] \
1927        -font "Arial 9"
1928
1929    checkbutton $inner.wireframe \
1930        -text "Show Wireframe" \
1931        -variable [itcl::scope _settings(volume-wireframe)] \
1932        -command [itcl::code $this AdjustSetting volume-wireframe] \
1933        -font "Arial 9"
1934
1935    checkbutton $inner.lighting \
1936        -text "Enable Lighting" \
1937        -variable [itcl::scope _settings(volume-lighting)] \
1938        -command [itcl::code $this AdjustSetting volume-lighting] \
1939        -font "Arial 9"
1940
1941    checkbutton $inner.edges \
1942        -text "Show Edges" \
1943        -variable [itcl::scope _settings(volume-edges)] \
1944        -command [itcl::code $this AdjustSetting volume-edges] \
1945        -font "Arial 9"
1946
1947    label $inner.opacity_l -text "Opacity" -font "Arial 9"
1948    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1949        -variable [itcl::scope _settings(volume-opacity)] \
1950        -width 10 \
1951        -showvalue off \
1952        -command [itcl::code $this AdjustSetting volume-opacity]
1953
1954    blt::table $inner \
1955        0,0 $inner.volume    -anchor w -pady 2 \
1956        1,0 $inner.wireframe -anchor w -pady 2 \
1957        2,0 $inner.lighting  -anchor w -pady 2 \
1958        3,0 $inner.edges     -anchor w -pady 2 \
1959        4,0 $inner.opacity_l -anchor w -pady 2 \
1960        5,0 $inner.opacity   -fill x   -pady 2
1961
1962    blt::table configure $inner r* c* -resize none
1963    blt::table configure $inner r6 c1 -resize expand
1964}
1965
1966
1967itcl::body Rappture::VtkStreamlinesViewer::BuildStreamsTab {} {
1968
1969    set fg [option get $itk_component(hull) font Font]
1970    #set bfg [option get $itk_component(hull) boldFont Font]
1971
1972    set inner [$itk_component(main) insert end \
1973        -title "Streams Settings" \
1974        -icon [Rappture::icon streamlines-on]]
1975    $inner configure -borderwidth 4
1976
1977    checkbutton $inner.streamlines \
1978        -text "Show Streamlines" \
1979        -variable [itcl::scope _settings(streamlines-visible)] \
1980        -command [itcl::code $this AdjustSetting streamlines-visible] \
1981        -font "Arial 9"
1982   
1983    checkbutton $inner.lighting \
1984        -text "Enable Lighting" \
1985        -variable [itcl::scope _settings(streamlines-lighting)] \
1986        -command [itcl::code $this AdjustSetting streamlines-lighting] \
1987        -font "Arial 9"
1988
1989    checkbutton $inner.seeds \
1990        -text "Show Seeds" \
1991        -variable [itcl::scope _settings(streamlines-seeds)] \
1992        -command [itcl::code $this AdjustSetting streamlines-seeds] \
1993        -font "Arial 9"
1994
1995    label $inner.mode_l -text "Mode" -font "Arial 9"
1996    itk_component add streammode {
1997        Rappture::Combobox $inner.mode -width 10 -editable no
1998    }
1999    $inner.mode choices insert end \
2000        "lines"    "lines" \
2001        "ribbons"   "ribbons" \
2002        "tubes"     "tubes"
2003    $itk_component(streammode) value "lines"
2004    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting streamlines-mode]
2005
2006    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2007    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2008        -variable [itcl::scope _settings(streamlines-opacity)] \
2009        -width 10 \
2010        -showvalue off \
2011        -command [itcl::code $this AdjustSetting streamlines-opacity]
2012
2013    label $inner.density_l -text "Number of Seeds" -font "Arial 9"
2014    ::scale $inner.density -from 1 -to 1000 -orient horizontal \
2015        -variable [itcl::scope _settings(streamlines-numpoints)] \
2016        -width 10 \
2017        -showvalue on \
2018        -command [itcl::code $this AdjustSetting streamlines-numpoints]
2019
2020    label $inner.scale_l -text "Scale" -font "Arial 9"
2021    ::scale $inner.scale -from 1 -to 100 -orient horizontal \
2022        -variable [itcl::scope _settings(streamlines-scale)] \
2023        -width 10 \
2024        -showvalue off \
2025        -command [itcl::code $this AdjustSetting streamlines-scale]
2026
2027    label $inner.field_l -text "Field" -font "Arial 9"
2028    itk_component add field {
2029        Rappture::Combobox $inner.field -width 10 -editable no
2030    }
2031    bind $inner.field <<Value>> \
2032        [itcl::code $this AdjustSetting streamlines-field]
2033
2034    label $inner.palette_l -text "Palette" -font "Arial 9"
2035    itk_component add palette {
2036        Rappture::Combobox $inner.palette -width 10 -editable no
2037    }
2038    $inner.palette choices insert end \
2039        "BCGYR"              "BCGYR"            \
2040        "BGYOR"              "BGYOR"            \
2041        "blue"               "blue"             \
2042        "blue-to-brown"      "blue-to-brown"    \
2043        "blue-to-orange"     "blue-to-orange"   \
2044        "blue-to-grey"       "blue-to-grey"     \
2045        "green-to-magenta"   "green-to-magenta" \
2046        "greyscale"          "greyscale"        \
2047        "nanohub"            "nanohub"          \
2048        "rainbow"            "rainbow"          \
2049        "spectral"           "spectral"         \
2050        "ROYGB"              "ROYGB"            \
2051        "RYGCB"              "RYGCB"            \
2052        "brown-to-blue"      "brown-to-blue"    \
2053        "grey-to-blue"       "grey-to-blue"     \
2054        "orange-to-blue"     "orange-to-blue"   
2055
2056    $itk_component(palette) value "BCGYR"
2057    bind $inner.palette <<Value>> \
2058        [itcl::code $this AdjustSetting streamlines-palette]
2059
2060    blt::table $inner \
2061        0,0 $inner.streamlines -anchor w -pady 2 -cspan 2 \
2062        1,0 $inner.lighting    -anchor w -pady 2 -cspan 2 \
2063        2,0 $inner.seeds       -anchor w -pady 2 -cspan 2 \
2064        3,0 $inner.density_l   -anchor w -pady 2 -cspan 2 \
2065        4,0 $inner.density     -fill x   -pady 2 -cspan 2 \
2066        5,0 $inner.mode_l      -anchor w -pady 2  \
2067        5,1 $inner.mode        -anchor w -pady 2  \
2068        6,0 $inner.opacity_l   -anchor w -pady 2 -cspan 2 \
2069        7,0 $inner.opacity     -fill x   -pady 2 -cspan 2 \
2070        8,0 $inner.field_l     -anchor w -pady 2  \
2071        8,1 $inner.field       -anchor w -pady 2  \
2072        9,0 $inner.palette_l   -anchor w -pady 2  \
2073        9,1 $inner.palette     -anchor w -pady 2  \
2074       
2075
2076    blt::table configure $inner r* c* -resize none
2077    blt::table configure $inner r10 c1 c2 -resize expand
2078}
2079
2080itcl::body Rappture::VtkStreamlinesViewer::BuildAxisTab {} {
2081
2082    set fg [option get $itk_component(hull) font Font]
2083    #set bfg [option get $itk_component(hull) boldFont Font]
2084
2085    set inner [$itk_component(main) insert end \
2086        -title "Axis Settings" \
2087        -icon [Rappture::icon axis1]]
2088    $inner configure -borderwidth 4
2089
2090    checkbutton $inner.visible \
2091        -text "Show Axes" \
2092        -variable [itcl::scope _settings(axis-visible)] \
2093        -command [itcl::code $this AdjustSetting axis-visible] \
2094        -font "Arial 9"
2095
2096    checkbutton $inner.labels \
2097        -text "Show Axis Labels" \
2098        -variable [itcl::scope _settings(axis-labels)] \
2099        -command [itcl::code $this AdjustSetting axis-labels] \
2100        -font "Arial 9"
2101
2102    checkbutton $inner.gridx \
2103        -text "Show X Grid" \
2104        -variable [itcl::scope _settings(axis-xgrid)] \
2105        -command [itcl::code $this AdjustSetting axis-xgrid] \
2106        -font "Arial 9"
2107    checkbutton $inner.gridy \
2108        -text "Show Y Grid" \
2109        -variable [itcl::scope _settings(axis-ygrid)] \
2110        -command [itcl::code $this AdjustSetting axis-ygrid] \
2111        -font "Arial 9"
2112    checkbutton $inner.gridz \
2113        -text "Show Z Grid" \
2114        -variable [itcl::scope _settings(axis-zgrid)] \
2115        -command [itcl::code $this AdjustSetting axis-zgrid] \
2116        -font "Arial 9"
2117
2118    label $inner.mode_l -text "Mode" -font "Arial 9"
2119
2120    itk_component add axismode {
2121        Rappture::Combobox $inner.mode -width 10 -editable no
2122    }
2123    $inner.mode choices insert end \
2124        "static_triad"    "static" \
2125        "closest_triad"   "closest" \
2126        "furthest_triad"  "furthest" \
2127        "outer_edges"     "outer"         
2128    $itk_component(axismode) value "static"
2129    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
2130
2131    blt::table $inner \
2132        0,0 $inner.visible -anchor w -cspan 2 \
2133        1,0 $inner.labels  -anchor w -cspan 2 \
2134        2,0 $inner.gridx   -anchor w -cspan 2 \
2135        3,0 $inner.gridy   -anchor w -cspan 2 \
2136        4,0 $inner.gridz   -anchor w -cspan 2 \
2137        5,0 $inner.mode_l  -anchor w -cspan 2 -padx { 2 0 } \
2138        6,0 $inner.mode    -fill x   -cspan 2
2139
2140    blt::table configure $inner r* c* -resize none
2141    blt::table configure $inner r7 c1 -resize expand
2142}
2143
2144
2145itcl::body Rappture::VtkStreamlinesViewer::BuildCameraTab {} {
2146    set inner [$itk_component(main) insert end \
2147        -title "Camera Settings" \
2148        -icon [Rappture::icon camera]]
2149    $inner configure -borderwidth 4
2150
2151    set labels { qx qy qz qw xpan ypan zoom }
2152    set row 0
2153    foreach tag $labels {
2154        label $inner.${tag}label -text $tag -font "Arial 9"
2155        entry $inner.${tag} -font "Arial 9"  -bg white \
2156            -textvariable [itcl::scope _view($tag)]
2157        bind $inner.${tag} <KeyPress-Return> \
2158            [itcl::code $this camera set ${tag}]
2159        blt::table $inner \
2160            $row,0 $inner.${tag}label -anchor e -pady 2 \
2161            $row,1 $inner.${tag} -anchor w -pady 2
2162        blt::table configure $inner r$row -resize none
2163        incr row
2164    }
2165    checkbutton $inner.ortho \
2166        -text "Orthographic Projection" \
2167        -variable [itcl::scope _view(ortho)] \
2168        -command [itcl::code $this camera set ortho] \
2169        -font "Arial 9"
2170    blt::table $inner \
2171            $row,0 $inner.ortho -columnspan 2 -anchor w -pady 2
2172    blt::table configure $inner r$row -resize none
2173    incr row
2174
2175    blt::table configure $inner c0 c1 -resize none
2176    blt::table configure $inner c2 -resize expand
2177    blt::table configure $inner r$row -resize expand
2178}
2179
2180itcl::body Rappture::VtkStreamlinesViewer::BuildCutplaneTab {} {
2181
2182    set fg [option get $itk_component(hull) font Font]
2183   
2184    set inner [$itk_component(main) insert end \
2185        -title "Cutplane Settings" \
2186        -icon [Rappture::icon cutbutton]]
2187
2188    $inner configure -borderwidth 4
2189
2190    checkbutton $inner.visible \
2191        -text "Show Cutplanes" \
2192        -variable [itcl::scope _settings(cutplane-visible)] \
2193        -command [itcl::code $this AdjustSetting cutplane-visible] \
2194        -font "Arial 9"
2195
2196    checkbutton $inner.wireframe \
2197        -text "Show Wireframe" \
2198        -variable [itcl::scope _settings(cutplane-wireframe)] \
2199        -command [itcl::code $this AdjustSetting cutplane-wireframe] \
2200        -font "Arial 9"
2201
2202    checkbutton $inner.lighting \
2203        -text "Enable Lighting" \
2204        -variable [itcl::scope _settings(cutplane-lighting)] \
2205        -command [itcl::code $this AdjustSetting cutplane-lighting] \
2206        -font "Arial 9"
2207
2208    checkbutton $inner.edges \
2209        -text "Show Edges" \
2210        -variable [itcl::scope _settings(cutplane-edges)] \
2211        -command [itcl::code $this AdjustSetting cutplane-edges] \
2212        -font "Arial 9"
2213
2214    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2215    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2216        -variable [itcl::scope _settings(cutplane-opacity)] \
2217        -width 10 \
2218        -showvalue off \
2219        -command [itcl::code $this AdjustSetting cutplane-opacity]
2220    $inner.opacity set $_settings(cutplane-opacity)
2221
2222    # X-value slicer...
2223    itk_component add xCutButton {
2224        Rappture::PushButton $inner.xbutton \
2225            -onimage [Rappture::icon x-cutplane] \
2226            -offimage [Rappture::icon x-cutplane] \
2227            -command [itcl::code $this AdjustSetting cutplane-xvisible] \
2228            -variable [itcl::scope _settings(cutplane-xvisible)]
2229    }
2230    Rappture::Tooltip::for $itk_component(xCutButton) \
2231        "Toggle the X-axis cutplane on/off"
2232
2233    itk_component add xCutScale {
2234        ::scale $inner.xval -from 100 -to 1 \
2235            -width 10 -orient vertical -showvalue yes \
2236            -borderwidth 1 -highlightthickness 0 \
2237            -command [itcl::code $this EventuallySetCutplane x] \
2238            -variable [itcl::scope _settings(cutplane-xposition)]
2239    } {
2240        usual
2241        ignore -borderwidth -highlightthickness
2242    }
2243    # Set the default cutplane value before disabling the scale.
2244    $itk_component(xCutScale) set 50
2245    $itk_component(xCutScale) configure -state disabled
2246    Rappture::Tooltip::for $itk_component(xCutScale) \
2247        "@[itcl::code $this Slice tooltip x]"
2248
2249    # Y-value slicer...
2250    itk_component add yCutButton {
2251        Rappture::PushButton $inner.ybutton \
2252            -onimage [Rappture::icon y-cutplane] \
2253            -offimage [Rappture::icon y-cutplane] \
2254            -command [itcl::code $this AdjustSetting cutplane-yvisible] \
2255            -variable [itcl::scope _settings(cutplane-yvisible)]
2256    }
2257    Rappture::Tooltip::for $itk_component(yCutButton) \
2258        "Toggle the Y-axis cutplane on/off"
2259
2260    itk_component add yCutScale {
2261        ::scale $inner.yval -from 100 -to 1 \
2262            -width 10 -orient vertical -showvalue yes \
2263            -borderwidth 1 -highlightthickness 0 \
2264            -command [itcl::code $this EventuallySetCutplane y] \
2265            -variable [itcl::scope _settings(cutplane-yposition)]
2266    } {
2267        usual
2268        ignore -borderwidth -highlightthickness
2269    }
2270    Rappture::Tooltip::for $itk_component(yCutScale) \
2271        "@[itcl::code $this Slice tooltip y]"
2272    # Set the default cutplane value before disabling the scale.
2273    $itk_component(yCutScale) set 50
2274    $itk_component(yCutScale) configure -state disabled
2275
2276    # Z-value slicer...
2277    itk_component add zCutButton {
2278        Rappture::PushButton $inner.zbutton \
2279            -onimage [Rappture::icon z-cutplane] \
2280            -offimage [Rappture::icon z-cutplane] \
2281            -command [itcl::code $this AdjustSetting cutplane-zvisible] \
2282            -variable [itcl::scope _settings(cutplane-zvisible)]
2283    }
2284    Rappture::Tooltip::for $itk_component(zCutButton) \
2285        "Toggle the Z-axis cutplane on/off"
2286
2287    itk_component add zCutScale {
2288        ::scale $inner.zval -from 100 -to 1 \
2289            -width 10 -orient vertical -showvalue yes \
2290            -borderwidth 1 -highlightthickness 0 \
2291            -command [itcl::code $this EventuallySetCutplane z] \
2292            -variable [itcl::scope _settings(cutplane-zposition)]
2293    } {
2294        usual
2295        ignore -borderwidth -highlightthickness
2296    }
2297    $itk_component(zCutScale) set 50
2298    $itk_component(zCutScale) configure -state disabled
2299    #$itk_component(zCutScale) configure -state disabled
2300    Rappture::Tooltip::for $itk_component(zCutScale) \
2301        "@[itcl::code $this Slice tooltip z]"
2302
2303    blt::table $inner \
2304        0,0 $inner.visible              -anchor w -pady 2 -cspan 4 \
2305        1,0 $inner.lighting             -anchor w -pady 2 -cspan 4 \
2306        2,0 $inner.wireframe            -anchor w -pady 2 -cspan 4 \
2307        3,0 $inner.edges                -anchor w -pady 2 -cspan 4 \
2308        4,0 $inner.opacity_l            -anchor w -pady 2 -cspan 3 \
2309        5,0 $inner.opacity              -fill x   -pady 2 -cspan 3 \
2310        6,0 $itk_component(xCutButton)  -anchor e -padx 2 -pady 2 \
2311        7,0 $itk_component(xCutScale)   -fill y \
2312        6,1 $itk_component(yCutButton)  -anchor e -padx 2 -pady 2 \
2313        7,1 $itk_component(yCutScale)   -fill y \
2314        6,2 $itk_component(zCutButton)  -anchor e -padx 2 -pady 2 \
2315        7,2 $itk_component(zCutScale)   -fill y \
2316
2317    blt::table configure $inner r* c* -resize none
2318    blt::table configure $inner r7 c3 -resize expand
2319}
2320
2321
2322
2323#
2324#  camera --
2325#
2326itcl::body Rappture::VtkStreamlinesViewer::camera {option args} {
2327    switch -- $option {
2328        "show" {
2329            puts [array get _view]
2330        }
2331        "set" {
2332            set who [lindex $args 0]
2333            set x $_view($who)
2334            set code [catch { string is double $x } result]
2335            if { $code != 0 || !$result } {
2336                return
2337            }
2338            switch -- $who {
2339                "ortho" {
2340                    if {$_view(ortho)} {
2341                        SendCmd "camera mode ortho"
2342                    } else {
2343                        SendCmd "camera mode persp"
2344                    }
2345                }
2346                "xpan" - "ypan" {
2347                    PanCamera
2348                }
2349                "qx" - "qy" - "qz" - "qw" {
2350                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2351                    $_arcball quaternion $q
2352                    EventuallyRotate $q
2353                }
2354                "zoom" {
2355                    SendCmd "camera zoom $_view(zoom)"
2356                }
2357            }
2358        }
2359    }
2360}
2361
2362itcl::body Rappture::VtkStreamlinesViewer::ConvertToVtkData { dataobj comp } {
2363    foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $comp] break
2364    set values [$dataobj values $comp]
2365    append out "# vtk DataFile Version 2.0 \n"
2366    append out "Test data \n"
2367    append out "ASCII \n"
2368    append out "DATASET STRUCTURED_POINTS \n"
2369    append out "DIMENSIONS $xN $yN 1 \n"
2370    append out "ORIGIN 0 0 0 \n"
2371    append out "SPACING 1 1 1 \n"
2372    append out "POINT_DATA [expr $xN * $yN] \n"
2373    append out "SCALARS field float 1 \n"
2374    append out "LOOKUP_TABLE default \n"
2375    append out [join $values "\n"]
2376    append out "\n"
2377    return $out
2378}
2379
2380
2381itcl::body Rappture::VtkStreamlinesViewer::GetVtkData { args } {
2382    set bytes ""
2383    foreach dataobj [get] {
2384        foreach comp [$dataobj components] {
2385            set tag $dataobj-$comp
2386            #set contents [ConvertToVtkData $dataobj $comp]
2387            set contents [$dataobj blob $comp]
2388            append bytes "$contents\n\n"
2389        }
2390    }
2391    return [list .vtk $bytes]
2392}
2393
2394itcl::body Rappture::VtkStreamlinesViewer::GetImage { args } {
2395    if { [image width $_image(download)] > 0 &&
2396         [image height $_image(download)] > 0 } {
2397        set bytes [$_image(download) data -format "jpeg -quality 100"]
2398        set bytes [Rappture::encoding::decode -as b64 $bytes]
2399        return [list .jpg $bytes]
2400    }
2401    return ""
2402}
2403
2404itcl::body Rappture::VtkStreamlinesViewer::BuildDownloadPopup { popup command } {
2405    Rappture::Balloon $popup \
2406        -title "[Rappture::filexfer::label downloadWord] as..."
2407    set inner [$popup component inner]
2408    label $inner.summary -text "" -anchor w
2409    radiobutton $inner.vtk_button -text "VTK data file" \
2410        -variable [itcl::scope _downloadPopup(format)] \
2411        -font "Helvetica 9 " \
2412        -value vtk 
2413    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
2414    radiobutton $inner.image_button -text "Image File" \
2415        -variable [itcl::scope _downloadPopup(format)] \
2416        -value image
2417    Rappture::Tooltip::for $inner.image_button \
2418        "Save as digital image."
2419
2420    button $inner.ok -text "Save" \
2421        -highlightthickness 0 -pady 2 -padx 3 \
2422        -command $command \
2423        -compound left \
2424        -image [Rappture::icon download]
2425
2426    button $inner.cancel -text "Cancel" \
2427        -highlightthickness 0 -pady 2 -padx 3 \
2428        -command [list $popup deactivate] \
2429        -compound left \
2430        -image [Rappture::icon cancel]
2431
2432    blt::table $inner \
2433        0,0 $inner.summary -cspan 2  \
2434        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
2435        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
2436        4,1 $inner.cancel -width .9i -fill y \
2437        4,0 $inner.ok -padx 2 -width .9i -fill y
2438    blt::table configure $inner r3 -height 4
2439    blt::table configure $inner r4 -pady 4
2440    raise $inner.image_button
2441    $inner.vtk_button invoke
2442    return $inner
2443}
2444
2445itcl::body Rappture::VtkStreamlinesViewer::SetObjectStyle { dataobj comp } {
2446    # Parse style string.
2447    set tag $dataobj-$comp
2448    set style [$dataobj style $comp]
2449    array set settings {
2450        -color \#808080
2451        -edges 0
2452        -edgecolor black
2453        -linewidth 1.0
2454        -opacity 0.4
2455        -wireframe 0
2456        -lighting 1
2457        -seeds 1
2458        -seedcolor white
2459        -visible 1
2460    }
2461    if { $dataobj != $_first } {
2462        set settings(-opacity) 1
2463    }
2464    array set settings $style
2465    SendCmd "streamlines add $tag"
2466    SendCmd "streamlines seed visible off $tag"
2467    set seeds [$dataobj hints seeds]
2468    if { $seeds != "" && ![info exists _seeds($dataobj)] } {
2469        set length [string length $seeds]
2470        SendCmd "streamlines seed fmesh 200 data follows $length $tag"
2471        SendCmd "$seeds"
2472        set _seeds($dataobj) 1
2473    }
2474    SendCmd "cutplane add $tag"
2475    SendCmd "cutplane edges 0 $tag"
2476    SendCmd "cutplane wireframe 0 $tag"
2477    SendCmd "cutplane lighting 1 $tag"
2478    SendCmd "cutplane linewidth 1 $tag"
2479    #SendCmd "cutplane linecolor 1 1 1 $tag"
2480    #SendCmd "cutplane visible $tag"
2481    foreach axis { x y z } {
2482        SendCmd "cutplane slice $axis 1.0 $tag"
2483        SendCmd "cutplane axis $axis 0 $tag"
2484    }
2485
2486    SendCmd "polydata add $tag"
2487    SendCmd "polydata edges $settings(-edges) $tag"
2488    set _settings(volume-edges) $settings(-edges)
2489    SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
2490    SendCmd "polydata lighting $settings(-lighting) $tag"
2491    set _settings(volume-lighting) $settings(-lighting)
2492    SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
2493    SendCmd "polydata linewidth $settings(-linewidth) $tag"
2494    SendCmd "polydata opacity $settings(-opacity) $tag"
2495    set _settings(volume-opacity) $settings(-opacity)
2496    SendCmd "polydata wireframe $settings(-wireframe) $tag"
2497    set _settings(volume-wireframe) $settings(-wireframe)
2498    set _settings(volume-opacity) [expr $settings(-opacity) * 100.0]
2499    SetColormap $dataobj $comp
2500}
2501
2502itcl::body Rappture::VtkStreamlinesViewer::IsValidObject { dataobj } {
2503    if {[catch {$dataobj isa Rappture::Field} valid] != 0 || !$valid} {
2504        return 0
2505    }
2506    return 1
2507}
2508
2509# ----------------------------------------------------------------------
2510# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
2511#
2512# Invoked automatically whenever the "legend" command comes in from
2513# the rendering server.  Indicates that binary image data with the
2514# specified <size> will follow.
2515# ----------------------------------------------------------------------
2516itcl::body Rappture::VtkStreamlinesViewer::ReceiveLegend { colormap title vmin vmax size } {
2517    #puts stderr "ReceiveLegend colormap=$colormap title=$title range=$vmin,$vmax size=$size"
2518    set _limits(vmin) $vmin
2519    set _limits(vmax) $vmax
2520    set _title $title
2521    regsub {\(mag\)} $title "" _title
2522    if { [IsConnected] } {
2523        set bytes [ReceiveBytes $size]
2524        if { ![info exists _image(legend)] } {
2525            set _image(legend) [image create photo]
2526        }
2527        $_image(legend) configure -data $bytes
2528        #puts stderr "read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
2529        DrawLegend $_title
2530    }
2531}
2532
2533#
2534# DrawLegend --
2535#
2536#       Draws the legend in it's own canvas which resides to the right
2537#       of the contour plot area.
2538#
2539itcl::body Rappture::VtkStreamlinesViewer::DrawLegend { name } {
2540    set c $itk_component(view)
2541    set w [winfo width $c]
2542    set h [winfo height $c]
2543    set font "Arial 8"
2544    set lineht [font metrics $font -linespace]
2545   
2546    if { [info exists _fields($name)] } {
2547        foreach { title units } $_fields($name) break
2548        if { $units != "" } {
2549            set title [format "%s (%s)" $title $units]
2550        }
2551    } else {
2552        set title $name
2553    }
2554    if { $_settings(legend-visible) } {
2555        set x [expr $w - 2]
2556        if { [$c find withtag "legend"] == "" } {
2557            set y 2
2558            $c create text $x $y \
2559                -anchor ne \
2560                -fill $itk_option(-plotforeground) -tags "title legend" \
2561                -font $font
2562            incr y $lineht
2563            $c create text $x $y \
2564                -anchor ne \
2565                -fill $itk_option(-plotforeground) -tags "vmax legend" \
2566                -font $font
2567            incr y $lineht
2568            $c create image $x $y \
2569                -anchor ne \
2570                -image $_image(legend) -tags "colormap legend"
2571            $c create text $x [expr {$h-2}] \
2572                -anchor se \
2573                -fill $itk_option(-plotforeground) -tags "vmin legend" \
2574                -font $font
2575            #$c bind colormap <Enter> [itcl::code $this EnterLegend %x %y]
2576            $c bind colormap <Leave> [itcl::code $this LeaveLegend]
2577            $c bind colormap <Motion> [itcl::code $this MotionLegend %x %y]
2578        }
2579        # Reset the item coordinates according the current size of the plot.
2580        $c itemconfigure title -text $title
2581        if { $_limits(vmin) != "" } {
2582            $c itemconfigure vmin -text [format %g $_limits(vmin)]
2583        }
2584        if { $_limits(vmax) != "" } {
2585            $c itemconfigure vmax -text [format %g $_limits(vmax)]
2586        }
2587        set y 2
2588        $c coords title $x $y
2589        incr y $lineht
2590        $c coords vmax $x $y
2591        incr y $lineht
2592        $c coords colormap $x $y
2593        $c coords vmin $x [expr {$h - 2}]
2594    }
2595}
2596
2597#
2598# EnterLegend --
2599#
2600itcl::body Rappture::VtkStreamlinesViewer::EnterLegend { x y } {
2601    SetLegendTip $x $y
2602}
2603
2604#
2605# MotionLegend --
2606#
2607itcl::body Rappture::VtkStreamlinesViewer::MotionLegend { x y } {
2608    Rappture::Tooltip::tooltip cancel
2609    set c $itk_component(view)
2610    SetLegendTip $x $y
2611}
2612
2613#
2614# LeaveLegend --
2615#
2616itcl::body Rappture::VtkStreamlinesViewer::LeaveLegend { } {
2617    Rappture::Tooltip::tooltip cancel
2618    .rappturetooltip configure -icon ""
2619}
2620
2621#
2622# SetLegendTip --
2623#
2624itcl::body Rappture::VtkStreamlinesViewer::SetLegendTip { x y } {
2625    set c $itk_component(view)
2626    set w [winfo width $c]
2627    set h [winfo height $c]
2628    set font "Arial 8"
2629    set lineht [font metrics $font -linespace]
2630   
2631    set imgHeight [image height $_image(legend)]
2632    set coords [$c coords colormap]
2633    set imgX [expr $w - [image width $_image(legend)] - 2]
2634    set imgY [expr $y - 2 * ($lineht + 2)]
2635
2636    if { [info exists _fields($_title)] } {
2637        foreach { title units } $_fields($_title) break
2638        if { $units != "" } {
2639            set title [format "%s (%s)" $title $units]
2640        }
2641    } else {
2642        set title $_title
2643    }
2644    # Make a swatch of the selected color
2645    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
2646        #puts stderr "out of range: $imgY"
2647        return
2648    }
2649    if { ![info exists _image(swatch)] } {
2650        set _image(swatch) [image create photo -width 24 -height 24]
2651    }
2652    set color [eval format "\#%02x%02x%02x" $pixel]
2653    $_image(swatch) put black  -to 0 0 23 23
2654    $_image(swatch) put $color -to 1 1 22 22
2655    .rappturetooltip configure -icon $_image(swatch)
2656
2657    # Compute the value of the point
2658    if { [info exists _limits(vmax)] && [info exists _limits(vmin)] } {
2659        set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
2660        set value [expr $t * ($_limits(vmax) - $_limits(vmin)) + $_limits(vmin)]
2661    } else {
2662        set value 0.0
2663    }
2664    set tipx [expr $x + 15]
2665    set tipy [expr $y - 5]
2666    Rappture::Tooltip::text $c "$title $value"
2667    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy   
2668}
2669
2670
2671# ----------------------------------------------------------------------
2672# USAGE: Slice move x|y|z <newval>
2673#
2674# Called automatically when the user drags the slider to move the
2675# cut plane that slices 3D data.  Gets the current value from the
2676# slider and moves the cut plane to the appropriate point in the
2677# data set.
2678# ----------------------------------------------------------------------
2679itcl::body Rappture::VtkStreamlinesViewer::Slice {option args} {
2680    switch -- $option {
2681        "move" {
2682            set axis [lindex $args 0]
2683            set oldval $_settings(axis-${axis}position)
2684            set newval [lindex $args 1]
2685            if {[llength $args] != 2} {
2686                error "wrong # args: should be \"Slice move x|y|z newval\""
2687            }
2688            set newpos [expr {0.01*$newval}]
2689            SendCmd "cutplane slice $axis $newpos"
2690        }
2691        "tooltip" {
2692            set axis [lindex $args 0]
2693            set val [$itk_component(${axis}CutScale) get]
2694            return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
2695        }
2696        default {
2697            error "bad option \"$option\": should be axis, move, or tooltip"
2698        }
2699    }
2700}
Note: See TracBrowser for help on using the repository browser.