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

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