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

Last change on this file since 3147 was 3147, checked in by ldelgass, 12 years ago

Fix typo in protocol command to set element colormap

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