source: branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl @ 4397

Last change on this file since 4397 was 4397, checked in by ldelgass, 8 years ago

Fixes: don't toggle isosurface visible button when toggling outline. In
Rebuild, start by making all objects invisible ('dataset visible 0'), then we
should set visibility on individual objects. Otherwise, previously visible
outlines and cutplanes were not being turned off in Rebuild.

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