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

Last change on this file since 2594 was 2594, checked in by ldelgass, 13 years ago

Re-enable setting number of seed points using 'streamlines seed numpts...'.
When setting active arrays, use 'dataset vector' for setting active vectors.

File size: 82.2 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: vtkviewer - Vtk drawing object viewer
4#
5#  It connects to the Vtk server running on a rendering farm,
6#  transmits data, and displays the results.
7# ======================================================================
8#  AUTHOR:  Michael McLennan, Purdue University
9#  Copyright (c) 2004-2005  Purdue Research Foundation
10#
11#  See the file "license.terms" for information on usage and
12#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13# ======================================================================
14package require Itk
15package require BLT
16#package require Img
17package require vtk
18
19option add *VtkStreamlinesViewer.width 4i widgetDefault
20option add *VtkStreamlinesViewer*cursor crosshair widgetDefault
21option add *VtkStreamlinesViewer.height 4i widgetDefault
22option add *VtkStreamlinesViewer.foreground black widgetDefault
23option add *VtkStreamlinesViewer.controlBackground gray widgetDefault
24option add *VtkStreamlinesViewer.controlDarkBackground #999999 widgetDefault
25option add *VtkStreamlinesViewer.plotBackground black widgetDefault
26option add *VtkStreamlinesViewer.plotForeground white widgetDefault
27option add *VtkStreamlinesViewer.font \
28    -*-helvetica-medium-r-normal-*-12-* widgetDefault
29
30# must use this name -- plugs into Rappture::resources::load
31proc VtkStreamlinesViewer_init_resources {} {
32    Rappture::resources::register \
33        vtkvis_server Rappture::VtkStreamlinesViewer::SetServerList
34}
35
36itcl::class Rappture::VtkStreamlinesViewer {
37    inherit Rappture::VisViewer
38
39    itk_option define -plotforeground plotForeground Foreground ""
40    itk_option define -plotbackground plotBackground Background ""
41
42    constructor { hostlist args } {
43        Rappture::VisViewer::constructor $hostlist
44    } {
45        # defined below
46    }
47    destructor {
48        # defined below
49    }
50    public proc SetServerList { namelist } {
51        Rappture::VisViewer::SetServerList "vtkvis" $namelist
52    }
53    public method add {dataobj {settings ""}}
54    public method camera {option args}
55    public method delete {args}
56    public method disconnect {}
57    public method download {option args}
58    public method get {args}
59    public method isconnected {}
60    public method limits { colormap }
61    public method sendto { string }
62    public method parameters {title args} {
63        # do nothing
64    }
65    public method scale {args}
66
67    protected method Connect {}
68    protected method CurrentDatasets {args}
69    protected method Disconnect {}
70    protected method DoResize {}
71    protected method 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         100
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 ""
962    FixSettings axis-xgrid axis-ygrid axis-zgrid axis-mode \
963        axis-visible axis-labels
964
965    SendCmd "imgflush"
966
967    set _limits(zmin) ""
968    set _limits(zmax) ""
969    set _first ""
970    foreach dataobj [get -objects] {
971        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
972            set _first $dataobj
973        }
974        set _obj2datasets($dataobj) ""
975        foreach comp [$dataobj components] {
976            set tag $dataobj-$comp
977            if { ![info exists _datasets($tag)] } {
978                set bytes [$dataobj blob $comp]
979                set length [string length $bytes]
980                append _outbuf "dataset add $tag data follows $length\n"
981                append _outbuf $bytes
982                set _datasets($tag) 1
983                SetObjectStyle $dataobj $comp
984            }
985            lappend _obj2datasets($dataobj) $tag
986            if { [info exists _obj2ovride($dataobj-raise)] } {
987                SendCmd "dataset visible 1 $tag"
988            } else {
989                SendCmd "dataset visible 0 $tag"
990            }
991        }
992    }
993    if {"" != $_first} {
994        set location [$_first hints camera]
995        if { $location != "" } {
996            array set view $location
997        }
998
999        foreach axis { x y z } {
1000            set label [$_first hints ${axis}label]
1001            if { $label != "" } {
1002                SendCmd "axis name $axis $label"
1003            }
1004            set units [$_first hints ${axis}units]
1005            if { $units != "" } {
1006                SendCmd "axis units $axis $units"
1007            }
1008        }
1009    }
1010    FixSettings streamlines-seeds streamlines-visible streamlines-opacity \
1011        volume-edges volume-lighting volume-opacity volume-visible \
1012        volume-wireframe streamlines-palette
1013
1014    set _first [lindex [get -objects] 0]
1015    if { $_reset || $_first == "" } {
1016        Zoom reset
1017        set _reset 0
1018    }
1019       
1020    set _buffering 0;                        # Turn off buffering.
1021
1022    # Actually write the commands to the server socket.  If it fails, we don't
1023    # care.  We're finished here.
1024    blt::busy hold $itk_component(hull)
1025    SendBytes $_outbuf;                       
1026    blt::busy release $itk_component(hull)
1027    set _outbuf "";                        # Clear the buffer.               
1028}
1029
1030# ----------------------------------------------------------------------
1031# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
1032#
1033# Returns a list of server IDs for the current datasets being displayed.  This
1034# is normally a single ID, but it might be a list of IDs if the current data
1035# object has multiple components.
1036# ----------------------------------------------------------------------
1037itcl::body Rappture::VtkStreamlinesViewer::CurrentDatasets {args} {
1038    set flag [lindex $args 0]
1039    switch -- $flag {
1040        "-all" {
1041            if { [llength $args] > 1 } {
1042                error "CurrentDatasets: can't specify dataobj after \"-all\""
1043            }
1044            set dlist [get -objects]
1045        }
1046        "-visible" {
1047            if { [llength $args] > 1 } {
1048                set dlist {}
1049                set args [lrange $args 1 end]
1050                foreach dataobj $args {
1051                    if { [info exists _obj2ovride($dataobj-raise)] } {
1052                        lappend dlist $dataobj
1053                    }
1054                }
1055            } else {
1056                set dlist [get -visible]
1057            }
1058        }           
1059        default {
1060            set dlist $args
1061        }
1062    }
1063    set rlist ""
1064    foreach dataobj $dlist {
1065        foreach comp [$dataobj components] {
1066            set tag $dataobj-$comp
1067            if { [info exists _datasets($tag)] && $_datasets($tag) } {
1068                lappend rlist $tag
1069            }
1070        }
1071    }
1072    return $rlist
1073}
1074
1075# ----------------------------------------------------------------------
1076# USAGE: Zoom in
1077# USAGE: Zoom out
1078# USAGE: Zoom reset
1079#
1080# Called automatically when the user clicks on one of the zoom
1081# controls for this widget.  Changes the zoom for the current view.
1082# ----------------------------------------------------------------------
1083itcl::body Rappture::VtkStreamlinesViewer::Zoom {option} {
1084    switch -- $option {
1085        "in" {
1086            set _view(zoom) [expr {$_view(zoom)*1.25}]
1087            SendCmd "camera zoom $_view(zoom)"
1088        }
1089        "out" {
1090            set _view(zoom) [expr {$_view(zoom)*0.8}]
1091            SendCmd "camera zoom $_view(zoom)"
1092        }
1093        "reset" {
1094            array set _view {
1095                qw      1
1096                qx      0
1097                qy      0
1098                qz      0
1099                zoom    1.0
1100                xpan   0
1101                ypan   0
1102            }
1103            SendCmd "camera reset all"
1104            if { $_first != "" } {
1105                set location [$_first hints camera]
1106                if { $location != "" } {
1107                    array set _view $location
1108                }
1109            }
1110            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1111            $_arcball quaternion $q
1112            DoRotate
1113        }
1114    }
1115}
1116
1117itcl::body Rappture::VtkStreamlinesViewer::PanCamera {} {
1118    set x $_view(xpan)
1119    set y $_view(ypan)
1120    SendCmd "camera pan $x $y"
1121}
1122
1123
1124# ----------------------------------------------------------------------
1125# USAGE: Rotate click <x> <y>
1126# USAGE: Rotate drag <x> <y>
1127# USAGE: Rotate release <x> <y>
1128#
1129# Called automatically when the user clicks/drags/releases in the
1130# plot area.  Moves the plot according to the user's actions.
1131# ----------------------------------------------------------------------
1132itcl::body Rappture::VtkStreamlinesViewer::Rotate {option x y} {
1133    switch -- $option {
1134        "click" {
1135            $itk_component(view) configure -cursor fleur
1136            set _click(x) $x
1137            set _click(y) $y
1138        }
1139        "drag" {
1140            if {[array size _click] == 0} {
1141                Rotate click $x $y
1142            } else {
1143                set w [winfo width $itk_component(view)]
1144                set h [winfo height $itk_component(view)]
1145                if {$w <= 0 || $h <= 0} {
1146                    return
1147                }
1148
1149                if {[catch {
1150                    # this fails sometimes for no apparent reason
1151                    set dx [expr {double($x-$_click(x))/$w}]
1152                    set dy [expr {double($y-$_click(y))/$h}]
1153                }]} {
1154                    return
1155                }
1156                if { $dx == 0 && $dy == 0 } {
1157                    return
1158                }
1159                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1160                EventuallyRotate $q
1161                set _click(x) $x
1162                set _click(y) $y
1163            }
1164        }
1165        "release" {
1166            Rotate drag $x $y
1167            $itk_component(view) configure -cursor ""
1168            catch {unset _click}
1169        }
1170        default {
1171            error "bad option \"$option\": should be click, drag, release"
1172        }
1173    }
1174}
1175
1176itcl::body Rappture::VtkStreamlinesViewer::Pick {x y} {
1177    foreach tag [CurrentDatasets -visible] {
1178        SendCmd "dataset getscalar pixel $x $y $tag"
1179    }
1180}
1181
1182# ----------------------------------------------------------------------
1183# USAGE: $this Pan click x y
1184#        $this Pan drag x y
1185#        $this Pan release x y
1186#
1187# Called automatically when the user clicks on one of the zoom
1188# controls for this widget.  Changes the zoom for the current view.
1189# ----------------------------------------------------------------------
1190itcl::body Rappture::VtkStreamlinesViewer::Pan {option x y} {
1191    switch -- $option {
1192        "set" {
1193            set w [winfo width $itk_component(view)]
1194            set h [winfo height $itk_component(view)]
1195            set x [expr $x / double($w)]
1196            set y [expr $y / double($h)]
1197            set _view(xpan) [expr $_view(xpan) + $x]
1198            set _view(ypan) [expr $_view(ypan) + $y]
1199            PanCamera
1200            return
1201        }
1202        "click" {
1203            set _click(x) $x
1204            set _click(y) $y
1205            $itk_component(view) configure -cursor hand1
1206        }
1207        "drag" {
1208            if { ![info exists _click(x)] } {
1209                set _click(x) $x
1210            }
1211            if { ![info exists _click(y)] } {
1212                set _click(y) $y
1213            }
1214            set w [winfo width $itk_component(view)]
1215            set h [winfo height $itk_component(view)]
1216            set dx [expr ($_click(x) - $x)/double($w)]
1217            set dy [expr ($_click(y) - $y)/double($h)]
1218            set _click(x) $x
1219            set _click(y) $y
1220            set _view(xpan) [expr $_view(xpan) - $dx]
1221            set _view(ypan) [expr $_view(ypan) - $dy]
1222            PanCamera
1223        }
1224        "release" {
1225            Pan drag $x $y
1226            $itk_component(view) configure -cursor ""
1227        }
1228        default {
1229            error "unknown option \"$option\": should set, click, drag, or release"
1230        }
1231    }
1232}
1233
1234# ----------------------------------------------------------------------
1235# USAGE: FixSettings <what> ?<value>?
1236#
1237# Used internally to update rendering settings whenever parameters
1238# change in the popup settings panel.  Sends the new settings off
1239# to the back end.
1240# ----------------------------------------------------------------------
1241itcl::body Rappture::VtkStreamlinesViewer::FixSettings { args } {
1242    foreach setting $args {
1243        AdjustSetting $setting
1244    }
1245}
1246
1247#
1248# AdjustSetting --
1249#
1250#       Changes/updates a specific setting in the widget.  There are
1251#       usually user-setable option.  Commands are sent to the render
1252#       server.
1253#
1254itcl::body Rappture::VtkStreamlinesViewer::AdjustSetting {what {value ""}} {
1255    if { ![isconnected] } {
1256        return
1257    }
1258    switch -- $what {
1259        "volume-opacity" {
1260            set val $_volume(opacity)
1261            set sval [expr { 0.01 * double($val) }]
1262            foreach dataset [CurrentDatasets -visible $_first] {
1263                SendCmd "polydata opacity $sval $dataset"
1264            }
1265        }
1266        "volume-wireframe" {
1267            set bool $_volume(wireframe)
1268            foreach dataset [CurrentDatasets -visible $_first] {
1269                SendCmd "polydata wireframe $bool $dataset"
1270            }
1271        }
1272        "volume-visible" {
1273            set bool $_volume(visible)
1274            foreach dataset [CurrentDatasets -visible $_first] {
1275                SendCmd "polydata visible $bool $dataset"
1276            }
1277            if { $bool } {
1278                Rappture::Tooltip::for $itk_component(volume) \
1279                    "Hide the volume"
1280            } else {
1281                Rappture::Tooltip::for $itk_component(volume) \
1282                    "Show the volume"
1283            }
1284        }
1285        "volume-lighting" {
1286            set bool $_volume(lighting)
1287            foreach dataset [CurrentDatasets -visible $_first] {
1288                SendCmd "polydata lighting $bool $dataset"
1289            }
1290        }
1291        "volume-edges" {
1292            set bool $_volume(edges)
1293            foreach dataset [CurrentDatasets -visible $_first] {
1294                SendCmd "polydata edges $bool $dataset"
1295            }
1296        }
1297        "axis-visible" {
1298            set bool $_axis(visible)
1299            SendCmd "axis visible all $bool"
1300        }
1301        "axis-labels" {
1302            set bool $_axis(labels)
1303            SendCmd "axis labels all $bool"
1304        }
1305        "axis-xgrid" {
1306            set bool $_axis(xgrid)
1307            SendCmd "axis grid x $bool"
1308        }
1309        "axis-ygrid" {
1310            set bool $_axis(ygrid)
1311            SendCmd "axis grid y $bool"
1312        }
1313        "axis-zgrid" {
1314            set bool $_axis(zgrid)
1315            SendCmd "axis grid z $bool"
1316        }
1317        "axis-mode" {
1318            set mode [$itk_component(axismode) value]
1319            set mode [$itk_component(axismode) translate $mode]
1320            SendCmd "axis flymode $mode"
1321        }
1322        "cutplane-edges" {
1323            set bool $_cutplane(edges)
1324            foreach dataset [CurrentDatasets -visible $_first] {
1325                SendCmd "cutplane edges $bool $dataset"
1326            }
1327        }
1328        "cutplane-visible" {
1329            set bool $_cutplane(visible)
1330            foreach dataset [CurrentDatasets -visible $_first] {
1331                SendCmd "cutplane visible $bool $dataset"
1332            }
1333        }
1334        "cutplane-wireframe" {
1335            set bool $_cutplane(wireframe)
1336            foreach dataset [CurrentDatasets -visible $_first] {
1337                SendCmd "cutplane wireframe $bool $dataset"
1338            }
1339        }
1340        "cutplane-lighting" {
1341            set bool $_cutplane(lighting)
1342            foreach dataset [CurrentDatasets -visible $_first] {
1343                SendCmd "cutplane lighting $bool $dataset"
1344            }
1345        }
1346        "cutplane-opacity" {
1347            set val $_cutplane(opacity)
1348            set sval [expr { 0.01 * double($val) }]
1349            foreach dataset [CurrentDatasets -visible $_first] {
1350                SendCmd "cutplane opacity $sval $dataset"
1351            }
1352        }
1353        "xcutplane-visible" - "ycutplane-visible" - "zcutplane-visible" {
1354            set axis [string range $what 0 0]
1355            set bool $_cutplane(${axis}visible)
1356            if { $bool } {
1357                $itk_component(${axis}CutScale) configure -state normal \
1358                    -troughcolor white
1359            } else {
1360                $itk_component(${axis}CutScale) configure -state disabled \
1361                    -troughcolor grey82
1362            }
1363            SendCmd "cutplane axis $axis $bool"
1364            SendCmd "cutplane colormode $_colorMode"
1365        }
1366        "xcutplane-position" - "ycutplane-position" - "zcutplane-position" {
1367            set axis [string range $what 0 0]
1368            set pos [expr $_cutplane(${axis}position) * 0.01]
1369            SendCmd "cutplane slice ${axis} ${pos}"
1370            set _cutplanePending 0
1371        }
1372        "streamlines-seeds" {
1373            set bool $_streamlines(seeds)
1374            foreach dataset [CurrentDatasets -visible $_first] {
1375                SendCmd "streamlines seed visible $bool $dataset"
1376            }
1377        }
1378        "streamlines-seeddensity" {
1379            set density $_streamlines(seeddensity)
1380            foreach dataset [CurrentDatasets -visible $_first] {
1381                foreach {dataobj comp} [split $dataset -] break
1382                # This command works for either random or fmesh seeds
1383                SendCmd "streamlines seed numpts $density $dataset"
1384            }
1385        }
1386        "streamlines-visible" {
1387            set bool $_streamlines(visible)
1388            foreach dataset [CurrentDatasets -visible $_first] {
1389                SendCmd "streamlines visible $bool $dataset"
1390            }
1391            if { $bool } {
1392                Rappture::Tooltip::for $itk_component(streamlines) \
1393                    "Hide the streamlines"
1394            } else {
1395                Rappture::Tooltip::for $itk_component(streamlines) \
1396                    "Show the streamlines"
1397            }
1398        }
1399        "streamlines-mode" {
1400            set mode [$itk_component(streammode) value]
1401            foreach dataset [CurrentDatasets -visible $_first] {
1402                switch -- $mode {
1403                    "lines" {
1404                        SendCmd "streamlines lines $dataset"
1405                    }
1406                    "ribbons" {
1407                        SendCmd "streamlines ribbons 3 0 $dataset"
1408                    }
1409                    "tubes" {
1410                        SendCmd "streamlines tubes 5 3 $dataset"
1411                    }
1412                }
1413            }
1414        }
1415        "streamlines-palette" {
1416            set palette [$itk_component(palette) value]
1417            foreach dataset [CurrentDatasets -visible $_first] {
1418                foreach {dataobj comp} [split $dataset -] break
1419                ChangeColormap $dataobj $comp $palette
1420            }
1421            RequestLegend
1422        }
1423        "streamlines-opacity" {
1424            set val $_streamlines(opacity)
1425            set sval [expr { 0.01 * double($val) }]
1426            foreach dataset [CurrentDatasets -visible $_first] {
1427                SendCmd "streamlines opacity $sval $dataset"
1428            }
1429        }
1430        "streamlines-scale" {
1431            set val $_streamlines(scale)
1432            set sval [expr { 0.01 * double($val) }]
1433            foreach dataset [CurrentDatasets -visible $_first] {
1434                SendCmd "streamlines scale $sval $sval $sval $dataset"
1435            }
1436        }
1437        "streamlines-lighting" {
1438            set bool $_streamlines(lighting)
1439            foreach dataset [CurrentDatasets -visible $_first] {
1440                SendCmd "streamlines lighting $bool $dataset"
1441            }
1442        }
1443        "streamlines-field" {
1444            set field [$itk_component(field) value]
1445            set _colorMode scalar
1446            set fieldType scalar
1447            if { $field == "U" } {
1448                set _colorMode vmag
1449                set fieldType vector
1450            }
1451            foreach dataset [CurrentDatasets -visible $_first] {
1452                SendCmd "dataset ${fieldType} ${field} $dataset"
1453                SendCmd "streamlines colormode $_colorMode $dataset"
1454                SendCmd "cutplane colormode $_colorMode $dataset"
1455            }
1456            RequestLegend
1457        }
1458        default {
1459            error "don't know how to fix $what"
1460        }
1461    }
1462}
1463
1464#
1465# RequestLegend --
1466#
1467#       Request a new legend from the server.  The size of the legend
1468#       is determined from the height of the canvas.  It will be rotated
1469#       to be vertical when drawn.
1470#
1471itcl::body Rappture::VtkStreamlinesViewer::RequestLegend {} {
1472    #puts stderr "RequestLegend _first=$_first"
1473    #puts stderr "RequestLegend width=$_width height=$_height"
1474    set font "Arial 8"
1475    set lineht [font metrics $font -linespace]
1476    set c $itk_component(legend)
1477    set w 12
1478    set h [expr {$_height - 3 * ($lineht + 2)}]
1479    if { $h < 1} {
1480        return
1481    }
1482    # Set the legend on the first streamlines dataset.
1483    foreach dataset [CurrentDatasets -visible] {
1484        foreach {dataobj comp} [split $dataset -] break
1485        if { [info exists _dataset2style($dataset)] } {
1486            puts stderr "legend $_dataset2style($dataset) $_colorMode {} $w $h 0"
1487            SendCmd "legend $_dataset2style($dataset) $_colorMode {} $w $h 0"
1488            break;
1489        }
1490    }
1491}
1492
1493#
1494# ChangeColormap --
1495#
1496itcl::body Rappture::VtkStreamlinesViewer::ChangeColormap {dataobj comp color} {
1497    set tag $dataobj-$comp
1498    if { ![info exist _style($tag)] } {
1499        error "no initial colormap"
1500    }
1501    array set style $_style($tag)
1502    set style(-color) $color
1503    set _style($tag) [array get style]
1504    SetColormap $dataobj $comp
1505}
1506
1507#
1508# SetColormap --
1509#
1510itcl::body Rappture::VtkStreamlinesViewer::SetColormap { dataobj comp } {
1511    array set style {
1512        -color BGYOR
1513        -levels 6
1514        -opacity 1.0
1515    }
1516    set tag $dataobj-$comp
1517    if { ![info exists _initialStyle($tag)] } {
1518        # Save the initial component style.
1519        set _initialStyle($tag) [$dataobj style $comp]
1520    }
1521
1522    # Override defaults with initial style defined in xml.
1523    array set style $_initialStyle($tag)
1524
1525    if { ![info exists _style($tag)] } {
1526        set _style($tag) [array get style]
1527    }
1528    # Override initial style with current style.
1529    array set style $_style($tag)
1530
1531    set name "$style(-color):$style(-levels):$style(-opacity)"
1532    if { ![info exists _colormaps($name)] } {
1533        BuildColormap $name [array get style]
1534        set _colormaps($name) 1
1535    }
1536    if { ![info exists _dataset2style($tag)] ||
1537         $_dataset2style($tag) != $name } {
1538        puts stderr "streamlines colormap $name $tag"
1539        puts stderr "cutplane colormap $name $tag"
1540        SendCmd "streamlines colormap $name $tag"
1541        SendCmd "cutplane colormap $name $tag"
1542        set _dataset2style($tag) $name
1543    }
1544}
1545
1546itcl::body Rappture::VtkStreamlinesViewer::ColorsToColormap { colors } {
1547    switch -- $colors {
1548        "grey-to-blue" {
1549            return {
1550                0.0                      0.200 0.200 0.200
1551                0.14285714285714285      0.400 0.400 0.400
1552                0.2857142857142857       0.600 0.600 0.600
1553                0.42857142857142855      0.900 0.900 0.900
1554                0.5714285714285714       0.800 1.000 1.000
1555                0.7142857142857143       0.600 1.000 1.000
1556                0.8571428571428571       0.400 0.900 1.000
1557                1.0                      0.000 0.600 0.800
1558            }
1559        }
1560        "blue-to-grey" {
1561            return {
1562                0.0                     0.000 0.600 0.800
1563                0.14285714285714285     0.400 0.900 1.000
1564                0.2857142857142857      0.600 1.000 1.000
1565                0.42857142857142855     0.800 1.000 1.000
1566                0.5714285714285714      0.900 0.900 0.900
1567                0.7142857142857143      0.600 0.600 0.600
1568                0.8571428571428571      0.400 0.400 0.400
1569                1.0                     0.200 0.200 0.200
1570            }
1571        }
1572        "blue" {
1573            return {
1574                0.0                     0.900 1.000 1.000
1575                0.1111111111111111      0.800 0.983 1.000
1576                0.2222222222222222      0.700 0.950 1.000
1577                0.3333333333333333      0.600 0.900 1.000
1578                0.4444444444444444      0.500 0.833 1.000
1579                0.5555555555555556      0.400 0.750 1.000
1580                0.6666666666666666      0.300 0.650 1.000
1581                0.7777777777777778      0.200 0.533 1.000
1582                0.8888888888888888      0.100 0.400 1.000
1583                1.0                     0.000 0.250 1.000
1584            }
1585        }
1586        "brown-to-blue" {
1587            return {
1588                0.0                             0.200   0.100   0.000
1589                0.09090909090909091             0.400   0.187   0.000
1590                0.18181818181818182             0.600   0.379   0.210
1591                0.2727272727272727              0.800   0.608   0.480
1592                0.36363636363636365             0.850   0.688   0.595
1593                0.45454545454545453             0.950   0.855   0.808
1594                0.5454545454545454              0.800   0.993   1.000
1595                0.6363636363636364              0.600   0.973   1.000
1596                0.7272727272727273              0.400   0.940   1.000
1597                0.8181818181818182              0.200   0.893   1.000
1598                0.9090909090909091              0.000   0.667   0.800
1599                1.0                             0.000   0.480   0.600
1600            }
1601        }
1602        "blue-to-brown" {
1603            return {
1604                0.0                             0.000   0.480   0.600
1605                0.09090909090909091             0.000   0.667   0.800
1606                0.18181818181818182             0.200   0.893   1.000
1607                0.2727272727272727              0.400   0.940   1.000
1608                0.36363636363636365             0.600   0.973   1.000
1609                0.45454545454545453             0.800   0.993   1.000
1610                0.5454545454545454              0.950   0.855   0.808
1611                0.6363636363636364              0.850   0.688   0.595
1612                0.7272727272727273              0.800   0.608   0.480
1613                0.8181818181818182              0.600   0.379   0.210
1614                0.9090909090909091              0.400   0.187   0.000
1615                1.0                             0.200   0.100   0.000
1616            }
1617        }
1618        "blue-to-orange" {
1619            return {
1620                0.0                             0.000   0.167   1.000
1621                0.09090909090909091             0.100   0.400   1.000
1622                0.18181818181818182             0.200   0.600   1.000
1623                0.2727272727272727              0.400   0.800   1.000
1624                0.36363636363636365             0.600   0.933   1.000
1625                0.45454545454545453             0.800   1.000   1.000
1626                0.5454545454545454              1.000   1.000   0.800
1627                0.6363636363636364              1.000   0.933   0.600
1628                0.7272727272727273              1.000   0.800   0.400
1629                0.8181818181818182              1.000   0.600   0.200
1630                0.9090909090909091              1.000   0.400   0.100
1631                1.0                             1.000   0.167   0.000
1632            }
1633        }
1634        "orange-to-blue" {
1635            return {
1636                0.0                             1.000   0.167   0.000
1637                0.09090909090909091             1.000   0.400   0.100
1638                0.18181818181818182             1.000   0.600   0.200
1639                0.2727272727272727              1.000   0.800   0.400
1640                0.36363636363636365             1.000   0.933   0.600
1641                0.45454545454545453             1.000   1.000   0.800
1642                0.5454545454545454              0.800   1.000   1.000
1643                0.6363636363636364              0.600   0.933   1.000
1644                0.7272727272727273              0.400   0.800   1.000
1645                0.8181818181818182              0.200   0.600   1.000
1646                0.9090909090909091              0.100   0.400   1.000
1647                1.0                             0.000   0.167   1.000
1648            }
1649        }
1650        "rainbow" {
1651            set clist {
1652                "#EE82EE"
1653                "#4B0082"
1654                "blue"
1655                "#008000"
1656                "yellow"
1657                "#FFA500"
1658                "red"
1659            }
1660        }
1661        "BGYOR" {
1662            set clist {
1663                "blue"
1664                "#008000"
1665                "yellow"
1666                "#FFA500"
1667                "red"
1668            }
1669        }
1670        "ROYGB" {
1671            set clist {
1672                "red"
1673                "#FFA500"
1674                "yellow"
1675                "#008000"
1676                "blue"
1677            }
1678        }
1679        "RYGCB" {
1680            set clist {
1681                "red"
1682                "yellow"
1683                "green"
1684                "cyan"
1685                "blue"
1686            }
1687        }
1688        "BCGYR" {
1689            set clist {
1690                "blue"
1691                "cyan"
1692                "green"
1693                "yellow"
1694                "red"
1695            }
1696        }
1697        "spectral" {
1698            return {
1699                0.0 0.150 0.300 1.000
1700                0.1 0.250 0.630 1.000
1701                0.2 0.450 0.850 1.000
1702                0.3 0.670 0.970 1.000
1703                0.4 0.880 1.000 1.000
1704                0.5 1.000 1.000 0.750
1705                0.6 1.000 0.880 0.600
1706                0.7 1.000 0.680 0.450
1707                0.8 0.970 0.430 0.370
1708                0.9 0.850 0.150 0.196
1709                1.0 0.650 0.000 0.130
1710            }
1711        }
1712        "green-to-magenta" {
1713            return {
1714                0.0 0.000 0.316 0.000
1715                0.06666666666666667 0.000 0.526 0.000
1716                0.13333333333333333 0.000 0.737 0.000
1717                0.2 0.000 0.947 0.000
1718                0.26666666666666666 0.316 1.000 0.316
1719                0.3333333333333333 0.526 1.000 0.526
1720                0.4 0.737 1.000 0.737
1721                0.4666666666666667 1.000 1.000 1.000
1722                0.5333333333333333 1.000 0.947 1.000
1723                0.6 1.000 0.737 1.000
1724                0.6666666666666666 1.000 0.526 1.000
1725                0.7333333333333333 1.000 0.316 1.000
1726                0.8 0.947 0.000 0.947
1727                0.8666666666666667 0.737 0.000 0.737
1728                0.9333333333333333 0.526 0.000 0.526
1729                1.0 0.316 0.000 0.316
1730            }
1731        }
1732        "greyscale" {
1733            return {
1734                0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
1735            }
1736        }
1737        "nanohub" {
1738            set clist "white yellow green cyan blue magenta"
1739        }
1740        default {
1741            set clist $colors
1742        }
1743    }
1744    set cmap {}
1745    for {set i 0} {$i < [llength $clist]} {incr i} {
1746        set x [expr {double($i)/([llength $clist]-1)}]
1747        set color [lindex $clist $i]
1748        append cmap "$x [Color2RGB $color] "
1749    }
1750    return $cmap
1751}
1752
1753#
1754# BuildColormap --
1755#
1756itcl::body Rappture::VtkStreamlinesViewer::BuildColormap { name styles } {
1757    array set style $styles
1758    set cmap [ColorsToColormap $style(-color)]
1759    if { [llength $cmap] == 0 } {
1760        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1761    }
1762    if { ![info exists _volume(opacity)] } {
1763        set _volume(opacity) $style(-opacity)
1764    }
1765    set max $_volume(opacity)
1766
1767    set wmap "0.0 1.0 1.0 1.0"
1768    SendCmd "colormap add $name { $cmap } { $wmap }"
1769}
1770
1771# ----------------------------------------------------------------------
1772# CONFIGURATION OPTION: -plotbackground
1773# ----------------------------------------------------------------------
1774itcl::configbody Rappture::VtkStreamlinesViewer::plotbackground {
1775    if { [isconnected] } {
1776        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1777        SendCmd "screen bgcolor $r $g $b"
1778    }
1779}
1780
1781# ----------------------------------------------------------------------
1782# CONFIGURATION OPTION: -plotforeground
1783# ----------------------------------------------------------------------
1784itcl::configbody Rappture::VtkStreamlinesViewer::plotforeground {
1785    if { [isconnected] } {
1786        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1787        #fix this!
1788        #SendCmd "color background $r $g $b"
1789    }
1790}
1791
1792itcl::body Rappture::VtkStreamlinesViewer::limits { dataobj } {
1793    array unset _limits $dataobj-*
1794    foreach comp [$dataobj components] {
1795        set tag $dataobj-$comp
1796        if { ![info exists _limits($tag)] } {
1797            set data [$dataobj blob $comp]
1798            set tmpfile file[pid].vtk
1799            set f [open "$tmpfile" "w"]
1800            puts $f $data
1801            close $f
1802            set reader [vtkDataSetReader $tag-xvtkDataSetReader]
1803            $reader SetFileName $tmpfile
1804            $reader ReadAllScalarsOn
1805            $reader ReadAllVectorsOn
1806            $reader ReadAllFieldsOn
1807            $reader Update
1808            set output [$reader GetOutput]
1809            set _limits($tag) [$output GetBounds]
1810            set pointData [$output GetPointData]
1811            puts stderr "\#scalars=[$reader GetNumberOfScalarsInFile]"
1812            puts stderr "\#fielddata=[$reader GetNumberOfFieldDataInFile]"
1813            puts stderr "fielddataname=[$reader GetFieldDataNameInFile 0]"
1814            set fieldData [$output GetFieldData]
1815            set pointData [$output GetPointData]
1816            puts stderr "field \#arrays=[$fieldData GetNumberOfArrays]"
1817            for { set i 0 } { $i < [$fieldData GetNumberOfArrays] } { incr i } {
1818                puts stderr [$fieldData GetArrayName $i]
1819            }
1820            puts stderr "point \#arrays=[$pointData GetNumberOfArrays]"
1821            for { set i 0 } { $i < [$pointData GetNumberOfArrays] } { incr i } {
1822                set name [$pointData GetArrayName $i]
1823                if { ![info exists _fields($name)] } {
1824                    $itk_component(field) choices insert end "$name" "$name"
1825                    set _fields($name) 1
1826                }
1827            }
1828            puts stderr "field \#components=[$fieldData GetNumberOfComponents]"
1829            puts stderr "point \#components=[$pointData GetNumberOfComponents]"
1830            puts stderr "field \#tuples=[$fieldData GetNumberOfTuples]"
1831            puts stderr "point \#tuples=[$pointData GetNumberOfTuples]"
1832            puts stderr "point \#scalars=[$pointData GetScalars]"
1833            puts stderr vectors=[$pointData GetVectors]
1834            rename $output ""
1835            rename $reader ""
1836            file delete $tmpfile
1837        }
1838        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1839        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1840            set limits(xmin) $xMin
1841        }
1842        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1843            set limits(xmax) $xMax
1844        }
1845        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1846            set limits(ymin) $xMin
1847        }
1848        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1849            set limits(ymax) $yMax
1850        }
1851        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1852            set limits(zmin) $zMin
1853        }
1854        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1855            set limits(zmax) $zMax
1856        }
1857    }
1858    return [array get limits]
1859}
1860
1861itcl::body Rappture::VtkStreamlinesViewer::BuildVolumeTab {} {
1862
1863    set fg [option get $itk_component(hull) font Font]
1864    #set bfg [option get $itk_component(hull) boldFont Font]
1865
1866    set inner [$itk_component(main) insert end \
1867        -title "Volume Settings" \
1868        -icon [Rappture::icon volume-on]]
1869    $inner configure -borderwidth 4
1870
1871    checkbutton $inner.volume \
1872        -text "Show Volume" \
1873        -variable [itcl::scope _volume(visible)] \
1874        -command [itcl::code $this AdjustSetting volume-visible] \
1875        -font "Arial 9"
1876
1877    checkbutton $inner.wireframe \
1878        -text "Show Wireframe" \
1879        -variable [itcl::scope _volume(wireframe)] \
1880        -command [itcl::code $this AdjustSetting volume-wireframe] \
1881        -font "Arial 9"
1882
1883    checkbutton $inner.lighting \
1884        -text "Enable Lighting" \
1885        -variable [itcl::scope _volume(lighting)] \
1886        -command [itcl::code $this AdjustSetting volume-lighting] \
1887        -font "Arial 9"
1888
1889    checkbutton $inner.edges \
1890        -text "Show Edges" \
1891        -variable [itcl::scope _volume(edges)] \
1892        -command [itcl::code $this AdjustSetting volume-edges] \
1893        -font "Arial 9"
1894
1895    label $inner.opacity_l -text "Opacity" -font "Arial 9"
1896    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1897        -variable [itcl::scope _volume(opacity)] \
1898        -width 10 \
1899        -showvalue off \
1900        -command [itcl::code $this AdjustSetting volume-opacity]
1901
1902    blt::table $inner \
1903        0,0 $inner.volume    -anchor w -pady 2 \
1904        1,0 $inner.wireframe -anchor w -pady 2 \
1905        2,0 $inner.lighting  -anchor w -pady 2 \
1906        3,0 $inner.edges     -anchor w -pady 2 \
1907        4,0 $inner.opacity_l -anchor w -pady 2 \
1908        5,0 $inner.opacity   -fill x   -pady 2
1909
1910    blt::table configure $inner r* c* -resize none
1911    blt::table configure $inner r6 c1 -resize expand
1912}
1913
1914
1915itcl::body Rappture::VtkStreamlinesViewer::BuildStreamsTab {} {
1916
1917    set fg [option get $itk_component(hull) font Font]
1918    #set bfg [option get $itk_component(hull) boldFont Font]
1919
1920    set inner [$itk_component(main) insert end \
1921        -title "Streams Settings" \
1922        -icon [Rappture::icon streamlines-on]]
1923    $inner configure -borderwidth 4
1924
1925    checkbutton $inner.streamlines \
1926        -text "Show Streamlines" \
1927        -variable [itcl::scope _streamlines(visible)] \
1928        -command [itcl::code $this AdjustSetting streamlines-visible] \
1929        -font "Arial 9"
1930   
1931    checkbutton $inner.lighting \
1932        -text "Enable Lighting" \
1933        -variable [itcl::scope _streamlines(lighting)] \
1934        -command [itcl::code $this AdjustSetting streamlines-lighting] \
1935        -font "Arial 9"
1936
1937    checkbutton $inner.seeds \
1938        -text "Show Seeds" \
1939        -variable [itcl::scope _streamlines(seeds)] \
1940        -command [itcl::code $this AdjustSetting streamlines-seeds] \
1941        -font "Arial 9"
1942
1943    label $inner.mode_l -text "Mode" -font "Arial 9"
1944    itk_component add streammode {
1945        Rappture::Combobox $inner.mode -width 10 -editable no
1946    }
1947    $inner.mode choices insert end \
1948        "lines"    "lines" \
1949        "ribbons"   "ribbons" \
1950        "tubes"     "tubes"
1951    $itk_component(streammode) value "lines"
1952    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting streamlines-mode]
1953
1954    label $inner.opacity_l -text "Opacity" -font "Arial 9"
1955    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1956        -variable [itcl::scope _streamlines(opacity)] \
1957        -width 10 \
1958        -showvalue off \
1959        -command [itcl::code $this AdjustSetting streamlines-opacity]
1960
1961    label $inner.density_l -text "Number of Seeds" -font "Arial 9"
1962    ::scale $inner.density -from 1 -to 1000 -orient horizontal \
1963        -variable [itcl::scope _streamlines(seeddensity)] \
1964        -width 10 \
1965        -showvalue on \
1966        -command [itcl::code $this AdjustSetting streamlines-seeddensity]
1967
1968    label $inner.scale_l -text "Scale" -font "Arial 9"
1969    ::scale $inner.scale -from 1 -to 100 -orient horizontal \
1970        -variable [itcl::scope _streamlines(scale)] \
1971        -width 10 \
1972        -showvalue off \
1973        -command [itcl::code $this AdjustSetting streamlines-scale]
1974
1975    label $inner.field_l -text "Field" -font "Arial 9"
1976    itk_component add field {
1977        Rappture::Combobox $inner.field -width 10 -editable no
1978    }
1979    bind $inner.field <<Value>> \
1980        [itcl::code $this AdjustSetting streamlines-field]
1981
1982    label $inner.palette_l -text "Palette" -font "Arial 9"
1983    itk_component add palette {
1984        Rappture::Combobox $inner.palette -width 10 -editable no
1985    }
1986    $inner.palette choices insert end \
1987        "BCGYR"              "BCGYR"            \
1988        "BGYOR"              "BGYOR"            \
1989        "blue"               "blue"             \
1990        "blue-to-brown"      "blue-to-brown"    \
1991        "blue-to-orange"     "blue-to-orange"   \
1992        "blue-to-grey"       "blue-to-grey"     \
1993        "green-to-magenta"   "green-to-magenta" \
1994        "greyscale"          "greyscale"        \
1995        "nanohub"            "nanohub"          \
1996        "rainbow"            "rainbow"          \
1997        "spectral"           "spectral"         \
1998        "ROYGB"              "ROYGB"            \
1999        "RYGCB"              "RYGCB"            \
2000        "brown-to-blue"      "brown-to-blue"    \
2001        "grey-to-blue"       "grey-to-blue"     \
2002        "orange-to-blue"     "orange-to-blue"   
2003
2004    $itk_component(palette) value "BCGYR"
2005    bind $inner.palette <<Value>> \
2006        [itcl::code $this AdjustSetting streamlines-palette]
2007
2008    blt::table $inner \
2009        0,0 $inner.streamlines -anchor w -pady 2 -cspan 2 \
2010        1,0 $inner.lighting    -anchor w -pady 2 -cspan 2 \
2011        2,0 $inner.seeds       -anchor w -pady 2 -cspan 2 \
2012        3,0 $inner.density_l   -anchor w -pady 2 -cspan 2 \
2013        4,0 $inner.density     -fill x   -pady 2 -cspan 2 \
2014        5,0 $inner.mode_l      -anchor w -pady 2  \
2015        5,1 $inner.mode        -anchor w -pady 2  \
2016        6,0 $inner.opacity_l   -anchor w -pady 2 -cspan 2 \
2017        7,0 $inner.opacity     -fill x   -pady 2 -cspan 2 \
2018        8,0 $inner.field_l     -anchor w -pady 2  \
2019        8,1 $inner.field       -anchor w -pady 2  \
2020        9,0 $inner.palette_l   -anchor w -pady 2  \
2021        9,1 $inner.palette     -anchor w -pady 2  \
2022       
2023
2024    blt::table configure $inner r* c* -resize none
2025    blt::table configure $inner r10 c1 c2 -resize expand
2026}
2027
2028itcl::body Rappture::VtkStreamlinesViewer::BuildAxisTab {} {
2029
2030    set fg [option get $itk_component(hull) font Font]
2031    #set bfg [option get $itk_component(hull) boldFont Font]
2032
2033    set inner [$itk_component(main) insert end \
2034        -title "Axis Settings" \
2035        -icon [Rappture::icon axis1]]
2036    $inner configure -borderwidth 4
2037
2038    checkbutton $inner.visible \
2039        -text "Show Axes" \
2040        -variable [itcl::scope _axis(visible)] \
2041        -command [itcl::code $this AdjustSetting axis-visible] \
2042        -font "Arial 9"
2043
2044    checkbutton $inner.labels \
2045        -text "Show Axis Labels" \
2046        -variable [itcl::scope _axis(labels)] \
2047        -command [itcl::code $this AdjustSetting axis-labels] \
2048        -font "Arial 9"
2049
2050    checkbutton $inner.gridx \
2051        -text "Show X Grid" \
2052        -variable [itcl::scope _axis(xgrid)] \
2053        -command [itcl::code $this AdjustSetting axis-xgrid] \
2054        -font "Arial 9"
2055    checkbutton $inner.gridy \
2056        -text "Show Y Grid" \
2057        -variable [itcl::scope _axis(ygrid)] \
2058        -command [itcl::code $this AdjustSetting axis-ygrid] \
2059        -font "Arial 9"
2060    checkbutton $inner.gridz \
2061        -text "Show Z Grid" \
2062        -variable [itcl::scope _axis(zgrid)] \
2063        -command [itcl::code $this AdjustSetting axis-zgrid] \
2064        -font "Arial 9"
2065
2066    label $inner.mode_l -text "Mode" -font "Arial 9"
2067
2068    itk_component add axismode {
2069        Rappture::Combobox $inner.mode -width 10 -editable no
2070    }
2071    $inner.mode choices insert end \
2072        "static_triad"    "static" \
2073        "closest_triad"   "closest" \
2074        "furthest_triad"  "furthest" \
2075        "outer_edges"     "outer"         
2076    $itk_component(axismode) value "static"
2077    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
2078
2079    blt::table $inner \
2080        0,0 $inner.visible -anchor w -cspan 2 \
2081        1,0 $inner.labels  -anchor w -cspan 2 \
2082        2,0 $inner.gridx   -anchor w -cspan 2 \
2083        3,0 $inner.gridy   -anchor w -cspan 2 \
2084        4,0 $inner.gridz   -anchor w -cspan 2 \
2085        5,0 $inner.mode_l  -anchor w -cspan 2 -padx { 2 0 } \
2086        6,0 $inner.mode    -fill x   -cspan 2
2087
2088    blt::table configure $inner r* c* -resize none
2089    blt::table configure $inner r7 c1 -resize expand
2090}
2091
2092
2093itcl::body Rappture::VtkStreamlinesViewer::BuildCameraTab {} {
2094    set inner [$itk_component(main) insert end \
2095        -title "Camera Settings" \
2096        -icon [Rappture::icon camera]]
2097    $inner configure -borderwidth 4
2098
2099    set labels { qx qy qz qw xpan ypan zoom }
2100    set row 0
2101    foreach tag $labels {
2102        label $inner.${tag}label -text $tag -font "Arial 9"
2103        entry $inner.${tag} -font "Arial 9"  -bg white \
2104            -textvariable [itcl::scope _view($tag)]
2105        bind $inner.${tag} <KeyPress-Return> \
2106            [itcl::code $this camera set ${tag}]
2107        blt::table $inner \
2108            $row,0 $inner.${tag}label -anchor e -pady 2 \
2109            $row,1 $inner.${tag} -anchor w -pady 2
2110        blt::table configure $inner r$row -resize none
2111        incr row
2112    }
2113    checkbutton $inner.ortho \
2114        -text "Orthographic Projection" \
2115        -variable [itcl::scope _view(ortho)] \
2116        -command [itcl::code $this camera set ortho] \
2117        -font "Arial 9"
2118    blt::table $inner \
2119            $row,0 $inner.ortho -columnspan 2 -anchor w -pady 2
2120    blt::table configure $inner r$row -resize none
2121    incr row
2122
2123    blt::table configure $inner c0 c1 -resize none
2124    blt::table configure $inner c2 -resize expand
2125    blt::table configure $inner r$row -resize expand
2126}
2127
2128itcl::body Rappture::VtkStreamlinesViewer::BuildCutplaneTab {} {
2129
2130    set fg [option get $itk_component(hull) font Font]
2131   
2132    set inner [$itk_component(main) insert end \
2133        -title "Cutplane Settings" \
2134        -icon [Rappture::icon cutbutton]]
2135
2136    $inner configure -borderwidth 4
2137
2138    checkbutton $inner.visible \
2139        -text "Show Cutplanes" \
2140        -variable [itcl::scope _cutplane(visible)] \
2141        -command [itcl::code $this AdjustSetting cutplane-visible] \
2142        -font "Arial 9"
2143
2144    checkbutton $inner.wireframe \
2145        -text "Show Wireframe" \
2146        -variable [itcl::scope _cutplane(wireframe)] \
2147        -command [itcl::code $this AdjustSetting cutplane-wireframe] \
2148        -font "Arial 9"
2149
2150    checkbutton $inner.lighting \
2151        -text "Enable Lighting" \
2152        -variable [itcl::scope _cutplane(lighting)] \
2153        -command [itcl::code $this AdjustSetting cutplane-lighting] \
2154        -font "Arial 9"
2155
2156    checkbutton $inner.edges \
2157        -text "Show Edges" \
2158        -variable [itcl::scope _cutplane(edges)] \
2159        -command [itcl::code $this AdjustSetting cutplane-edges] \
2160        -font "Arial 9"
2161
2162    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2163    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2164        -variable [itcl::scope _cutplane(opacity)] \
2165        -width 10 \
2166        -showvalue off \
2167        -command [itcl::code $this AdjustSetting cutplane-opacity]
2168    $inner.opacity set $_cutplane(opacity)
2169
2170    # X-value slicer...
2171    itk_component add xCutButton {
2172        Rappture::PushButton $inner.xbutton \
2173            -onimage [Rappture::icon x-cutplane] \
2174            -offimage [Rappture::icon x-cutplane] \
2175            -command [itcl::code $this AdjustSetting xcutplane-visible] \
2176            -variable [itcl::scope _cutplane(xvisible)]
2177    }
2178    Rappture::Tooltip::for $itk_component(xCutButton) \
2179        "Toggle the X-axis cutplane on/off"
2180
2181    itk_component add xCutScale {
2182        ::scale $inner.xval -from 100 -to 1 \
2183            -width 10 -orient vertical -showvalue yes \
2184            -borderwidth 1 -highlightthickness 0 \
2185            -command [itcl::code $this EventuallySetCutplane x] \
2186            -variable [itcl::scope _cutplane(xposition)]
2187    } {
2188        usual
2189        ignore -borderwidth -highlightthickness
2190    }
2191    # Set the default cutplane value before disabling the scale.
2192    $itk_component(xCutScale) set 100
2193    $itk_component(xCutScale) configure -state disabled
2194    Rappture::Tooltip::for $itk_component(xCutScale) \
2195        "@[itcl::code $this Slice tooltip x]"
2196
2197    # Y-value slicer...
2198    itk_component add yCutButton {
2199        Rappture::PushButton $inner.ybutton \
2200            -onimage [Rappture::icon y-cutplane] \
2201            -offimage [Rappture::icon y-cutplane] \
2202            -command [itcl::code $this AdjustSetting ycutplane-visible] \
2203            -variable [itcl::scope _cutplane(yvisible)]
2204    }
2205    Rappture::Tooltip::for $itk_component(yCutButton) \
2206        "Toggle the Y-axis cutplane on/off"
2207
2208    itk_component add yCutScale {
2209        ::scale $inner.yval -from 100 -to 1 \
2210            -width 10 -orient vertical -showvalue yes \
2211            -borderwidth 1 -highlightthickness 0 \
2212            -command [itcl::code $this EventuallySetCutplane y] \
2213            -variable [itcl::scope _cutplane(yposition)]
2214    } {
2215        usual
2216        ignore -borderwidth -highlightthickness
2217    }
2218    Rappture::Tooltip::for $itk_component(yCutScale) \
2219        "@[itcl::code $this Slice tooltip y]"
2220    # Set the default cutplane value before disabling the scale.
2221    $itk_component(yCutScale) set 100
2222    $itk_component(yCutScale) configure -state disabled
2223
2224    # Z-value slicer...
2225    itk_component add zCutButton {
2226        Rappture::PushButton $inner.zbutton \
2227            -onimage [Rappture::icon z-cutplane] \
2228            -offimage [Rappture::icon z-cutplane] \
2229            -command [itcl::code $this AdjustSetting zcutplane-visible] \
2230            -variable [itcl::scope _cutplane(zvisible)]
2231    }
2232    Rappture::Tooltip::for $itk_component(zCutButton) \
2233        "Toggle the Z-axis cutplane on/off"
2234
2235    itk_component add zCutScale {
2236        ::scale $inner.zval -from 100 -to 1 \
2237            -width 10 -orient vertical -showvalue yes \
2238            -borderwidth 1 -highlightthickness 0 \
2239            -command [itcl::code $this EventuallySetCutplane z] \
2240            -variable [itcl::scope _cutplane(zposition)]
2241    } {
2242        usual
2243        ignore -borderwidth -highlightthickness
2244    }
2245    $itk_component(zCutScale) set 100
2246    $itk_component(zCutScale) configure -state disabled
2247    #$itk_component(zCutScale) configure -state disabled
2248    Rappture::Tooltip::for $itk_component(zCutScale) \
2249        "@[itcl::code $this Slice tooltip z]"
2250
2251    blt::table $inner \
2252        0,0 $inner.visible              -anchor w -pady 2 -cspan 4 \
2253        1,0 $inner.lighting             -anchor w -pady 2 -cspan 4 \
2254        2,0 $inner.wireframe            -anchor w -pady 2 -cspan 4 \
2255        3,0 $inner.edges                -anchor w -pady 2 -cspan 4 \
2256        4,0 $inner.opacity_l            -anchor w -pady 2 -cspan 4 \
2257        5,0 $inner.opacity              -fill x   -pady 2 -cspan 4 \
2258        6,0 $itk_component(xCutButton)  -anchor e -padx 2 -pady 2 \
2259        7,0 $itk_component(xCutScale)   -fill y \
2260        6,1 $itk_component(yCutButton)  -anchor e -padx 2 -pady 2 \
2261        7,1 $itk_component(yCutScale)   -fill y \
2262        6,2 $itk_component(zCutButton)  -anchor e -padx 2 -pady 2 \
2263        7,2 $itk_component(zCutScale)   -fill y \
2264
2265    blt::table configure $inner r* c* -resize none
2266    blt::table configure $inner r7 c3 -resize expand
2267}
2268
2269
2270
2271#
2272#  camera --
2273#
2274itcl::body Rappture::VtkStreamlinesViewer::camera {option args} {
2275    switch -- $option {
2276        "show" {
2277            puts [array get _view]
2278        }
2279        "set" {
2280            set who [lindex $args 0]
2281            set x $_view($who)
2282            set code [catch { string is double $x } result]
2283            if { $code != 0 || !$result } {
2284                return
2285            }
2286            switch -- $who {
2287                "ortho" {
2288                    if {$_view(ortho)} {
2289                        SendCmd "camera mode ortho"
2290                    } else {
2291                        SendCmd "camera mode persp"
2292                    }
2293                }
2294                "xpan" - "ypan" {
2295                    PanCamera
2296                }
2297                "qx" - "qy" - "qz" - "qw" {
2298                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2299                    $_arcball quaternion $q
2300                    EventuallyRotate $q
2301                }
2302                "zoom" {
2303                    SendCmd "camera zoom $_view(zoom)"
2304                }
2305            }
2306        }
2307    }
2308}
2309
2310itcl::body Rappture::VtkStreamlinesViewer::ConvertToVtkData { dataobj comp } {
2311    foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $comp] break
2312    set values [$dataobj values $comp]
2313    append out "# vtk DataFile Version 2.0 \n"
2314    append out "Test data \n"
2315    append out "ASCII \n"
2316    append out "DATASET STRUCTURED_POINTS \n"
2317    append out "DIMENSIONS $xN $yN 1 \n"
2318    append out "ORIGIN 0 0 0 \n"
2319    append out "SPACING 1 1 1 \n"
2320    append out "POINT_DATA [expr $xN * $yN] \n"
2321    append out "SCALARS field float 1 \n"
2322    append out "LOOKUP_TABLE default \n"
2323    append out [join $values "\n"]
2324    append out "\n"
2325    return $out
2326}
2327
2328
2329itcl::body Rappture::VtkStreamlinesViewer::GetVtkData { args } {
2330    set bytes ""
2331    foreach dataobj [get] {
2332        foreach comp [$dataobj components] {
2333            set tag $dataobj-$comp
2334            #set contents [ConvertToVtkData $dataobj $comp]
2335            set contents [$dataobj blob $comp]
2336            append bytes "$contents\n\n"
2337        }
2338    }
2339    return [list .vtk $bytes]
2340}
2341
2342itcl::body Rappture::VtkStreamlinesViewer::GetImage { args } {
2343    if { [image width $_image(download)] > 0 &&
2344         [image height $_image(download)] > 0 } {
2345        set bytes [$_image(download) data -format "jpeg -quality 100"]
2346        set bytes [Rappture::encoding::decode -as b64 $bytes]
2347        return [list .jpg $bytes]
2348    }
2349    return ""
2350}
2351
2352itcl::body Rappture::VtkStreamlinesViewer::BuildDownloadPopup { popup command } {
2353    Rappture::Balloon $popup \
2354        -title "[Rappture::filexfer::label downloadWord] as..."
2355    set inner [$popup component inner]
2356    label $inner.summary -text "" -anchor w
2357    radiobutton $inner.vtk_button -text "VTK data file" \
2358        -variable [itcl::scope _downloadPopup(format)] \
2359        -font "Helvetica 9 " \
2360        -value vtk 
2361    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
2362    radiobutton $inner.image_button -text "Image File" \
2363        -variable [itcl::scope _downloadPopup(format)] \
2364        -value image
2365    Rappture::Tooltip::for $inner.image_button \
2366        "Save as digital image."
2367
2368    button $inner.ok -text "Save" \
2369        -highlightthickness 0 -pady 2 -padx 3 \
2370        -command $command \
2371        -compound left \
2372        -image [Rappture::icon download]
2373
2374    button $inner.cancel -text "Cancel" \
2375        -highlightthickness 0 -pady 2 -padx 3 \
2376        -command [list $popup deactivate] \
2377        -compound left \
2378        -image [Rappture::icon cancel]
2379
2380    blt::table $inner \
2381        0,0 $inner.summary -cspan 2  \
2382        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
2383        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
2384        4,1 $inner.cancel -width .9i -fill y \
2385        4,0 $inner.ok -padx 2 -width .9i -fill y
2386    blt::table configure $inner r3 -height 4
2387    blt::table configure $inner r4 -pady 4
2388    raise $inner.image_button
2389    $inner.vtk_button invoke
2390    return $inner
2391}
2392
2393itcl::body Rappture::VtkStreamlinesViewer::SetObjectStyle { dataobj comp } {
2394    # Parse style string.
2395    set tag $dataobj-$comp
2396    set style [$dataobj style $comp]
2397    #puts stderr "style $dataobj-$comp \"$style\""
2398    if { $dataobj != $_first } {
2399        set settings(-wireframe) 1
2400    }
2401    array set settings {
2402        -color \#808080
2403        -edges 0
2404        -edgecolor black
2405        -linewidth 1.0
2406        -opacity 0.4
2407        -wireframe 0
2408        -lighting 1
2409        -seeds 1
2410        -seedcolor white
2411        -visible 1
2412    }
2413    array set settings $style
2414    SendCmd "streamlines add $tag"
2415    SendCmd "streamlines seed visible off $tag"
2416    set seeds [$dataobj hints seeds]
2417    if { $seeds != "" && ![info exists _seeds($dataobj)] } {
2418        set length [string length $seeds]
2419        SendCmd "streamlines seed fmesh 200 data follows $length $tag"
2420        SendCmd "$seeds"
2421        set _seeds($dataobj) 1
2422    }
2423    SendCmd "cutplane add $tag"
2424    SendCmd "cutplane colormode $_colorMode $tag"
2425    SendCmd "cutplane edges 0 $tag"
2426    SendCmd "cutplane wireframe 0 $tag"
2427    SendCmd "cutplane lighting 1 $tag"
2428    SendCmd "cutplane linewidth 1 $tag"
2429    #SendCmd "cutplane linecolor 1 1 1 $tag"
2430    #puts stderr "cutplane axis $axis $bool"
2431    #SendCmd "cutplane visible $tag"
2432    foreach axis { x y z } {
2433        SendCmd "cutplane slice $axis 1.0 $tag"
2434        SendCmd "cutplane axis $axis 0 $tag"
2435    }
2436
2437    SendCmd "polydata add $tag"
2438    SendCmd "polydata edges $settings(-edges) $tag"
2439    set _volume(edges) $settings(-edges)
2440    SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
2441    SendCmd "polydata lighting $settings(-lighting) $tag"
2442    set _volume(lighting) $settings(-lighting)
2443    SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
2444    SendCmd "polydata linewidth $settings(-linewidth) $tag"
2445    SendCmd "polydata opacity $settings(-opacity) $tag"
2446    set _volume(opacity) $settings(-opacity)
2447    SendCmd "polydata wireframe $settings(-wireframe) $tag"
2448    set _volume(wireframe) $settings(-wireframe)
2449    set _volume(opacity) [expr $settings(-opacity) * 100.0]
2450    SetColormap $dataobj $comp
2451}
2452
2453itcl::body Rappture::VtkStreamlinesViewer::IsValidObject { dataobj } {
2454    if {[catch {$dataobj isa Rappture::Field} valid] != 0 || !$valid} {
2455        return 0
2456    }
2457    return 1
2458}
2459
2460# ----------------------------------------------------------------------
2461# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
2462#
2463# Invoked automatically whenever the "legend" command comes in from
2464# the rendering server.  Indicates that binary image data with the
2465# specified <size> will follow.
2466# ----------------------------------------------------------------------
2467itcl::body Rappture::VtkStreamlinesViewer::ReceiveLegend { colormap title vmin vmax size } {
2468    #puts stderr "ReceiveLegend colormap=$colormap title=$title range=$vmin,$vmax size=$size"
2469    set _limits(vmin) $vmin
2470    set _limits(vmax) $vmax
2471    set _title $title
2472    if { [IsConnected] } {
2473        set bytes [ReceiveBytes $size]
2474        if { ![info exists _image(legend)] } {
2475            set _image(legend) [image create photo]
2476        }
2477        $_image(legend) configure -data $bytes
2478        #puts stderr "read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
2479        DrawLegend $title
2480    }
2481}
2482
2483#
2484# DrawLegend --
2485#
2486#       Draws the legend in it's own canvas which resides to the right
2487#       of the contour plot area.
2488#
2489itcl::body Rappture::VtkStreamlinesViewer::DrawLegend { title } {
2490    set c $itk_component(view)
2491    set w [winfo width $c]
2492    set h [winfo height $c]
2493    set font "Arial 8"
2494    set lineht [font metrics $font -linespace]
2495   
2496    regsub {\(mag\)} $title "" title
2497    if { $_settings(legend) } {
2498        set x [expr $w - 2]
2499        if { [$c find withtag "legend"] == "" } {
2500            set y 2
2501            $c create text $x $y \
2502                -anchor ne \
2503                -fill $itk_option(-plotforeground) -tags "title legend" \
2504                -font $font
2505            incr y $lineht
2506            $c create text $x $y \
2507                -anchor ne \
2508                -fill $itk_option(-plotforeground) -tags "vmax legend" \
2509                -font $font
2510            incr y $lineht
2511            $c create image $x $y \
2512                -anchor ne \
2513                -image $_image(legend) -tags "colormap legend"
2514            $c create text $x [expr {$h-2}] \
2515                -anchor se \
2516                -fill $itk_option(-plotforeground) -tags "vmin legend" \
2517                -font $font
2518            #$c bind colormap <Enter> [itcl::code $this EnterLegend %x %y]
2519            $c bind colormap <Leave> [itcl::code $this LeaveLegend]
2520            $c bind colormap <Motion> [itcl::code $this MotionLegend %x %y]
2521        }
2522        # Reset the item coordinates according the current size of the plot.
2523        $c itemconfigure title -text $title
2524        if { $_limits(vmin) != "" } {
2525            $c itemconfigure vmin -text [format %g $_limits(vmin)]
2526        }
2527        if { $_limits(vmax) != "" } {
2528            $c itemconfigure vmax -text [format %g $_limits(vmax)]
2529        }
2530        set y 2
2531        $c coords title $x $y
2532        incr y $lineht
2533        $c coords vmax $x $y
2534        incr y $lineht
2535        $c coords colormap $x $y
2536        $c coords vmin $x [expr {$h - 2}]
2537    }
2538}
2539
2540#
2541# EnterLegend --
2542#
2543itcl::body Rappture::VtkStreamlinesViewer::EnterLegend { x y } {
2544    SetLegendTip $x $y
2545}
2546
2547#
2548# MotionLegend --
2549#
2550itcl::body Rappture::VtkStreamlinesViewer::MotionLegend { x y } {
2551    Rappture::Tooltip::tooltip cancel
2552    set c $itk_component(view)
2553    SetLegendTip $x $y
2554}
2555
2556#
2557# LeaveLegend --
2558#
2559itcl::body Rappture::VtkStreamlinesViewer::LeaveLegend { } {
2560    Rappture::Tooltip::tooltip cancel
2561    .rappturetooltip configure -icon ""
2562}
2563
2564#
2565# SetLegendTip --
2566#
2567itcl::body Rappture::VtkStreamlinesViewer::SetLegendTip { x y } {
2568    set c $itk_component(view)
2569    set w [winfo width $c]
2570    set h [winfo height $c]
2571    set font "Arial 8"
2572    set lineht [font metrics $font -linespace]
2573   
2574    set imgHeight [image height $_image(legend)]
2575    set coords [$c coords colormap]
2576    set imgX [expr $w - [image width $_image(legend)] - 2]
2577    set imgY [expr $y - 2 * ($lineht + 2)]
2578
2579    # Make a swatch of the selected color
2580    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
2581        #puts stderr "out of range: $imgY"
2582        return
2583    }
2584    if { ![info exists _image(swatch)] } {
2585        set _image(swatch) [image create photo -width 24 -height 24]
2586    }
2587    set color [eval format "\#%02x%02x%02x" $pixel]
2588    $_image(swatch) put black  -to 0 0 23 23
2589    $_image(swatch) put $color -to 1 1 22 22
2590    .rappturetooltip configure -icon $_image(swatch)
2591
2592    # Compute the value of the point
2593    set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
2594    #puts stderr "t=$t x=$x y=$y imgY=$imgY"
2595    set value [expr $t * ($_limits(vmax) - $_limits(vmin)) + $_limits(vmin)]
2596    set tipx [expr $x + 15]
2597    set tipy [expr $y - 5]
2598    #puts stderr "tipx=$tipx tipy=$tipy x=$x y=$y"
2599    Rappture::Tooltip::text $c "$_title $value"
2600    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy   
2601}
2602
2603
2604# ----------------------------------------------------------------------
2605# USAGE: Slice move x|y|z <newval>
2606#
2607# Called automatically when the user drags the slider to move the
2608# cut plane that slices 3D data.  Gets the current value from the
2609# slider and moves the cut plane to the appropriate point in the
2610# data set.
2611# ----------------------------------------------------------------------
2612itcl::body Rappture::VtkStreamlinesViewer::Slice {option args} {
2613    switch -- $option {
2614        "move" {
2615            set axis [lindex $args 0]
2616            set oldval $_axis(${axis}position)
2617            set newval [lindex $args 1]
2618            if {[llength $args] != 2} {
2619                error "wrong # args: should be \"Slice move x|y|z newval\""
2620            }
2621            set newpos [expr {0.01*$newval}]
2622            SendCmd "cutplane slice $axis $newpos"
2623        }
2624        "tooltip" {
2625            set axis [lindex $args 0]
2626            set val [$itk_component(${axis}CutScale) get]
2627            return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
2628        }
2629        default {
2630            error "bad option \"$option\": should be axis, move, or tooltip"
2631        }
2632    }
2633}
Note: See TracBrowser for help on using the repository browser.