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

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

fix z-axis labels for contour/heightmap

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