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

Last change on this file since 5092 was 5092, checked in by ldelgass, 5 years ago

Add update in Rebuild to allow initial canvas size to be set. We don't want to
do this in the constructor since that can cause an error when the add method is
called before the constructor returns.

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