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

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

For current usage of glyphs in drawings in vtkviewer, vector field has x,y,z
scaling and so we don't want to orient glyphs based on the vector field.

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