source: branches/Rappture 1.2/gui/scripts/vtkstreamlinesviewer.tcl @ 3297

Last change on this file since 3297 was 3297, checked in by gah, 12 years ago

fix nanovis clientinfo addition

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