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

Last change on this file since 2584 was 2584, checked in by gah, 13 years ago

updates to visviewer: please wait popup

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