source: branches/1.3/gui/scripts/vtkstreamlinesviewer.tcl @ 3844

Last change on this file since 3844 was 3844, checked in by ldelgass, 11 years ago

Sync with trunk. Branch now differs only from trunk by r3722 (branch is version
1.3, trunk is version 1.4)

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