source: trunk/gui/scripts/vtkviewer.tcl @ 3793

Last change on this file since 3793 was 3793, checked in by ldelgass, 10 years ago

Fixes for VTK molecule viewer: sliders were calling nonexistant methods. Fix
tooltip for atom scale: 1.0 is the default radius, it is only the VDW radius if
the representation is set to space filling. Otherwise it is covalent, atomic,
or Angstroms (if scaling is 'none') depending on rscale setting. Leave default
rscale alone when setting object style, it will be changed by representation
setting anyway. Change default polydata color to white. Should be specified
by either a style or color scalars. Colormap and colormode settings for
polydata are still commented out until server support for colormapped polydata
is released.

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