source: trunk/gui/scripts/vtkheightmapviewer.tcl @ 3093

Last change on this file since 3093 was 3032, checked in by gah, 12 years ago

intermediate updates for vtkcontourviewer

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