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
RevLine 
[5006]1# -*- mode: tcl; indent-tabs-mode: nil -*-
[2504]2# ----------------------------------------------------------------------
[4444]3#  COMPONENT: vtkstreamlinesviewer - Vtk streamlines object viewer
[2504]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
[4344]9#  Copyright (c) 2004-2014  HUBzero Foundation, LLC
[2504]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
[2743]16package require Img
[2504]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
[6052]41    constructor { args } {
42        Rappture::VisViewer::constructor
[2504]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 {}
[5006]59    public method parameters {title args} {
60        # do nothing
[2504]61    }
62    public method scale {args}
63
64    # The following methods are only used by this class.
[4765]65    private method AdjustSetting {what {value ""}}
[2504]66    private method BuildAxisTab {}
67    private method BuildCameraTab {}
[5770]68    private method BuildColormap { name }
[2584]69    private method BuildCutplaneTab {}
[5006]70    private method BuildDownloadPopup { widget command }
[2504]71    private method BuildStreamsTab {}
[5764]72    private method BuildSurfaceTab {}
[3442]73    private method DrawLegend {}
[2649]74    private method Combo { option }
[4765]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 {}
[5006]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 }
[4765]88    private method InitSettings { args  }
[5006]89    private method IsValidObject { dataobj }
[2504]90    private method LeaveLegend {}
[5006]91    private method MotionLegend { x y }
[4765]92    private method Pan {option x y}
[2504]93    private method PanCamera {}
[4765]94    private method Pick {x y}
[5006]95    private method QuaternionToView { q } {
[4765]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 }
[2587]102    private method RequestLegend {}
[4765]103    private method Rotate {option x y}
[5770]104    private method SetCurrentColormap { color }
[2504]105    private method SetLegendTip { x y }
[5006]106    private method SetObjectStyle { dataobj comp }
107    private method Slice {option args}
[3517]108    private method SetOrientation { side }
[5006]109    private method ViewToQuaternion {} {
[4765]110        return [list $_view(-qw) $_view(-qx) $_view(-qy) $_view(-qz)]
111    }
112    private method Zoom {option}
[2504]113
114    private variable _arcball ""
115
[2744]116    private variable _dlist ""     ;    # list of data objects
117    private variable _obj2ovride   ;    # maps dataobj => style override
[5006]118    private variable _datasets     ;    # contains all the dataobj-component
[2744]119                                   ;    # datasets in the server
120    private variable _colormaps    ;    # contains all the colormaps
121                                   ;    # in the server.
[5770]122    private variable _currentColormap ""
[2504]123
[2744]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
[2504]127    private variable _settings
[5156]128    private variable _reset 1;          # Connection to server has been reset.
[2504]129
[2744]130    private variable _first ""     ;    # This is the topmost dataset.
[2504]131    private variable _start 0
132    private variable _title ""
[2547]133    private variable _seeds
[2504]134    private variable _width 0
135    private variable _height 0
136    private variable _resizePending 0
[2600]137    private variable _reseedPending 0
[2504]138    private variable _rotatePending 0
[2584]139    private variable _cutplanePending 0
[2652]140    private variable _legendPending 0
[5006]141    private variable _fields
[3405]142    private variable _curFldName ""
143    private variable _curFldLabel ""
[2744]144    private variable _field      ""
[2600]145    private variable _numSeeds 200
[2587]146    private variable _colorMode "vmag";#  Mode of colormap (vmag or scalar)
[5764]147
148    private common _downloadPopup;      # download options from popup
149    private common _hardcopy
[2504]150}
151
152itk::usual VtkStreamlinesViewer {
153    keep -background -foreground -cursor -font
154    keep -plotbackground -plotforeground
155}
156
157# ----------------------------------------------------------------------
158# CONSTRUCTOR
159# ----------------------------------------------------------------------
[6052]160itcl::body Rappture::VtkStreamlinesViewer::constructor {args} {
[2671]161    set _serverType "vtkvis"
162
[3454]163    EnableWaitDialog 2000
[3446]164
[2504]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
[2600]173    # Reseed event
174    $_dispatcher register !reseed
175    $_dispatcher dispatch $this !reseed "[itcl::code $this DoReseed]; list"
176
[2504]177    # Rotate event
178    $_dispatcher register !rotate
179    $_dispatcher dispatch $this !rotate "[itcl::code $this DoRotate]; list"
180
[2652]181    # Legend event
182    $_dispatcher register !legend
183    $_dispatcher dispatch $this !legend "[itcl::code $this RequestLegend]; list"
184
[2584]185    # X-Cutplane event
186    $_dispatcher register !xcutplane
187    $_dispatcher dispatch $this !xcutplane \
[4771]188        "[itcl::code $this AdjustSetting -cutplanexposition]; list"
[2504]189
[2584]190    # Y-Cutplane event
191    $_dispatcher register !ycutplane
192    $_dispatcher dispatch $this !ycutplane \
[4771]193        "[itcl::code $this AdjustSetting -cutplaneyposition]; list"
[2584]194
195    # Z-Cutplane event
196    $_dispatcher register !zcutplane
197    $_dispatcher dispatch $this !zcutplane \
[4771]198        "[itcl::code $this AdjustSetting -cutplanezposition]; list"
[2584]199
[2504]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 {
[4765]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
[2504]217    }
218    set _arcball [blt::arcball create 100 100]
[4765]219    $_arcball quaternion [ViewToQuaternion]
[2504]220
221    array set _settings [subst {
[4771]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
[5764]242        -streamlineslength          70
[4771]243        -streamlinesseedsvisible    0
244        -streamlinesvisible         1
[5764]245        -surfaceedges               0
246        -surfacelighting            1
247        -surfaceopacity             40
248        -surfacevisible             1
249        -surfacewireframe           0
[4771]250        -xgrid                      0
251        -ygrid                      0
252        -zgrid                      0
[2504]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
[2649]263    itk_component add fieldmenu {
264        menu $itk_component(plotarea).menu -bg black -fg white -relief flat \
[5006]265            -tearoff no
[2649]266    } {
[2744]267        usual
268        ignore -background -foreground -relief -tearoff
[2649]269    }
[2504]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"
[3330]279    bind $c <Control-F1> [itcl::code $this ToggleConsole]
[2504]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)]
[5006]285    set _map(cwidth) -1
286    set _map(cheight) -1
[2504]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
[5764]327    itk_component add surface {
328        Rappture::PushButton $f.surface \
[2584]329            -onimage [Rappture::icon volume-on] \
330            -offimage [Rappture::icon volume-off] \
[5764]331            -variable [itcl::scope _settings(-surfacevisible)] \
332            -command [itcl::code $this AdjustSetting -surfacevisible]
[2584]333    }
[5764]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
[2584]338
339    itk_component add streamlines {
340        Rappture::PushButton $f.streamlines \
[2585]341            -onimage [Rappture::icon streamlines-on] \
342            -offimage [Rappture::icon streamlines-off] \
[4771]343            -variable [itcl::scope _settings(-streamlinesvisible)] \
344            -command [itcl::code $this AdjustSetting -streamlinesvisible] \
[2584]345    }
346    $itk_component(streamlines) select
347    Rappture::Tooltip::for $itk_component(streamlines) \
[5764]348        "Show/Hide the streamlines"
[2584]349    pack $itk_component(streamlines) -padx 2 -pady 2
350
[2622]351    itk_component add cutplane {
352        Rappture::PushButton $f.cutplane \
353            -onimage [Rappture::icon cutbutton] \
354            -offimage [Rappture::icon cutbutton] \
[4771]355            -variable [itcl::scope _settings(-cutplanevisible)] \
[5006]356            -command [itcl::code $this AdjustSetting -cutplanevisible]
[2622]357    }
358    Rappture::Tooltip::for $itk_component(cutplane) \
[5764]359        "Show/Hide the cutplanes"
[2622]360    pack $itk_component(cutplane) -padx 2 -pady 2
361
[2504]362    if { [catch {
[5764]363        BuildSurfaceTab
[2744]364        BuildStreamsTab
365        BuildCutplaneTab
366        BuildAxisTab
367        BuildCameraTab
[2504]368    } errs] != 0 } {
[2744]369        puts stderr errs=$errs
[2504]370    }
371    # Legend
372
373    set _image(legend) [image create photo]
374    itk_component add legend {
[5006]375        canvas $itk_component(plotarea).legend -width 50 -highlightthickness 0
[2504]376    } {
377        usual
378        ignore -highlightthickness
379        rename -background -plotbackground plotBackground Background
380    }
381
[5006]382    # Hack around the Tk panewindow.  The problem is that the requested
[2504]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) \
[5006]388        0,0 $itk_component(view) -fill both -reqwidth $w
[2504]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
[3443]407    #bind $itk_component(view) <ButtonRelease-3> \
408    #    [itcl::code $this Pick %x %y]
[2504]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 } {
[2744]460        set _width 500
[2504]461    }
462    if { $_height < 2 } {
[2744]463        set _height 500
[2504]464    }
465    set _start [clock clicks -milliseconds]
466    SendCmd "screen size $_width $_height"
[3438]467
[2673]468    set _legendPending 1
[2504]469    set _resizePending 0
470}
471
472itcl::body Rappture::VtkStreamlinesViewer::DoRotate {} {
[5006]473    SendCmd "camera orient [ViewToQuaternion]"
[2504]474    set _rotatePending 0
475}
476
[2600]477itcl::body Rappture::VtkStreamlinesViewer::DoReseed {} {
478    foreach dataset [CurrentDatasets -visible] {
[2744]479        foreach {dataobj comp} [split $dataset -] break
480        # This command works for either random or fmesh seeds
481        SendCmd "streamlines seed numpts $_numSeeds $dataset"
[2600]482    }
483    set _reseedPending 0
484}
485
[2504]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
[2600]492        $_dispatcher event -after 400 !resize
[2504]493    }
494}
495
[2600]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
[2504]504set rotate_delay 100
505
506itcl::body Rappture::VtkStreamlinesViewer::EventuallyRotate { q } {
[4765]507    QuaternionToView $q
[2504]508    if { !$_rotatePending } {
509        set _rotatePending 1
[5006]510        global rotate_delay
[2504]511        $_dispatcher event -after $rotate_delay !rotate
512    }
513}
514
[2584]515itcl::body Rappture::VtkStreamlinesViewer::EventuallySetCutplane { axis args } {
516    if { !$_cutplanePending } {
517        set _cutplanePending 1
518        $_dispatcher event -after 100 !${axis}cutplane
519    }
520}
521
[2504]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 ""
[2744]538        -type ""
[2504]539    }
540    array set params $settings
541    set params(-description) ""
542    set params(-param) ""
[3799]543    array set params $settings
544
[2504]545    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
546        # can't handle -autocolors yet
547        set params(-color) black
548    }
[3813]549    set pos [lsearch -exact $_dlist $dataobj]
[2504]550    if {$pos < 0} {
[2744]551        lappend _dlist $dataobj
[2504]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#
[6142]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.
[2504]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]
[2744]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
[2504]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 {
[2744]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                }
[5006]613                if {[info exists _obj2ovride($dataobj-raise)] &&
[2744]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
[5006]641        }
[2744]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        }
[2504]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 {
[3431]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]
[2744]687        }
[3431]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]
[2744]702        }
[2504]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:"
[2744]738            update idletasks            ;# Fix initial sizes
[2504]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    }
[5156]774    set _reset 1
[2504]775    set result [VisViewer::Connect $_hosts]
776    if { $result } {
[3592]777        if { $_reportClientInfo }  {
778            # Tell the server the viewer, hub, user and session.
[4075]779            # Do this immediately on connect before buffering any commands
[3592]780            global env
781
782            set info {}
783            set user "???"
[5006]784            if { [info exists env(USER)] } {
[3592]785                set user $env(USER)
[5006]786            }
[3592]787            set session "???"
[5006]788            if { [info exists env(SESSION)] } {
[3592]789                set session $env(SESSION)
[5006]790            }
[4669]791            lappend info "version" "$Rappture::version"
792            lappend info "build" "$Rappture::build"
793            lappend info "svnurl" "$Rappture::svnurl"
794            lappend info "installdir" "$Rappture::installdir"
[3592]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
[2504]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
[2652]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
[2504]843    # disconnected -- no more data sitting on server
[5006]844    array unset _datasets
845    array unset _colormaps
846    array unset _seeds
[2504]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" } {
[2744]865        if 0 {
[4767]866            set f [open "last.ppm" "w"]
867            fconfigure $f -encoding binary
868            puts -nonewline $f $bytes
[2744]869            close $f
870        }
[2504]871        $_image(plot) configure -data $bytes
[2744]872        set time [clock seconds]
873        set date [clock format $time]
[5006]874        #puts stderr "$date: received image [image width $_image(plot)]x[image height $_image(plot)] image>"
[2744]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        }
[2504]880    } elseif { $info(type) == "print" } {
881        set tag $this-print-$info(-token)
882        set _hardcopy($tag) $bytes
883    }
[2652]884    if { $_legendPending } {
[2744]885        RequestLegend
[2652]886    }
[2504]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 {
[2744]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" {
[2504]921            foreach { name } [lindex $args 1] {
922                #puts stderr "Dataset: $name"
923            }
[2744]924        }
925        default {
926            error "unknown dataset option \"$option\" from server"
927        }
[2504]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 } {
[5092]942        update
[2744]943        $_dispatcher event -idle !rebuild
944        return
[2504]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
[3418]949    # generates a new call to Rebuild).
[3421]950    StartBufferingCommands
951    set _legendPending 1
[3330]952
953    set _first ""
954    if { $_reset } {
[5006]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
[3400]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"
[2504]965    }
966
967    set _first ""
[3400]968    SendCmd "dataset visible 0"
[2504]969    foreach dataobj [get -objects] {
[2744]970        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
971            set _first $dataobj
972        }
[2504]973        foreach comp [$dataobj components] {
974            set tag $dataobj-$comp
975            if { ![info exists _datasets($tag)] } {
[3330]976                set bytes [$dataobj vtkdata $comp]
[2504]977                set length [string length $bytes]
[5006]978                if 0 {
[3405]979                    set f [open /tmp/vtkstreamlines.vtk "w"]
980                    fconfigure $f -translation binary -encoding binary
[4767]981                    puts -nonewline $f $bytes
[3405]982                    close $f
[5006]983                }
[3421]984                if { $_reportClientInfo }  {
[3392]985                    set info {}
[4749]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]
[3392]991                    lappend info "dataset_label" [$dataobj hints label]
992                    lappend info "dataset_size"  $length
[3394]993                    lappend info "dataset_tag"   $tag
[3392]994                    SendCmd "clientinfo [list $info]"
995                }
[3421]996                SendCmd "dataset add $tag data follows $length"
[5134]997                SendData $bytes
[2504]998                set _datasets($tag) 1
[2744]999                SetObjectStyle $dataobj $comp
1000            }
1001            if { [info exists _obj2ovride($dataobj-raise)] } {
1002                SendCmd "dataset visible 1 $tag"
1003            }
[2504]1004        }
1005    }
1006    if {"" != $_first} {
[2744]1007        foreach axis { x y z } {
1008            set label [$_first hints ${axis}label]
1009            if { $label != "" } {
[4199]1010                SendCmd [list axis name $axis $label]
[2744]1011            }
1012            set units [$_first hints ${axis}units]
1013            if { $units != "" } {
[4199]1014                SendCmd [list axis units $axis $units]
[2744]1015            }
1016        }
[5006]1017        $itk_component(field) choices delete 0 end
1018        $itk_component(fieldmenu) delete 0 end
1019        array unset _fields
[3421]1020        set _curFldName ""
[5764]1021        set _curFldLabel ""
[3405]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]
[5764]1038                if { $_curFldName == "" && $components == 3 } {
[3421]1039                    set _curFldName $fname
1040                    set _curFldLabel $label
1041                }
[3405]1042            }
1043        }
1044        $itk_component(field) value $_curFldLabel
[2504]1045    }
[2601]1046
[2605]1047    if { $_reset } {
[4771]1048        InitSettings -streamlinesseedsvisible -streamlinesopacity \
[5386]1049            -streamlinesvisible \
[4771]1050            -streamlineslighting \
1051            -streamlinescolormap -field \
[5764]1052            -surfacevisible -surfaceedges -surfacelighting -surfaceopacity \
1053            -surfacewireframe \
[5006]1054            -cutplanevisible \
1055            -cutplanexposition -cutplaneyposition -cutplanezposition \
1056            -cutplanexvisible -cutplaneyvisible -cutplanezvisible
[3400]1057
[5006]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
[2744]1067        Zoom reset
[3394]1068        SendCmd "camera reset"
[2744]1069        set _reset 0
[2592]1070    }
[2504]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)
[3421]1074    StopBufferingCommands
[2504]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]
[5006]1087    switch -- $flag {
[2744]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            }
[5006]1106        }
[2744]1107        default {
1108            set dlist $args
1109        }
[2504]1110    }
1111    set rlist ""
1112    foreach dataobj $dlist {
[2744]1113        foreach comp [$dataobj components] {
1114            set tag $dataobj-$comp
1115            if { [info exists _datasets($tag)] && $_datasets($tag) } {
1116                lappend rlist $tag
1117            }
1118        }
[2504]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" {
[4765]1134            set _view(-zoom) [expr {$_view(-zoom)*1.25}]
1135            SendCmd "camera zoom $_view(-zoom)"
[2504]1136        }
1137        "out" {
[4765]1138            set _view(-zoom) [expr {$_view(-zoom)*0.8}]
1139            SendCmd "camera zoom $_view(-zoom)"
[2504]1140        }
1141        "reset" {
1142            array set _view {
[4765]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
[2504]1150            }
1151            if { $_first != "" } {
1152                set location [$_first hints camera]
1153                if { $location != "" } {
1154                    array set _view $location
1155                }
1156            }
[4765]1157            $_arcball quaternion [ViewToQuaternion]
[2744]1158            DoRotate
[3550]1159            SendCmd "camera reset"
[2504]1160        }
1161    }
1162}
1163
1164itcl::body Rappture::VtkStreamlinesViewer::PanCamera {} {
[4765]1165    set x $_view(-xpan)
1166    set y $_view(-ypan)
[2504]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                }
[2744]1202                if { $dx == 0 && $dy == 0 } {
1203                    return
1204                }
1205                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1206                EventuallyRotate $q
[2504]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] {
[5068]1224        SendCmd "dataset getscalar pixel $x $y $tag"
[5006]1225    }
[2504]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 {
[2744]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)]
[4765]1243            set _view(-xpan) [expr $_view(-xpan) + $x]
1244            set _view(-ypan) [expr $_view(-ypan) + $y]
[2744]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
[4765]1266            set _view(-xpan) [expr $_view(-xpan) - $dx]
1267            set _view(-ypan) [expr $_view(-ypan) - $dy]
[2744]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        }
[2504]1277    }
1278}
1279
1280# ----------------------------------------------------------------------
[2600]1281# USAGE: InitSettings <what> ?<value>?
[2504]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# ----------------------------------------------------------------------
[2600]1287itcl::body Rappture::VtkStreamlinesViewer::InitSettings { args } {
1288    foreach spec $args {
[4771]1289        if { [info exists _settings($_first${spec})] } {
[2744]1290            # Reset global setting with dataobj specific setting
[4771]1291            set _settings($spec) $_settings($_first${spec})
[2744]1292        }
1293        AdjustSetting $spec
[2504]1294    }
1295}
1296
1297#
1298# AdjustSetting --
1299#
[2744]1300#       Changes/updates a specific setting in the widget.  There are
1301#       usually user-setable option.  Commands are sent to the render
1302#       server.
[2504]1303#
1304itcl::body Rappture::VtkStreamlinesViewer::AdjustSetting {what {value ""}} {
1305    if { ![isconnected] } {
[2744]1306        return
[2504]1307    }
1308    switch -- $what {
[4771]1309        "-axesvisible" {
[4679]1310            set bool $_settings($what)
[2744]1311            SendCmd "axis visible all $bool"
[2504]1312        }
[4771]1313        "-axislabelsvisible" {
[4679]1314            set bool $_settings($what)
[2744]1315            SendCmd "axis labels all $bool"
[2504]1316        }
[4771]1317        "-axisminorticks" {
[4679]1318            set bool $_settings($what)
1319            SendCmd "axis minticks all $bool"
1320        }
[4771]1321        "-axismode" {
[2744]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"
[2504]1326        }
[4771]1327        "-cutplaneedges" {
[2744]1328            set bool $_settings($what)
[3400]1329            SendCmd "cutplane edges $bool"
[2587]1330        }
[4771]1331        "-cutplanevisible" {
[2744]1332            set bool $_settings($what)
[3400]1333            SendCmd "cutplane visible $bool"
[5764]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            }
[2587]1341        }
[4771]1342        "-cutplanewireframe" {
[2744]1343            set bool $_settings($what)
[3400]1344            SendCmd "cutplane wireframe $bool"
[2587]1345        }
[4771]1346        "-cutplanelighting" {
[2744]1347            set bool $_settings($what)
[3400]1348            SendCmd "cutplane lighting $bool"
[2587]1349        }
[4771]1350        "-cutplaneopacity" {
[2744]1351            set val $_settings($what)
1352            set sval [expr { 0.01 * double($val) }]
[3400]1353            SendCmd "cutplane opacity $sval"
[2587]1354        }
[4771]1355        "-cutplanexvisible" - "-cutplaneyvisible" - "-cutplanezvisible" {
1356            set axis [string range $what 9 9]
[2744]1357            set bool $_settings($what)
[2504]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            }
[3400]1365            SendCmd "cutplane axis $axis $bool"
[2744]1366        }
[4771]1367        "-cutplanexposition" - "-cutplaneyposition" - "-cutplanezposition" {
1368            set axis [string range $what 9 9]
[2744]1369            set pos [expr $_settings($what) * 0.01]
[3400]1370            SendCmd "cutplane slice ${axis} ${pos}"
[2744]1371            set _cutplanePending 0
1372        }
[4771]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" {
[2744]1401            set bool $_settings($what)
[3400]1402            SendCmd "streamlines seed visible $bool"
[2504]1403        }
[4771]1404        "-streamlinesnumseeds" {
[2744]1405            set density $_settings($what)
1406            EventuallyReseed $density
[2579]1407        }
[4771]1408        "-streamlinesvisible" {
[2744]1409            set bool $_settings($what)
[3400]1410            SendCmd "streamlines visible $bool"
[2744]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            }
[2504]1418        }
[4771]1419        "-streamlinesmode" {
[2744]1420            set mode [$itk_component(streammode) value]
[4771]1421            set _settings($what) $mode
[3400]1422            switch -- $mode {
1423                "lines" {
1424                    SendCmd "streamlines lines"
[2744]1425                }
[3400]1426                "ribbons" {
1427                    SendCmd "streamlines ribbons 3 0"
1428                }
1429                "tubes" {
1430                    SendCmd "streamlines tubes 5 3"
1431                }
[2504]1432            }
1433        }
[4771]1434        "-streamlinescolormap" {
[3442]1435            set colormap [$itk_component(colormap) value]
[4771]1436            set _settings($what) $colormap
[5770]1437            SetCurrentColormap $colormap
[2744]1438            set _legendPending 1
[2586]1439        }
[4771]1440        "-streamlinesopacity" {
[4679]1441            set val $_settings($what)
[2744]1442            set sval [expr { 0.01 * double($val) }]
[3400]1443            SendCmd "streamlines opacity $sval"
[2504]1444        }
[5764]1445        "-streamlineslength" {
[4679]1446            set val $_settings($what)
[5764]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"
[2579]1454        }
[4771]1455        "-streamlineslighting" {
[4679]1456            set bool $_settings($what)
[3400]1457            SendCmd "streamlines lighting $bool"
[2579]1458        }
[5764]1459        "-surfaceopacity" {
[4771]1460            set val $_settings($what)
1461            set sval [expr { 0.01 * double($val) }]
1462            SendCmd "polydata opacity $sval"
1463        }
[5764]1464        "-surfacewireframe" {
[4771]1465            set bool $_settings($what)
1466            SendCmd "polydata wireframe $bool"
1467        }
[5764]1468        "-surfacevisible" {
[4771]1469            set bool $_settings($what)
1470            SendCmd "polydata visible $bool"
1471            if { $bool } {
[5764]1472                Rappture::Tooltip::for $itk_component(surface) \
1473                    "Hide the boundary surface"
[2744]1474            } else {
[5764]1475                Rappture::Tooltip::for $itk_component(surface) \
1476                    "Show the boundary surface"
[2584]1477            }
1478        }
[5764]1479        "-surfacelighting" {
[4771]1480            set bool $_settings($what)
1481            SendCmd "polydata lighting $bool"
1482        }
[5764]1483        "-surfaceedges" {
[4771]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        }
[2504]1492        default {
1493            error "don't know how to fix $what"
1494        }
1495    }
1496}
1497
1498#
1499# RequestLegend --
1500#
[2744]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.
[2504]1504#
[2587]1505itcl::body Rappture::VtkStreamlinesViewer::RequestLegend {} {
[2504]1506    set font "Arial 8"
1507    set lineht [font metrics $font -linespace]
1508    set w 12
[2584]1509    set h [expr {$_height - 3 * ($lineht + 2)}]
[3899]1510    if { $h < 1 } {
[2744]1511        return
[2504]1512    }
1513    # Set the legend on the first streamlines dataset.
[5770]1514    if { $_currentColormap != "" } {
1515        set cmap $_currentColormap
1516        if { ![info exists _colormaps($cmap)] } {
1517            BuildColormap $cmap
1518            set _colormaps($cmap) 1
[2504]1519        }
[5770]1520        #SendCmd "legend $cmap $_colorMode $_curFldName {} $w $h 0"
1521        SendCmd "legend2 $cmap $w $h"
[2504]1522    }
1523}
1524
1525#
[5770]1526# SetCurrentColormap --
[2586]1527#
[5770]1528itcl::body Rappture::VtkStreamlinesViewer::SetCurrentColormap { name } {
1529    # Keep track of the colormaps that we build.
[2586]1530    if { ![info exists _colormaps($name)] } {
[5770]1531        BuildColormap $name
[2744]1532        set _colormaps($name) 1
[2504]1533    }
[5770]1534    set _currentColormap $name
1535    SendCmd "streamlines colormap $_currentColormap"
1536    SendCmd "cutplane colormap $_currentColormap"
[2504]1537}
1538
[2585]1539#
1540# BuildColormap --
1541#
[5770]1542itcl::body Rappture::VtkStreamlinesViewer::BuildColormap { name } {
1543    set cmap [ColorsToColormap $name]
[2504]1544    if { [llength $cmap] == 0 } {
[2744]1545        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
[2504]1546    }
[5184]1547    set amap "0.0 1.0 1.0 1.0"
1548    SendCmd "colormap add $name { $cmap } { $amap }"
[2504]1549}
1550
1551# ----------------------------------------------------------------------
1552# CONFIGURATION OPTION: -plotbackground
1553# ----------------------------------------------------------------------
1554itcl::configbody Rappture::VtkStreamlinesViewer::plotbackground {
1555    if { [isconnected] } {
[4765]1556        set rgb [Color2RGB $itk_option(-plotbackground)]
1557        SendCmd "screen bgcolor $rgb"
[2504]1558    }
1559}
1560
1561# ----------------------------------------------------------------------
1562# CONFIGURATION OPTION: -plotforeground
1563# ----------------------------------------------------------------------
1564itcl::configbody Rappture::VtkStreamlinesViewer::plotforeground {
1565    if { [isconnected] } {
[4765]1566        set rgb [Color2RGB $itk_option(-plotforeground)]
1567        SendCmd "axis color all $rgb"
1568        SendCmd "outline color $rgb"
1569        SendCmd "cutplane color $rgb"
[2504]1570    }
1571}
1572
[5764]1573itcl::body Rappture::VtkStreamlinesViewer::BuildSurfaceTab {} {
[2504]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 \
[5764]1579        -title "Boundary Surface Settings" \
[2504]1580        -icon [Rappture::icon volume-on]]
1581    $inner configure -borderwidth 4
1582
[5764]1583    checkbutton $inner.surface \
1584        -text "Show Surface" \
1585        -variable [itcl::scope _settings(-surfacevisible)] \
1586        -command [itcl::code $this AdjustSetting -surfacevisible] \
[2504]1587        -font "Arial 9"
1588
1589    checkbutton $inner.wireframe \
1590        -text "Show Wireframe" \
[5764]1591        -variable [itcl::scope _settings(-surfacewireframe)] \
1592        -command [itcl::code $this AdjustSetting -surfacewireframe] \
[2504]1593        -font "Arial 9"
1594
1595    checkbutton $inner.lighting \
1596        -text "Enable Lighting" \
[5764]1597        -variable [itcl::scope _settings(-surfacelighting)] \
1598        -command [itcl::code $this AdjustSetting -surfacelighting] \
[2504]1599        -font "Arial 9"
1600
1601    checkbutton $inner.edges \
1602        -text "Show Edges" \
[5764]1603        -variable [itcl::scope _settings(-surfaceedges)] \
1604        -command [itcl::code $this AdjustSetting -surfaceedges] \
[2504]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 \
[5764]1609        -variable [itcl::scope _settings(-surfaceopacity)] \
[2504]1610        -width 10 \
1611        -showvalue off \
[5764]1612        -command [itcl::code $this AdjustSetting -surfaceopacity]
[2504]1613
1614    blt::table $inner \
[3330]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 \
[5006]1619        3,1 $inner.opacity   -fill x   -pady 2
[2504]1620
1621    blt::table configure $inner r* c* -resize none
[3330]1622    blt::table configure $inner r4 c1 -resize expand
[2504]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" \
[2585]1632        -icon [Rappture::icon streamlines-on]]
[2504]1633    $inner configure -borderwidth 4
1634
1635    checkbutton $inner.streamlines \
1636        -text "Show Streamlines" \
[4771]1637        -variable [itcl::scope _settings(-streamlinesvisible)] \
1638        -command [itcl::code $this AdjustSetting -streamlinesvisible] \
[2504]1639        -font "Arial 9"
[5006]1640
[2579]1641    checkbutton $inner.lighting \
1642        -text "Enable Lighting" \
[4771]1643        -variable [itcl::scope _settings(-streamlineslighting)] \
1644        -command [itcl::code $this AdjustSetting -streamlineslighting] \
[2579]1645        -font "Arial 9"
1646
[2504]1647    checkbutton $inner.seeds \
1648        -text "Show Seeds" \
[4771]1649        -variable [itcl::scope _settings(-streamlinesseedsvisible)] \
1650        -command [itcl::code $this AdjustSetting -streamlinesseedsvisible] \
[2504]1651        -font "Arial 9"
1652
[5006]1653    label $inner.mode_l -text "Mode" -font "Arial 9"
[2504]1654    itk_component add streammode {
[2744]1655        Rappture::Combobox $inner.mode -width 10 -editable no
[2504]1656    }
1657    $inner.mode choices insert end \
1658        "lines"    "lines" \
1659        "ribbons"   "ribbons" \
[5006]1660        "tubes"     "tubes"
[4771]1661    $itk_component(streammode) value $_settings(-streamlinesmode)
1662    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting -streamlinesmode]
[2504]1663
1664    label $inner.opacity_l -text "Opacity" -font "Arial 9"
1665    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
[4771]1666        -variable [itcl::scope _settings(-streamlinesopacity)] \
[2504]1667        -width 10 \
1668        -showvalue off \
[4771]1669        -command [itcl::code $this AdjustSetting -streamlinesopacity]
[2504]1670
[3330]1671    label $inner.density_l -text "No. Seeds" -font "Arial 9"
[2587]1672    ::scale $inner.density -from 1 -to 1000 -orient horizontal \
[4771]1673        -variable [itcl::scope _settings(-streamlinesnumseeds)] \
[2579]1674        -width 10 \
[2587]1675        -showvalue on \
[4771]1676        -command [itcl::code $this AdjustSetting -streamlinesnumseeds]
[2579]1677
[5764]1678    label $inner.scale_l -text "Length" -font "Arial 9"
[2579]1679    ::scale $inner.scale -from 1 -to 100 -orient horizontal \
[5764]1680        -variable [itcl::scope _settings(-streamlineslength)] \
[2579]1681        -width 10 \
1682        -showvalue off \
[5764]1683        -command [itcl::code $this AdjustSetting -streamlineslength]
[2579]1684
[5006]1685    label $inner.field_l -text "Color by" -font "Arial 9"
[2584]1686    itk_component add field {
[2744]1687        Rappture::Combobox $inner.field -width 10 -editable no
[2584]1688    }
1689    bind $inner.field <<Value>> \
[4771]1690        [itcl::code $this AdjustSetting -field]
[2584]1691
[5006]1692    label $inner.colormap_l -text "Colormap" -font "Arial 9"
[3442]1693    itk_component add colormap {
1694        Rappture::Combobox $inner.colormap -width 10 -editable no
[2586]1695    }
[4336]1696    $inner.colormap choices insert end [GetColormapList]
[2587]1697
[3442]1698    $itk_component(colormap) value "BCGYR"
1699    bind $inner.colormap <<Value>> \
[4771]1700        [itcl::code $this AdjustSetting -streamlinescolormap]
[2586]1701
[2504]1702    blt::table $inner \
[3442]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  \
[3330]1707        2,0 $inner.mode_l      -anchor w -pady 2  \
1708        2,1 $inner.mode        -fill x   -pady 2  \
[5764]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 \
[3330]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  \
[2504]1717
1718    blt::table configure $inner r* c* -resize none
[6130]1719    blt::table configure $inner r8 c1 c2 -resize expand
[2504]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" \
[4679]1729        -icon [Rappture::icon axis2]]
[2504]1730    $inner configure -borderwidth 4
1731
1732    checkbutton $inner.visible \
[4679]1733        -text "Axes" \
[4771]1734        -variable [itcl::scope _settings(-axesvisible)] \
1735        -command [itcl::code $this AdjustSetting -axesvisible] \
[2504]1736        -font "Arial 9"
1737
1738    checkbutton $inner.labels \
[4679]1739        -text "Axis Labels" \
[4771]1740        -variable [itcl::scope _settings(-axislabelsvisible)] \
1741        -command [itcl::code $this AdjustSetting -axislabelsvisible] \
[2504]1742        -font "Arial 9"
[5006]1743    label $inner.grid_l -text "Grid" -font "Arial 9"
[3330]1744    checkbutton $inner.xgrid \
[4679]1745        -text "X" \
[4771]1746        -variable [itcl::scope _settings(-xgrid)] \
1747        -command [itcl::code $this AdjustSetting -xgrid] \
[2504]1748        -font "Arial 9"
[3330]1749    checkbutton $inner.ygrid \
[4679]1750        -text "Y" \
[4771]1751        -variable [itcl::scope _settings(-ygrid)] \
1752        -command [itcl::code $this AdjustSetting -ygrid] \
[2504]1753        -font "Arial 9"
[3330]1754    checkbutton $inner.zgrid \
[4679]1755        -text "Z" \
[4771]1756        -variable [itcl::scope _settings(-zgrid)] \
1757        -command [itcl::code $this AdjustSetting -zgrid] \
[2504]1758        -font "Arial 9"
[4679]1759    checkbutton $inner.minorticks \
1760        -text "Minor Ticks" \
[4771]1761        -variable [itcl::scope _settings(-axisminorticks)] \
1762        -command [itcl::code $this AdjustSetting -axisminorticks] \
[4679]1763        -font "Arial 9"
[2504]1764
[5006]1765    label $inner.mode_l -text "Mode" -font "Arial 9"
[2504]1766
1767    itk_component add axismode {
[2744]1768        Rappture::Combobox $inner.mode -width 10 -editable no
[2504]1769    }
1770    $inner.mode choices insert end \
1771        "static_triad"    "static" \
1772        "closest_triad"   "closest" \
[3923]1773        "furthest_triad"  "farthest" \
[5006]1774        "outer_edges"     "outer"
[4771]1775    $itk_component(axismode) value $_settings(-axismode)
1776    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting -axismode]
[2504]1777
1778    blt::table $inner \
[4679]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
[2504]1788
1789    blt::table configure $inner r* c* -resize none
[4679]1790    blt::table configure $inner r7 c6 -resize expand
1791    blt::table configure $inner r3 -height 0.125i
[2504]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
[3517]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 \
[3534]1810        0,0 $inner.view_l -anchor e -pady 2 \
1811        0,1 $inner.view -anchor w -pady 2
[4771]1812    blt::table configure $inner r0 -resize none
[3517]1813
[2504]1814    set labels { qx qy qz qw xpan ypan zoom }
[3517]1815    set row 1
[2504]1816    foreach tag $labels {
1817        label $inner.${tag}label -text $tag -font "Arial 9"
1818        entry $inner.${tag} -font "Arial 9"  -bg white \
[4765]1819            -textvariable [itcl::scope _view(-$tag)]
[4757]1820        bind $inner.${tag} <Return> \
[4765]1821            [itcl::code $this camera set -${tag}]
[4757]1822        bind $inner.${tag} <KP_Enter> \
[4765]1823            [itcl::code $this camera set -${tag}]
[2504]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" \
[4765]1832        -variable [itcl::scope _view(-ortho)] \
1833        -command [itcl::code $this camera set -ortho] \
[2504]1834        -font "Arial 9"
1835    blt::table $inner \
[3441]1836            $row,0 $inner.ortho -cspan 2 -anchor w -pady 2
[2504]1837    blt::table configure $inner r$row -resize none
1838    incr row
1839
[4771]1840    blt::table configure $inner c* -resize none
[2504]1841    blt::table configure $inner c2 -resize expand
1842    blt::table configure $inner r$row -resize expand
1843}
1844
[2584]1845itcl::body Rappture::VtkStreamlinesViewer::BuildCutplaneTab {} {
[2504]1846
1847    set fg [option get $itk_component(hull) font Font]
[5006]1848
[2504]1849    set inner [$itk_component(main) insert end \
[2587]1850        -title "Cutplane Settings" \
[5006]1851        -icon [Rappture::icon cutbutton]]
[2504]1852
1853    $inner configure -borderwidth 4
1854
[2587]1855    checkbutton $inner.visible \
1856        -text "Show Cutplanes" \
[4771]1857        -variable [itcl::scope _settings(-cutplanevisible)] \
1858        -command [itcl::code $this AdjustSetting -cutplanevisible] \
[2587]1859        -font "Arial 9"
1860
1861    checkbutton $inner.wireframe \
1862        -text "Show Wireframe" \
[4771]1863        -variable [itcl::scope _settings(-cutplanewireframe)] \
1864        -command [itcl::code $this AdjustSetting -cutplanewireframe] \
[2587]1865        -font "Arial 9"
1866
1867    checkbutton $inner.lighting \
1868        -text "Enable Lighting" \
[4771]1869        -variable [itcl::scope _settings(-cutplanelighting)] \
1870        -command [itcl::code $this AdjustSetting -cutplanelighting] \
[2587]1871        -font "Arial 9"
1872
1873    checkbutton $inner.edges \
1874        -text "Show Edges" \
[4771]1875        -variable [itcl::scope _settings(-cutplaneedges)] \
1876        -command [itcl::code $this AdjustSetting -cutplaneedges] \
[2587]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 \
[4771]1881        -variable [itcl::scope _settings(-cutplaneopacity)] \
[2587]1882        -width 10 \
1883        -showvalue off \
[4771]1884        -command [itcl::code $this AdjustSetting -cutplaneopacity]
1885    $inner.opacity set $_settings(-cutplaneopacity)
[2587]1886
[2504]1887    # X-value slicer...
1888    itk_component add xCutButton {
1889        Rappture::PushButton $inner.xbutton \
[3330]1890            -onimage [Rappture::icon x-cutplane-red] \
1891            -offimage [Rappture::icon x-cutplane-red] \
[4771]1892            -command [itcl::code $this AdjustSetting -cutplanexvisible] \
1893            -variable [itcl::scope _settings(-cutplanexvisible)]
[2504]1894    }
1895    Rappture::Tooltip::for $itk_component(xCutButton) \
[2584]1896        "Toggle the X-axis cutplane on/off"
[3330]1897    $itk_component(xCutButton) select
[2504]1898
1899    itk_component add xCutScale {
[3330]1900        ::scale $inner.xval -from 100 -to 0 \
[2504]1901            -width 10 -orient vertical -showvalue yes \
1902            -borderwidth 1 -highlightthickness 0 \
[2584]1903            -command [itcl::code $this EventuallySetCutplane x] \
[4771]1904            -variable [itcl::scope _settings(-cutplanexposition)] \
[5006]1905            -foreground red3 -font "Arial 9 bold"
[2504]1906    } {
1907        usual
[3330]1908        ignore -borderwidth -highlightthickness -foreground -font
[2504]1909    }
[2584]1910    # Set the default cutplane value before disabling the scale.
[2600]1911    $itk_component(xCutScale) set 50
[2504]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 \
[3330]1919            -onimage [Rappture::icon y-cutplane-green] \
1920            -offimage [Rappture::icon y-cutplane-green] \
[4771]1921            -command [itcl::code $this AdjustSetting -cutplaneyvisible] \
1922            -variable [itcl::scope _settings(-cutplaneyvisible)]
[2504]1923    }
1924    Rappture::Tooltip::for $itk_component(yCutButton) \
[2584]1925        "Toggle the Y-axis cutplane on/off"
[3330]1926    $itk_component(yCutButton) select
[2504]1927
1928    itk_component add yCutScale {
[3330]1929        ::scale $inner.yval -from 100 -to 0 \
[2504]1930            -width 10 -orient vertical -showvalue yes \
1931            -borderwidth 1 -highlightthickness 0 \
[2584]1932            -command [itcl::code $this EventuallySetCutplane y] \
[4771]1933            -variable [itcl::scope _settings(-cutplaneyposition)] \
[5006]1934            -foreground green3 -font "Arial 9 bold"
[2504]1935    } {
1936        usual
[3330]1937        ignore -borderwidth -highlightthickness -foreground -font
[2504]1938    }
1939    Rappture::Tooltip::for $itk_component(yCutScale) \
1940        "@[itcl::code $this Slice tooltip y]"
[2584]1941    # Set the default cutplane value before disabling the scale.
[2600]1942    $itk_component(yCutScale) set 50
[2504]1943    $itk_component(yCutScale) configure -state disabled
1944
1945    # Z-value slicer...
1946    itk_component add zCutButton {
1947        Rappture::PushButton $inner.zbutton \
[3330]1948            -onimage [Rappture::icon z-cutplane-blue] \
1949            -offimage [Rappture::icon z-cutplane-blue] \
[4771]1950            -command [itcl::code $this AdjustSetting -cutplanezvisible] \
1951            -variable [itcl::scope _settings(-cutplanezvisible)]
[2504]1952    }
1953    Rappture::Tooltip::for $itk_component(zCutButton) \
[2584]1954        "Toggle the Z-axis cutplane on/off"
[3330]1955    $itk_component(zCutButton) select
[2504]1956
1957    itk_component add zCutScale {
[3330]1958        ::scale $inner.zval -from 100 -to 0 \
[2504]1959            -width 10 -orient vertical -showvalue yes \
1960            -borderwidth 1 -highlightthickness 0 \
[2584]1961            -command [itcl::code $this EventuallySetCutplane z] \
[4771]1962            -variable [itcl::scope _settings(-cutplanezposition)] \
[5006]1963            -foreground blue3 -font "Arial 9 bold"
[2504]1964    } {
1965        usual
[3330]1966        ignore -borderwidth -highlightthickness -foreground -font
[2504]1967    }
[2600]1968    $itk_component(zCutScale) set 50
[2504]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 \
[3330]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 \
[5006]1979        4,0 $itk_component(xCutButton)  -anchor w -padx 2 -pady 2 \
[3330]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 \
[2504]1985
1986    blt::table configure $inner r* c* -resize none
[3330]1987    blt::table configure $inner r7 c4 -resize expand
[2504]1988}
1989
1990#
[5006]1991#  camera --
[2504]1992#
1993itcl::body Rappture::VtkStreamlinesViewer::camera {option args} {
[5006]1994    switch -- $option {
[2504]1995        "show" {
1996            puts [array get _view]
1997        }
1998        "set" {
[4765]1999            set what [lindex $args 0]
2000            set x $_view($what)
[2504]2001            set code [catch { string is double $x } result]
2002            if { $code != 0 || !$result } {
2003                return
2004            }
[4765]2005            switch -- $what {
2006                "-ortho" {
2007                    if {$_view($what)} {
[2504]2008                        SendCmd "camera mode ortho"
2009                    } else {
2010                        SendCmd "camera mode persp"
2011                    }
2012                }
[4765]2013                "-xpan" - "-ypan" {
[2504]2014                    PanCamera
2015                }
[4765]2016                "-qx" - "-qy" - "-qz" - "-qw" {
2017                    set q [ViewToQuaternion]
[2744]2018                    $_arcball quaternion $q
2019                    EventuallyRotate $q
[2504]2020                }
[4765]2021                "-zoom" {
2022                    SendCmd "camera zoom $_view($what)"
[2504]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
[3731]2034            set contents [$dataobj vtkdata $comp]
2035            append bytes "$contents\n"
[2504]2036        }
2037    }
[2584]2038    return [list .vtk $bytes]
[2504]2039}
2040
2041itcl::body Rappture::VtkStreamlinesViewer::GetImage { args } {
[5006]2042    if { [image width $_image(download)] > 0 &&
[2744]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]
[2504]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]
[5006]2055    label $inner.summary -text "" -anchor w
[2504]2056    radiobutton $inner.vtk_button -text "VTK data file" \
2057        -variable [itcl::scope _downloadPopup(format)] \
2058        -font "Helvetica 9 " \
[5006]2059        -value vtk
[2504]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)] \
[5006]2063        -value image
[2504]2064    Rappture::Tooltip::for $inner.image_button \
2065        "Save as digital image."
2066
2067    button $inner.ok -text "Save" \
[2744]2068        -highlightthickness 0 -pady 2 -padx 3 \
[2504]2069        -command $command \
[2744]2070        -compound left \
2071        -image [Rappture::icon download]
[2504]2072
2073    button $inner.cancel -text "Cancel" \
[2744]2074        -highlightthickness 0 -pady 2 -padx 3 \
2075        -command [list $popup deactivate] \
2076        -compound left \
2077        -image [Rappture::icon cancel]
[2504]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 \
[5006]2084        4,0 $inner.ok -padx 2 -width .9i -fill y
[2504]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
[5770]2095    array set style {
[5764]2096        -color BCGYR
2097        -constcolor white
2098        -edgecolor black
[2744]2099        -edges 0
[5764]2100        -lighting 1
[2744]2101        -linewidth 1.0
[5764]2102        -mode lines
2103        -numseeds 200
2104        -opacity 1.0
[2744]2105        -seeds 1
2106        -seedcolor white
[5764]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
[2744]2115        -visible 1
[2504]2116    }
[5770]2117    array set style [$dataobj style $comp]
[6045]2118
[4679]2119    StartBufferingCommands
[2504]2120    SendCmd "streamlines add $tag"
[5770]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"
[2547]2130    set seeds [$dataobj hints seeds]
2131    if { $seeds != "" && ![info exists _seeds($dataobj)] } {
[2744]2132        set length [string length $seeds]
[5770]2133        SendCmd "streamlines seed fmesh $style(-numseeds) data follows $length $tag"
[5134]2134        SendData $seeds
[2744]2135        set _seeds($dataobj) 1
[2547]2136    }
[5770]2137    set _settings(-streamlineslighting) $style(-lighting)
2138    $itk_component(streammode) value $style(-mode)
[5764]2139    AdjustSetting -streamlinesmode
[5770]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)
[5764]2145
[2584]2146    SendCmd "cutplane add $tag"
[5764]2147
[2504]2148    SendCmd "polydata add $tag"
[5770]2149    SendCmd "polydata color [Color2RGB $style(-surfacecolor)] $tag"
[3833]2150    SendCmd "polydata colormode constant {} $tag"
[5770]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)
[4679]2162    StopBufferingCommands
[5770]2163    SetCurrentColormap $style(-color)
2164    $itk_component(colormap) value $style(-color)
[2504]2165}
2166
2167itcl::body Rappture::VtkStreamlinesViewer::IsValidObject { dataobj } {
2168    if {[catch {$dataobj isa Rappture::Field} valid] != 0 || !$valid} {
[2744]2169        return 0
[2504]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 } {
[2673]2182    set _legendPending 0
[2504]2183    set _title $title
[5006]2184    regsub {\(mag\)} $title "" _title
[2504]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>"
[3442]2192        if { [catch {DrawLegend} errs] != 0 } {
[2744]2193            puts stderr errs=$errs
2194        }
[2504]2195    }
2196}
2197
2198#
2199# DrawLegend --
2200#
[2744]2201#       Draws the legend in it's own canvas which resides to the right
2202#       of the contour plot area.
[2504]2203#
[3442]2204itcl::body Rappture::VtkStreamlinesViewer::DrawLegend {} {
2205    set fname $_curFldName
[2504]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]
[5006]2211
[3442]2212    if { [info exists _fields($fname)] } {
2213        foreach { title units } $_fields($fname) break
[2744]2214        if { $units != "" } {
2215            set title [format "%s (%s)" $title $units]
2216        }
[2606]2217    } else {
[3442]2218        set title $fname
[2604]2219    }
[4771]2220    if { $_settings(-legendvisible) } {
[2744]2221        set x [expr $w - 2]
2222        if { [$c find withtag "legend"] == "" } {
[5006]2223            set y 2
[2744]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
[3431]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]
[2744]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}]
[2504]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]
[5006]2298
[2504]2299    set imgHeight [image height $_image(legend)]
2300    set coords [$c coords colormap]
2301    set imgX [expr $w - [image width $_image(legend)] - 2]
[2584]2302    set imgY [expr $y - 2 * ($lineht + 2)]
[2504]2303
[2606]2304    if { [info exists _fields($_title)] } {
[2744]2305        foreach { title units } $_fields($_title) break
2306        if { $units != "" } {
2307            set title [format "%s (%s)" $title $units]
2308        }
[2606]2309    } else {
[2744]2310        set title $_title
[2606]2311    }
[2504]2312    # Make a swatch of the selected color
2313    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
[2744]2314        #puts stderr "out of range: $imgY"
2315        return
[2504]2316    }
2317    if { ![info exists _image(swatch)] } {
[2744]2318        set _image(swatch) [image create photo -width 24 -height 24]
[2504]2319    }
2320    set color [eval format "\#%02x%02x%02x" $pixel]
[5006]2321    $_image(swatch) put black  -to 0 0 23 23
2322    $_image(swatch) put $color -to 1 1 22 22
[2504]2323    .rappturetooltip configure -icon $_image(swatch)
2324
2325    # Compute the value of the point
[3431]2326    if { [info exists _limits($_curFldName)] } {
2327        foreach {vmin vmax} $_limits($_curFldName) break
[2744]2328        set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
[3431]2329        set value [expr $t * ($vmax - $vmin) + $vmin]
[2622]2330    } else {
[2744]2331        set value 0.0
[2622]2332    }
[5006]2333    set tipx [expr $x + 15]
[2504]2334    set tipy [expr $y - 5]
[2606]2335    Rappture::Tooltip::text $c "$title $value"
[5006]2336    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy
[2504]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}]
[2584]2356            SendCmd "cutplane slice $axis $newpos"
[2504]2357        }
[2744]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        }
[2504]2363        default {
2364            error "bad option \"$option\": should be axis, move, or tooltip"
2365        }
2366    }
2367}
[2649]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} {
[5006]2381    set c $itk_component(view)
[2649]2382    switch -- $option {
2383        post {
[2744]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
[2649]2389        }
2390        activate {
[2744]2391            $c itemconfigure title -fill red
[2649]2392        }
2393        deactivate {
[5006]2394            $c itemconfigure title -fill white
[2649]2395        }
[2744]2396        invoke {
[3405]2397            $itk_component(field) value $_curFldLabel
[4771]2398            AdjustSetting -field
[2744]2399        }
[2649]2400        default {
2401            error "bad option \"$option\": should be post, unpost, select"
2402        }
2403    }
2404}
[3421]2405
[5006]2406itcl::body Rappture::VtkStreamlinesViewer::SetOrientation { side } {
[3517]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    }
[4765]2415    foreach name { -qw -qx -qy -qz } value $positions($side) {
[3517]2416        set _view($name) $value
[5006]2417    }
[4765]2418    set q [ViewToQuaternion]
[3517]2419    $_arcball quaternion $q
[5006]2420    SendCmd "camera orient $q"
[3534]2421    SendCmd "camera reset"
[4765]2422    set _view(-xpan) 0
2423    set _view(-ypan) 0
2424    set _view(-zoom) 1.0
[3517]2425}
Note: See TracBrowser for help on using the repository browser.