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

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