source: trunk/gui/scripts/vtkcontourviewer.tcl @ 2943

Last change on this file since 2943 was 2873, checked in by ldelgass, 12 years ago

Try to set axis labels for vtkcontourviewer. Still need to fix problem that
mesh axis labels don't propagate from meshes to fields.

File size: 64.9 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: vtkcontourviewer - Contour plot 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
16package require Img
17                   
18option add *VtkContourViewer.width 4i widgetDefault
19option add *VtkContourViewer*cursor crosshair widgetDefault
20option add *VtkContourViewer.height 4i widgetDefault
21option add *VtkContourViewer.foreground black widgetDefault
22option add *VtkContourViewer.controlBackground gray widgetDefault
23option add *VtkContourViewer.controlDarkBackground #999999 widgetDefault
24option add *VtkContourViewer.plotBackground black widgetDefault
25option add *VtkContourViewer.plotForeground white widgetDefault
26option add *VtkContourViewer.font \
27    -*-helvetica-medium-r-normal-*-12-* widgetDefault
28
29# must use this name -- plugs into Rappture::resources::load
30proc VtkContourViewer_init_resources {} {
31    Rappture::resources::register \
32        vtkvis_server Rappture::VtkContourViewer::SetServerList
33}
34
35itcl::class Rappture::VtkContourViewer {
36    inherit Rappture::VisViewer
37
38    itk_option define -plotforeground plotForeground Foreground ""
39    itk_option define -plotbackground plotBackground Background ""
40
41    constructor { hostlist args } {
42        Rappture::VisViewer::constructor $hostlist
43    } {
44        # defined below
45    }
46    destructor {
47        # defined below
48    }
49    public proc SetServerList { namelist } {
50        Rappture::VisViewer::SetServerList "vtkvis" $namelist
51    }
52    public method add {dataobj {settings ""}}
53    public method camera {option args}
54    public method delete {args}
55    public method disconnect {}
56    public method download {option args}
57    public method get {args}
58    public method isconnected {}
59    public method limits { colormap }
60    public method sendto { string }
61    public method parameters {title args} {
62        # do nothing
63    }
64    public method scale {args}
65
66    protected method Connect {}
67    protected method CurrentDatasets {{what -all}}
68    protected method Disconnect {}
69    protected method DoResize {}
70    protected method FixLegend {}
71    protected method FixSettings {what {value ""}}
72    protected method Pan {option x y}
73    protected method Pick {x y}
74    protected method Rebuild {}
75    protected method ReceiveDataset { args }
76    protected method ReceiveImage { args }
77    protected method DrawLegend {}
78    protected method ReceiveLegend { colormap title vmin vmax size }
79    protected method Rotate {option x y}
80    protected method SendCmd {string}
81    protected method Zoom {option}
82
83    private method AdjustSelectionRectangle { x y }
84    private method BeginSelectionRectangle { x y }
85    private method EndSelectionRectangle { x y }
86    private method KillSelectionRectangle {}
87    private method MarchingAnts {}
88
89    # The following methods are only used by this class.
90    private method BuildCameraTab {}
91    private method BuildViewTab {}
92    private method BuildColormap { colormap dataobj comp }
93    private method ColorsToColormap { color }
94    private method EventuallyResize { w h }
95    private method EventuallyResizeLegend { }
96    private method SetStyles { dataobj comp }
97    private method PanCamera {}
98    private method ConvertToVtkData { dataobj comp }
99    private method GetImage { args }
100    private method GetVtkData { args }
101    private method BuildDownloadPopup { widget command }
102
103    private variable _arcball ""
104    private variable _outbuf       ;# buffer for outgoing commands
105
106    private variable _dlist ""     ;# list of data objects
107    private variable _allDataObjs
108    private variable _obj2ovride   ;# maps dataobj => style override
109    private variable _datasets     ;# contains all the dataobj-component
110                                   ;# datasets in the server
111    private variable _colormaps    ;# contains all the colormaps
112                                   ;# in the server.
113    private variable _dataset2style    ;# maps dataobj-component to transfunc
114    private variable _style2datasets   ;# maps tf back to list of
115                                    # dataobj-components using the tf.
116
117    private variable _click        ;# info used for rotate operations
118    private variable _limits       ;# autoscale min/max for all axes
119    private variable _view         ;# view params for 3D view
120    private common   _settings
121    # Array of transfer functions in server.  If 0 the transfer has been
122    # defined but not loaded.  If 1 the transfer function has been named
123    # and loaded.
124    private variable _first ""     ;# This is the topmost dataset.
125    private variable _buffering 0
126
127    # This indicates which isomarkers and transfer function to use when
128    # changing markers, opacity, or thickness.
129    common _downloadPopup          ;# download options from popup
130    private common _hardcopy
131    private variable _width 0
132    private variable _height 0
133    private variable _resizePending 0
134    private variable _resizeLegendPending 0
135    private variable _outline
136}
137
138itk::usual VtkContourViewer {
139    keep -background -foreground -cursor -font
140    keep -plotbackground -plotforeground
141}
142
143# ----------------------------------------------------------------------
144# CONSTRUCTOR
145# ----------------------------------------------------------------------
146itcl::body Rappture::VtkContourViewer::constructor {hostlist args} {
147    package require vtk
148    set  _serverType "vtkvis"
149
150    # Draw legend event
151    $_dispatcher register !legend
152    $_dispatcher dispatch $this !legend "[itcl::code $this FixLegend]; list"
153
154    # Rebuild event
155    $_dispatcher register !rebuild
156    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
157
158    # Resize event
159    $_dispatcher register !resize
160    $_dispatcher dispatch $this !resize "[itcl::code $this DoResize]; list"
161
162    set _outbuf ""
163
164    #
165    # Populate parser with commands handle incoming requests
166    #
167    $_parser alias image [itcl::code $this ReceiveImage]
168    $_parser alias legend [itcl::code $this ReceiveLegend]
169    $_parser alias dataset [itcl::code $this ReceiveDataset]
170
171    array set _outline {
172        id -1
173        afterId -1
174        x1 -1
175        y1 -1
176        x2 -1
177        y2 -1
178    }
179
180    # Initialize the view to some default parameters.
181    array set _view {
182        qx              0
183        qy              0
184        qz              0
185        qw              1
186        zoom            1.0
187        pan-x           0
188        pan-y           0
189        ortho-x         0.0
190        ortho-y         0.0
191        ortho-w         -1.0
192        ortho-h         -1.0
193    }
194    set _arcball [blt::arcball create 100 100]
195    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
196    $_arcball quaternion $q
197
198    set _limits(vmin) 0.0
199    set _limits(vmax) 1.0
200
201    array set _settings [subst {
202        $this-axes              1
203        $this-edges             0
204        $this-lighting          1
205        $this-opacity           100
206        $this-volume            1
207        $this-isolines          1
208        $this-wireframe         0
209        $this-legend            1
210        $this-colormap          1
211    }]
212
213    itk_component add view {
214        canvas $itk_component(plotarea).view \
215            -highlightthickness 0 -borderwidth 0
216    } {
217        usual
218        ignore -highlightthickness -borderwidth  -background
219    }
220
221    set c $itk_component(view)
222    bind $c <Configure> [itcl::code $this EventuallyResize %w %h]
223    bind $c <4> [itcl::code $this Zoom in 0.25]
224    bind $c <5> [itcl::code $this Zoom out 0.25]
225    bind $c <KeyPress-Left>  [list %W xview scroll 10 units]
226    bind $c <KeyPress-Right> [list %W xview scroll -10 units]
227    bind $c <KeyPress-Up>    [list %W yview scroll 10 units]
228    bind $c <KeyPress-Down>  [list %W yview scroll -10 units]
229    bind $c <Enter> "focus %W"
230
231    bind $c <ButtonPress-1> [itcl::code $this BeginSelectionRectangle %x %y]
232    bind $c <B1-Motion> [itcl::code $this AdjustSelectionRectangle %x %y]
233    bind $c <ButtonRelease-1> [itcl::code $this EndSelectionRectangle %x %y]
234    # Fix the scrollregion in case we go off screen
235    $c configure -scrollregion [$c bbox all]
236
237    set _map(id) [$c create image 0 0 -anchor nw -image $_image(plot)]
238    set _map(cwidth) -1
239    set _map(cheight) -1
240    set _map(zoom) 1.0
241    set _map(original) ""
242
243    set f [$itk_component(main) component controls]
244    itk_component add reset {
245        button $f.reset -borderwidth 1 -padx 1 -pady 1 \
246            -highlightthickness 0 \
247            -image [Rappture::icon reset-view] \
248            -command [itcl::code $this Zoom reset]
249    } {
250        usual
251        ignore -highlightthickness
252    }
253    pack $itk_component(reset) -side top -padx 2 -pady 2
254    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
255
256    itk_component add zoomin {
257        button $f.zin -borderwidth 1 -padx 1 -pady 1 \
258            -highlightthickness 0 \
259            -image [Rappture::icon zoom-in] \
260            -command [itcl::code $this Zoom in]
261    } {
262        usual
263        ignore -highlightthickness
264    }
265    pack $itk_component(zoomin) -side top -padx 2 -pady 2
266    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
267
268    itk_component add zoomout {
269        button $f.zout -borderwidth 1 -padx 1 -pady 1 \
270            -highlightthickness 0 \
271            -image [Rappture::icon zoom-out] \
272            -command [itcl::code $this Zoom out]
273    } {
274        usual
275        ignore -highlightthickness
276    }
277    pack $itk_component(zoomout) -side top -padx 2 -pady 2
278    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
279
280    BuildViewTab
281    BuildCameraTab
282
283    # Legend
284
285    set _image(legend) [image create photo]
286    itk_component add legend {
287        canvas $itk_component(plotarea).legend -width 50 -highlightthickness 0
288    } {
289        usual
290        ignore -highlightthickness
291        rename -background -plotbackground plotBackground Background
292    }
293    bind $itk_component(legend) <Configure> \
294        [itcl::code $this EventuallyResizeLegend]
295
296    # Hack around the Tk panewindow.  The problem is that the requested
297    # size of the 3d view isn't set until an image is retrieved from
298    # the server.  So the panewindow uses the tiny size.
299    set w 10000
300    pack forget $itk_component(view)
301    blt::table $itk_component(plotarea) \
302        0,0 $itk_component(view) -fill both -reqwidth $w \
303        1,0 $itk_component(legend) -fill x
304    blt::table $itk_component(plotarea) \
305        0,0 $itk_component(view) -fill both -reqwidth $w \
306        0,1 $itk_component(legend) -fill y
307    blt::table configure $itk_component(plotarea) c1 -resize none
308
309    if 0 {
310    bind $itk_component(view) <Configure> \
311        [itcl::code $this EventuallyResize %w %h]
312    }
313    # Bindings for panning via mouse
314    bind $itk_component(view) <ButtonPress-2> \
315        [itcl::code $this Pan click %x %y]
316    bind $itk_component(view) <B2-Motion> \
317        [itcl::code $this Pan drag %x %y]
318    bind $itk_component(view) <ButtonRelease-2> \
319        [itcl::code $this Pan release %x %y]
320
321    bind $itk_component(view) <ButtonRelease-3> \
322        [itcl::code $this Pick %x %y]
323
324    # Bindings for panning via keyboard
325    bind $itk_component(view) <KeyPress-Left> \
326        [itcl::code $this Pan set -10 0]
327    bind $itk_component(view) <KeyPress-Right> \
328        [itcl::code $this Pan set 10 0]
329    bind $itk_component(view) <KeyPress-Up> \
330        [itcl::code $this Pan set 0 -10]
331    bind $itk_component(view) <KeyPress-Down> \
332        [itcl::code $this Pan set 0 10]
333    bind $itk_component(view) <Shift-KeyPress-Left> \
334        [itcl::code $this Pan set -2 0]
335    bind $itk_component(view) <Shift-KeyPress-Right> \
336        [itcl::code $this Pan set 2 0]
337    bind $itk_component(view) <Shift-KeyPress-Up> \
338        [itcl::code $this Pan set 0 -2]
339    bind $itk_component(view) <Shift-KeyPress-Down> \
340        [itcl::code $this Pan set 0 2]
341
342    # Bindings for zoom via keyboard
343    bind $itk_component(view) <KeyPress-Prior> \
344        [itcl::code $this Zoom out]
345    bind $itk_component(view) <KeyPress-Next> \
346        [itcl::code $this Zoom in]
347
348    bind $itk_component(view) <Enter> "focus $itk_component(view)"
349
350    if {[string equal "x11" [tk windowingsystem]]} {
351        # Bindings for zoom via mouse
352        bind $itk_component(view) <4> [itcl::code $this Zoom out]
353        bind $itk_component(view) <5> [itcl::code $this Zoom in]
354    }
355
356    set _image(download) [image create photo]
357
358    eval itk_initialize $args
359
360    Connect
361}
362
363# ----------------------------------------------------------------------
364# DESTRUCTOR
365# ----------------------------------------------------------------------
366itcl::body Rappture::VtkContourViewer::destructor {} {
367    $_dispatcher cancel !rebuild
368    $_dispatcher cancel !resize
369    image delete $_image(plot)
370    image delete $_image(legend)
371    image delete $_image(download)
372    array unset _settings $this-*
373    catch { blt::arcball destroy $_arcball}
374}
375
376itcl::body Rappture::VtkContourViewer::DoResize {} {
377    if { $_width < 2 } {
378        set _width 500
379    }
380    if { $_height < 2 } {
381        set _height 500
382    }
383    SendCmd "screen size $_width $_height"
384    if { $_settings($this-legend) } {
385        EventuallyResizeLegend
386    }
387    set _resizePending 0
388}
389
390itcl::body Rappture::VtkContourViewer::EventuallyResize { w h } {
391    set _width $w
392    set _height $h
393    $_arcball resize $w $h
394    if { !$_resizePending } {
395        $_dispatcher event -after 100 !resize
396        set _resizePending 1
397    }
398}
399
400itcl::body Rappture::VtkContourViewer::EventuallyResizeLegend {} {
401    if { !$_resizeLegendPending } {
402        $_dispatcher event -after 100 !legend
403        set _resizeLegendPending 1
404    }
405}
406
407# ----------------------------------------------------------------------
408# USAGE: add <dataobj> ?<settings>?
409#
410# Clients use this to add a data object to the plot.  The optional
411# <settings> are used to configure the plot.  Allowed settings are
412# -color, -brightness, -width, -linestyle, and -raise.
413# ----------------------------------------------------------------------
414itcl::body Rappture::VtkContourViewer::add {dataobj {settings ""}} {
415    array set params {
416        -color auto
417        -width 1
418        -linestyle solid
419        -brightness 0
420        -raise 0
421        -description ""
422        -param ""
423        -type ""
424    }
425    foreach {opt val} $settings {
426        if {![info exists params($opt)]} {
427            error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
428        }
429        set params($opt) $val
430    }
431    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
432        # can't handle -autocolors yet
433        set params(-color) black
434    }
435    set pos [lsearch -exact $dataobj $_dlist]
436    if {$pos < 0} {
437        lappend _dlist $dataobj
438        set _allDataObjs($dataobj) 1
439        set _obj2ovride($dataobj-color) $params(-color)
440        set _obj2ovride($dataobj-width) $params(-width)
441        set _obj2ovride($dataobj-raise) $params(-raise)
442        $_dispatcher event -idle !rebuild
443    }
444}
445
446# ----------------------------------------------------------------------
447# USAGE: get ?-objects?
448# USAGE: get ?-image view|legend?
449#
450# Clients use this to query the list of objects being plotted, in
451# order from bottom to top of this result.  The optional "-image"
452# flag can also request the internal images being shown.
453# ----------------------------------------------------------------------
454itcl::body Rappture::VtkContourViewer::get {args} {
455    if {[llength $args] == 0} {
456        set args "-objects"
457    }
458
459    set op [lindex $args 0]
460    switch -- $op {
461      -objects {
462        # put the dataobj list in order according to -raise options
463        set dlist $_dlist
464        foreach obj $dlist {
465            if {[info exists _obj2ovride($obj-raise)] && $_obj2ovride($obj-raise)} {
466                set i [lsearch -exact $dlist $obj]
467                if {$i >= 0} {
468                    set dlist [lreplace $dlist $i $i]
469                    lappend dlist $obj
470                }
471            }
472        }
473        return $dlist
474      }
475      -image {
476        if {[llength $args] != 2} {
477            error "wrong # args: should be \"get -image view|legend\""
478        }
479        switch -- [lindex $args end] {
480            view {
481                return $_image(plot)
482            }
483            legend {
484                return $_image(legend)
485            }
486            default {
487                error "bad image name \"[lindex $args end]\": should be view or legend"
488            }
489        }
490      }
491      default {
492        error "bad option \"$op\": should be -objects or -image"
493      }
494    }
495}
496
497# ----------------------------------------------------------------------
498# USAGE: delete ?<dataobj1> <dataobj2> ...?
499#
500#       Clients use this to delete a dataobj from the plot.  If no dataobjs
501#       are specified, then all dataobjs are deleted.  No data objects are
502#       deleted.  They are only removed from the display list.
503#
504# ----------------------------------------------------------------------
505itcl::body Rappture::VtkContourViewer::delete {args} {
506    if {[llength $args] == 0} {
507        set args $_dlist
508    }
509    # Delete all specified dataobjs
510    set changed 0
511    foreach dataobj $args {
512        set pos [lsearch -exact $_dlist $dataobj]
513        if { $pos >= 0 } {
514            set _dlist [lreplace $_dlist $pos $pos]
515            array unset _limits $dataobj*
516            array unset _obj2ovride $dataobj-*
517            set changed 1
518        }
519    }
520    # If anything changed, then rebuild the plot
521    if {$changed} {
522        $_dispatcher event -idle !rebuild
523    }
524}
525
526# ----------------------------------------------------------------------
527# USAGE: scale ?<data1> <data2> ...?
528#
529# Sets the default limits for the overall plot according to the
530# limits of the data for all of the given <data> objects.  This
531# accounts for all objects--even those not showing on the screen.
532# Because of this, the limits are appropriate for all objects as
533# the user scans through data in the ResultSet viewer.
534# ----------------------------------------------------------------------
535itcl::body Rappture::VtkContourViewer::scale {args} {
536    foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} {
537        set _limits($val) ""
538    }
539    foreach obj $args {
540        foreach axis {x y z v} {
541
542            foreach { min max } [$obj limits $axis] break
543
544            if {"" != $min && "" != $max} {
545                if {"" == $_limits(${axis}min)} {
546                    set _limits(${axis}min) $min
547                    set _limits(${axis}max) $max
548                } else {
549                    if {$min < $_limits(${axis}min)} {
550                        set _limits(${axis}min) $min
551                    }
552                    if {$max > $_limits(${axis}max)} {
553                        set _limits(${axis}max) $max
554                    }
555                }
556            }
557        }
558    }
559}
560
561# ----------------------------------------------------------------------
562# USAGE: download coming
563# USAGE: download controls <downloadCommand>
564# USAGE: download now
565#
566# Clients use this method to create a downloadable representation
567# of the plot.  Returns a list of the form {ext string}, where
568# "ext" is the file extension (indicating the type of data) and
569# "string" is the data itself.
570# ----------------------------------------------------------------------
571itcl::body Rappture::VtkContourViewer::download {option args} {
572    switch $option {
573        coming {
574            if {[catch {
575                blt::winop snap $itk_component(plotarea) $_image(download)
576            }]} {
577                $_image(download) configure -width 1 -height 1
578                $_image(download) put #000000
579            }
580        }
581        controls {
582            set popup .vtkcontourviewerdownload
583            if { ![winfo exists .vtkcontourviewerdownload] } {
584                set inner [BuildDownloadPopup $popup [lindex $args 0]]
585            } else {
586                set inner [$popup component inner]
587            }
588            set _downloadPopup(image_controls) $inner.image_frame
589            set num [llength [get]]
590            set num [expr {($num == 1) ? "1 result" : "$num results"}]
591            set word [Rappture::filexfer::label downloadWord]
592            $inner.summary configure -text "$word $num in the following format:"
593            update idletasks            ;# Fix initial sizes
594            return $popup
595        }
596        now {
597            set popup .vtkcontourviewerdownload
598            if {[winfo exists .vtkcontourviewerdownload]} {
599                $popup deactivate
600            }
601            switch -- $_downloadPopup(format) {
602                "image" {
603                    return [$this GetImage [lindex $args 0]]
604                }
605                "vtk" {
606                    return [$this GetVtkData [lindex $args 0]]
607                }
608            }
609            return ""
610        }
611        default {
612            error "bad option \"$option\": should be coming, controls, now"
613        }
614    }
615}
616
617# ----------------------------------------------------------------------
618# USAGE: Connect ?<host:port>,<host:port>...?
619#
620# Clients use this method to establish a connection to a new
621# server, or to reestablish a connection to the previous server.
622# Any existing connection is automatically closed.
623# ----------------------------------------------------------------------
624itcl::body Rappture::VtkContourViewer::Connect {} {
625    set _hosts [GetServerList "vtkvis"]
626    if { "" == $_hosts } {
627        return 0
628    }
629    set result [VisViewer::Connect $_hosts]
630    if { $result } {
631        set w [winfo width $itk_component(view)]
632        set h [winfo height $itk_component(view)]
633        EventuallyResize $w $h
634    }
635    return $result
636}
637
638#
639# isconnected --
640#
641#       Indicates if we are currently connected to the visualization server.
642#
643itcl::body Rappture::VtkContourViewer::isconnected {} {
644    return [VisViewer::IsConnected]
645}
646
647#
648# disconnect --
649#
650itcl::body Rappture::VtkContourViewer::disconnect {} {
651    Disconnect
652}
653
654#
655# Disconnect --
656#
657#       Clients use this method to disconnect from the current rendering
658#       server.
659#
660itcl::body Rappture::VtkContourViewer::Disconnect {} {
661    VisViewer::Disconnect
662
663    # disconnected -- no more data sitting on server
664    set _outbuf ""
665    array unset _datasets
666    array unset _colormaps
667}
668
669#
670# sendto --
671#
672itcl::body Rappture::VtkContourViewer::sendto { bytes } {
673    SendBytes "$bytes\n"
674}
675
676#
677# SendCmd
678#
679#       Send commands off to the rendering server.  If we're currently
680#       sending data objects to the server, buffer the commands to be
681#       sent later.
682#
683itcl::body Rappture::VtkContourViewer::SendCmd {string} {
684    if { $_buffering } {
685        append _outbuf $string "\n"
686    } else {
687        SendBytes "$string\n"
688    }
689}
690
691# ----------------------------------------------------------------------
692# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
693#
694# Invoked automatically whenever the "image" command comes in from
695# the rendering server.  Indicates that binary image data with the
696# specified <size> will follow.
697# ----------------------------------------------------------------------
698itcl::body Rappture::VtkContourViewer::ReceiveImage { args } {
699    array set info {
700        -token "???"
701        -bytes 0
702        -type image
703        -bbox {0 0 -1 -1}
704    }
705    array set info $args
706    set bytes [ReceiveBytes $info(-bytes)]
707    foreach { _view(ortho-x) _view(ortho-y) _view(ortho-w) _view(ortho-h) } $info(-bbox) break
708    #puts stderr "bbox: $_view(ortho-x) $_view(ortho-y) $_view(ortho-w) $_view(ortho-h)"
709    if { $info(-type) == "image" } {
710        $_image(plot) configure -data $bytes
711        #puts stderr "received image [image width $_image(plot)]x[image height $_image(plot)] image>"       
712    } elseif { $info(type) == "print" } {
713        set tag $this-print-$info(-token)
714        set _hardcopy($tag) $bytes
715    }
716}
717
718# ----------------------------------------------------------------------
719# USAGE: FixLegend
720#
721# Used internally to update the legend area whenever it changes size
722# or when the field changes.  Asks the server to send a new legend
723# for the current field.
724# ----------------------------------------------------------------------
725itcl::body Rappture::VtkContourViewer::FixLegend {} {
726    puts stderr "FixLegend _first=$_first"
727    set _resizeLegendPending 0
728    set lineht [font metrics $itk_option(-font) -linespace]
729    set c $itk_component(legend)
730    set w 20
731    set h [expr {[winfo height $itk_component(view)] - 2 * ($lineht+2)}]
732    puts stderr "in fixlegend w=$w h=$h"
733    if {$w > 0 && $h > 0 && $_first != "" } {
734        set tag [lindex [CurrentDatasets] 0]
735        puts stderr "tag=$tag [info exists _dataset2style($tag)]"
736        if { [info exists _dataset2style($tag)] } {
737            SendCmd "legend $_dataset2style($tag) scalar {} {} $w $h 0"
738        }
739    } else {
740        #$itk_component(legend) delete all
741    }
742}
743
744#
745# DrawLegend --
746#
747#       Draws the legend in it's own canvas which resides to the right
748#       of the contour plot area.
749#
750itcl::body Rappture::VtkContourViewer::DrawLegend {} {
751    set c $itk_component(legend)
752    set w [winfo width $c]
753    set h [winfo height $c]
754    puts stderr "DrawLegend w=$w h=$h"
755    set lineht [font metrics $itk_option(-font) -linespace]
756   
757    if { $_settings($this-legend) } {
758        if { [$c find withtag "legend"] == "" } {
759            $c create image [expr {$w-2}] [expr {$lineht+2}] -anchor ne \
760                -image $_image(legend) -tags "transfunc legend"
761            $c create text [expr {$w-2}] 2 -anchor ne \
762                -fill $itk_option(-plotforeground) -tags "vmax legend" \
763                -font "Arial 6"
764            $c create text [expr {$w-2}] [expr {$h-2}] -anchor se \
765                -fill $itk_option(-plotforeground) -tags "vmin legend" \
766                -font "Arial 6"
767        }
768        # Reset the item coordinates according the current size of the plot.
769        $c coords transfunc [expr {$w-2}] [expr {$lineht+2}]
770        if { $_limits(vmin) != "" } {
771            $c itemconfigure vmin -text [format %g $_limits(vmin)]
772        }
773        if { $_limits(vmax) != "" } {
774            $c itemconfigure vmax -text [format %g $_limits(vmax)]
775        }
776        $c coords vmin [expr {$w-2}] [expr {$h-2}]
777        $c coords vmax [expr {$w-2}] 2
778    }
779}
780
781# ----------------------------------------------------------------------
782# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
783#
784# Invoked automatically whenever the "legend" command comes in from
785# the rendering server.  Indicates that binary image data with the
786# specified <size> will follow.
787# ----------------------------------------------------------------------
788itcl::body Rappture::VtkContourViewer::ReceiveLegend { colormap title vmin vmax size } {
789    #puts stderr "ReceiveLegend colormap=$colormap title=$title range=$vmin,$vmax size=$size"
790    if { [IsConnected] } {
791        set bytes [ReceiveBytes $size]
792        if { ![info exists _image(legend)] } {
793            set _image(legend) [image create photo]
794        }
795        $_image(legend) configure -data $bytes
796        puts stderr "read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
797        DrawLegend
798    }
799}
800
801#
802# ReceiveDataset --
803#
804itcl::body Rappture::VtkContourViewer::ReceiveDataset { args } {
805    if { ![isconnected] } {
806        return
807    }
808    set option [lindex $args 0]
809    switch -- $option {
810        "scalar" {
811            set option [lindex $args 1]
812            switch -- $option {
813                "world" {
814                    foreach { x y z value tag } [lrange $args 2 end] break
815                    puts stderr "world x=$x y=$y z=$z value=$value tag=$tag"
816                }
817                "pixel" {
818                    foreach { x y value tag } [lrange $args 2 end] break
819                    puts stderr "pixel x=$x y=$y value=$value tag=$tag"
820                }
821            }
822        }
823        "vector" {
824            set option [lindex $args 1]
825            switch -- $option {
826                "world" {
827                    foreach { x y z vx vy vz tag } [lrange $args 2 end] break
828                    puts stderr "world x=$x y=$y z=$z value=$vx $xy $vz tag=$tag"
829                }
830                "pixel" {
831                    foreach { x y vx vy vz tag } [lrange $args 2 end] break
832                    puts stderr "pixel x=$x y=$y value=$vx $xy $vz tag=$tag"
833                }
834            }
835        }
836        "names" {
837            foreach { name } [lindex $args 1] {
838                puts stderr "Dataset: $name"
839            }
840        }
841        default {
842            error "unknown dataset option \"$option\" from server"
843        }
844    }
845}
846
847# ----------------------------------------------------------------------
848# USAGE: Rebuild
849#
850# Called automatically whenever something changes that affects the
851# data in the widget.  Clears any existing data and rebuilds the
852# widget to display new data.
853# ----------------------------------------------------------------------
854itcl::body Rappture::VtkContourViewer::Rebuild {} {
855
856    # Turn on buffering of commands to the server.  We don't want to
857    # be preempted by a server disconnect/reconnect (which automatically
858    # generates a new call to Rebuild).   
859    set _buffering 1
860
861    set w [winfo width $itk_component(view)]
862    set h [winfo height $itk_component(view)]
863    EventuallyResize $w $h
864   
865    $_arcball resize $w $h
866
867    set _limits(vmin) ""
868    set _limits(vmax) ""
869    foreach dataobj [get] {
870        foreach comp [$dataobj components] {
871            set tag $dataobj-$comp
872            if { ![info exists _datasets($tag)] } {
873                set bytes [ConvertToVtkData $dataobj $comp]
874                set length [string length $bytes]
875                array set style {-levels 6}
876                array set style [lindex [$dataobj components -style $comp] 0]
877                append _outbuf "dataset add $tag data follows $length\n"
878                append _outbuf $bytes
879                append _outbuf "heightmap add numcontours [expr {$style(-levels)+1}] 0 $tag\n"
880                SetStyles $dataobj $comp
881                set _datasets($tag) 1
882                foreach {min max} [$dataobj limits v] break
883                if { ($_limits(vmin) == "") || ($min < $_limits(vmin)) } {
884                    set _limits(vmin) $min
885                }
886                if { ($_limits(vmax) == "") || ($max < $_limits(vmax)) } {
887                    set _limits(vmax) $max
888                }
889            }
890        }
891    }
892    #
893    # Reset the camera and other view parameters
894    #
895    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
896    $_arcball quaternion $q
897    #SendCmd "camera mode persp"
898    #SendCmd "camera orient $q"
899
900    SendCmd "camera mode image"
901    if {$_view(ortho-w) > 0} {
902        SendCmd "camera ortho world $_view(ortho-x) $_view(ortho-y) $_view(ortho-w) $_view(ortho-h)"
903    } else {
904        PanCamera
905        SendCmd "camera zoom $_view(zoom)"
906    }
907    FixSettings opacity
908    FixSettings isolines
909    FixSettings colormap
910    FixSettings lighting
911    FixSettings wireframe
912    FixSettings axes
913    FixSettings edges
914
915    # Nothing to send -- activate the proper ivol
916    foreach tag [CurrentDatasets] {
917        SendCmd "dataset visible 0 $tag"
918    }
919    set _first [lindex [get] 0]
920    if {"" != $_first} {
921        set location [$_first hints camera]
922        if { $location != "" } {
923            array set view $location
924        }
925
926        foreach axis { x y z } {
927            set label [$_first hints ${axis}label]
928            if { $label != "" } {
929                SendCmd "axis name $axis $label"
930            }
931            set units [$_first hints ${axis}units]
932            if { $units != "" } {
933                SendCmd "axis units $axis $units"
934            }
935        }
936
937        foreach tag [array names _datasets $_first-*]  {
938            SendCmd "dataset visible 1 $tag"
939            SendCmd "heightmap opacity 1.0 $tag"
940        }
941    }
942
943    FixLegend
944
945    set _buffering 0;                        # Turn off buffering.
946
947    # Actually write the commands to the server socket.  If it fails, we don't
948    # care.  We're finished here.
949    blt::busy hold $itk_component(hull)
950    SendBytes $_outbuf;                       
951    blt::busy release $itk_component(hull)
952    set _outbuf "";                        # Clear the buffer.               
953}
954
955# ----------------------------------------------------------------------
956# USAGE: CurrentDatasets ?-cutplanes?
957#
958# Returns a list of server IDs for the current datasets being displayed.  This
959# is normally a single ID, but it might be a list of IDs if the current data
960# object has multiple components.
961# ----------------------------------------------------------------------
962itcl::body Rappture::VtkContourViewer::CurrentDatasets {{what -all}} {
963    set rlist ""
964    if { $_first == "" } {
965        return
966    }
967    foreach comp [$_first components] {
968        set tag $_first-$comp
969        if { [info exists _datasets($tag)] && $_datasets($tag) } {
970            lappend rlist $tag
971        }
972    }
973    return $rlist
974}
975
976# ----------------------------------------------------------------------
977# USAGE: Zoom in
978# USAGE: Zoom out
979# USAGE: Zoom reset
980#
981# Called automatically when the user clicks on one of the zoom
982# controls for this widget.  Changes the zoom for the current view.
983# ----------------------------------------------------------------------
984itcl::body Rappture::VtkContourViewer::Zoom {option} {
985    switch -- $option {
986        "in" {
987            set _view(zoom) [expr {$_view(zoom)*1.25}]
988            SendCmd "camera zoom $_view(zoom)"
989        }
990        "out" {
991            set _view(zoom) [expr {$_view(zoom)*0.8}]
992            SendCmd "camera zoom $_view(zoom)"
993        }
994        "reset" {
995            array set _view {
996                qx      0
997                qy      0
998                qz      0
999                qw      1
1000                zoom    1.0
1001                pan-x   0
1002                pan-y   0
1003            }
1004            SendCmd "camera reset all"
1005            if { $_first != "" } {
1006                set location [$_first hints camera]
1007                if { $location != "" } {
1008                    array set _view $location
1009                }
1010            }
1011            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1012            $_arcball quaternion $q
1013        }
1014    }
1015}
1016
1017itcl::body Rappture::VtkContourViewer::PanCamera {} {
1018    set x $_view(pan-x)
1019    set y $_view(pan-y)
1020    SendCmd "camera pan $x $y"
1021}
1022
1023
1024# ----------------------------------------------------------------------
1025# USAGE: Rotate click <x> <y>
1026# USAGE: Rotate drag <x> <y>
1027# USAGE: Rotate release <x> <y>
1028#
1029# Called automatically when the user clicks/drags/releases in the
1030# plot area.  Moves the plot according to the user's actions.
1031# ----------------------------------------------------------------------
1032itcl::body Rappture::VtkContourViewer::Rotate {option x y} {
1033    switch -- $option {
1034        click {
1035            $itk_component(view) configure -cursor fleur
1036            set _click(x) $x
1037            set _click(y) $y
1038        }
1039        drag {
1040            if {[array size _click] == 0} {
1041                Rotate click $x $y
1042            } else {
1043                set w [winfo width $itk_component(view)]
1044                set h [winfo height $itk_component(view)]
1045                if {$w <= 0 || $h <= 0} {
1046                    return
1047                }
1048
1049                if {[catch {
1050                    # this fails sometimes for no apparent reason
1051                    set dx [expr {double($x-$_click(x))/$w}]
1052                    set dy [expr {double($y-$_click(y))/$h}]
1053                }]} {
1054                    return
1055                }
1056                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1057                foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
1058                SendCmd "camera orient $q"
1059                set _click(x) $x
1060                set _click(y) $y
1061            }
1062        }
1063        release {
1064            Rotate drag $x $y
1065            $itk_component(view) configure -cursor ""
1066            catch {unset _click}
1067        }
1068        default {
1069            error "bad option \"$option\": should be click, drag, release"
1070        }
1071    }
1072}
1073
1074itcl::body Rappture::VtkContourViewer::Pick {x y} {
1075    foreach tag [CurrentDatasets -visible] {
1076        SendCmd "dataset getscalar pixel $x $y $tag"
1077    }
1078}
1079
1080# ----------------------------------------------------------------------
1081# USAGE: $this Pan click x y
1082#        $this Pan drag x y
1083#        $this Pan release x y
1084#
1085# Called automatically when the user clicks on one of the zoom
1086# controls for this widget.  Changes the zoom for the current view.
1087# ----------------------------------------------------------------------
1088itcl::body Rappture::VtkContourViewer::Pan {option x y} {
1089    switch -- $option {
1090        "set" {
1091            set w [winfo width $itk_component(view)]
1092            set h [winfo height $itk_component(view)]
1093            set x [expr $x / double($w)]
1094            set y [expr $y / double($h)]
1095            set _view(pan-x) [expr $_view(pan-x) + $x]
1096            set _view(pan-y) [expr $_view(pan-y) + $y]
1097            PanCamera
1098            return
1099        }
1100        "click" {
1101            set _click(x) $x
1102            set _click(y) $y
1103            $itk_component(view) configure -cursor hand1
1104        }
1105        "drag" {
1106            set w [winfo width $itk_component(view)]
1107            set h [winfo height $itk_component(view)]
1108            set dx [expr ($_click(x) - $x)/double($w)]
1109            set dy [expr ($_click(y) - $y)/double($h)]
1110            set _click(x) $x
1111            set _click(y) $y
1112            set _view(pan-x) [expr $_view(pan-x) - $dx]
1113            set _view(pan-y) [expr $_view(pan-y) - $dy]
1114            PanCamera
1115        }
1116        "release" {
1117            Pan drag $x $y
1118            $itk_component(view) configure -cursor ""
1119        }
1120        default {
1121            error "unknown option \"$option\": should set, click, drag, or release"
1122        }
1123    }
1124}
1125
1126# ----------------------------------------------------------------------
1127# USAGE: FixSettings <what> ?<value>?
1128#
1129# Used internally to update rendering settings whenever parameters
1130# change in the popup settings panel.  Sends the new settings off
1131# to the back end.
1132# ----------------------------------------------------------------------
1133itcl::body Rappture::VtkContourViewer::FixSettings {what {value ""}} {
1134    switch -- $what {
1135        "opacity" {
1136            if {[isconnected]} {
1137                set val $_settings($this-opacity)
1138                set sval [expr { 0.01 * double($val) }]
1139                foreach dataset [CurrentDatasets] {
1140                    SendCmd "heightmap opacity $sval $dataset"
1141                }
1142            }
1143        }
1144        "wireframe" {
1145            if {[isconnected]} {
1146                set bool $_settings($this-wireframe)
1147                foreach dataset [CurrentDatasets] {
1148                    SendCmd "heightmap wireframe $bool $dataset"
1149                }
1150            }
1151        }
1152        "colormap" {
1153            if {[isconnected]} {
1154                set bool $_settings($this-colormap)
1155                foreach dataset [CurrentDatasets] {
1156                    SendCmd "heightmap surface $bool $dataset"
1157                }
1158            }
1159        }
1160        "isolines" {
1161            if {[isconnected]} {
1162                set bool $_settings($this-isolines)
1163                foreach dataset [CurrentDatasets] {
1164                    SendCmd "heightmap isolines $bool $dataset"
1165                }
1166            }
1167        }
1168        "edges" {
1169            if {[isconnected]} {
1170                set bool $_settings($this-edges)
1171                foreach dataset [CurrentDatasets] {
1172                    SendCmd "heightmap edges $bool $dataset"
1173                }
1174            }
1175        }
1176        "lighting" {
1177            if {[isconnected]} {
1178                set bool $_settings($this-lighting)
1179                foreach dataset [CurrentDatasets] {
1180                    SendCmd "heightmap lighting $bool $dataset"
1181                }
1182            }
1183        }
1184        "axes" {
1185            if { [isconnected] } {
1186                set bool $_settings($this-axes)
1187                SendCmd "axis visible all $bool"
1188            }
1189        }
1190        "legend" {
1191            if { $_settings($this-legend) } {
1192                blt::table $itk_component(plotarea) \
1193                    0,0 $itk_component(view) -fill both \
1194                    0,1 $itk_component(legend) -fill y
1195                blt::table configure $itk_component(plotarea) c1 -resize none
1196            } else {
1197                blt::table forget $itk_component(legend)
1198            }
1199        }
1200        default {
1201            error "don't know how to fix $what"
1202        }
1203    }
1204}
1205
1206
1207#
1208# SetStyles --
1209#
1210itcl::body Rappture::VtkContourViewer::SetStyles { dataobj comp } {
1211    array set style {
1212        -color BCGYR
1213        -levels 6
1214        -opacity 1.0
1215    }
1216    set tag $dataobj-$comp
1217    array set style [lindex [$dataobj components -style $comp] 0]
1218    set colormap "$style(-color):$style(-levels):$style(-opacity)"
1219    if { [info exists _colormaps($colormap)] } {
1220        puts stderr "Colormap $colormap already built"
1221    }
1222    if { ![info exists _dataset2style($tag)] } {
1223        set _dataset2style($tag) $colormap
1224        lappend _style2datasets($colormap) $tag
1225    }
1226    if { ![info exists _colormaps($colormap)] } {
1227        # Build the pseudo colormap if it doesn't exist.
1228        BuildColormap $colormap $dataobj $comp
1229        set _colormaps($colormap) 1
1230    }
1231    #SendCmd "heightmap numcontours $style(-levels) $tag\n"
1232    SendCmd "heightmap colormap $colormap $tag"
1233    return $colormap
1234}
1235
1236itcl::body Rappture::VtkContourViewer::ColorsToColormap { colors } {
1237    switch -- $colors {
1238        "grey-to-blue" {
1239            return {
1240                0.0                      0.200 0.200 0.200
1241                0.14285714285714285      0.400 0.400 0.400
1242                0.2857142857142857       0.600 0.600 0.600
1243                0.42857142857142855      0.900 0.900 0.900
1244                0.5714285714285714       0.800 1.000 1.000
1245                0.7142857142857143       0.600 1.000 1.000
1246                0.8571428571428571       0.400 0.900 1.000
1247                1.0                      0.000 0.600 0.800
1248            }
1249        }
1250        "blue-to-grey" {
1251            return {
1252                0.0                     0.000 0.600 0.800
1253                0.14285714285714285     0.400 0.900 1.000
1254                0.2857142857142857      0.600 1.000 1.000
1255                0.42857142857142855     0.800 1.000 1.000
1256                0.5714285714285714      0.900 0.900 0.900
1257                0.7142857142857143      0.600 0.600 0.600
1258                0.8571428571428571      0.400 0.400 0.400
1259                1.0                     0.200 0.200 0.200
1260            }
1261        }
1262        "blue" {
1263            return {
1264                0.0                     0.900 1.000 1.000
1265                0.1111111111111111      0.800 0.983 1.000
1266                0.2222222222222222      0.700 0.950 1.000
1267                0.3333333333333333      0.600 0.900 1.000
1268                0.4444444444444444      0.500 0.833 1.000
1269                0.5555555555555556      0.400 0.750 1.000
1270                0.6666666666666666      0.300 0.650 1.000
1271                0.7777777777777778      0.200 0.533 1.000
1272                0.8888888888888888      0.100 0.400 1.000
1273                1.0                     0.000 0.250 1.000
1274            }
1275        }
1276        "brown-to-blue" {
1277            return {
1278                0.0                             0.200   0.100   0.000
1279                0.09090909090909091             0.400   0.187   0.000
1280                0.18181818181818182             0.600   0.379   0.210
1281                0.2727272727272727              0.800   0.608   0.480
1282                0.36363636363636365             0.850   0.688   0.595
1283                0.45454545454545453             0.950   0.855   0.808
1284                0.5454545454545454              0.800   0.993   1.000
1285                0.6363636363636364              0.600   0.973   1.000
1286                0.7272727272727273              0.400   0.940   1.000
1287                0.8181818181818182              0.200   0.893   1.000
1288                0.9090909090909091              0.000   0.667   0.800
1289                1.0                             0.000   0.480   0.600
1290            }
1291        }
1292        "blue-to-brown" {
1293            return {
1294                0.0                             0.000   0.480   0.600
1295                0.09090909090909091             0.000   0.667   0.800
1296                0.18181818181818182             0.200   0.893   1.000
1297                0.2727272727272727              0.400   0.940   1.000
1298                0.36363636363636365             0.600   0.973   1.000
1299                0.45454545454545453             0.800   0.993   1.000
1300                0.5454545454545454              0.950   0.855   0.808
1301                0.6363636363636364              0.850   0.688   0.595
1302                0.7272727272727273              0.800   0.608   0.480
1303                0.8181818181818182              0.600   0.379   0.210
1304                0.9090909090909091              0.400   0.187   0.000
1305                1.0                             0.200   0.100   0.000
1306            }
1307        }
1308        "blue-to-orange" {
1309            return {
1310                0.0                             0.000   0.167   1.000
1311                0.09090909090909091             0.100   0.400   1.000
1312                0.18181818181818182             0.200   0.600   1.000
1313                0.2727272727272727              0.400   0.800   1.000
1314                0.36363636363636365             0.600   0.933   1.000
1315                0.45454545454545453             0.800   1.000   1.000
1316                0.5454545454545454              1.000   1.000   0.800
1317                0.6363636363636364              1.000   0.933   0.600
1318                0.7272727272727273              1.000   0.800   0.400
1319                0.8181818181818182              1.000   0.600   0.200
1320                0.9090909090909091              1.000   0.400   0.100
1321                1.0                             1.000   0.167   0.000
1322            }
1323        }
1324        "orange-to-blue" {
1325            return {
1326                0.0                             1.000   0.167   0.000
1327                0.09090909090909091             1.000   0.400   0.100
1328                0.18181818181818182             1.000   0.600   0.200
1329                0.2727272727272727              1.000   0.800   0.400
1330                0.36363636363636365             1.000   0.933   0.600
1331                0.45454545454545453             1.000   1.000   0.800
1332                0.5454545454545454              0.800   1.000   1.000
1333                0.6363636363636364              0.600   0.933   1.000
1334                0.7272727272727273              0.400   0.800   1.000
1335                0.8181818181818182              0.200   0.600   1.000
1336                0.9090909090909091              0.100   0.400   1.000
1337                1.0                             0.000   0.167   1.000
1338            }
1339        }
1340        "rainbow" {
1341            set clist {
1342                "#EE82EE"
1343                "#4B0082"
1344                "blue"
1345                "#008000"
1346                "yellow"
1347                "#FFA500"
1348                "red"
1349            }
1350        }
1351        "BGYOR" {
1352            set clist {
1353                "blue"
1354                "#008000"
1355                "yellow"
1356                "#FFA500"
1357                "red"
1358            }
1359        }
1360        "ROYGB" {
1361            set clist {
1362                "red"
1363                "#FFA500"
1364                "yellow"
1365                "#008000"
1366                "blue"
1367            }
1368        }
1369        "RYGCB" {
1370            set clist {
1371                "red"
1372                "yellow"
1373                "green"
1374                "cyan"
1375                "blue"
1376            }
1377        }
1378        "BCGYR" {
1379            set clist {
1380                "blue"
1381                "cyan"
1382                "green"
1383                "yellow"
1384                "red"
1385            }
1386        }
1387        "spectral" {
1388            return {
1389                0.0 0.150 0.300 1.000
1390                0.1 0.250 0.630 1.000
1391                0.2 0.450 0.850 1.000
1392                0.3 0.670 0.970 1.000
1393                0.4 0.880 1.000 1.000
1394                0.5 1.000 1.000 0.750
1395                0.6 1.000 0.880 0.600
1396                0.7 1.000 0.680 0.450
1397                0.8 0.970 0.430 0.370
1398                0.9 0.850 0.150 0.196
1399                1.0 0.650 0.000 0.130
1400            }
1401        }
1402        "green-to-magenta" {
1403            return {
1404                0.0 0.000 0.316 0.000
1405                0.06666666666666667 0.000 0.526 0.000
1406                0.13333333333333333 0.000 0.737 0.000
1407                0.2 0.000 0.947 0.000
1408                0.26666666666666666 0.316 1.000 0.316
1409                0.3333333333333333 0.526 1.000 0.526
1410                0.4 0.737 1.000 0.737
1411                0.4666666666666667 1.000 1.000 1.000
1412                0.5333333333333333 1.000 0.947 1.000
1413                0.6 1.000 0.737 1.000
1414                0.6666666666666666 1.000 0.526 1.000
1415                0.7333333333333333 1.000 0.316 1.000
1416                0.8 0.947 0.000 0.947
1417                0.8666666666666667 0.737 0.000 0.737
1418                0.9333333333333333 0.526 0.000 0.526
1419                1.0 0.316 0.000 0.316
1420            }
1421        }
1422        "greyscale" {
1423            return {
1424                0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
1425            }
1426        }
1427        "nanohub" {
1428            set clist "white yellow green cyan blue magenta"
1429        }
1430        default {
1431            set clist $colors
1432        }
1433    }
1434    set cmap {}
1435    for {set i 0} {$i < [llength $clist]} {incr i} {
1436        set x [expr {double($i)/([llength $clist]-1)}]
1437        set color [lindex $clist $i]
1438        append cmap "$x [Color2RGB $color] "
1439    }
1440    return $cmap
1441}
1442
1443#
1444# BuildColormap --
1445#
1446itcl::body Rappture::VtkContourViewer::BuildColormap { colormap dataobj comp } {
1447    puts stderr "BuildColormap $colormap"
1448    array set style {
1449        -color BCGYR
1450        -levels 6
1451        -opacity 1.0
1452    }
1453    array set style [lindex [$dataobj components -style $comp] 0]
1454
1455    set cmap [ColorsToColormap $style(-color)]
1456
1457    if { [llength $cmap] == 0 } {
1458        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1459    }
1460    set tag $this-$colormap
1461    if { ![info exists _settings($tag-opacity)] } {
1462        set _settings($tag-opacity) $style(-opacity)
1463    }
1464    set max $_settings($tag-opacity)
1465
1466    set wmap "0.0 1.0 1.0 1.0"
1467    SendCmd "colormap add $colormap { $cmap } { $wmap }"
1468}
1469
1470# ----------------------------------------------------------------------
1471# CONFIGURATION OPTION: -plotbackground
1472# ----------------------------------------------------------------------
1473itcl::configbody Rappture::VtkContourViewer::plotbackground {
1474    if { [isconnected] } {
1475        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1476        SendCmd "screen bgcolor $r $g $b"
1477    }
1478}
1479
1480# ----------------------------------------------------------------------
1481# CONFIGURATION OPTION: -plotforeground
1482# ----------------------------------------------------------------------
1483itcl::configbody Rappture::VtkContourViewer::plotforeground {
1484    if { [isconnected] } {
1485        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1486        #fix this!
1487        #SendCmd "color background $r $g $b"
1488    }
1489}
1490
1491itcl::body Rappture::VtkContourViewer::limits { colormap } {
1492    set _limits(min) 0.0
1493    set _limits(max) 1.0
1494    if { ![info exists _style2datasets($colormap)] } {
1495        return [array get _limits]
1496    }
1497    set min ""; set max ""
1498    foreach tag $_style2datasets($colormap) {
1499        if { ![info exists _datasets($tag)] } {
1500            continue
1501        }
1502        if { ![info exists _limits($tag-min)] } {
1503            continue
1504        }
1505        if { $min == "" || $min > $_limits($tag-min) } {
1506            set min $_limits($tag-min)
1507        }
1508        if { $max == "" || $max < $_limits($tag-max) } {
1509            set max $_limits($tag-max)
1510        }
1511    }
1512    if { $min != "" } {
1513        set _limits(min) $min
1514    }
1515    if { $max != "" } {
1516        set _limits(max) $max
1517    }
1518    return [array get _limits]
1519}
1520
1521
1522itcl::body Rappture::VtkContourViewer::BuildViewTab {} {
1523
1524    set fg [option get $itk_component(hull) font Font]
1525    #set bfg [option get $itk_component(hull) boldFont Font]
1526
1527    set inner [$itk_component(main) insert end \
1528        -title "View Settings" \
1529        -icon [Rappture::icon wrench]]
1530    $inner configure -borderwidth 4
1531
1532    checkbutton $inner.axes \
1533        -text "Axes" \
1534        -variable [itcl::scope _settings($this-axes)] \
1535        -command [itcl::code $this FixSettings axes] \
1536        -font "Arial 9"
1537
1538    checkbutton $inner.colormap \
1539        -text "Colormap" \
1540        -variable [itcl::scope _settings($this-colormap)] \
1541        -command [itcl::code $this FixSettings colormap] \
1542        -font "Arial 9"
1543
1544    checkbutton $inner.isolines \
1545        -text "Isolines" \
1546        -variable [itcl::scope _settings($this-isolines)] \
1547        -command [itcl::code $this FixSettings isolines] \
1548        -font "Arial 9"
1549
1550    checkbutton $inner.wireframe \
1551        -text "Wireframe" \
1552        -variable [itcl::scope _settings($this-wireframe)] \
1553        -command [itcl::code $this FixSettings wireframe] \
1554        -font "Arial 9"
1555
1556    checkbutton $inner.lighting \
1557        -text "Lighting" \
1558        -variable [itcl::scope _settings($this-lighting)] \
1559        -command [itcl::code $this FixSettings lighting] \
1560        -font "Arial 9"
1561
1562    checkbutton $inner.legend \
1563        -text "Legend" \
1564        -variable [itcl::scope _settings($this-legend)] \
1565        -command [itcl::code $this FixSettings legend] \
1566        -font "Arial 9"
1567
1568    checkbutton $inner.edges \
1569        -text "Edges" \
1570        -variable [itcl::scope _settings($this-edges)] \
1571        -command [itcl::code $this FixSettings edges] \
1572        -font "Arial 9"
1573
1574    label $inner.clear -text "Clear" -font "Arial 9"
1575    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1576        -variable [itcl::scope _settings($this-opacity)] \
1577        -width 10 \
1578        -showvalue off -command [itcl::code $this FixSettings opacity]
1579    label $inner.opaque -text "Opaque" -font "Arial 9"
1580
1581    blt::table $inner \
1582        0,0 $inner.axes -columnspan 4 -anchor w -pady 2 \
1583        1,0 $inner.colormap -columnspan 4 -anchor w -pady 2 \
1584        2,0 $inner.isolines -columnspan 4 -anchor w -pady 2 \
1585        3,0 $inner.wireframe -columnspan 4 -anchor w -pady 2 \
1586        4,0 $inner.lighting  -columnspan 4 -anchor w \
1587        5,0 $inner.legend  -columnspan 4 -anchor w \
1588        6,0 $inner.edges -columnspan 4 -anchor w -pady 2 \
1589        7,0 $inner.clear -anchor e -pady 2 \
1590        7,1 $inner.opacity -columnspan 2 -pady 2 -fill x\
1591        7,3 $inner.opaque -anchor w -pady 2
1592
1593    blt::table configure $inner r* -resize none
1594    blt::table configure $inner r8 -resize expand
1595}
1596
1597itcl::body Rappture::VtkContourViewer::BuildCameraTab {} {
1598    set inner [$itk_component(main) insert end \
1599        -title "Camera Settings" \
1600        -icon [Rappture::icon camera]]
1601    $inner configure -borderwidth 4
1602
1603    set labels { qx qy qz qw pan-x pan-y zoom }
1604    set row 0
1605    foreach tag $labels {
1606        label $inner.${tag}label -text $tag -font "Arial 9"
1607        entry $inner.${tag} -font "Arial 9"  -bg white \
1608            -textvariable [itcl::scope _view($tag)]
1609        bind $inner.${tag} <KeyPress-Return> \
1610            [itcl::code $this camera set ${tag}]
1611        blt::table $inner \
1612            $row,0 $inner.${tag}label -anchor e -pady 2 \
1613            $row,1 $inner.${tag} -anchor w -pady 2
1614        blt::table configure $inner r$row -resize none
1615        incr row
1616    }
1617    blt::table configure $inner c0 c1 -resize none
1618    blt::table configure $inner c2 -resize expand
1619    blt::table configure $inner r$row -resize expand
1620}
1621
1622
1623#
1624#  camera --
1625#
1626itcl::body Rappture::VtkContourViewer::camera {option args} {
1627    switch -- $option {
1628        "show" {
1629            puts [array get _view]
1630        }
1631        "set" {
1632            set who [lindex $args 0]
1633            set x $_view($who)
1634            set code [catch { string is double $x } result]
1635            if { $code != 0 || !$result } {
1636                return
1637            }
1638            switch -- $who {
1639                "pan-x" - "pan-y" {
1640                    PanCamera
1641                }
1642                "qx" - "qy" - "qz" - "qw" {
1643                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1644                    $_arcball quaternion $q
1645                    #SendCmd "camera orient $q"
1646                }
1647                "zoom" {
1648                    SendCmd "camera zoom $_view(zoom)"
1649                }
1650            }
1651        }
1652    }
1653}
1654
1655itcl::body Rappture::VtkContourViewer::ConvertToVtkData { dataobj comp } {
1656    set ds ""
1657    set arr ""
1658    if {[$dataobj isunirect2d]} {
1659        foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $comp] break
1660        set spacingX [expr {double($x2 - $x1)/double($xN - 1)}]
1661        set spacingY [expr {double($y2 - $y1)/double($yN - 1)}]
1662
1663        set ds [vtkImageData $dataobj-grdataTemp]
1664        $ds SetDimensions $xN $yN 1
1665        $ds SetOrigin $x1 $y1 0
1666        $ds SetSpacing $spacingX $spacingY 0
1667        set arr [vtkDoubleArray $dataobj-arrTemp]
1668        foreach {val} [$dataobj values $comp] {
1669            $arr InsertNextValue $val
1670        }
1671        [$ds GetPointData] SetScalars $arr
1672    } elseif {[$dataobj isunirect3d]} {
1673        foreach { x1 x2 xN y1 y2 yN z1 z2 zN } [$dataobj mesh $comp] break
1674        set spacingX [expr {double($x2 - $x1)/double($xN - 1)}]
1675        set spacingY [expr {double($y2 - $y1)/double($yN - 1)}]
1676        set spacingZ [expr {double($z2 - $z1)/double($zN - 1)}]
1677
1678        set ds [vtkImageData $dataobj-grdataTemp]
1679        $ds SetDimensions $xN $yN $zN
1680        $ds SetOrigin $x1 $y1 $z1
1681        $ds SetSpacing $spacingX $spacingY $spacingZ
1682        set arr [vtkDoubleArray $dataobj-arrTemp]
1683        foreach {val} [$dataobj values $comp] {
1684            $arr InsertNextValue $val
1685        }
1686        [$ds GetPointData] SetScalars $arr
1687    } else {
1688        set mesh [$dataobj mesh $comp]
1689        switch -- [$mesh GetClassName] {
1690            vtkPoints {
1691                # handle cloud of points
1692                set ds [vtkPolyData $dataobj-polydataTemp]
1693                $ds SetPoints $mesh
1694                [$ds GetPointData] SetScalars [$dataobj values $comp]
1695            }
1696            vtkPolyData {
1697                set ds [vtkPolyData $dataobj-polydataTemp]
1698                $ds ShallowCopy $mesh
1699                [$ds GetPointData] SetScalars [$dataobj values $comp]
1700            }
1701            vtkUnstructuredGrid {
1702                # handle 3D grid with connectivity
1703                set ds [vtkUnstructuredGrid $dataobj-grdataTemp]
1704                $ds ShallowCopy $mesh
1705                [$ds GetPointData] SetScalars [$dataobj values $comp]
1706            }
1707            vtkRectilinearGrid {
1708                # handle 3D grid with connectivity
1709                set ds [vtkRectilinearGrid $dataobj-grdataTemp]
1710                $ds ShallowCopy $mesh
1711                [$ds GetPointData] SetScalars [$dataobj values $comp]
1712            }
1713            default {
1714                error "don't know how to handle [$mesh GetClassName] data"
1715            }
1716        }
1717    }
1718
1719    if {"" != $ds} {
1720        set writer [vtkDataSetWriter $this-dsWriterTmp]
1721        $writer SetInput $ds
1722        $writer SetFileTypeToASCII
1723        $writer WriteToOutputStringOn
1724        $writer Write
1725        set out [$writer GetOutputString]
1726        $ds Delete
1727        $writer Delete
1728        if {"" != $arr} {
1729            $arr Delete
1730        }
1731    } else {
1732        set out ""
1733        error "No DataSet to write"
1734    }
1735
1736    append out "\n"
1737    return $out
1738}
1739
1740#
1741# MarchingAnts --
1742#
1743#       Called from "after" timer events.  This routine is changes
1744#       the dash offset of the selection outline rectangle to simulate
1745#       marching ants.
1746#
1747itcl::body Rappture::VtkContourViewer::MarchingAnts {} {
1748    set c $itk_component(view)
1749    if { [winfo exists $c] && ![winfo viewable $c] } {
1750        KillSelectionRectangle
1751        return
1752    }
1753    $c itemconfigure $_outline(id) -dashoffset $_outline(offset)
1754    incr _outline(offset)
1755    set _outline(afterId) [after 100 [itcl::code $this MarchingAnts]]
1756}
1757
1758#
1759# BeginSelectionRectangle --
1760#
1761#       Called from ButtonPress-1 events.  This routine creates the
1762#       the selection outline rectangle.  It also clears the selection
1763#       in the sensor tree.
1764#
1765itcl::body Rappture::VtkContourViewer::BeginSelectionRectangle { x y } {
1766    set c $itk_component(view)
1767    set x [$c canvasx $x]
1768    set y [$c canvasy $y]
1769    if { $_outline(id) >= 0 } {
1770        after cancel $_outline(afterId)
1771        set _outline(afterId) -1
1772        $c delete $_outline(id)
1773        set _outline(id) -1
1774    }
1775    set _outline(offset) 0
1776    set _outline(x1) $x
1777    set _outline(y1) $y
1778    set _outline(id) \
1779        [$c create line $x $y $x $y -dash "4 4" -width 2 -fill black]
1780    MarchingAnts
1781}
1782
1783#
1784# AdjustSelectionRectangle --
1785#
1786#       Called from B1-Motion events.  This routine redraws the selection
1787#       outline rectangle and redraws the sensors using the "selected"
1788#       icon.
1789#
1790itcl::body Rappture::VtkContourViewer::AdjustSelectionRectangle { x y } {
1791    set c $itk_component(view)
1792    set x [$c canvasx $x]
1793    set y [$c canvasy $y]
1794    $c coords $_outline(id) $_outline(x1) $_outline(y1) $_outline(x1) $y \
1795        $x $y $x $_outline(y1) $_outline(x1) $_outline(y1)
1796    set _outline(x2) $x
1797    set _outline(y2) $y
1798}
1799
1800#
1801# KillSelectionRectangle --
1802#
1803#       Removes the outline rectangle and adjusts the sensor icon
1804#       according to the sensor's selected/deselected status.
1805#
1806itcl::body Rappture::VtkContourViewer::KillSelectionRectangle { } {
1807    after cancel $_outline(afterId)
1808    set _outline(afterId) -1
1809    set c $itk_component(view)
1810    $c delete $_outline(id)
1811    set _outline(id) -1
1812}
1813
1814#
1815# EndSelectionRectangle --
1816#
1817#       Called from the ButtonRelease event to finish the outline of the
1818#       selection rectangle.  If the outline is too small (less than 10
1819#       pixels in length or width) the outline is removed and the selection
1820#       is ignored.  Otherwise a popup menu is automatically generated and
1821#       displayed.
1822#
1823itcl::body Rappture::VtkContourViewer::EndSelectionRectangle { x y } {
1824    set c $itk_component(view)
1825    AdjustSelectionRectangle $x $y
1826    set cx [$c canvasx $x]
1827    set cy [$c canvasy $y]
1828    set cw [winfo width $c]
1829    set ch [winfo height $c]
1830    if { abs($_outline(x1) - $cx) < 10 && abs($_outline(y1) - $cy) < 10 }  {
1831        KillSelectionRectangle
1832    } else {
1833        # Need x,y coordinates to be in the bottom left for camera ortho
1834        if {$_outline(x2) > $_outline(x1)} {
1835            set ox [expr int($_outline(x1))]
1836            set w [expr int($_outline(x2) - $_outline(x1))]
1837        } else {
1838            set ox [expr int($_outline(x2))]
1839            set w [expr int($_outline(x1) - $_outline(x2))]
1840        }
1841        if {$_outline(y2) > $_outline(y1)} {
1842            set oy [expr int($_outline(y2))]
1843            set h [expr int($_outline(y2) - $_outline(y1))]
1844        } else {
1845            set oy [expr int($_outline(y1))]
1846            set h [expr int($_outline(y1) - $_outline(y2))]
1847        }
1848        SendCmd "camera ortho pixel $ox $oy $w $h"
1849        KillSelectionRectangle
1850    }
1851}
1852
1853itcl::body Rappture::VtkContourViewer::GetVtkData { args } {
1854    set bytes ""
1855    foreach dataobj [get] {
1856        foreach comp [$dataobj components] {
1857            set tag $dataobj-$comp
1858            set contents [ConvertToVtkData $dataobj $comp]
1859            append bytes "$contents\n\n"
1860        }
1861    }
1862    return [list .txt $bytes]
1863}
1864
1865itcl::body Rappture::VtkContourViewer::GetImage { args } {
1866    if { [image width $_image(download)] > 0 &&
1867         [image height $_image(download)] > 0 } {
1868        set bytes [$_image(download) data -format "jpeg -quality 100"]
1869        set bytes [Rappture::encoding::decode -as b64 $bytes]
1870        return [list .jpg $bytes]
1871    }
1872    return ""
1873}
1874
1875itcl::body Rappture::VtkContourViewer::BuildDownloadPopup { popup command } {
1876    Rappture::Balloon $popup \
1877        -title "[Rappture::filexfer::label downloadWord] as..."
1878    set inner [$popup component inner]
1879    label $inner.summary -text "" -anchor w
1880    radiobutton $inner.vtk_button -text "VTK data file" \
1881        -variable [itcl::scope _downloadPopup(format)] \
1882        -font "Helvetica 9 " \
1883        -value vtk 
1884    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
1885    radiobutton $inner.image_button -text "Image File" \
1886        -variable [itcl::scope _downloadPopup(format)] \
1887        -value image
1888    Rappture::Tooltip::for $inner.image_button \
1889        "Save as digital image."
1890
1891    button $inner.ok -text "Save" \
1892        -highlightthickness 0 -pady 2 -padx 3 \
1893        -command $command \
1894        -compound left \
1895        -image [Rappture::icon download]
1896
1897    button $inner.cancel -text "Cancel" \
1898        -highlightthickness 0 -pady 2 -padx 3 \
1899        -command [list $popup deactivate] \
1900        -compound left \
1901        -image [Rappture::icon cancel]
1902
1903    blt::table $inner \
1904        0,0 $inner.summary -cspan 2  \
1905        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
1906        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
1907        4,1 $inner.cancel -width .9i -fill y \
1908        4,0 $inner.ok -padx 2 -width .9i -fill y
1909    blt::table configure $inner r3 -height 4
1910    blt::table configure $inner r4 -pady 4
1911    raise $inner.image_button
1912    $inner.vtk_button invoke
1913    return $inner
1914}
1915
Note: See TracBrowser for help on using the repository browser.