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

Last change on this file since 6142 was 6142, checked in by ldelgass, 9 years ago

minor cleanups

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