source: branches/uiuc_vtk_viewers/gui/scripts/vtkisosurfaceviewer.tcl @ 4954

Last change on this file since 4954 was 4954, checked in by dkearney, 10 years ago

three major features being added:

  1. setting custom min/max range from the IsosurfaceTab?
  2. setting custom min/max range from the legend
  3. isosurface probe from the legend

Most of the new work was performed in the following methods:
LegendB1Motion
LegendPointToValue?
LegendRangeAction?
LegendTitleAction?
LegendProbeSingleContour?

The min/max custom range values are stored in _settings array. Through out
the code, when we want the limits of a field being displayed, we also check
to see if a custom range has been enabled. If it has, in most cases, we use
the custom range as the limits instead of the limits of the currently
displayed field.

The current implementation allows for the custom range to exceed the range of
the data in the field.

also renamed the Combo method to LegendTitleAction? to make its objective more clear

split some commonly used features into their own methods, hopefully we can find
common code among all of the viewers and move these to a super class:

DisableMouseRotationBindings?
SetupMouseRotationBindings?
SetupMousePanningBindings?
SetupKeyboardBindins?

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