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

Last change on this file since 2587 was 2587, checked in by gah, 13 years ago

streamlines update: cutplanes, paletttes

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