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

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

These was are all related to the omenwire example.

o Added validity test for fields, meshes, clouds, and unirect2ds. There is

now a "isvalid" method that viewers should use to verify that the data object
can be plotted.

In some cases with fields this means that the widget won't even be created.
The resultviewer tests for the dimensionality which is by default 0.

o Thanks to Leif for pointing this out, it's not enough to check if the field

is valid. Individual components of the field may be invalid. Added check so
that viewers are never passed the names of invalid field components.

o Changed many "error" commands to just print to stderr and tolerantly deal

with the error.

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