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

Last change on this file since 3330 was 3330, checked in by gah, 11 years ago

merge (by hand) with Rappture1.2 branch

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