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

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

Fixes for VTK molecule viewer: use scale values based on Angstroms (note that
client needs to send VTK data file in Angstroms), set radius scaling when
changing representation type

File size: 89.3 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                }
1321            }
1322            set _legendPending 1
1323        }
1324        "molecule-representation" {
1325            set value [$itk_component(representation) value]
1326            set value [$itk_component(representation) translate $value]
1327            switch -- $value {
1328                "ballandstick" {
1329                    set rscale covalent
1330                    set ashow 1
1331                    set bshow 1
1332                    set ascale 0.3
1333                    set bscale 0.075
1334                }
1335                "balls" - "spheres" {
1336                    set rscale covalent
1337                    set ashow 1
1338                    set bshow 0
1339                    set ascale 0.3
1340                    set bscale 0.075
1341                }
1342                "sticks" {
1343                    set rscale none
1344                    set ashow 1
1345                    set bshow 1
1346                    set ascale 0.075
1347                    set bscale 0.075
1348                }
1349                "spacefilling" {
1350                    set rscale van_der_waals
1351                    set ashow 1
1352                    set bshow 0
1353                    set ascale 1.0
1354                    set bscale 0.075
1355                }
1356                "rods"  {
1357                    set rscale none
1358                    set ashow 1
1359                    set bshow 1
1360                    set ascale 0.1
1361                    set bscale 0.1
1362                }
1363                "wireframe" - "lines" {
1364                    set rscale van_der_waals
1365                    set ashow 0
1366                    set bshow 1
1367                    set ascale 0.3
1368                    set bscale 0.005
1369                }
1370                default {
1371                    error "unknown representation $value"
1372                }
1373            }
1374            foreach dataset [CurrentDatasets -visible $_first] {
1375                foreach {dataobj comp} [split $dataset -] break
1376                set type [$dataobj type $comp]
1377                if { $type == "molecule" } {
1378                    SendCmd [subst {molecule rscale $rscale $dataset
1379molecule atoms $ashow $dataset
1380molecule bonds $bshow $dataset
1381molecule ascale $ascale $dataset
1382molecule bscale $bscale $dataset}]
1383                }
1384            }
1385        }
1386        "molecule-labels" {
1387            set bool $_settings(molecule-labels)
1388            foreach dataset [CurrentDatasets -visible $_first] {
1389               foreach { dataobj comp } [split $dataset -] break
1390               set type [$dataobj type $comp]
1391               if { $type == "molecule" } {
1392                   SendCmd "molecule labels $bool $dataset"
1393               }
1394            }
1395        }
1396        "axis-visible" {
1397            set bool $_axis(visible)
1398            SendCmd "axis visible all $bool"
1399        }
1400        "axis-labels" {
1401            set bool $_axis(labels)
1402            SendCmd "axis labels all $bool"
1403        }
1404        "axis-xgrid" {
1405            set bool $_axis(xgrid)
1406            SendCmd "axis grid x $bool"
1407        }
1408        "axis-ygrid" {
1409            set bool $_axis(ygrid)
1410            SendCmd "axis grid y $bool"
1411        }
1412        "axis-zgrid" {
1413            set bool $_axis(zgrid)
1414            SendCmd "axis grid z $bool"
1415        }
1416        "axis-mode" {
1417            set mode [$itk_component(axismode) value]
1418            set mode [$itk_component(axismode) translate $mode]
1419            SendCmd "axis flymode $mode"
1420        }
1421        "axis-xcutaway" - "axis-ycutaway" - "axis-zcutaway" {
1422            set axis [string range $what 5 5]
1423            set bool $_axis(${axis}cutaway)
1424            if { $bool } {
1425                set pos [expr $_axis(${axis}position) * 0.01]
1426                set dir $_axis(${axis}direction)
1427                $itk_component(${axis}CutScale) configure -state normal \
1428                    -troughcolor white
1429                SendCmd "renderer clipplane $axis $pos $dir"
1430            } else {
1431                $itk_component(${axis}CutScale) configure -state disabled \
1432                    -troughcolor grey82
1433                SendCmd "renderer clipplane $axis 1 -1"
1434            }
1435        }
1436        "axis-xposition" - "axis-yposition" - "axis-zposition" -
1437        "axis-xdirection" - "axis-ydirection" - "axis-zdirection" {
1438            set axis [string range $what 5 5]
1439            #set dir $_axis(${axis}direction)
1440            set pos [expr $_axis(${axis}position) * 0.01]
1441            SendCmd "renderer clipplane ${axis} $pos -1"
1442        }
1443        default {
1444            error "don't know how to fix $what"
1445        }
1446    }
1447}
1448
1449#
1450# RequestLegend --
1451#
1452#       Request a new legend from the server.  The size of the legend
1453#       is determined from the height of the canvas.  It will be rotated
1454#       to be vertical when drawn.
1455#
1456itcl::body Rappture::VtkViewer::RequestLegend {} {
1457    set font "Arial 8"
1458    set lineht [font metrics $font -linespace]
1459    set c $itk_component(legend)
1460    set w 12
1461    set h [expr {$_height - 2 * ($lineht + 2)}]
1462    if { $h < 1} {
1463        return
1464    }
1465    # Set the legend on the first dataset.
1466    foreach dataset [CurrentDatasets -visible] {
1467        foreach {dataobj comp} [split $dataset -] break
1468        if { [info exists _dataset2style($dataset)] } {
1469            SendCmd "legend $_dataset2style($dataset) vmag {} {} $w $h 0"
1470            break;
1471        }
1472    }
1473}
1474
1475#
1476# ChangeColormap --
1477#
1478itcl::body Rappture::VtkViewer::ChangeColormap {dataobj comp color} {
1479    set tag $dataobj-$comp
1480    if { ![info exist _style($tag)] } {
1481        error "no initial colormap"
1482    }
1483    array set style $_style($tag)
1484    set style(-color) $color
1485    set _style($tag) [array get style]
1486    SetColormap $dataobj $comp
1487}
1488
1489#
1490# SetColormap --
1491#
1492itcl::body Rappture::VtkViewer::SetColormap { dataobj comp } {
1493    array set style {
1494        -color BCGYR
1495        -levels 6
1496        -opacity 1.0
1497    }
1498    if {[$dataobj type $comp] == "molecule"} {
1499        set style(-color) elementDefault
1500    }
1501    set tag $dataobj-$comp
1502    if { ![info exists _initialStyle($tag)] } {
1503        # Save the initial component style.
1504        set _initialStyle($tag) [$dataobj style $comp]
1505    }
1506
1507    # Override defaults with initial style defined in xml.
1508    array set style $_initialStyle($tag)
1509
1510    if { ![info exists _style($tag)] } {
1511        set _style($tag) [array get style]
1512    }
1513    # Override initial style with current style.
1514    array set style $_style($tag)
1515
1516    if { $style(-color) == "elementDefault" } {
1517        set name "$style(-color)"
1518    } else {
1519        set name "$style(-color):$style(-levels):$style(-opacity)"
1520    }
1521    if { ![info exists _colormaps($name)] } {
1522        BuildColormap $name [array get style]
1523        set _colormaps($name) 1
1524    }
1525    if { ![info exists _dataset2style($tag)] ||
1526         $_dataset2style($tag) != $name } {
1527        set _dataset2style($tag) $name
1528        switch -- [$dataobj type $comp] {
1529            "polygon" {
1530                SendCmd "pseudocolor colormap $name $tag"
1531            }
1532            "glyphs" {
1533                SendCmd "glyphs colormap $name $tag"
1534            }
1535            "molecule" {
1536                SendCmd "molecule colormap $name $tag"
1537            }
1538        }
1539    }
1540}
1541
1542itcl::body Rappture::VtkViewer::ColorsToColormap { colors } {
1543    switch -- $colors {
1544        "grey-to-blue" {
1545            return {
1546                0.0                      0.200 0.200 0.200
1547                0.14285714285714285      0.400 0.400 0.400
1548                0.2857142857142857       0.600 0.600 0.600
1549                0.42857142857142855      0.900 0.900 0.900
1550                0.5714285714285714       0.800 1.000 1.000
1551                0.7142857142857143       0.600 1.000 1.000
1552                0.8571428571428571       0.400 0.900 1.000
1553                1.0                      0.000 0.600 0.800
1554            }
1555        }
1556        "blue-to-grey" {
1557            return {
1558                0.0                     0.000 0.600 0.800
1559                0.14285714285714285     0.400 0.900 1.000
1560                0.2857142857142857      0.600 1.000 1.000
1561                0.42857142857142855     0.800 1.000 1.000
1562                0.5714285714285714      0.900 0.900 0.900
1563                0.7142857142857143      0.600 0.600 0.600
1564                0.8571428571428571      0.400 0.400 0.400
1565                1.0                     0.200 0.200 0.200
1566            }
1567        }
1568        "blue" {
1569            return {
1570                0.0                     0.900 1.000 1.000
1571                0.1111111111111111      0.800 0.983 1.000
1572                0.2222222222222222      0.700 0.950 1.000
1573                0.3333333333333333      0.600 0.900 1.000
1574                0.4444444444444444      0.500 0.833 1.000
1575                0.5555555555555556      0.400 0.750 1.000
1576                0.6666666666666666      0.300 0.650 1.000
1577                0.7777777777777778      0.200 0.533 1.000
1578                0.8888888888888888      0.100 0.400 1.000
1579                1.0                     0.000 0.250 1.000
1580            }
1581        }
1582        "brown-to-blue" {
1583            return {
1584                0.0                             0.200   0.100   0.000
1585                0.09090909090909091             0.400   0.187   0.000
1586                0.18181818181818182             0.600   0.379   0.210
1587                0.2727272727272727              0.800   0.608   0.480
1588                0.36363636363636365             0.850   0.688   0.595
1589                0.45454545454545453             0.950   0.855   0.808
1590                0.5454545454545454              0.800   0.993   1.000
1591                0.6363636363636364              0.600   0.973   1.000
1592                0.7272727272727273              0.400   0.940   1.000
1593                0.8181818181818182              0.200   0.893   1.000
1594                0.9090909090909091              0.000   0.667   0.800
1595                1.0                             0.000   0.480   0.600
1596            }
1597        }
1598        "blue-to-brown" {
1599            return {
1600                0.0                             0.000   0.480   0.600
1601                0.09090909090909091             0.000   0.667   0.800
1602                0.18181818181818182             0.200   0.893   1.000
1603                0.2727272727272727              0.400   0.940   1.000
1604                0.36363636363636365             0.600   0.973   1.000
1605                0.45454545454545453             0.800   0.993   1.000
1606                0.5454545454545454              0.950   0.855   0.808
1607                0.6363636363636364              0.850   0.688   0.595
1608                0.7272727272727273              0.800   0.608   0.480
1609                0.8181818181818182              0.600   0.379   0.210
1610                0.9090909090909091              0.400   0.187   0.000
1611                1.0                             0.200   0.100   0.000
1612            }
1613        }
1614        "blue-to-orange" {
1615            return {
1616                0.0                             0.000   0.167   1.000
1617                0.09090909090909091             0.100   0.400   1.000
1618                0.18181818181818182             0.200   0.600   1.000
1619                0.2727272727272727              0.400   0.800   1.000
1620                0.36363636363636365             0.600   0.933   1.000
1621                0.45454545454545453             0.800   1.000   1.000
1622                0.5454545454545454              1.000   1.000   0.800
1623                0.6363636363636364              1.000   0.933   0.600
1624                0.7272727272727273              1.000   0.800   0.400
1625                0.8181818181818182              1.000   0.600   0.200
1626                0.9090909090909091              1.000   0.400   0.100
1627                1.0                             1.000   0.167   0.000
1628            }
1629        }
1630        "orange-to-blue" {
1631            return {
1632                0.0                             1.000   0.167   0.000
1633                0.09090909090909091             1.000   0.400   0.100
1634                0.18181818181818182             1.000   0.600   0.200
1635                0.2727272727272727              1.000   0.800   0.400
1636                0.36363636363636365             1.000   0.933   0.600
1637                0.45454545454545453             1.000   1.000   0.800
1638                0.5454545454545454              0.800   1.000   1.000
1639                0.6363636363636364              0.600   0.933   1.000
1640                0.7272727272727273              0.400   0.800   1.000
1641                0.8181818181818182              0.200   0.600   1.000
1642                0.9090909090909091              0.100   0.400   1.000
1643                1.0                             0.000   0.167   1.000
1644            }
1645        }
1646        "rainbow" {
1647            set clist {
1648                "#EE82EE"
1649                "#4B0082"
1650                "blue"
1651                "#008000"
1652                "yellow"
1653                "#FFA500"
1654                "red"
1655            }
1656        }
1657        "BGYOR" {
1658            set clist {
1659                "blue"
1660                "#008000"
1661                "yellow"
1662                "#FFA500"
1663                "red"
1664            }
1665        }
1666        "ROYGB" {
1667            set clist {
1668                "red"
1669                "#FFA500"
1670                "yellow"
1671                "#008000"
1672                "blue"
1673            }
1674        }
1675        "RYGCB" {
1676            set clist {
1677                "red"
1678                "yellow"
1679                "green"
1680                "cyan"
1681                "blue"
1682            }
1683        }
1684        "BCGYR" {
1685            set clist {
1686                "blue"
1687                "cyan"
1688                "green"
1689                "yellow"
1690                "red"
1691            }
1692        }
1693        "spectral" {
1694            return {
1695                0.0 0.150 0.300 1.000
1696                0.1 0.250 0.630 1.000
1697                0.2 0.450 0.850 1.000
1698                0.3 0.670 0.970 1.000
1699                0.4 0.880 1.000 1.000
1700                0.5 1.000 1.000 0.750
1701                0.6 1.000 0.880 0.600
1702                0.7 1.000 0.680 0.450
1703                0.8 0.970 0.430 0.370
1704                0.9 0.850 0.150 0.196
1705                1.0 0.650 0.000 0.130
1706            }
1707        }
1708        "green-to-magenta" {
1709            return {
1710                0.0 0.000 0.316 0.000
1711                0.06666666666666667 0.000 0.526 0.000
1712                0.13333333333333333 0.000 0.737 0.000
1713                0.2 0.000 0.947 0.000
1714                0.26666666666666666 0.316 1.000 0.316
1715                0.3333333333333333 0.526 1.000 0.526
1716                0.4 0.737 1.000 0.737
1717                0.4666666666666667 1.000 1.000 1.000
1718                0.5333333333333333 1.000 0.947 1.000
1719                0.6 1.000 0.737 1.000
1720                0.6666666666666666 1.000 0.526 1.000
1721                0.7333333333333333 1.000 0.316 1.000
1722                0.8 0.947 0.000 0.947
1723                0.8666666666666667 0.737 0.000 0.737
1724                0.9333333333333333 0.526 0.000 0.526
1725                1.0 0.316 0.000 0.316
1726            }
1727        }
1728        "greyscale" {
1729            return {
1730                0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
1731            }
1732        }
1733        "nanohub" {
1734            set clist "white yellow green cyan blue magenta"
1735        }
1736        default {
1737            set clist $colors
1738        }
1739    }
1740    set cmap {}
1741    set numColors [llength $clist]
1742    for {set i 0} {$i < $numColors} {incr i} {
1743        if { $numColors > 1 } {
1744            set x [expr {double($i)/($numColors-1)}]
1745        } else {
1746            set x [expr double($i)]
1747        }
1748        set color [lindex $clist $i]
1749        append cmap "$x [Color2RGB $color] "
1750    }
1751    return $cmap
1752}
1753
1754#
1755# BuildColormap --
1756#
1757itcl::body Rappture::VtkViewer::BuildColormap { name styles } {
1758    puts stderr name=$name
1759    if { $name ==  "elementDefault" } {
1760        return
1761    }
1762    array set style $styles
1763    set cmap [ColorsToColormap $style(-color)]
1764    if { [llength $cmap] == 0 } {
1765        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1766    }
1767    if { ![info exists _settings(mesh-opacity)] } {
1768        set _settings(mesh-opacity) $style(-opacity)
1769    }
1770    set max $_settings(mesh-opacity)
1771
1772    set wmap "0.0 1.0 1.0 1.0"
1773    SendCmd "colormap add $name { $cmap } { $wmap }"
1774}
1775
1776
1777# ----------------------------------------------------------------------
1778# CONFIGURATION OPTION: -plotbackground
1779# ----------------------------------------------------------------------
1780itcl::configbody Rappture::VtkViewer::plotbackground {
1781    if { [isconnected] } {
1782        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1783        SendCmd "screen bgcolor $r $g $b"
1784    }
1785}
1786
1787# ----------------------------------------------------------------------
1788# CONFIGURATION OPTION: -plotforeground
1789# ----------------------------------------------------------------------
1790itcl::configbody Rappture::VtkViewer::plotforeground {
1791    if { [isconnected] } {
1792        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1793        #fix this!
1794        #SendCmd "color background $r $g $b"
1795    }
1796}
1797
1798itcl::body Rappture::VtkViewer::limits { dataobj } {
1799
1800    array unset _limits $dataobj-*
1801    foreach comp [$dataobj components] {
1802        set tag $dataobj-$comp
1803        if { ![info exists _limits($tag)] } {
1804            set data [$dataobj data $comp]
1805            if { $data == "" } {
1806                continue
1807            }
1808            set tmpfile file[pid].vtk
1809            set f [open "$tmpfile" "w"]
1810            fconfigure $f -translation binary -encoding binary
1811            puts $f $data
1812            close $f
1813            set reader [vtkDataSetReader $tag-xvtkDataSetReader]
1814            $reader SetFileName $tmpfile
1815            $reader ReadAllNormalsOn
1816            $reader ReadAllScalarsOn
1817            $reader ReadAllVectorsOn
1818            $reader ReadAllFieldsOn
1819            $reader Update
1820            set output [$reader GetOutput]
1821            set _limits($tag) [$output GetBounds]
1822            set pointData [$output GetPointData]
1823            set fieldData [$output GetFieldData]
1824            if 0 {
1825                puts stderr "\#scalars=[$reader GetNumberOfScalarsInFile]"
1826                puts stderr "\#vectors=[$reader GetNumberOfVectorsInFile]"
1827                puts stderr "\#tensors=[$reader GetNumberOfTensorsInFile]"
1828                puts stderr "\#normals=[$reader GetNumberOfNormalsInFile]"
1829                puts stderr "\#fielddata=[$reader GetNumberOfFieldDataInFile]"
1830                puts stderr "fielddataname=[$reader GetFieldDataNameInFile 0]"
1831                puts stderr "field \#arrays=[$fieldData GetNumberOfArrays]"
1832                puts stderr "point \#arrays=[$pointData GetNumberOfArrays]"
1833                puts stderr "field \#components=[$fieldData GetNumberOfComponents]"
1834                puts stderr "point \#components=[$pointData GetNumberOfComponents]"
1835                puts stderr "field \#tuples=[$fieldData GetNumberOfTuples]"
1836                puts stderr "point \#tuples=[$pointData GetNumberOfTuples]"
1837                puts stderr "point \#scalars=[$pointData GetScalars]"
1838                puts stderr vectors=[$pointData GetVectors]
1839            }
1840            rename $output ""
1841            rename $reader ""
1842            file delete $tmpfile
1843        }
1844        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1845        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1846            set limits(xmin) $xMin
1847        }
1848        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1849            set limits(xmax) $xMax
1850        }
1851        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1852            set limits(ymin) $xMin
1853        }
1854        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1855            set limits(ymax) $yMax
1856        }
1857        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1858            set limits(zmin) $zMin
1859        }
1860        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1861            set limits(zmax) $zMax
1862        }
1863    }
1864    return [array get limits]
1865}
1866
1867itcl::body Rappture::VtkViewer::BuildMeshTab {} {
1868
1869    set fg [option get $itk_component(hull) font Font]
1870    #set bfg [option get $itk_component(hull) boldFont Font]
1871
1872    set inner [$itk_component(main) insert end \
1873        -title "Mesh Settings" \
1874        -icon [Rappture::icon mesh]]
1875    $inner configure -borderwidth 4
1876
1877    checkbutton $inner.mesh \
1878        -text "Show Mesh" \
1879        -variable [itcl::scope _settings(mesh-visible)] \
1880        -command [itcl::code $this AdjustSetting mesh-visible] \
1881        -font "Arial 9"
1882
1883    checkbutton $inner.wireframe \
1884        -text "Show Wireframe" \
1885        -variable [itcl::scope _settings(mesh-wireframe)] \
1886        -command [itcl::code $this AdjustSetting mesh-wireframe] \
1887        -font "Arial 9"
1888
1889    checkbutton $inner.lighting \
1890        -text "Enable Lighting" \
1891        -variable [itcl::scope _settings(mesh-lighting)] \
1892        -command [itcl::code $this AdjustSetting mesh-lighting] \
1893        -font "Arial 9"
1894
1895    checkbutton $inner.edges \
1896        -text "Show Edges" \
1897        -variable [itcl::scope _settings(mesh-edges)] \
1898        -command [itcl::code $this AdjustSetting mesh-edges] \
1899        -font "Arial 9"
1900
1901    label $inner.palette_l -text "Palette" -font "Arial 9"
1902    itk_component add meshpalette {
1903        Rappture::Combobox $inner.palette -width 10 -editable no
1904    }
1905    $inner.palette choices insert end \
1906        "BCGYR"              "BCGYR"            \
1907        "BGYOR"              "BGYOR"            \
1908        "blue"               "blue"             \
1909        "blue-to-brown"      "blue-to-brown"    \
1910        "blue-to-orange"     "blue-to-orange"   \
1911        "blue-to-grey"       "blue-to-grey"     \
1912        "green-to-magenta"   "green-to-magenta" \
1913        "greyscale"          "greyscale"        \
1914        "nanohub"            "nanohub"          \
1915        "rainbow"            "rainbow"          \
1916        "spectral"           "spectral"         \
1917        "ROYGB"              "ROYGB"            \
1918        "RYGCB"              "RYGCB"            \
1919        "brown-to-blue"      "brown-to-blue"    \
1920        "grey-to-blue"       "grey-to-blue"     \
1921        "orange-to-blue"     "orange-to-blue"   
1922
1923    $itk_component(meshpalette) value "BCGYR"
1924    bind $inner.palette <<Value>> \
1925        [itcl::code $this AdjustSetting mesh-palette]
1926
1927    label $inner.opacity_l -text "Opacity" -font "Arial 9"
1928    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1929        -variable [itcl::scope _settings(mesh-opacity)] \
1930        -width 10 \
1931        -showvalue off \
1932        -command [itcl::code $this AdjustSetting mesh-opacity]
1933
1934    blt::table $inner \
1935        0,0 $inner.mesh    -cspan 2 -anchor w -pady 2 \
1936        1,0 $inner.wireframe -cspan 2 -anchor w -pady 2 \
1937        2,0 $inner.lighting  -cspan 2 -anchor w -pady 2 \
1938        3,0 $inner.edges     -cspan 2 -anchor w -pady 2 \
1939        4,0 $inner.opacity_l -anchor w -pady 2 \
1940        4,1 $inner.opacity   -fill x   -pady 2 \
1941        5,0 $inner.palette_l -anchor w -pady 2 \
1942        5,1 $inner.palette   -fill x   -pady 2 
1943
1944    blt::table configure $inner r* c* -resize none
1945    blt::table configure $inner r7 c1 -resize expand
1946}
1947
1948itcl::body Rappture::VtkViewer::BuildAxisTab {} {
1949
1950    set fg [option get $itk_component(hull) font Font]
1951    #set bfg [option get $itk_component(hull) boldFont Font]
1952
1953    set inner [$itk_component(main) insert end \
1954        -title "Axis Settings" \
1955        -icon [Rappture::icon axis1]]
1956    $inner configure -borderwidth 4
1957
1958    checkbutton $inner.visible \
1959        -text "Show Axes" \
1960        -variable [itcl::scope _axis(visible)] \
1961        -command [itcl::code $this AdjustSetting axis-visible] \
1962        -font "Arial 9"
1963
1964    checkbutton $inner.labels \
1965        -text "Show Axis Labels" \
1966        -variable [itcl::scope _axis(labels)] \
1967        -command [itcl::code $this AdjustSetting axis-labels] \
1968        -font "Arial 9"
1969
1970    checkbutton $inner.gridx \
1971        -text "Show X Grid" \
1972        -variable [itcl::scope _axis(xgrid)] \
1973        -command [itcl::code $this AdjustSetting axis-xgrid] \
1974        -font "Arial 9"
1975    checkbutton $inner.gridy \
1976        -text "Show Y Grid" \
1977        -variable [itcl::scope _axis(ygrid)] \
1978        -command [itcl::code $this AdjustSetting axis-ygrid] \
1979        -font "Arial 9"
1980    checkbutton $inner.gridz \
1981        -text "Show Z Grid" \
1982        -variable [itcl::scope _axis(zgrid)] \
1983        -command [itcl::code $this AdjustSetting axis-zgrid] \
1984        -font "Arial 9"
1985
1986    label $inner.mode_l -text "Mode" -font "Arial 9"
1987
1988    itk_component add axismode {
1989        Rappture::Combobox $inner.mode -width 10 -editable no
1990    }
1991    $inner.mode choices insert end \
1992        "static_triad"    "static" \
1993        "closest_triad"   "closest" \
1994        "furthest_triad"  "furthest" \
1995        "outer_edges"     "outer"         
1996    $itk_component(axismode) value "static"
1997    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
1998
1999    blt::table $inner \
2000        0,0 $inner.visible -anchor w -cspan 2 \
2001        1,0 $inner.labels  -anchor w -cspan 2 \
2002        2,0 $inner.gridx   -anchor w -cspan 2 \
2003        3,0 $inner.gridy   -anchor w -cspan 2 \
2004        4,0 $inner.gridz   -anchor w -cspan 2 \
2005        5,0 $inner.mode_l  -anchor w -cspan 2 -padx { 2 0 } \
2006        6,0 $inner.mode    -fill x   -cspan 2
2007
2008    blt::table configure $inner r* c* -resize none
2009    blt::table configure $inner r7 c1 -resize expand
2010}
2011
2012
2013itcl::body Rappture::VtkViewer::BuildCameraTab {} {
2014    set inner [$itk_component(main) insert end \
2015        -title "Camera Settings" \
2016        -icon [Rappture::icon camera]]
2017    $inner configure -borderwidth 4
2018
2019    set labels { qx qy qz qw xpan ypan zoom }
2020    set row 0
2021    foreach tag $labels {
2022        label $inner.${tag}label -text $tag -font "Arial 9"
2023        entry $inner.${tag} -font "Arial 9"  -bg white \
2024            -textvariable [itcl::scope _view($tag)]
2025        bind $inner.${tag} <KeyPress-Return> \
2026            [itcl::code $this camera set ${tag}]
2027        blt::table $inner \
2028            $row,0 $inner.${tag}label -anchor e -pady 2 \
2029            $row,1 $inner.${tag} -anchor w -pady 2
2030        blt::table configure $inner r$row -resize none
2031        incr row
2032    }
2033    checkbutton $inner.ortho \
2034        -text "Orthographic Projection" \
2035        -variable [itcl::scope _view(ortho)] \
2036        -command [itcl::code $this camera set ortho] \
2037        -font "Arial 9"
2038    blt::table $inner \
2039            $row,0 $inner.ortho -columnspan 2 -anchor w -pady 2
2040    blt::table configure $inner r$row -resize none
2041    incr row
2042
2043    blt::table configure $inner c0 c1 -resize none
2044    blt::table configure $inner c2 -resize expand
2045    blt::table configure $inner r$row -resize expand
2046}
2047
2048itcl::body Rappture::VtkViewer::BuildCutawayTab {} {
2049
2050    set fg [option get $itk_component(hull) font Font]
2051   
2052    set inner [$itk_component(main) insert end \
2053        -title "Cutaway Along Axis" \
2054        -icon [Rappture::icon cutbutton]]
2055
2056    $inner configure -borderwidth 4
2057
2058    # X-value slicer...
2059    itk_component add xCutButton {
2060        Rappture::PushButton $inner.xbutton \
2061            -onimage [Rappture::icon x-cutplane] \
2062            -offimage [Rappture::icon x-cutplane] \
2063            -command [itcl::code $this AdjustSetting axis-xcutaway] \
2064            -variable [itcl::scope _axis(xcutaway)]
2065    }
2066    Rappture::Tooltip::for $itk_component(xCutButton) \
2067        "Toggle the X-axis cutaway on/off"
2068
2069    itk_component add xCutScale {
2070        ::scale $inner.xval -from 100 -to 1 \
2071            -width 10 -orient vertical -showvalue yes \
2072            -borderwidth 1 -highlightthickness 0 \
2073            -command [itcl::code $this Slice move x] \
2074            -variable [itcl::scope _axis(xposition)]
2075    } {
2076        usual
2077        ignore -borderwidth -highlightthickness
2078    }
2079    # Set the default cutaway value before disabling the scale.
2080    $itk_component(xCutScale) set 100
2081    $itk_component(xCutScale) configure -state disabled
2082    Rappture::Tooltip::for $itk_component(xCutScale) \
2083        "@[itcl::code $this Slice tooltip x]"
2084
2085    itk_component add xDirButton {
2086        Rappture::PushButton $inner.xdir \
2087            -onimage [Rappture::icon arrow-down] \
2088            -onvalue -1 \
2089            -offimage [Rappture::icon arrow-up] \
2090            -offvalue 1 \
2091            -command [itcl::code $this AdjustSetting axis-xdirection] \
2092            -variable [itcl::scope _axis(xdirection)]
2093    }
2094    set _axis(xdirection) -1
2095    Rappture::Tooltip::for $itk_component(xDirButton) \
2096        "Toggle the direction of the X-axis cutaway"
2097
2098    # Y-value slicer...
2099    itk_component add yCutButton {
2100        Rappture::PushButton $inner.ybutton \
2101            -onimage [Rappture::icon y-cutplane] \
2102            -offimage [Rappture::icon y-cutplane] \
2103            -command [itcl::code $this AdjustSetting axis-ycutaway] \
2104            -variable [itcl::scope _axis(ycutaway)]
2105    }
2106    Rappture::Tooltip::for $itk_component(yCutButton) \
2107        "Toggle the Y-axis cutaway on/off"
2108
2109    itk_component add yCutScale {
2110        ::scale $inner.yval -from 100 -to 1 \
2111            -width 10 -orient vertical -showvalue yes \
2112            -borderwidth 1 -highlightthickness 0 \
2113            -command [itcl::code $this Slice move y] \
2114            -variable [itcl::scope _axis(yposition)]
2115    } {
2116        usual
2117        ignore -borderwidth -highlightthickness
2118    }
2119    Rappture::Tooltip::for $itk_component(yCutScale) \
2120        "@[itcl::code $this Slice tooltip y]"
2121    # Set the default cutaway value before disabling the scale.
2122    $itk_component(yCutScale) set 100
2123    $itk_component(yCutScale) configure -state disabled
2124
2125    itk_component add yDirButton {
2126        Rappture::PushButton $inner.ydir \
2127            -onimage [Rappture::icon arrow-down] \
2128            -onvalue -1 \
2129            -offimage [Rappture::icon arrow-up] \
2130            -offvalue 1 \
2131            -command [itcl::code $this AdjustSetting axis-ydirection] \
2132            -variable [itcl::scope _axis(ydirection)]
2133    }
2134    Rappture::Tooltip::for $itk_component(yDirButton) \
2135        "Toggle the direction of the Y-axis cutaway"
2136    set _axis(ydirection) -1
2137
2138    # Z-value slicer...
2139    itk_component add zCutButton {
2140        Rappture::PushButton $inner.zbutton \
2141            -onimage [Rappture::icon z-cutplane] \
2142            -offimage [Rappture::icon z-cutplane] \
2143            -command [itcl::code $this AdjustSetting axis-zcutaway] \
2144            -variable [itcl::scope _axis(zcutaway)]
2145    }
2146    Rappture::Tooltip::for $itk_component(zCutButton) \
2147        "Toggle the Z-axis cutaway on/off"
2148
2149    itk_component add zCutScale {
2150        ::scale $inner.zval -from 100 -to 1 \
2151            -width 10 -orient vertical -showvalue yes \
2152            -borderwidth 1 -highlightthickness 0 \
2153            -command [itcl::code $this Slice move z] \
2154            -variable [itcl::scope _axis(zposition)]
2155    } {
2156        usual
2157        ignore -borderwidth -highlightthickness
2158    }
2159    $itk_component(zCutScale) set 100
2160    $itk_component(zCutScale) configure -state disabled
2161    #$itk_component(zCutScale) configure -state disabled
2162    Rappture::Tooltip::for $itk_component(zCutScale) \
2163        "@[itcl::code $this Slice tooltip z]"
2164
2165    itk_component add zDirButton {
2166        Rappture::PushButton $inner.zdir \
2167            -onimage [Rappture::icon arrow-down] \
2168            -onvalue -1 \
2169            -offimage [Rappture::icon arrow-up] \
2170            -offvalue 1 \
2171            -command [itcl::code $this AdjustSetting axis-zdirection] \
2172            -variable [itcl::scope _axis(zdirection)]
2173    }
2174    set _axis(zdirection) -1
2175    Rappture::Tooltip::for $itk_component(zDirButton) \
2176        "Toggle the direction of the Z-axis cutaway"
2177
2178    blt::table $inner \
2179        0,0 $itk_component(xCutButton)  -anchor e -padx 2 -pady 2 \
2180        1,0 $itk_component(xCutScale)   -fill y \
2181        0,1 $itk_component(yCutButton)  -anchor e -padx 2 -pady 2 \
2182        1,1 $itk_component(yCutScale)   -fill y \
2183        0,2 $itk_component(zCutButton)  -anchor e -padx 2 -pady 2 \
2184        1,2 $itk_component(zCutScale)   -fill y \
2185
2186    blt::table configure $inner r* c* -resize none
2187    blt::table configure $inner r1 c3 -resize expand
2188}
2189
2190itcl::body Rappture::VtkViewer::BuildMoleculeTab {} {
2191    set fg [option get $itk_component(hull) font Font]
2192
2193    set inner [$itk_component(main) insert end \
2194        -title "Molecule Settings" \
2195        -icon [Rappture::icon molecule]]
2196    $inner configure -borderwidth 4
2197
2198    checkbutton $inner.molecule \
2199        -text "Show Molecule" \
2200        -variable [itcl::scope _settings(molecule-visible)] \
2201        -command [itcl::code $this AdjustSetting molecule-visible] \
2202        -font "Arial 9"
2203
2204    checkbutton $inner.label \
2205        -text "Show Atom Labels" \
2206        -variable [itcl::scope _settings(molecule-labels)] \
2207        -command [itcl::code $this AdjustSetting molecule-labels] \
2208        -font "Arial 9"
2209
2210    checkbutton $inner.wireframe \
2211        -text "Show Wireframe" \
2212        -variable [itcl::scope _settings(molecule-wireframe)] \
2213        -command [itcl::code $this AdjustSetting molecule-wireframe] \
2214        -font "Arial 9"
2215
2216    checkbutton $inner.lighting \
2217        -text "Enable Lighting" \
2218        -variable [itcl::scope _settings(molecule-lighting)] \
2219        -command [itcl::code $this AdjustSetting molecule-lighting] \
2220        -font "Arial 9"
2221
2222    checkbutton $inner.edges \
2223        -text "Show Edges" \
2224        -variable [itcl::scope _settings(molecule-edges)] \
2225        -command [itcl::code $this AdjustSetting molecule-edges] \
2226        -font "Arial 9"
2227
2228    label $inner.rep_l -text "Molecule Representation" \
2229        -font "Arial 9"
2230
2231    itk_component add representation {
2232        Rappture::Combobox $inner.rep -width 20 -editable no
2233    }
2234    $inner.rep choices insert end \
2235        "ballandstick"  "Ball and Stick" \
2236        "spheres"       "Spheres"       \
2237        "sticks"        "Sticks"        \
2238        "rods"          "Rods"          \
2239        "wireframe"     "Wireframe"     \
2240        "spacefilling"  "Space Filling"
2241
2242    bind $inner.rep <<Value>> \
2243        [itcl::code $this AdjustSetting molecule-representation]
2244    $inner.rep value "Ball and Stick"
2245
2246    label $inner.palette_l -text "Palette" -font "Arial 9"
2247    itk_component add moleculepalette {
2248        Rappture::Combobox $inner.palette -width 10 -editable no
2249    }
2250    $inner.palette choices insert end \
2251        "elementDefault"             "elementDefault" \
2252        "BCGYR"              "BCGYR"            \
2253        "BGYOR"              "BGYOR"            \
2254        "blue"               "blue"             \
2255        "blue-to-brown"      "blue-to-brown"    \
2256        "blue-to-orange"     "blue-to-orange"   \
2257        "blue-to-grey"       "blue-to-grey"     \
2258        "green-to-magenta"   "green-to-magenta" \
2259        "greyscale"          "greyscale"        \
2260        "nanohub"            "nanohub"          \
2261        "rainbow"            "rainbow"          \
2262        "spectral"           "spectral"         \
2263        "ROYGB"              "ROYGB"            \
2264        "RYGCB"              "RYGCB"            \
2265        "brown-to-blue"      "brown-to-blue"    \
2266        "grey-to-blue"       "grey-to-blue"     \
2267        "orange-to-blue"     "orange-to-blue"   
2268
2269    $itk_component(moleculepalette) value "elementDefault"
2270    bind $inner.palette <<Value>> \
2271        [itcl::code $this AdjustSetting molecule-palette]
2272
2273    checkbutton $inner.labels -text "Show labels on atoms" \
2274        -command [itcl::code $this labels update] \
2275        -variable [itcl::scope _settings(molecule-labels)] \
2276        -font "Arial 9"
2277    Rappture::Tooltip::for $inner.labels \
2278        "Display atom symbol and serial number."
2279
2280    checkbutton $inner.rock -text "Rock molecule back and forth" \
2281        -variable [itcl::scope _settings(molecule-rock)] \
2282        -font "Arial 9"
2283    Rappture::Tooltip::for $inner.rock \
2284        "Rotate the object back and forth around the y-axis."
2285
2286    checkbutton $inner.cell -text "Parallelepiped" \
2287        -font "Arial 9"
2288    $inner.cell select
2289
2290    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2291    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2292        -variable [itcl::scope _settings(molecule-opacity)] \
2293        -width 10 \
2294        -showvalue off \
2295        -command [itcl::code $this AdjustSetting molecule-opacity]
2296
2297    blt::table $inner \
2298        0,0 $inner.molecule -anchor w -pady {1 0} \
2299        1,0 $inner.label -anchor w -pady {1 0} \
2300        2,0 $inner.edges -anchor w -pady {1 0} \
2301        3,0 $inner.rep_l -anchor w -pady { 2 0 } \
2302        4,0 $inner.rep -anchor w  \
2303        5,0 $inner.palette_l -anchor w -pady 2 \
2304        6,0 $inner.palette   -fill x   -pady 2  \
2305        7,0 $inner.opacity_l -anchor w -pady 2 \
2306        8,0 $inner.opacity   -fill x   -pady 2
2307   
2308    blt::table configure $inner r* -resize none
2309    blt::table configure $inner r9 -resize expand
2310}
2311
2312#
2313#  camera --
2314#
2315itcl::body Rappture::VtkViewer::camera {option args} {
2316    switch -- $option {
2317        "show" {
2318            puts [array get _view]
2319        }
2320        "set" {
2321            set who [lindex $args 0]
2322            set x $_view($who)
2323            set code [catch { string is double $x } result]
2324            if { $code != 0 || !$result } {
2325                return
2326            }
2327            switch -- $who {
2328                "ortho" {
2329                    if {$_view(ortho)} {
2330                        SendCmd "camera mode ortho"
2331                    } else {
2332                        SendCmd "camera mode persp"
2333                    }
2334                }
2335                "xpan" - "ypan" {
2336                    PanCamera
2337                }
2338                "qx" - "qy" - "qz" - "qw" {
2339                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2340                    $_arcball quaternion $q
2341                    EventuallyRotate $q
2342                }
2343                "zoom" {
2344                    SendCmd "camera zoom $_view(zoom)"
2345                }
2346            }
2347        }
2348    }
2349}
2350
2351itcl::body Rappture::VtkViewer::ConvertToVtkData { dataobj comp } {
2352    foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $comp] break
2353    set values [$dataobj values $comp]
2354    append out "# vtk DataFile Version 2.0 \n"
2355    append out "Test data \n"
2356    append out "ASCII \n"
2357    append out "DATASET STRUCTURED_POINTS \n"
2358    append out "DIMENSIONS $xN $yN 1 \n"
2359    append out "ORIGIN 0 0 0 \n"
2360    append out "SPACING 1 1 1 \n"
2361    append out "POINT_DATA [expr $xN * $yN] \n"
2362    append out "SCALARS field float 1 \n"
2363    append out "LOOKUP_TABLE default \n"
2364    append out [join $values "\n"]
2365    append out "\n"
2366    return $out
2367}
2368
2369
2370itcl::body Rappture::VtkViewer::GetVtkData { args } {
2371    set bytes ""
2372    foreach dataobj [get] {
2373        foreach comp [$dataobj components] {
2374            set tag $dataobj-$comp
2375            set contents [ConvertToVtkData $dataobj $comp]
2376            append bytes "$contents\n\n"
2377        }
2378    }
2379    return [list .txt $bytes]
2380}
2381
2382itcl::body Rappture::VtkViewer::GetImage { args } {
2383    if { [image width $_image(download)] > 0 &&
2384         [image height $_image(download)] > 0 } {
2385        set bytes [$_image(download) data -format "jpeg -quality 100"]
2386        set bytes [Rappture::encoding::decode -as b64 $bytes]
2387        return [list .jpg $bytes]
2388    }
2389    return ""
2390}
2391
2392itcl::body Rappture::VtkViewer::BuildDownloadPopup { popup command } {
2393    Rappture::Balloon $popup \
2394        -title "[Rappture::filexfer::label downloadWord] as..."
2395    set inner [$popup component inner]
2396    label $inner.summary -text "" -anchor w
2397    radiobutton $inner.vtk_button -text "VTK data file" \
2398        -variable [itcl::scope _downloadPopup(format)] \
2399        -font "Helvetica 9 " \
2400        -value vtk 
2401    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
2402    radiobutton $inner.image_button -text "Image File" \
2403        -variable [itcl::scope _downloadPopup(format)] \
2404        -value image
2405    Rappture::Tooltip::for $inner.image_button \
2406        "Save as digital image."
2407
2408    button $inner.ok -text "Save" \
2409        -highlightthickness 0 -pady 2 -padx 3 \
2410        -command $command \
2411        -compound left \
2412        -image [Rappture::icon download]
2413
2414    button $inner.cancel -text "Cancel" \
2415        -highlightthickness 0 -pady 2 -padx 3 \
2416        -command [list $popup deactivate] \
2417        -compound left \
2418        -image [Rappture::icon cancel]
2419
2420    blt::table $inner \
2421        0,0 $inner.summary -cspan 2  \
2422        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
2423        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
2424        4,1 $inner.cancel -width .9i -fill y \
2425        4,0 $inner.ok -padx 2 -width .9i -fill y
2426    blt::table configure $inner r3 -height 4
2427    blt::table configure $inner r4 -pady 4
2428    raise $inner.image_button
2429    $inner.vtk_button invoke
2430    return $inner
2431}
2432
2433itcl::body Rappture::VtkViewer::SetObjectStyle { dataobj comp } {
2434    # Parse style string.
2435    set tag $dataobj-$comp
2436    set type [$dataobj type $comp]
2437    set style [$dataobj style $comp]
2438    if { $dataobj != $_first } {
2439        set settings(-wireframe) 1
2440    }
2441    if { $type == "glyphs" } {
2442        array set settings {
2443            -color \#808080
2444            -gscale 1
2445            -edges 0
2446            -edgecolor black
2447            -linewidth 1.0
2448            -opacity 1.0
2449            -wireframe 0
2450            -lighting 1
2451            -visible 1
2452        }
2453        set shape [$dataobj shape $comp]
2454        array set settings $style
2455        SendCmd "glyphs add $shape $tag"
2456        SendCmd "glyphs normscale 0 $tag"
2457        SendCmd "glyphs gscale $settings(-gscale) $tag"
2458        SendCmd "glyphs wireframe $settings(-wireframe) $tag"
2459        #SendCmd "glyphs ccolor [Color2RGB $settings(-color)] $tag"
2460        #SendCmd "glyphs colormode ccolor {} $tag"
2461        SendCmd "glyphs gorient 0 {} $tag"
2462        SendCmd "glyphs smode vcomp {} $tag"
2463        SendCmd "glyphs opacity $settings(-opacity) $tag"
2464        SendCmd "glyphs visible $settings(-visible) $tag"
2465        set _settings(glyphs-wireframe) $settings(-wireframe)
2466        set _haveGlyphs 1
2467    } elseif { $type == "molecule" } {
2468        array set settings {
2469            -color \#808080
2470            -gscale 1
2471            -edges 0
2472            -edgecolor black
2473            -linewidth 1.0
2474            -opacity 1.0
2475            -wireframe 0
2476            -lighting 1
2477            -visible 1
2478        }
2479        array set settings $style
2480        SendCmd "molecule add $tag"
2481        SendCmd "molecule opacity $settings(-opacity) $tag"
2482        SendCmd "molecule visible $settings(-visible) $tag"
2483        SendCmd "molecule rscale van_der_waals $tag"
2484        set _settings(molecule-wireframe) $settings(-wireframe)
2485        set _haveMolecules 1
2486    } else {
2487        array set settings {
2488            -color \#6666FF
2489            -edges 1
2490            -edgecolor black
2491            -linewidth 1.0
2492            -opacity 1.0
2493            -wireframe 0
2494            -lighting 1
2495            -visible 1
2496        }
2497        array set settings $style
2498        SendCmd "polydata add $tag"
2499        SendCmd "polydata visible $settings(-visible) $tag"
2500        set _settings(mesh-visible) $settings(-visible)
2501        SendCmd "polydata edges $settings(-edges) $tag"
2502        set _settings(mesh-edges) $settings(-edges)
2503        SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
2504        SendCmd "polydata lighting $settings(-lighting) $tag"
2505        set _settings(mesh-lighting) $settings(-lighting)
2506        SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
2507        SendCmd "polydata linewidth $settings(-linewidth) $tag"
2508        SendCmd "polydata opacity $settings(-opacity) $tag"
2509        set _settings(mesh-opacity) $settings(-opacity)
2510        SendCmd "polydata wireframe $settings(-wireframe) $tag"
2511        set _settings(mesh-wireframe) $settings(-wireframe)
2512    }
2513    set _settings(mesh-opacity) [expr $settings(-opacity) * 100.0]
2514    SetColormap $dataobj $comp
2515}
2516
2517itcl::body Rappture::VtkViewer::IsValidObject { dataobj } {
2518    if {[catch {$dataobj isa Rappture::Drawing} valid] != 0 || !$valid} {
2519        return 0
2520    }
2521    return 1
2522}
2523
2524# ----------------------------------------------------------------------
2525# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
2526#
2527# Invoked automatically whenever the "legend" command comes in from
2528# the rendering server.  Indicates that binary image data with the
2529# specified <size> will follow.
2530# ----------------------------------------------------------------------
2531itcl::body Rappture::VtkViewer::ReceiveLegend { colormap title vmin vmax size } {
2532    set _limits(vmin) $vmin
2533    set _limits(vmax) $vmax
2534    set _title $title
2535    if { [IsConnected] } {
2536        set bytes [ReceiveBytes $size]
2537        if { ![info exists _image(legend)] } {
2538            set _image(legend) [image create photo]
2539        }
2540        $_image(legend) configure -data $bytes
2541        DrawLegend
2542    }
2543}
2544
2545#
2546# DrawLegend --
2547#
2548#       Draws the legend in it's own canvas which resides to the right
2549#       of the contour plot area.
2550#
2551itcl::body Rappture::VtkViewer::DrawLegend {} {
2552    set c $itk_component(view)
2553    set w [winfo width $c]
2554    set h [winfo height $c]
2555    set font "Arial 8"
2556    set lineht [font metrics $font -linespace]
2557   
2558    if { $_settings(legend) } {
2559        set x [expr $w - 2]
2560        if { [$c find withtag "legend"] == "" } {
2561            $c create image $x [expr {$lineht+2}] \
2562                -anchor ne \
2563                -image $_image(legend) -tags "colormap legend"
2564            $c create text $x 2 \
2565                -anchor ne \
2566                -fill $itk_option(-plotforeground) -tags "vmax legend" \
2567                -font $font
2568            $c create text $x [expr {$h-2}] \
2569                -anchor se \
2570                -fill $itk_option(-plotforeground) -tags "vmin legend" \
2571                -font $font
2572            #$c bind colormap <Enter> [itcl::code $this EnterLegend %x %y]
2573            $c bind colormap <Leave> [itcl::code $this LeaveLegend]
2574            $c bind colormap <Motion> [itcl::code $this MotionLegend %x %y]
2575        }
2576        # Reset the item coordinates according the current size of the plot.
2577        $c coords colormap $x [expr {$lineht+2}]
2578        if { $_limits(vmin) != "" } {
2579            $c itemconfigure vmin -text [format %g $_limits(vmin)]
2580        }
2581        if { $_limits(vmax) != "" } {
2582            $c itemconfigure vmax -text [format %g $_limits(vmax)]
2583        }
2584        $c coords vmin $x [expr {$h-2}]
2585        $c coords vmax $x 2
2586    }
2587}
2588
2589#
2590# EnterLegend --
2591#
2592itcl::body Rappture::VtkViewer::EnterLegend { x y } {
2593    SetLegendTip $x $y
2594}
2595
2596#
2597# MotionLegend --
2598#
2599itcl::body Rappture::VtkViewer::MotionLegend { x y } {
2600    Rappture::Tooltip::tooltip cancel
2601    set c $itk_component(view)
2602    SetLegendTip $x $y
2603}
2604
2605#
2606# LeaveLegend --
2607#
2608itcl::body Rappture::VtkViewer::LeaveLegend { } {
2609    Rappture::Tooltip::tooltip cancel
2610    .rappturetooltip configure -icon ""
2611}
2612
2613#
2614# SetLegendTip --
2615#
2616itcl::body Rappture::VtkViewer::SetLegendTip { x y } {
2617    set c $itk_component(view)
2618    set w [winfo width $c]
2619    set h [winfo height $c]
2620    set font "Arial 8"
2621    set lineht [font metrics $font -linespace]
2622   
2623    set imgHeight [image height $_image(legend)]
2624    set coords [$c coords colormap]
2625    set imgX [expr $w - [image width $_image(legend)] - 2]
2626    set imgY [expr $y - $lineht - 2]
2627
2628    # Make a swatch of the selected color
2629    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
2630        return
2631    }
2632    if { ![info exists _image(swatch)] } {
2633        set _image(swatch) [image create photo -width 24 -height 24]
2634    }
2635    set color [eval format "\#%02x%02x%02x" $pixel]
2636    $_image(swatch) put black  -to 0 0 23 23
2637    $_image(swatch) put $color -to 1 1 22 22
2638    .rappturetooltip configure -icon $_image(swatch)
2639
2640    # Compute the value of the point
2641    set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
2642    set value [expr $t * ($_limits(vmax) - $_limits(vmin)) + $_limits(vmin)]
2643    set tipx [expr $x + 15]
2644    set tipy [expr $y - 5]
2645    Rappture::Tooltip::text $c "$_title $value"
2646    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy   
2647}
2648
2649
2650# ----------------------------------------------------------------------
2651# USAGE: Slice move x|y|z <newval>
2652#
2653# Called automatically when the user drags the slider to move the
2654# cut plane that slices 3D data.  Gets the current value from the
2655# slider and moves the cut plane to the appropriate point in the
2656# data set.
2657# ----------------------------------------------------------------------
2658itcl::body Rappture::VtkViewer::Slice {option args} {
2659    switch -- $option {
2660        "move" {
2661            set axis [lindex $args 0]
2662            set oldval $_axis(${axis}position)
2663            set newval [lindex $args 1]
2664            if {[llength $args] != 2} {
2665                error "wrong # args: should be \"Slice move x|y|z newval\""
2666            }
2667            set newpos [expr {0.01*$newval}]
2668            SendCmd "renderer clipplane $axis $newpos -1"
2669        }
2670        "tooltip" {
2671            set axis [lindex $args 0]
2672            set val [$itk_component(${axis}CutScale) get]
2673            return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
2674        }
2675        default {
2676            error "bad option \"$option\": should be axis, move, or tooltip"
2677        }
2678    }
2679}
2680
Note: See TracBrowser for help on using the repository browser.