source: branches/1.7/gui/scripts/vtkstreamlinesviewer.tcl @ 6238

Last change on this file since 6238 was 6238, checked in by ldelgass, 6 years ago

merge r6235:6236 from trunk (streamlines scaling)

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