source: trunk/gui/scripts/vtkstreamlinesviewer.tcl @ 6338

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

sync up viewer font setting

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