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

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

move "package require vtk" into constructor so that applications do not have to load vtk to use Rappture widgets

File size: 98.0 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: vtkviewer - Vtk drawing object viewer
4#
5#  It connects to the Vtk server running on a rendering farm,
6#  transmits data, and displays the results.
7# ======================================================================
8#  AUTHOR:  Michael McLennan, Purdue University
9#  Copyright (c) 2004-2005  Purdue Research Foundation
10#
11#  See the file "license.terms" for information on usage and
12#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13# ======================================================================
14package require Itk
15package require BLT
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
1064        if 0 {
1065            # Tell the server the name of the tool, the version, and dataset
1066            # that we are rendering.  Have to do it here because we don't know
1067            # what data objects are using the renderer until be get here.
1068            set args ""
1069            lappend args tool [$_first hints toolId]
1070            lappend args version [$_first hints toolRevision]
1071            lappend args dataset [$_first hints label]
1072            SendCmd "clientinfo $args"
1073        }
1074
1075        foreach axis { x y z } {
1076            set label [$_first hints ${axis}label]
1077            if { $label != "" } {
1078                SendCmd "axis name $axis $label"
1079            }
1080            set units [$_first hints ${axis}units]
1081            if { $units != "" } {
1082                SendCmd "axis units $axis $units"
1083            }
1084        }
1085        array unset _scalarFields
1086        array unset _vectorFields
1087        set _currentField [$_first hints default]
1088        $itk_component(field) choices delete 0 end
1089        $itk_component(fieldmenu) delete 0 end
1090        array unset _fields
1091        foreach { name title units } [$_first hints vectors] {
1092            set _vectorFields($title) $name
1093            $itk_component(field) choices insert end "$name" "$title"
1094            $itk_component(fieldmenu) add radiobutton -label "$title" \
1095                -value $title -variable [itcl::scope _currentField] \
1096                -selectcolor red \
1097                -activebackground black \
1098                -activeforeground white \
1099                -font "Arial 8" \
1100                -command [itcl::code $this Combo invoke]
1101            set _fields($name) [list $title $units]
1102        }
1103        foreach { name title units } [$_first hints scalars] {
1104            set _scalarFields($title) $name
1105            $itk_component(field) choices insert end "$name" "$title"
1106            $itk_component(fieldmenu) add radiobutton -label "$title" \
1107                -value $title -variable [itcl::scope _currentField] \
1108                -selectcolor red \
1109                -activebackground black \
1110                -activeforeground white \
1111                -font "Arial 8" \
1112                -command [itcl::code $this Combo invoke]
1113            set _fields($name) [list $title $units]
1114        }
1115        $itk_component(field) value $_currentField
1116    }
1117
1118    InitSettings streamlines-visible streamlines-palette volume-visible
1119
1120    if { $_reset } {
1121        InitSettings streamlines-seeds streamlines-opacity \
1122            streamlines-numpoints streamlines-lighting \
1123            streamlines-palette streamlines-field \
1124            volume-edges volume-lighting volume-opacity volume-wireframe
1125        Zoom reset
1126        set _reset 0
1127    }
1128    set _buffering 0;                        # Turn off buffering.
1129
1130    # Actually write the commands to the server socket.  If it fails, we don't
1131    # care.  We're finished here.
1132    blt::busy hold $itk_component(hull)
1133    sendto $_outbuf;                       
1134    blt::busy release $itk_component(hull)
1135    set _outbuf "";                        # Clear the buffer.               
1136}
1137
1138# ----------------------------------------------------------------------
1139# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
1140#
1141# Returns a list of server IDs for the current datasets being displayed.  This
1142# is normally a single ID, but it might be a list of IDs if the current data
1143# object has multiple components.
1144# ----------------------------------------------------------------------
1145itcl::body Rappture::VtkStreamlinesViewer::CurrentDatasets {args} {
1146    set flag [lindex $args 0]
1147    switch -- $flag {
1148        "-all" {
1149            if { [llength $args] > 1 } {
1150                error "CurrentDatasets: can't specify dataobj after \"-all\""
1151            }
1152            set dlist [get -objects]
1153        }
1154        "-visible" {
1155            if { [llength $args] > 1 } {
1156                set dlist {}
1157                set args [lrange $args 1 end]
1158                foreach dataobj $args {
1159                    if { [info exists _obj2ovride($dataobj-raise)] } {
1160                        lappend dlist $dataobj
1161                    }
1162                }
1163            } else {
1164                set dlist [get -visible]
1165            }
1166        }           
1167        default {
1168            set dlist $args
1169        }
1170    }
1171    set rlist ""
1172    foreach dataobj $dlist {
1173        foreach comp [$dataobj components] {
1174            set tag $dataobj-$comp
1175            if { [info exists _datasets($tag)] && $_datasets($tag) } {
1176                lappend rlist $tag
1177            }
1178        }
1179    }
1180    return $rlist
1181}
1182
1183# ----------------------------------------------------------------------
1184# USAGE: Zoom in
1185# USAGE: Zoom out
1186# USAGE: Zoom reset
1187#
1188# Called automatically when the user clicks on one of the zoom
1189# controls for this widget.  Changes the zoom for the current view.
1190# ----------------------------------------------------------------------
1191itcl::body Rappture::VtkStreamlinesViewer::Zoom {option} {
1192    switch -- $option {
1193        "in" {
1194            set _view(zoom) [expr {$_view(zoom)*1.25}]
1195            SendCmd "camera zoom $_view(zoom)"
1196        }
1197        "out" {
1198            set _view(zoom) [expr {$_view(zoom)*0.8}]
1199            SendCmd "camera zoom $_view(zoom)"
1200        }
1201        "reset" {
1202            array set _view {
1203                qw      1
1204                qx      0
1205                qy      0
1206                qz      0
1207                zoom    1.0
1208                xpan   0
1209                ypan   0
1210            }
1211            SendCmd "camera reset all"
1212            if { $_first != "" } {
1213                set location [$_first hints camera]
1214                if { $location != "" } {
1215                    array set _view $location
1216                }
1217            }
1218            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1219            $_arcball quaternion $q
1220            DoRotate
1221        }
1222    }
1223}
1224
1225itcl::body Rappture::VtkStreamlinesViewer::PanCamera {} {
1226    set x $_view(xpan)
1227    set y $_view(ypan)
1228    SendCmd "camera pan $x $y"
1229}
1230
1231
1232# ----------------------------------------------------------------------
1233# USAGE: Rotate click <x> <y>
1234# USAGE: Rotate drag <x> <y>
1235# USAGE: Rotate release <x> <y>
1236#
1237# Called automatically when the user clicks/drags/releases in the
1238# plot area.  Moves the plot according to the user's actions.
1239# ----------------------------------------------------------------------
1240itcl::body Rappture::VtkStreamlinesViewer::Rotate {option x y} {
1241    switch -- $option {
1242        "click" {
1243            $itk_component(view) configure -cursor fleur
1244            set _click(x) $x
1245            set _click(y) $y
1246        }
1247        "drag" {
1248            if {[array size _click] == 0} {
1249                Rotate click $x $y
1250            } else {
1251                set w [winfo width $itk_component(view)]
1252                set h [winfo height $itk_component(view)]
1253                if {$w <= 0 || $h <= 0} {
1254                    return
1255                }
1256
1257                if {[catch {
1258                    # this fails sometimes for no apparent reason
1259                    set dx [expr {double($x-$_click(x))/$w}]
1260                    set dy [expr {double($y-$_click(y))/$h}]
1261                }]} {
1262                    return
1263                }
1264                if { $dx == 0 && $dy == 0 } {
1265                    return
1266                }
1267                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1268                EventuallyRotate $q
1269                set _click(x) $x
1270                set _click(y) $y
1271            }
1272        }
1273        "release" {
1274            Rotate drag $x $y
1275            $itk_component(view) configure -cursor ""
1276            catch {unset _click}
1277        }
1278        default {
1279            error "bad option \"$option\": should be click, drag, release"
1280        }
1281    }
1282}
1283
1284itcl::body Rappture::VtkStreamlinesViewer::Pick {x y} {
1285    foreach tag [CurrentDatasets -visible] {
1286        SendCmdNoSplash "dataset getscalar pixel $x $y $tag"
1287    }
1288}
1289
1290# ----------------------------------------------------------------------
1291# USAGE: $this Pan click x y
1292#        $this Pan drag x y
1293#        $this Pan release x y
1294#
1295# Called automatically when the user clicks on one of the zoom
1296# controls for this widget.  Changes the zoom for the current view.
1297# ----------------------------------------------------------------------
1298itcl::body Rappture::VtkStreamlinesViewer::Pan {option x y} {
1299    switch -- $option {
1300        "set" {
1301            set w [winfo width $itk_component(view)]
1302            set h [winfo height $itk_component(view)]
1303            set x [expr $x / double($w)]
1304            set y [expr $y / double($h)]
1305            set _view(xpan) [expr $_view(xpan) + $x]
1306            set _view(ypan) [expr $_view(ypan) + $y]
1307            PanCamera
1308            return
1309        }
1310        "click" {
1311            set _click(x) $x
1312            set _click(y) $y
1313            $itk_component(view) configure -cursor hand1
1314        }
1315        "drag" {
1316            if { ![info exists _click(x)] } {
1317                set _click(x) $x
1318            }
1319            if { ![info exists _click(y)] } {
1320                set _click(y) $y
1321            }
1322            set w [winfo width $itk_component(view)]
1323            set h [winfo height $itk_component(view)]
1324            set dx [expr ($_click(x) - $x)/double($w)]
1325            set dy [expr ($_click(y) - $y)/double($h)]
1326            set _click(x) $x
1327            set _click(y) $y
1328            set _view(xpan) [expr $_view(xpan) - $dx]
1329            set _view(ypan) [expr $_view(ypan) - $dy]
1330            PanCamera
1331        }
1332        "release" {
1333            Pan drag $x $y
1334            $itk_component(view) configure -cursor ""
1335        }
1336        default {
1337            error "unknown option \"$option\": should set, click, drag, or release"
1338        }
1339    }
1340}
1341
1342# ----------------------------------------------------------------------
1343# USAGE: InitSettings <what> ?<value>?
1344#
1345# Used internally to update rendering settings whenever parameters
1346# change in the popup settings panel.  Sends the new settings off
1347# to the back end.
1348# ----------------------------------------------------------------------
1349itcl::body Rappture::VtkStreamlinesViewer::InitSettings { args } {
1350    foreach spec $args {
1351        if { [info exists _settings($_first-$spec)] } {
1352            # Reset global setting with dataobj specific setting
1353            set _settings($spec) $_settings($_first-$spec)
1354        }
1355        AdjustSetting $spec
1356    }
1357}
1358
1359#
1360# AdjustSetting --
1361#
1362#       Changes/updates a specific setting in the widget.  There are
1363#       usually user-setable option.  Commands are sent to the render
1364#       server.
1365#
1366itcl::body Rappture::VtkStreamlinesViewer::AdjustSetting {what {value ""}} {
1367    if { ![isconnected] } {
1368        return
1369    }
1370    switch -- $what {
1371        "volume-opacity" {
1372            set val $_settings(volume-opacity)
1373            set sval [expr { 0.01 * double($val) }]
1374            foreach dataset [CurrentDatasets -visible] {
1375                SendCmd "polydata opacity $sval $dataset"
1376            }
1377        }
1378        "volume-wireframe" {
1379            set bool $_settings(volume-wireframe)
1380            foreach dataset [CurrentDatasets -visible] {
1381                SendCmd "polydata wireframe $bool $dataset"
1382            }
1383        }
1384        "volume-visible" {
1385            set bool $_settings(volume-visible)
1386            foreach dataset [CurrentDatasets -visible] {
1387                SendCmd "polydata visible $bool $dataset"
1388            }
1389            if { $bool } {
1390                Rappture::Tooltip::for $itk_component(volume) \
1391                    "Hide the volume"
1392            } else {
1393                Rappture::Tooltip::for $itk_component(volume) \
1394                    "Show the volume"
1395            }
1396        }
1397        "volume-lighting" {
1398            set bool $_settings(volume-lighting)
1399            foreach dataset [CurrentDatasets -visible] {
1400                SendCmd "polydata lighting $bool $dataset"
1401            }
1402        }
1403        "volume-edges" {
1404            set bool $_settings(volume-edges)
1405            foreach dataset [CurrentDatasets -visible] {
1406                SendCmd "polydata edges $bool $dataset"
1407            }
1408        }
1409        "axis-visible" {
1410            set bool $_settings(axis-visible)
1411            SendCmd "axis visible all $bool"
1412        }
1413        "axis-labels" {
1414            set bool $_settings(axis-labels)
1415            SendCmd "axis labels all $bool"
1416        }
1417        "axis-xgrid" - "axis-ygrid" - "axis-zgrid" {
1418            set axis [string range $what 5 5]
1419            set bool $_settings($what)
1420            SendCmd "axis grid $axis $bool"
1421        }
1422        "axis-mode" {
1423            set mode [$itk_component(axismode) value]
1424            set mode [$itk_component(axismode) translate $mode]
1425            set _settings($what) $mode
1426            SendCmd "axis flymode $mode"
1427        }
1428        "cutplane-edges" {
1429            set bool $_settings($what)
1430            foreach dataset [CurrentDatasets -visible] {
1431                SendCmd "cutplane edges $bool $dataset"
1432            }
1433        }
1434        "cutplane-visible" {
1435            set bool $_settings($what)
1436            foreach dataset [CurrentDatasets -visible] {
1437                SendCmd "cutplane visible $bool $dataset"
1438            }
1439        }
1440        "cutplane-wireframe" {
1441            set bool $_settings($what)
1442            foreach dataset [CurrentDatasets -visible] {
1443                SendCmd "cutplane wireframe $bool $dataset"
1444            }
1445        }
1446        "cutplane-lighting" {
1447            set bool $_settings($what)
1448            foreach dataset [CurrentDatasets -visible] {
1449                SendCmd "cutplane lighting $bool $dataset"
1450            }
1451        }
1452        "cutplane-opacity" {
1453            set val $_settings($what)
1454            set sval [expr { 0.01 * double($val) }]
1455            foreach dataset [CurrentDatasets -visible] {
1456                SendCmd "cutplane opacity $sval $dataset"
1457            }
1458        }
1459        "cutplane-xvisible" - "cutplane-yvisible" - "cutplane-zvisible" {
1460            set axis [string range $what 9 9]
1461            set bool $_settings($what)
1462            if { $bool } {
1463                $itk_component(${axis}CutScale) configure -state normal \
1464                    -troughcolor white
1465            } else {
1466                $itk_component(${axis}CutScale) configure -state disabled \
1467                    -troughcolor grey82
1468            }
1469            foreach dataset [CurrentDatasets -visible] {
1470                SendCmd "cutplane axis $axis $bool $dataset"
1471            }
1472        }
1473        "cutplane-xposition" - "cutplane-yposition" - "cutplane-zposition" {
1474            set axis [string range $what 9 9]
1475            set pos [expr $_settings($what) * 0.01]
1476            foreach dataset [CurrentDatasets -visible] {
1477                SendCmd "cutplane slice ${axis} ${pos} $dataset"
1478            }
1479            set _cutplanePending 0
1480        }
1481        "streamlines-seeds" {
1482            set bool $_settings($what)
1483            foreach dataset [CurrentDatasets -visible] {
1484                SendCmd "streamlines seed visible $bool $dataset"
1485            }
1486        }
1487        "streamlines-numpoints" {
1488            set density $_settings($what)
1489            EventuallyReseed $density
1490        }
1491        "streamlines-visible" {
1492            set bool $_settings($what)
1493            foreach dataset [CurrentDatasets -visible] {
1494                SendCmd "streamlines visible $bool $dataset"
1495            }
1496            if { $bool } {
1497                Rappture::Tooltip::for $itk_component(streamlines) \
1498                    "Hide the streamlines"
1499            } else {
1500                Rappture::Tooltip::for $itk_component(streamlines) \
1501                    "Show the streamlines"
1502            }
1503        }
1504        "streamlines-mode" {
1505            set mode [$itk_component(streammode) value]
1506            set _settings(streamlines-mode) $mode
1507            foreach dataset [CurrentDatasets -visible] {
1508                switch -- $mode {
1509                    "lines" {
1510                        SendCmd "streamlines lines $dataset"
1511                    }
1512                    "ribbons" {
1513                        SendCmd "streamlines ribbons 3 0 $dataset"
1514                    }
1515                    "tubes" {
1516                        SendCmd "streamlines tubes 5 3 $dataset"
1517                    }
1518                }
1519            }
1520        }
1521        "streamlines-palette" {
1522            set palette [$itk_component(palette) value]
1523            set _settings(streamlines-palette) $palette
1524            foreach dataset [CurrentDatasets -visible $_first] {
1525                foreach {dataobj comp} [split $dataset -] break
1526                ChangeColormap $dataobj $comp $palette
1527            }
1528            set _legendPending 1
1529        }
1530        "streamlines-opacity" {
1531            set val $_settings(streamlines-opacity)
1532            set sval [expr { 0.01 * double($val) }]
1533            foreach dataset [CurrentDatasets -visible $_first] {
1534                SendCmd "streamlines opacity $sval $dataset"
1535            }
1536        }
1537        "streamlines-scale" {
1538            set val $_settings(streamlines-scale)
1539            set sval [expr { 0.01 * double($val) }]
1540            foreach dataset [CurrentDatasets -visible $_first] {
1541                SendCmd "streamlines scale $sval $sval $sval $dataset"
1542            }
1543        }
1544        "streamlines-lighting" {
1545            set bool $_settings(streamlines-lighting)
1546            foreach dataset [CurrentDatasets -visible $_first] {
1547                SendCmd "streamlines lighting $bool $dataset"
1548            }
1549        }
1550        "streamlines-field" {
1551            set new [$itk_component(field) value]
1552            set value [$itk_component(field) translate $new]
1553            set _settings(streamlines-field) $value
1554            if { [info exists _scalarFields($new)] } {
1555                set name $_scalarFields($new)
1556                set _colorMode scalar
1557                set _currentField $new
1558            } elseif { [info exists _vectorFields($new)] } {
1559                set name $_vectorFields($new)
1560                set _colorMode vmag
1561                set _currentField $new
1562            } else {
1563                puts stderr "unknown field \"$new\""
1564                return
1565            }
1566            foreach dataset [CurrentDatasets -visible] {
1567                puts stderr "streamlines colormode $_colorMode ${name} $dataset"
1568                puts stderr "cutplane colormode $_colorMode ${name} $dataset"
1569                SendCmd "streamlines colormode $_colorMode ${name} $dataset"
1570                SendCmd "cutplane colormode $_colorMode ${name} $dataset"
1571            }
1572            set _legendPending 1
1573        }
1574        default {
1575            error "don't know how to fix $what"
1576        }
1577    }
1578}
1579
1580#
1581# RequestLegend --
1582#
1583#       Request a new legend from the server.  The size of the legend
1584#       is determined from the height of the canvas.  It will be rotated
1585#       to be vertical when drawn.
1586#
1587itcl::body Rappture::VtkStreamlinesViewer::RequestLegend {} {
1588    set font "Arial 8"
1589    set lineht [font metrics $font -linespace]
1590    set c $itk_component(legend)
1591    set w 12
1592    set h [expr {$_height - 3 * ($lineht + 2)}]
1593    if { $h < 1} {
1594        return
1595    }
1596    if { [info exists _scalarFields($_currentField)] } {
1597        set name $_scalarFields($_currentField)
1598    } elseif { [info exists _vectorFields($_currentField)] } {
1599        set name $_vectorFields($_currentField)
1600    } else {
1601        return
1602    }
1603    # Set the legend on the first streamlines dataset.
1604    foreach dataset [CurrentDatasets -visible $_first] {
1605        foreach {dataobj comp} [split $dataset -] break
1606        if { [info exists _dataset2style($dataset)] } {
1607            SendCmdNoSplash \
1608                "legend $_dataset2style($dataset) $_colorMode $name {} $w $h 0"
1609            break;
1610        }
1611    }
1612}
1613
1614#
1615# ChangeColormap --
1616#
1617itcl::body Rappture::VtkStreamlinesViewer::ChangeColormap {dataobj comp color} {
1618    set tag $dataobj-$comp
1619    if { ![info exist _style($tag)] } {
1620        error "no initial colormap"
1621    }
1622    array set style $_style($tag)
1623    set style(-color) $color
1624    set _style($tag) [array get style]
1625    SetColormap $dataobj $comp
1626}
1627
1628#
1629# SetColormap --
1630#
1631itcl::body Rappture::VtkStreamlinesViewer::SetColormap { dataobj comp } {
1632    array set style {
1633        -color BCGYR
1634        -levels 6
1635        -opacity 1.0
1636    }
1637    set tag $dataobj-$comp
1638    if { ![info exists _initialStyle($tag)] } {
1639        # Save the initial component style.
1640        set _initialStyle($tag) [$dataobj style $comp]
1641    }
1642
1643    # Override defaults with initial style defined in xml.
1644    array set style $_initialStyle($tag)
1645
1646    if { ![info exists _style($tag)] } {
1647        set _style($tag) [array get style]
1648    }
1649    # Override initial style with current style.
1650    array set style $_style($tag)
1651
1652    set name "$style(-color):$style(-levels):$style(-opacity)"
1653    if { ![info exists _colormaps($name)] } {
1654        BuildColormap $name [array get style]
1655        set _colormaps($name) 1
1656    }
1657    if { ![info exists _dataset2style($tag)] ||
1658         $_dataset2style($tag) != $name } {
1659        SendCmd "streamlines colormap $name $tag"
1660        SendCmd "cutplane colormap $name $tag"
1661        set _dataset2style($tag) $name
1662    }
1663}
1664
1665itcl::body Rappture::VtkStreamlinesViewer::ColorsToColormap { colors } {
1666    switch -- $colors {
1667        "grey-to-blue" {
1668            return {
1669                0.0                      0.200 0.200 0.200
1670                0.14285714285714285      0.400 0.400 0.400
1671                0.2857142857142857       0.600 0.600 0.600
1672                0.42857142857142855      0.900 0.900 0.900
1673                0.5714285714285714       0.800 1.000 1.000
1674                0.7142857142857143       0.600 1.000 1.000
1675                0.8571428571428571       0.400 0.900 1.000
1676                1.0                      0.000 0.600 0.800
1677            }
1678        }
1679        "blue-to-grey" {
1680            return {
1681                0.0                     0.000 0.600 0.800
1682                0.14285714285714285     0.400 0.900 1.000
1683                0.2857142857142857      0.600 1.000 1.000
1684                0.42857142857142855     0.800 1.000 1.000
1685                0.5714285714285714      0.900 0.900 0.900
1686                0.7142857142857143      0.600 0.600 0.600
1687                0.8571428571428571      0.400 0.400 0.400
1688                1.0                     0.200 0.200 0.200
1689            }
1690        }
1691        "blue" {
1692            return {
1693                0.0                     0.900 1.000 1.000
1694                0.1111111111111111      0.800 0.983 1.000
1695                0.2222222222222222      0.700 0.950 1.000
1696                0.3333333333333333      0.600 0.900 1.000
1697                0.4444444444444444      0.500 0.833 1.000
1698                0.5555555555555556      0.400 0.750 1.000
1699                0.6666666666666666      0.300 0.650 1.000
1700                0.7777777777777778      0.200 0.533 1.000
1701                0.8888888888888888      0.100 0.400 1.000
1702                1.0                     0.000 0.250 1.000
1703            }
1704        }
1705        "brown-to-blue" {
1706            return {
1707                0.0                             0.200   0.100   0.000
1708                0.09090909090909091             0.400   0.187   0.000
1709                0.18181818181818182             0.600   0.379   0.210
1710                0.2727272727272727              0.800   0.608   0.480
1711                0.36363636363636365             0.850   0.688   0.595
1712                0.45454545454545453             0.950   0.855   0.808
1713                0.5454545454545454              0.800   0.993   1.000
1714                0.6363636363636364              0.600   0.973   1.000
1715                0.7272727272727273              0.400   0.940   1.000
1716                0.8181818181818182              0.200   0.893   1.000
1717                0.9090909090909091              0.000   0.667   0.800
1718                1.0                             0.000   0.480   0.600
1719            }
1720        }
1721        "blue-to-brown" {
1722            return {
1723                0.0                             0.000   0.480   0.600
1724                0.09090909090909091             0.000   0.667   0.800
1725                0.18181818181818182             0.200   0.893   1.000
1726                0.2727272727272727              0.400   0.940   1.000
1727                0.36363636363636365             0.600   0.973   1.000
1728                0.45454545454545453             0.800   0.993   1.000
1729                0.5454545454545454              0.950   0.855   0.808
1730                0.6363636363636364              0.850   0.688   0.595
1731                0.7272727272727273              0.800   0.608   0.480
1732                0.8181818181818182              0.600   0.379   0.210
1733                0.9090909090909091              0.400   0.187   0.000
1734                1.0                             0.200   0.100   0.000
1735            }
1736        }
1737        "blue-to-orange" {
1738            return {
1739                0.0                             0.000   0.167   1.000
1740                0.09090909090909091             0.100   0.400   1.000
1741                0.18181818181818182             0.200   0.600   1.000
1742                0.2727272727272727              0.400   0.800   1.000
1743                0.36363636363636365             0.600   0.933   1.000
1744                0.45454545454545453             0.800   1.000   1.000
1745                0.5454545454545454              1.000   1.000   0.800
1746                0.6363636363636364              1.000   0.933   0.600
1747                0.7272727272727273              1.000   0.800   0.400
1748                0.8181818181818182              1.000   0.600   0.200
1749                0.9090909090909091              1.000   0.400   0.100
1750                1.0                             1.000   0.167   0.000
1751            }
1752        }
1753        "orange-to-blue" {
1754            return {
1755                0.0                             1.000   0.167   0.000
1756                0.09090909090909091             1.000   0.400   0.100
1757                0.18181818181818182             1.000   0.600   0.200
1758                0.2727272727272727              1.000   0.800   0.400
1759                0.36363636363636365             1.000   0.933   0.600
1760                0.45454545454545453             1.000   1.000   0.800
1761                0.5454545454545454              0.800   1.000   1.000
1762                0.6363636363636364              0.600   0.933   1.000
1763                0.7272727272727273              0.400   0.800   1.000
1764                0.8181818181818182              0.200   0.600   1.000
1765                0.9090909090909091              0.100   0.400   1.000
1766                1.0                             0.000   0.167   1.000
1767            }
1768        }
1769        "rainbow" {
1770            set clist {
1771                "#EE82EE"
1772                "#4B0082"
1773                "blue"
1774                "#008000"
1775                "yellow"
1776                "#FFA500"
1777                "red"
1778            }
1779        }
1780        "BGYOR" {
1781            set clist {
1782                "blue"
1783                "#008000"
1784                "yellow"
1785                "#FFA500"
1786                "red"
1787            }
1788        }
1789        "ROYGB" {
1790            set clist {
1791                "red"
1792                "#FFA500"
1793                "yellow"
1794                "#008000"
1795                "blue"
1796            }
1797        }
1798        "RYGCB" {
1799            set clist {
1800                "red"
1801                "yellow"
1802                "green"
1803                "cyan"
1804                "blue"
1805            }
1806        }
1807        "BCGYR" {
1808            set clist {
1809                "blue"
1810                "cyan"
1811                "green"
1812                "yellow"
1813                "red"
1814            }
1815        }
1816        "spectral" {
1817            return {
1818                0.0 0.150 0.300 1.000
1819                0.1 0.250 0.630 1.000
1820                0.2 0.450 0.850 1.000
1821                0.3 0.670 0.970 1.000
1822                0.4 0.880 1.000 1.000
1823                0.5 1.000 1.000 0.750
1824                0.6 1.000 0.880 0.600
1825                0.7 1.000 0.680 0.450
1826                0.8 0.970 0.430 0.370
1827                0.9 0.850 0.150 0.196
1828                1.0 0.650 0.000 0.130
1829            }
1830        }
1831        "green-to-magenta" {
1832            return {
1833                0.0 0.000 0.316 0.000
1834                0.06666666666666667 0.000 0.526 0.000
1835                0.13333333333333333 0.000 0.737 0.000
1836                0.2 0.000 0.947 0.000
1837                0.26666666666666666 0.316 1.000 0.316
1838                0.3333333333333333 0.526 1.000 0.526
1839                0.4 0.737 1.000 0.737
1840                0.4666666666666667 1.000 1.000 1.000
1841                0.5333333333333333 1.000 0.947 1.000
1842                0.6 1.000 0.737 1.000
1843                0.6666666666666666 1.000 0.526 1.000
1844                0.7333333333333333 1.000 0.316 1.000
1845                0.8 0.947 0.000 0.947
1846                0.8666666666666667 0.737 0.000 0.737
1847                0.9333333333333333 0.526 0.000 0.526
1848                1.0 0.316 0.000 0.316
1849            }
1850        }
1851        "greyscale" {
1852            return {
1853                0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
1854            }
1855        }
1856        "nanohub" {
1857            set clist "white yellow green cyan blue magenta"
1858        }
1859        default {
1860            set clist $colors
1861        }
1862    }
1863    set cmap {}
1864    for {set i 0} {$i < [llength $clist]} {incr i} {
1865        set x [expr {double($i)/([llength $clist]-1)}]
1866        set color [lindex $clist $i]
1867        append cmap "$x [Color2RGB $color] "
1868    }
1869    return $cmap
1870}
1871
1872#
1873# BuildColormap --
1874#
1875itcl::body Rappture::VtkStreamlinesViewer::BuildColormap { name styles } {
1876    array set style $styles
1877    set cmap [ColorsToColormap $style(-color)]
1878    if { [llength $cmap] == 0 } {
1879        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1880    }
1881    if { ![info exists _settings(volume-opacity)] } {
1882        set _settings(volume-opacity) $style(-opacity)
1883    }
1884    set max $_settings(volume-opacity)
1885
1886    set wmap "0.0 1.0 1.0 1.0"
1887    SendCmd "colormap add $name { $cmap } { $wmap }"
1888}
1889
1890# ----------------------------------------------------------------------
1891# CONFIGURATION OPTION: -plotbackground
1892# ----------------------------------------------------------------------
1893itcl::configbody Rappture::VtkStreamlinesViewer::plotbackground {
1894    if { [isconnected] } {
1895        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1896        SendCmd "screen bgcolor $r $g $b"
1897    }
1898}
1899
1900# ----------------------------------------------------------------------
1901# CONFIGURATION OPTION: -plotforeground
1902# ----------------------------------------------------------------------
1903itcl::configbody Rappture::VtkStreamlinesViewer::plotforeground {
1904    if { [isconnected] } {
1905        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1906        #fix this!
1907        #SendCmd "color background $r $g $b"
1908    }
1909}
1910
1911itcl::body Rappture::VtkStreamlinesViewer::limits { dataobj } {
1912    return
1913    array unset _limits $dataobj-*
1914    foreach comp [$dataobj components] {
1915        set tag $dataobj-$comp
1916        if { ![info exists _limits($tag)] } {
1917            set data [$dataobj blob $comp]
1918            set tmpfile file[pid].vtk
1919            set f [open "$tmpfile" "w"]
1920            fconfigure $f -translation binary -encoding binary
1921            puts $f $data
1922            close $f
1923            set reader [vtkDataSetReader $tag-xvtkDataSetReader]
1924            $reader SetFileName $tmpfile
1925            $reader ReadAllScalarsOn
1926            $reader ReadAllVectorsOn
1927            $reader ReadAllFieldsOn
1928            $reader Update
1929            set output [$reader GetOutput]
1930            set _limits($tag) [$output GetBounds]
1931            set pointData [$output GetPointData]
1932            puts stderr "\#scalars=[$reader GetNumberOfScalarsInFile]"
1933            puts stderr "\#fielddata=[$reader GetNumberOfFieldDataInFile]"
1934            puts stderr "fielddataname=[$reader GetFieldDataNameInFile 0]"
1935            set fieldData [$output GetFieldData]
1936            set pointData [$output GetPointData]
1937            puts stderr "field \#arrays=[$fieldData GetNumberOfArrays]"
1938            for { set i 0 } { $i < [$fieldData GetNumberOfArrays] } { incr i } {
1939                puts stderr [$fieldData GetArrayName $i]
1940            }
1941            puts stderr "point \#arrays=[$pointData GetNumberOfArrays]"
1942            for { set i 0 } { $i < [$pointData GetNumberOfArrays] } { incr i } {
1943                set name [$pointData GetArrayName $i]
1944                if { ![info exists _fields($name)] } {
1945                    $itk_component(field) choices insert end "$name" "$name"
1946                    set _fields($name) 1
1947                }
1948            }
1949            puts stderr "field \#components=[$fieldData GetNumberOfComponents]"
1950            puts stderr "point \#components=[$pointData GetNumberOfComponents]"
1951            puts stderr "field \#tuples=[$fieldData GetNumberOfTuples]"
1952            puts stderr "point \#tuples=[$pointData GetNumberOfTuples]"
1953            puts stderr "point \#scalars=[$pointData GetScalars]"
1954            puts stderr vectors=[$pointData GetVectors]
1955            rename $output ""
1956            rename $reader ""
1957            file delete $tmpfile
1958        }
1959        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1960        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1961            set limits(xmin) $xMin
1962        }
1963        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1964            set limits(xmax) $xMax
1965        }
1966        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1967            set limits(ymin) $xMin
1968        }
1969        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1970            set limits(ymax) $yMax
1971        }
1972        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1973            set limits(zmin) $zMin
1974        }
1975        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1976            set limits(zmax) $zMax
1977        }
1978    }
1979    return [array get limits]
1980}
1981
1982itcl::body Rappture::VtkStreamlinesViewer::BuildVolumeTab {} {
1983
1984    set fg [option get $itk_component(hull) font Font]
1985    #set bfg [option get $itk_component(hull) boldFont Font]
1986
1987    set inner [$itk_component(main) insert end \
1988        -title "Volume Settings" \
1989        -icon [Rappture::icon volume-on]]
1990    $inner configure -borderwidth 4
1991
1992    checkbutton $inner.volume \
1993        -text "Show Volume" \
1994        -variable [itcl::scope _settings(volume-visible)] \
1995        -command [itcl::code $this AdjustSetting volume-visible] \
1996        -font "Arial 9"
1997
1998    checkbutton $inner.wireframe \
1999        -text "Show Wireframe" \
2000        -variable [itcl::scope _settings(volume-wireframe)] \
2001        -command [itcl::code $this AdjustSetting volume-wireframe] \
2002        -font "Arial 9"
2003
2004    checkbutton $inner.lighting \
2005        -text "Enable Lighting" \
2006        -variable [itcl::scope _settings(volume-lighting)] \
2007        -command [itcl::code $this AdjustSetting volume-lighting] \
2008        -font "Arial 9"
2009
2010    checkbutton $inner.edges \
2011        -text "Show Edges" \
2012        -variable [itcl::scope _settings(volume-edges)] \
2013        -command [itcl::code $this AdjustSetting volume-edges] \
2014        -font "Arial 9"
2015
2016    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2017    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2018        -variable [itcl::scope _settings(volume-opacity)] \
2019        -width 10 \
2020        -showvalue off \
2021        -command [itcl::code $this AdjustSetting volume-opacity]
2022
2023    blt::table $inner \
2024        0,0 $inner.volume    -anchor w -pady 2 \
2025        1,0 $inner.wireframe -anchor w -pady 2 \
2026        2,0 $inner.lighting  -anchor w -pady 2 \
2027        3,0 $inner.edges     -anchor w -pady 2 \
2028        4,0 $inner.opacity_l -anchor w -pady 2 \
2029        5,0 $inner.opacity   -fill x   -pady 2
2030
2031    blt::table configure $inner r* c* -resize none
2032    blt::table configure $inner r6 c1 -resize expand
2033}
2034
2035
2036itcl::body Rappture::VtkStreamlinesViewer::BuildStreamsTab {} {
2037
2038    set fg [option get $itk_component(hull) font Font]
2039    #set bfg [option get $itk_component(hull) boldFont Font]
2040
2041    set inner [$itk_component(main) insert end \
2042        -title "Streams Settings" \
2043        -icon [Rappture::icon streamlines-on]]
2044    $inner configure -borderwidth 4
2045
2046    checkbutton $inner.streamlines \
2047        -text "Show Streamlines" \
2048        -variable [itcl::scope _settings(streamlines-visible)] \
2049        -command [itcl::code $this AdjustSetting streamlines-visible] \
2050        -font "Arial 9"
2051   
2052    checkbutton $inner.lighting \
2053        -text "Enable Lighting" \
2054        -variable [itcl::scope _settings(streamlines-lighting)] \
2055        -command [itcl::code $this AdjustSetting streamlines-lighting] \
2056        -font "Arial 9"
2057
2058    checkbutton $inner.seeds \
2059        -text "Show Seeds" \
2060        -variable [itcl::scope _settings(streamlines-seeds)] \
2061        -command [itcl::code $this AdjustSetting streamlines-seeds] \
2062        -font "Arial 9"
2063
2064    label $inner.mode_l -text "Mode" -font "Arial 9"
2065    itk_component add streammode {
2066        Rappture::Combobox $inner.mode -width 10 -editable no
2067    }
2068    $inner.mode choices insert end \
2069        "lines"    "lines" \
2070        "ribbons"   "ribbons" \
2071        "tubes"     "tubes"
2072    $itk_component(streammode) value "lines"
2073    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting streamlines-mode]
2074
2075    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2076    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2077        -variable [itcl::scope _settings(streamlines-opacity)] \
2078        -width 10 \
2079        -showvalue off \
2080        -command [itcl::code $this AdjustSetting streamlines-opacity]
2081
2082    label $inner.density_l -text "Number of Seeds" -font "Arial 9"
2083    ::scale $inner.density -from 1 -to 1000 -orient horizontal \
2084        -variable [itcl::scope _settings(streamlines-numpoints)] \
2085        -width 10 \
2086        -showvalue on \
2087        -command [itcl::code $this AdjustSetting streamlines-numpoints]
2088
2089    label $inner.scale_l -text "Scale" -font "Arial 9"
2090    ::scale $inner.scale -from 1 -to 100 -orient horizontal \
2091        -variable [itcl::scope _settings(streamlines-scale)] \
2092        -width 10 \
2093        -showvalue off \
2094        -command [itcl::code $this AdjustSetting streamlines-scale]
2095
2096    label $inner.field_l -text "Field" -font "Arial 9"
2097    itk_component add field {
2098        Rappture::Combobox $inner.field -width 10 -editable no
2099    }
2100    bind $inner.field <<Value>> \
2101        [itcl::code $this AdjustSetting streamlines-field]
2102
2103    label $inner.palette_l -text "Palette" -font "Arial 9"
2104    itk_component add palette {
2105        Rappture::Combobox $inner.palette -width 10 -editable no
2106    }
2107    $inner.palette choices insert end \
2108        "BCGYR"              "BCGYR"            \
2109        "BGYOR"              "BGYOR"            \
2110        "blue"               "blue"             \
2111        "blue-to-brown"      "blue-to-brown"    \
2112        "blue-to-orange"     "blue-to-orange"   \
2113        "blue-to-grey"       "blue-to-grey"     \
2114        "green-to-magenta"   "green-to-magenta" \
2115        "greyscale"          "greyscale"        \
2116        "nanohub"            "nanohub"          \
2117        "rainbow"            "rainbow"          \
2118        "spectral"           "spectral"         \
2119        "ROYGB"              "ROYGB"            \
2120        "RYGCB"              "RYGCB"            \
2121        "brown-to-blue"      "brown-to-blue"    \
2122        "grey-to-blue"       "grey-to-blue"     \
2123        "orange-to-blue"     "orange-to-blue"   
2124
2125    $itk_component(palette) value "BCGYR"
2126    bind $inner.palette <<Value>> \
2127        [itcl::code $this AdjustSetting streamlines-palette]
2128
2129    blt::table $inner \
2130        0,0 $inner.streamlines -anchor w -pady 2 -cspan 2 \
2131        1,0 $inner.lighting    -anchor w -pady 2 -cspan 2 \
2132        2,0 $inner.seeds       -anchor w -pady 2 -cspan 2 \
2133        3,0 $inner.density_l   -anchor w -pady 2 -cspan 2 \
2134        4,0 $inner.density     -fill x   -pady 2 -cspan 2 \
2135        5,0 $inner.mode_l      -anchor w -pady 2  \
2136        5,1 $inner.mode        -anchor w -pady 2  \
2137        6,0 $inner.opacity_l   -anchor w -pady 2 -cspan 2 \
2138        7,0 $inner.opacity     -fill x   -pady 2 -cspan 2 \
2139        8,0 $inner.field_l     -anchor w -pady 2  \
2140        8,1 $inner.field       -anchor w -pady 2  \
2141        9,0 $inner.palette_l   -anchor w -pady 2  \
2142        9,1 $inner.palette     -anchor w -pady 2  \
2143       
2144
2145    blt::table configure $inner r* c* -resize none
2146    blt::table configure $inner r10 c1 c2 -resize expand
2147}
2148
2149itcl::body Rappture::VtkStreamlinesViewer::BuildAxisTab {} {
2150
2151    set fg [option get $itk_component(hull) font Font]
2152    #set bfg [option get $itk_component(hull) boldFont Font]
2153
2154    set inner [$itk_component(main) insert end \
2155        -title "Axis Settings" \
2156        -icon [Rappture::icon axis1]]
2157    $inner configure -borderwidth 4
2158
2159    checkbutton $inner.visible \
2160        -text "Show Axes" \
2161        -variable [itcl::scope _settings(axis-visible)] \
2162        -command [itcl::code $this AdjustSetting axis-visible] \
2163        -font "Arial 9"
2164
2165    checkbutton $inner.labels \
2166        -text "Show Axis Labels" \
2167        -variable [itcl::scope _settings(axis-labels)] \
2168        -command [itcl::code $this AdjustSetting axis-labels] \
2169        -font "Arial 9"
2170
2171    checkbutton $inner.gridx \
2172        -text "Show X Grid" \
2173        -variable [itcl::scope _settings(axis-xgrid)] \
2174        -command [itcl::code $this AdjustSetting axis-xgrid] \
2175        -font "Arial 9"
2176    checkbutton $inner.gridy \
2177        -text "Show Y Grid" \
2178        -variable [itcl::scope _settings(axis-ygrid)] \
2179        -command [itcl::code $this AdjustSetting axis-ygrid] \
2180        -font "Arial 9"
2181    checkbutton $inner.gridz \
2182        -text "Show Z Grid" \
2183        -variable [itcl::scope _settings(axis-zgrid)] \
2184        -command [itcl::code $this AdjustSetting axis-zgrid] \
2185        -font "Arial 9"
2186
2187    label $inner.mode_l -text "Mode" -font "Arial 9"
2188
2189    itk_component add axismode {
2190        Rappture::Combobox $inner.mode -width 10 -editable no
2191    }
2192    $inner.mode choices insert end \
2193        "static_triad"    "static" \
2194        "closest_triad"   "closest" \
2195        "furthest_triad"  "furthest" \
2196        "outer_edges"     "outer"         
2197    $itk_component(axismode) value "static"
2198    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
2199
2200    blt::table $inner \
2201        0,0 $inner.visible -anchor w -cspan 2 \
2202        1,0 $inner.labels  -anchor w -cspan 2 \
2203        2,0 $inner.gridx   -anchor w -cspan 2 \
2204        3,0 $inner.gridy   -anchor w -cspan 2 \
2205        4,0 $inner.gridz   -anchor w -cspan 2 \
2206        5,0 $inner.mode_l  -anchor w -cspan 2 -padx { 2 0 } \
2207        6,0 $inner.mode    -fill x   -cspan 2
2208
2209    blt::table configure $inner r* c* -resize none
2210    blt::table configure $inner r7 c1 -resize expand
2211}
2212
2213
2214itcl::body Rappture::VtkStreamlinesViewer::BuildCameraTab {} {
2215    set inner [$itk_component(main) insert end \
2216        -title "Camera Settings" \
2217        -icon [Rappture::icon camera]]
2218    $inner configure -borderwidth 4
2219
2220    set labels { qx qy qz qw xpan ypan zoom }
2221    set row 0
2222    foreach tag $labels {
2223        label $inner.${tag}label -text $tag -font "Arial 9"
2224        entry $inner.${tag} -font "Arial 9"  -bg white \
2225            -textvariable [itcl::scope _view($tag)]
2226        bind $inner.${tag} <KeyPress-Return> \
2227            [itcl::code $this camera set ${tag}]
2228        blt::table $inner \
2229            $row,0 $inner.${tag}label -anchor e -pady 2 \
2230            $row,1 $inner.${tag} -anchor w -pady 2
2231        blt::table configure $inner r$row -resize none
2232        incr row
2233    }
2234    checkbutton $inner.ortho \
2235        -text "Orthographic Projection" \
2236        -variable [itcl::scope _view(ortho)] \
2237        -command [itcl::code $this camera set ortho] \
2238        -font "Arial 9"
2239    blt::table $inner \
2240            $row,0 $inner.ortho -columnspan 2 -anchor w -pady 2
2241    blt::table configure $inner r$row -resize none
2242    incr row
2243
2244    blt::table configure $inner c0 c1 -resize none
2245    blt::table configure $inner c2 -resize expand
2246    blt::table configure $inner r$row -resize expand
2247}
2248
2249itcl::body Rappture::VtkStreamlinesViewer::BuildCutplaneTab {} {
2250
2251    set fg [option get $itk_component(hull) font Font]
2252   
2253    set inner [$itk_component(main) insert end \
2254        -title "Cutplane Settings" \
2255        -icon [Rappture::icon cutbutton]]
2256
2257    $inner configure -borderwidth 4
2258
2259    checkbutton $inner.visible \
2260        -text "Show Cutplanes" \
2261        -variable [itcl::scope _settings(cutplane-visible)] \
2262        -command [itcl::code $this AdjustSetting cutplane-visible] \
2263        -font "Arial 9"
2264
2265    checkbutton $inner.wireframe \
2266        -text "Show Wireframe" \
2267        -variable [itcl::scope _settings(cutplane-wireframe)] \
2268        -command [itcl::code $this AdjustSetting cutplane-wireframe] \
2269        -font "Arial 9"
2270
2271    checkbutton $inner.lighting \
2272        -text "Enable Lighting" \
2273        -variable [itcl::scope _settings(cutplane-lighting)] \
2274        -command [itcl::code $this AdjustSetting cutplane-lighting] \
2275        -font "Arial 9"
2276
2277    checkbutton $inner.edges \
2278        -text "Show Edges" \
2279        -variable [itcl::scope _settings(cutplane-edges)] \
2280        -command [itcl::code $this AdjustSetting cutplane-edges] \
2281        -font "Arial 9"
2282
2283    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2284    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2285        -variable [itcl::scope _settings(cutplane-opacity)] \
2286        -width 10 \
2287        -showvalue off \
2288        -command [itcl::code $this AdjustSetting cutplane-opacity]
2289    $inner.opacity set $_settings(cutplane-opacity)
2290
2291    # X-value slicer...
2292    itk_component add xCutButton {
2293        Rappture::PushButton $inner.xbutton \
2294            -onimage [Rappture::icon x-cutplane] \
2295            -offimage [Rappture::icon x-cutplane] \
2296            -command [itcl::code $this AdjustSetting cutplane-xvisible] \
2297            -variable [itcl::scope _settings(cutplane-xvisible)]
2298    }
2299    Rappture::Tooltip::for $itk_component(xCutButton) \
2300        "Toggle the X-axis cutplane on/off"
2301
2302    itk_component add xCutScale {
2303        ::scale $inner.xval -from 100 -to 1 \
2304            -width 10 -orient vertical -showvalue yes \
2305            -borderwidth 1 -highlightthickness 0 \
2306            -command [itcl::code $this EventuallySetCutplane x] \
2307            -variable [itcl::scope _settings(cutplane-xposition)]
2308    } {
2309        usual
2310        ignore -borderwidth -highlightthickness
2311    }
2312    # Set the default cutplane value before disabling the scale.
2313    $itk_component(xCutScale) set 50
2314    $itk_component(xCutScale) configure -state disabled
2315    Rappture::Tooltip::for $itk_component(xCutScale) \
2316        "@[itcl::code $this Slice tooltip x]"
2317
2318    # Y-value slicer...
2319    itk_component add yCutButton {
2320        Rappture::PushButton $inner.ybutton \
2321            -onimage [Rappture::icon y-cutplane] \
2322            -offimage [Rappture::icon y-cutplane] \
2323            -command [itcl::code $this AdjustSetting cutplane-yvisible] \
2324            -variable [itcl::scope _settings(cutplane-yvisible)]
2325    }
2326    Rappture::Tooltip::for $itk_component(yCutButton) \
2327        "Toggle the Y-axis cutplane on/off"
2328
2329    itk_component add yCutScale {
2330        ::scale $inner.yval -from 100 -to 1 \
2331            -width 10 -orient vertical -showvalue yes \
2332            -borderwidth 1 -highlightthickness 0 \
2333            -command [itcl::code $this EventuallySetCutplane y] \
2334            -variable [itcl::scope _settings(cutplane-yposition)]
2335    } {
2336        usual
2337        ignore -borderwidth -highlightthickness
2338    }
2339    Rappture::Tooltip::for $itk_component(yCutScale) \
2340        "@[itcl::code $this Slice tooltip y]"
2341    # Set the default cutplane value before disabling the scale.
2342    $itk_component(yCutScale) set 50
2343    $itk_component(yCutScale) configure -state disabled
2344
2345    # Z-value slicer...
2346    itk_component add zCutButton {
2347        Rappture::PushButton $inner.zbutton \
2348            -onimage [Rappture::icon z-cutplane] \
2349            -offimage [Rappture::icon z-cutplane] \
2350            -command [itcl::code $this AdjustSetting cutplane-zvisible] \
2351            -variable [itcl::scope _settings(cutplane-zvisible)]
2352    }
2353    Rappture::Tooltip::for $itk_component(zCutButton) \
2354        "Toggle the Z-axis cutplane on/off"
2355
2356    itk_component add zCutScale {
2357        ::scale $inner.zval -from 100 -to 1 \
2358            -width 10 -orient vertical -showvalue yes \
2359            -borderwidth 1 -highlightthickness 0 \
2360            -command [itcl::code $this EventuallySetCutplane z] \
2361            -variable [itcl::scope _settings(cutplane-zposition)]
2362    } {
2363        usual
2364        ignore -borderwidth -highlightthickness
2365    }
2366    $itk_component(zCutScale) set 50
2367    $itk_component(zCutScale) configure -state disabled
2368    #$itk_component(zCutScale) configure -state disabled
2369    Rappture::Tooltip::for $itk_component(zCutScale) \
2370        "@[itcl::code $this Slice tooltip z]"
2371
2372    blt::table $inner \
2373        0,0 $inner.visible              -anchor w -pady 2 -cspan 4 \
2374        1,0 $inner.lighting             -anchor w -pady 2 -cspan 4 \
2375        2,0 $inner.wireframe            -anchor w -pady 2 -cspan 4 \
2376        3,0 $inner.edges                -anchor w -pady 2 -cspan 4 \
2377        4,0 $inner.opacity_l            -anchor w -pady 2 -cspan 3 \
2378        5,0 $inner.opacity              -fill x   -pady 2 -cspan 3 \
2379        6,0 $itk_component(xCutButton)  -anchor e -padx 2 -pady 2 \
2380        7,0 $itk_component(xCutScale)   -fill y \
2381        6,1 $itk_component(yCutButton)  -anchor e -padx 2 -pady 2 \
2382        7,1 $itk_component(yCutScale)   -fill y \
2383        6,2 $itk_component(zCutButton)  -anchor e -padx 2 -pady 2 \
2384        7,2 $itk_component(zCutScale)   -fill y \
2385
2386    blt::table configure $inner r* c* -resize none
2387    blt::table configure $inner r7 c3 -resize expand
2388}
2389
2390
2391
2392#
2393#  camera --
2394#
2395itcl::body Rappture::VtkStreamlinesViewer::camera {option args} {
2396    switch -- $option {
2397        "show" {
2398            puts [array get _view]
2399        }
2400        "set" {
2401            set who [lindex $args 0]
2402            set x $_view($who)
2403            set code [catch { string is double $x } result]
2404            if { $code != 0 || !$result } {
2405                return
2406            }
2407            switch -- $who {
2408                "ortho" {
2409                    if {$_view(ortho)} {
2410                        SendCmd "camera mode ortho"
2411                    } else {
2412                        SendCmd "camera mode persp"
2413                    }
2414                }
2415                "xpan" - "ypan" {
2416                    PanCamera
2417                }
2418                "qx" - "qy" - "qz" - "qw" {
2419                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2420                    $_arcball quaternion $q
2421                    EventuallyRotate $q
2422                }
2423                "zoom" {
2424                    SendCmd "camera zoom $_view(zoom)"
2425                }
2426            }
2427        }
2428    }
2429}
2430
2431itcl::body Rappture::VtkStreamlinesViewer::ConvertToVtkData { dataobj comp } {
2432    foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $comp] break
2433    set values [$dataobj values $comp]
2434    append out "# vtk DataFile Version 2.0 \n"
2435    append out "Test data \n"
2436    append out "ASCII \n"
2437    append out "DATASET STRUCTURED_POINTS \n"
2438    append out "DIMENSIONS $xN $yN 1 \n"
2439    append out "ORIGIN 0 0 0 \n"
2440    append out "SPACING 1 1 1 \n"
2441    append out "POINT_DATA [expr $xN * $yN] \n"
2442    append out "SCALARS field float 1 \n"
2443    append out "LOOKUP_TABLE default \n"
2444    append out [join $values "\n"]
2445    append out "\n"
2446    return $out
2447}
2448
2449
2450itcl::body Rappture::VtkStreamlinesViewer::GetVtkData { args } {
2451    set bytes ""
2452    foreach dataobj [get] {
2453        foreach comp [$dataobj components] {
2454            set tag $dataobj-$comp
2455            #set contents [ConvertToVtkData $dataobj $comp]
2456            set contents [$dataobj blob $comp]
2457            append bytes "$contents\n\n"
2458        }
2459    }
2460    return [list .vtk $bytes]
2461}
2462
2463itcl::body Rappture::VtkStreamlinesViewer::GetImage { args } {
2464    if { [image width $_image(download)] > 0 &&
2465         [image height $_image(download)] > 0 } {
2466        set bytes [$_image(download) data -format "jpeg -quality 100"]
2467        set bytes [Rappture::encoding::decode -as b64 $bytes]
2468        return [list .jpg $bytes]
2469    }
2470    return ""
2471}
2472
2473itcl::body Rappture::VtkStreamlinesViewer::BuildDownloadPopup { popup command } {
2474    Rappture::Balloon $popup \
2475        -title "[Rappture::filexfer::label downloadWord] as..."
2476    set inner [$popup component inner]
2477    label $inner.summary -text "" -anchor w
2478    radiobutton $inner.vtk_button -text "VTK data file" \
2479        -variable [itcl::scope _downloadPopup(format)] \
2480        -font "Helvetica 9 " \
2481        -value vtk 
2482    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
2483    radiobutton $inner.image_button -text "Image File" \
2484        -variable [itcl::scope _downloadPopup(format)] \
2485        -value image
2486    Rappture::Tooltip::for $inner.image_button \
2487        "Save as digital image."
2488
2489    button $inner.ok -text "Save" \
2490        -highlightthickness 0 -pady 2 -padx 3 \
2491        -command $command \
2492        -compound left \
2493        -image [Rappture::icon download]
2494
2495    button $inner.cancel -text "Cancel" \
2496        -highlightthickness 0 -pady 2 -padx 3 \
2497        -command [list $popup deactivate] \
2498        -compound left \
2499        -image [Rappture::icon cancel]
2500
2501    blt::table $inner \
2502        0,0 $inner.summary -cspan 2  \
2503        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
2504        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
2505        4,1 $inner.cancel -width .9i -fill y \
2506        4,0 $inner.ok -padx 2 -width .9i -fill y
2507    blt::table configure $inner r3 -height 4
2508    blt::table configure $inner r4 -pady 4
2509    raise $inner.image_button
2510    $inner.vtk_button invoke
2511    return $inner
2512}
2513
2514itcl::body Rappture::VtkStreamlinesViewer::SetObjectStyle { dataobj comp } {
2515    # Parse style string.
2516    set tag $dataobj-$comp
2517    set style [$dataobj style $comp]
2518    array set settings {
2519        -color \#808080
2520        -edges 0
2521        -edgecolor black
2522        -linewidth 1.0
2523        -opacity 0.4
2524        -wireframe 0
2525        -lighting 1
2526        -seeds 1
2527        -seedcolor white
2528        -visible 1
2529    }
2530    if { $dataobj != $_first } {
2531        set settings(-opacity) 1
2532    }
2533    array set settings $style
2534    SendCmd "streamlines add $tag"
2535    SendCmd "streamlines seed visible off $tag"
2536    set seeds [$dataobj hints seeds]
2537    if { $seeds != "" && ![info exists _seeds($dataobj)] } {
2538        set length [string length $seeds]
2539        SendCmd "streamlines seed fmesh 200 data follows $length $tag"
2540        SendCmd "$seeds"
2541        set _seeds($dataobj) 1
2542    }
2543    SendCmd "cutplane add $tag"
2544    SendCmd "cutplane edges 0 $tag"
2545    SendCmd "cutplane wireframe 0 $tag"
2546    SendCmd "cutplane lighting 1 $tag"
2547    SendCmd "cutplane linewidth 1 $tag"
2548    #SendCmd "cutplane linecolor 1 1 1 $tag"
2549    #SendCmd "cutplane visible $tag"
2550    foreach axis { x y z } {
2551        SendCmd "cutplane slice $axis 0.5 $tag"
2552        SendCmd "cutplane axis $axis 0 $tag"
2553    }
2554
2555    SendCmd "polydata add $tag"
2556    SendCmd "polydata edges $settings(-edges) $tag"
2557    set _settings(volume-edges) $settings(-edges)
2558    SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
2559    SendCmd "polydata lighting $settings(-lighting) $tag"
2560    set _settings(volume-lighting) $settings(-lighting)
2561    SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
2562    SendCmd "polydata linewidth $settings(-linewidth) $tag"
2563    SendCmd "polydata opacity $settings(-opacity) $tag"
2564    set _settings(volume-opacity) $settings(-opacity)
2565    SendCmd "polydata wireframe $settings(-wireframe) $tag"
2566    set _settings(volume-wireframe) $settings(-wireframe)
2567    set _settings(volume-opacity) [expr $settings(-opacity) * 100.0]
2568    SetColormap $dataobj $comp
2569}
2570
2571itcl::body Rappture::VtkStreamlinesViewer::IsValidObject { dataobj } {
2572    if {[catch {$dataobj isa Rappture::Field} valid] != 0 || !$valid} {
2573        return 0
2574    }
2575    return 1
2576}
2577
2578# ----------------------------------------------------------------------
2579# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
2580#
2581# Invoked automatically whenever the "legend" command comes in from
2582# the rendering server.  Indicates that binary image data with the
2583# specified <size> will follow.
2584# ----------------------------------------------------------------------
2585itcl::body Rappture::VtkStreamlinesViewer::ReceiveLegend { colormap title vmin vmax size } {
2586    set _legendPending 0
2587    puts stderr "ReceiveLegend colormap=$colormap title=$title range=$vmin,$vmax size=$size"
2588    set _limits(vmin) $vmin
2589    set _limits(vmax) $vmax
2590    set _title $title
2591    regsub {\(mag\)} $title "" _title
2592    if { [IsConnected] } {
2593        set bytes [ReceiveBytes $size]
2594        if { ![info exists _image(legend)] } {
2595            set _image(legend) [image create photo]
2596        }
2597        $_image(legend) configure -data $bytes
2598        #puts stderr "read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
2599        if { [catch {DrawLegend $_title} errs] != 0 } {
2600            puts stderr errs=$errs
2601        }
2602    }
2603}
2604
2605#
2606# DrawLegend --
2607#
2608#       Draws the legend in it's own canvas which resides to the right
2609#       of the contour plot area.
2610#
2611itcl::body Rappture::VtkStreamlinesViewer::DrawLegend { name } {
2612    set c $itk_component(view)
2613    set w [winfo width $c]
2614    set h [winfo height $c]
2615    set font "Arial 8"
2616    set lineht [font metrics $font -linespace]
2617   
2618    if { [info exists _fields($name)] } {
2619        foreach { title units } $_fields($name) break
2620        if { $units != "" } {
2621            set title [format "%s (%s)" $title $units]
2622        }
2623    } else {
2624        set title $name
2625    }
2626    if { $_settings(legend-visible) } {
2627        set x [expr $w - 2]
2628        if { [$c find withtag "legend"] == "" } {
2629            set y 2
2630            $c create text $x $y \
2631                -anchor ne \
2632                -fill $itk_option(-plotforeground) -tags "title legend" \
2633                -font $font
2634            incr y $lineht
2635            $c create text $x $y \
2636                -anchor ne \
2637                -fill $itk_option(-plotforeground) -tags "vmax legend" \
2638                -font $font
2639            incr y $lineht
2640            $c create image $x $y \
2641                -anchor ne \
2642                -image $_image(legend) -tags "colormap legend"
2643            $c create text $x [expr {$h-2}] \
2644                -anchor se \
2645                -fill $itk_option(-plotforeground) -tags "vmin legend" \
2646                -font $font
2647            #$c bind colormap <Enter> [itcl::code $this EnterLegend %x %y]
2648            $c bind colormap <Leave> [itcl::code $this LeaveLegend]
2649            $c bind colormap <Motion> [itcl::code $this MotionLegend %x %y]
2650        }
2651        $c bind title <ButtonPress> [itcl::code $this Combo post]
2652        $c bind title <Enter> [itcl::code $this Combo activate]
2653        $c bind title <Leave> [itcl::code $this Combo deactivate]
2654        # Reset the item coordinates according the current size of the plot.
2655        $c itemconfigure title -text $title
2656        if { $_limits(vmin) != "" } {
2657            $c itemconfigure vmin -text [format %g $_limits(vmin)]
2658        }
2659        if { $_limits(vmax) != "" } {
2660            $c itemconfigure vmax -text [format %g $_limits(vmax)]
2661        }
2662        set y 2
2663        $c coords title $x $y
2664        incr y $lineht
2665        $c coords vmax $x $y
2666        incr y $lineht
2667        $c coords colormap $x $y
2668        $c coords vmin $x [expr {$h - 2}]
2669    }
2670}
2671
2672#
2673# EnterLegend --
2674#
2675itcl::body Rappture::VtkStreamlinesViewer::EnterLegend { x y } {
2676    SetLegendTip $x $y
2677}
2678
2679#
2680# MotionLegend --
2681#
2682itcl::body Rappture::VtkStreamlinesViewer::MotionLegend { x y } {
2683    Rappture::Tooltip::tooltip cancel
2684    set c $itk_component(view)
2685    SetLegendTip $x $y
2686}
2687
2688#
2689# LeaveLegend --
2690#
2691itcl::body Rappture::VtkStreamlinesViewer::LeaveLegend { } {
2692    Rappture::Tooltip::tooltip cancel
2693    .rappturetooltip configure -icon ""
2694}
2695
2696#
2697# SetLegendTip --
2698#
2699itcl::body Rappture::VtkStreamlinesViewer::SetLegendTip { x y } {
2700    set c $itk_component(view)
2701    set w [winfo width $c]
2702    set h [winfo height $c]
2703    set font "Arial 8"
2704    set lineht [font metrics $font -linespace]
2705   
2706    set imgHeight [image height $_image(legend)]
2707    set coords [$c coords colormap]
2708    set imgX [expr $w - [image width $_image(legend)] - 2]
2709    set imgY [expr $y - 2 * ($lineht + 2)]
2710
2711    if { [info exists _fields($_title)] } {
2712        foreach { title units } $_fields($_title) break
2713        if { $units != "" } {
2714            set title [format "%s (%s)" $title $units]
2715        }
2716    } else {
2717        set title $_title
2718    }
2719    # Make a swatch of the selected color
2720    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
2721        #puts stderr "out of range: $imgY"
2722        return
2723    }
2724    if { ![info exists _image(swatch)] } {
2725        set _image(swatch) [image create photo -width 24 -height 24]
2726    }
2727    set color [eval format "\#%02x%02x%02x" $pixel]
2728    $_image(swatch) put black  -to 0 0 23 23
2729    $_image(swatch) put $color -to 1 1 22 22
2730    .rappturetooltip configure -icon $_image(swatch)
2731
2732    # Compute the value of the point
2733    if { [info exists _limits(vmax)] && [info exists _limits(vmin)] } {
2734        set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
2735        set value [expr $t * ($_limits(vmax) - $_limits(vmin)) + $_limits(vmin)]
2736    } else {
2737        set value 0.0
2738    }
2739    set tipx [expr $x + 15]
2740    set tipy [expr $y - 5]
2741    Rappture::Tooltip::text $c "$title $value"
2742    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy   
2743}
2744
2745
2746# ----------------------------------------------------------------------
2747# USAGE: Slice move x|y|z <newval>
2748#
2749# Called automatically when the user drags the slider to move the
2750# cut plane that slices 3D data.  Gets the current value from the
2751# slider and moves the cut plane to the appropriate point in the
2752# data set.
2753# ----------------------------------------------------------------------
2754itcl::body Rappture::VtkStreamlinesViewer::Slice {option args} {
2755    switch -- $option {
2756        "move" {
2757            set axis [lindex $args 0]
2758            set oldval $_settings(axis-${axis}position)
2759            set newval [lindex $args 1]
2760            if {[llength $args] != 2} {
2761                error "wrong # args: should be \"Slice move x|y|z newval\""
2762            }
2763            set newpos [expr {0.01*$newval}]
2764            SendCmd "cutplane slice $axis $newpos"
2765        }
2766        "tooltip" {
2767            set axis [lindex $args 0]
2768            set val [$itk_component(${axis}CutScale) get]
2769            return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
2770        }
2771        default {
2772            error "bad option \"$option\": should be axis, move, or tooltip"
2773        }
2774    }
2775}
2776
2777
2778# ----------------------------------------------------------------------
2779# USAGE: _dropdown post
2780# USAGE: _dropdown unpost
2781# USAGE: _dropdown select
2782#
2783# Used internally to handle the dropdown list for this combobox.  The
2784# post/unpost options are invoked when the list is posted or unposted
2785# to manage the relief of the controlling button.  The select option
2786# is invoked whenever there is a selection from the list, to assign
2787# the value back to the gauge.
2788# ----------------------------------------------------------------------
2789itcl::body Rappture::VtkStreamlinesViewer::Combo {option} {
2790    set c $itk_component(view)
2791    switch -- $option {
2792        post {
2793            foreach { x1 y1 x2 y2 } [$c bbox title] break
2794            set x1 [expr [winfo width $itk_component(view)] - [winfo reqwidth $itk_component(fieldmenu)]]
2795            set x [expr $x1 + [winfo rootx $itk_component(view)]]
2796            set y [expr $y2 + [winfo rooty $itk_component(view)]]
2797            puts stderr "combo x=$x y=$y"
2798            tk_popup $itk_component(fieldmenu) $x $y
2799        }
2800        activate {
2801            $c itemconfigure title -fill red
2802        }
2803        deactivate {
2804            $c itemconfigure title -fill white
2805        }
2806        invoke {
2807            $itk_component(field) value $_currentField
2808            AdjustSetting streamlines-field
2809        }
2810        default {
2811            error "bad option \"$option\": should be post, unpost, select"
2812        }
2813    }
2814}
Note: See TracBrowser for help on using the repository browser.