source: branches/Rappture 1.2/gui/scripts/vtkisosurfaceviewer.tcl @ 3311

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

add emacs mode line to tcl files.

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