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

Last change on this file since 2583 was 2583, checked in by ldelgass, 13 years ago

Fix for reset in test app - don't try to get axis hints if $_first is empty
--This line, and these below, will be ignored--

M vtkstreamlinesviewer.tcl

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