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

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

Make vtkvis contour viewer use same default color map as other vtkvis viewers.

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