source: trunk/gui/scripts/field.tcl @ 1463

Last change on this file since 1463 was 1463, checked in by gah, 15 years ago
File size: 25.6 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: field - extracts data from an XML description of a field
3#
4#  This object represents one field in an XML description of a device.
5#  It simplifies the process of extracting data vectors that represent
6#  the field.
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 Itcl
15package require BLT
16
17namespace eval Rappture { # forward declaration }
18
19itcl::class Rappture::Field {
20    constructor {xmlobj path} { # defined below }
21    destructor { # defined below }
22
23    public method components {args}
24    public method mesh {{what -overall}}
25    public method values {{what -overall}}
26    public method blob {{what -overall}}
27    public method limits {axis}
28    public method controls {option args}
29    public method hints {{key ""}}
30    public method isunirect2d {}
31    public method isunirect3d {}
32    public method extents {{what -overall}}
33    public method flowhints { cname }
34    protected method _build {}
35    protected method _getValue {expr}
36
37    private variable _xmlobj ""  ;# ref to XML obj with device data
38
39    private variable _units ""   ;# system of units for this field
40    private variable _limits     ;# maps box name => {z0 z1} limits
41    private variable _zmax 0     ;# length of the device
42
43    private variable _field ""   ;# lib obj representing this field
44    private variable _comp2dims  ;# maps component name => dimensionality
45    private variable _comp2xy    ;# maps component name => x,y vectors
46    private variable _comp2vtk   ;# maps component name => vtkFloatArray
47    private variable _comp2dx    ;# maps component name => OpenDX data
48    private variable _comp2unirect2d ;# maps component name => unirect2d obj
49    private variable _comp2unirect3d ;# maps component name => unirect3d obj
50    private variable _comp2style ;# maps component name => style settings
51    private variable _comp2cntls ;# maps component name => x,y control points
52    private variable _comp2extents
53    private variable _comp2flowhints
54    private common _counter 0    ;# counter for unique vector names
55}
56
57# ----------------------------------------------------------------------
58# CONSTRUCTOR
59# ----------------------------------------------------------------------
60itcl::body Rappture::Field::constructor {xmlobj path} {
61    if {![Rappture::library isvalid $xmlobj]} {
62        error "bad value \"$xmlobj\": should be Rappture::library"
63    }
64    set _xmlobj $xmlobj
65    set _field [$xmlobj element -as object $path]
66    set _units [$_field get units]
67
68    set xunits [$xmlobj get units]
69    if {"" == $xunits || "arbitrary" == $xunits} {
70        set xunits "um"
71    }
72
73    # determine the overall size of the device
74    set z0 [set z1 0]
75    foreach elem [$_xmlobj children components] {
76        switch -glob -- $elem {
77            box* {
78                if {![regexp {[0-9]$} $elem]} {
79                    set elem "${elem}0"
80                }
81                set z0 [$_xmlobj get components.$elem.corner0]
82                set z0 [Rappture::Units::convert $z0 \
83                    -context $xunits -to $xunits -units off]
84
85                set z1 [$_xmlobj get components.$elem.corner1]
86                set z1 [Rappture::Units::convert $z1 \
87                    -context $xunits -to $xunits -units off]
88
89                set _limits($elem) [list $z0 $z1]
90            }
91        }
92    }
93    set _zmax $z1
94
95    # build up vectors for various components of the field
96    _build
97}
98
99# ----------------------------------------------------------------------
100# DESTRUCTOR
101# ----------------------------------------------------------------------
102itcl::body Rappture::Field::destructor {} {
103    itcl::delete object $_field
104    # don't destroy the _xmlobj! we don't own it!
105
106    foreach name [array names _comp2xy] {
107        eval blt::vector destroy $_comp2xy($name)
108    }
109    foreach name [array names _comp2vtk] {
110        set mobj [lindex $_comp2vtk($name) 0]
111        set class [$mobj info class]
112        ${class}::release $mobj
113
114        set fobj [lindex $_comp2vtk($name) 1]
115        rename $fobj ""
116    }
117    foreach name [array names _comp2unirect2d] {
118        itcl::delete object $_comp2unirect2d($name)
119    }
120    foreach name [array names _comp2unirect3d] {
121        itcl::delete object $_comp2unirect3d($name)
122    }
123    foreach name [array names _comp2flowhints] {
124        itcl::delete object $_comp2flowhints($name)
125    }
126}
127
128# ----------------------------------------------------------------------
129# USAGE: components ?-name|-dimensions|-style? ?<pattern>?
130#
131# Returns a list of names or types for the various components of
132# this field.  If the optional glob-style <pattern> is specified,
133# then it returns only the components with names matching the pattern.
134# ----------------------------------------------------------------------
135itcl::body Rappture::Field::components {args} {
136    Rappture::getopts args params {
137        flag what -name default
138        flag what -dimensions
139        flag what -style
140        flag what -particles
141        flag what -flow
142        flag what -box
143    }
144
145    set pattern *
146    if {[llength $args] > 0} {
147        set pattern [lindex $args 0]
148        set args [lrange $args 1 end]
149    }
150    if {[llength $args] > 0} {
151        error "wrong # args: should be \"components ?switches? ?pattern?\""
152    }
153
154    set rlist ""
155
156    # BE CAREFUL: return component names in proper order
157    foreach cname [$_field children -type component] {
158        if {[info exists _comp2dims($cname)]
159              && [string match $pattern $cname]} {
160
161            switch -- $params(what) {
162                -name { lappend rlist $cname }
163                -dimensions { lappend rlist $_comp2dims($cname) }
164                -style { lappend rlist $_comp2style($cname) }
165            }
166        }
167    }
168    return $rlist
169}
170
171# ----------------------------------------------------------------------
172# USAGE: mesh ?<name>?
173#
174# Returns a list {xvec yvec} for the specified field component <name>.
175# If the name is not specified, then it returns the vectors for the
176# overall field (sum of all components).
177# ----------------------------------------------------------------------
178itcl::body Rappture::Field::mesh {{what -overall}} {
179    if {$what == "-overall" || $what == "component0"} {
180        set what [lindex [components -name] 0]
181    }
182    if {[info exists _comp2xy($what)]} {
183        return [lindex $_comp2xy($what) 0]  ;# return xv
184    }
185    if { [info exists _comp2vtk($what)] } {
186        set mobj [lindex $_comp2vtk($what) 0]
187        return [$mobj mesh]
188    }
189    if {[info exists _comp2dx($what)]} {
190        return ""  ;# no mesh -- it's embedded in the value data
191    }
192    if {[info exists _comp2unirect2d($what)]} {
193        set mobj [lindex $_comp2unirect2d($what) 0]
194        return [$mobj mesh]
195    }
196    if {[info exists _comp2unirect3d($what)]} {
197        set mobj [lindex $_comp2unirect3d($what) 0]
198        return [$mobj mesh]
199    }
200    error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]"
201}
202
203# ----------------------------------------------------------------------
204# USAGE: values ?<name>?
205#
206# Returns a list {xvec yvec} for the specified field component <name>.
207# If the name is not specified, then it returns the vectors for the
208# overall field (sum of all components).
209# ----------------------------------------------------------------------
210itcl::body Rappture::Field::values {{what -overall}} {
211    if {$what == "component0"} {
212        set what "component"
213    }
214    if {[info exists _comp2xy($what)]} {
215        return [lindex $_comp2xy($what) 1]  ;# return yv
216    }
217    if { [info exists _comp2vtk($what)] } {
218        return [lindex $_comp2vtk($what) 1]  ;# return vtkFloatArray
219    }
220    if {[info exists _comp2dx($what)]} {
221        return $_comp2dx($what)  ;# return gzipped, base64-encoded DX data
222    }
223    if {[info exists _comp2unirect2d($what)]} {
224        return [$_comp2unirect2d($what) values]
225    }
226    if {[info exists _comp2unirect3d($what)]} {
227        return [$_comp2unirect3d($what) blob]
228    }
229    error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]"
230}
231
232# ----------------------------------------------------------------------
233# USAGE: blob ?<name>?
234#
235# Returns a string representing the blob of data for the mesh and values.
236# ----------------------------------------------------------------------
237itcl::body Rappture::Field::blob {{what -overall}} {
238    if {$what == "component0"} {
239        set what "component"
240    }
241    if {[info exists _comp2xy($what)]} {
242        return ""
243    }
244    if { [info exists _comp2vtk($what)] } {
245        return ""
246    }
247    if {[info exists _comp2dx($what)]} {
248        return $_comp2dx($what)  ;# return gzipped, base64-encoded DX data
249    }
250    if {[info exists _comp2unirect2d($what)]} {
251        set mobj $_comp2unirect2d($what)
252        return [$mobj blob]
253    }
254    if {[info exists _comp2unirect3d($what)]} {
255        set mobj $_comp2unirect3d($what)
256        return [$mobj blob]
257    }
258    error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]"
259}
260
261# ----------------------------------------------------------------------
262# USAGE: limits <axis>
263#
264# Returns a list {min max} representing the limits for the specified
265# axis.
266# ----------------------------------------------------------------------
267itcl::body Rappture::Field::limits {which} {
268    set min ""
269    set max ""
270
271    blt::vector create tmp zero
272    foreach comp [array names _comp2dims] {
273        switch -- $_comp2dims($comp) {
274            1D {
275                switch -- $which {
276                    x - xlin { set pos 0; set log 0; set axis xaxis }
277                    xlog { set pos 0; set log 1; set axis xaxis }
278                    y - ylin - v - vlin { set pos 1; set log 0; set axis yaxis }
279                    ylog - vlog { set pos 1; set log 1; set axis yaxis }
280                    default {
281                        error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog"
282                    }
283                }
284
285                set vname [lindex $_comp2xy($comp) $pos]
286                $vname variable vec
287
288                if {$log} {
289                    # on a log scale, use abs value and ignore 0's
290                    $vname dup tmp
291                    $vname dup zero
292                    zero expr {tmp == 0}            ;# find the 0's
293                    tmp expr {abs(tmp)}             ;# get the abs value
294                    tmp expr {tmp + zero*max(tmp)}  ;# replace 0's with abs max
295                    set vmin [blt::vector expr min(tmp)]
296                    set vmax [blt::vector expr max(tmp)]
297                } else {
298                    set vmin $vec(min)
299                    set vmax $vec(max)
300                }
301
302                if {"" == $min} {
303                    set min $vmin
304                } elseif {$vmin < $min} {
305                    set min $vmin
306                }
307                if {"" == $max} {
308                    set max $vmax
309                } elseif {$vmax > $max} {
310                    set max $vmax
311                }
312            }
313            2D - 3D {
314                if {[info exists _comp2unirect2d($comp)]} {
315                    set limits [$_comp2unirect2d($comp) limits $which]
316                    foreach {vmin vmax} $limits break
317                    set axis vaxis
318                } elseif {[info exists _comp2unirect3d($comp)]} {
319                    set limits [$_comp2unirect3d($comp) limits $which]
320                    foreach {vmin vmax} $limits break
321                    set axis vaxis
322                } elseif {[info exists _comp2vtk($comp)]} {
323                    foreach {xv yv} $_comp2vtk($comp) break
324                    switch -- $which {
325                        x - xlin - xlog {
326                            foreach {vmin vmax} [$xv limits x] break
327                            set axis xaxis
328                        }
329                        y - ylin - ylog {
330                            foreach {vmin vmax} [$xv limits y] break
331                            set axis yaxis
332                        }
333                        z - zlin - zlog {
334                            foreach {vmin vmax} [$xv limits z] break
335                            set axis zaxis
336                        }
337                        v - vlin - vlog {
338                            catch {unset style}
339                            array set style $_comp2style($comp)
340                            if {[info exists style(-min)] && [info exists style(-max)]} {
341                                # This component has its own hard-coded
342                                # min/max range.  Ignore it for overall limits.
343                                set vmin $min
344                                set vmax $max
345                            } else {
346                                foreach {vmin vmax} [$yv GetRange] break
347                            }
348                            set axis vaxis
349                        }
350                        default {
351                            error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog"
352                        }
353                    }
354                } else {
355                    set vmin 0  ;# HACK ALERT! must be OpenDX data
356                    set vmax 1
357                    set axis vaxis
358                }
359            }
360        }
361        if {"" == $min} {
362            set min $vmin
363        } elseif {$vmin < $min} {
364            set min $vmin
365        }
366        if {"" == $max} {
367            set max $vmax
368        } elseif {$vmax > $max} {
369            set max $vmax
370        }
371    }
372    blt::vector destroy tmp zero
373
374    set val [$_field get $axis.min]
375    if {"" != $val && "" != $min} {
376        if {$val > $min} {
377            # tool specified this min -- don't go any lower
378            set min $val
379        }
380    }
381
382    set val [$_field get $axis.max]
383    if {"" != $val && "" != $max} {
384        if {$val < $max} {
385            # tool specified this max -- don't go any higher
386            set max $val
387        }
388    }
389    return [list $min $max]
390}
391
392# ----------------------------------------------------------------------
393# USAGE: controls get ?<name>?
394# USAGE: controls validate <path> <value>
395# USAGE: controls put <path> <value>
396#
397# Returns a list {path1 x1 y1 val1  path2 x2 y2 val2 ...} representing
398# control points for the specified field component <name>.
399# ----------------------------------------------------------------------
400itcl::body Rappture::Field::controls {option args} {
401    switch -- $option {
402        get {
403            set what [lindex $args 0]
404            if {[info exists _comp2cntls($what)]} {
405                return $_comp2cntls($what)
406            }
407            return ""
408        }
409        validate {
410            set path [lindex $args 0]
411            set value [lindex $args 1]
412            set units [$_xmlobj get $path.units]
413
414            if {"" != $units} {
415                set nv [Rappture::Units::convert \
416                    $value -context $units -to $units -units off]
417            } else {
418                set nv $value
419            }
420            if {![string is double $nv]
421                  || [regexp -nocase {^(inf|nan)$} $nv]} {
422                error "Value out of range"
423            }
424
425            set rawmin [$_xmlobj get $path.min]
426            if {"" != $rawmin} {
427                set minv $rawmin
428                if {"" != $units} {
429                    set minv [Rappture::Units::convert \
430                        $minv -context $units -to $units -units off]
431                    set nv [Rappture::Units::convert \
432                        $value -context $units -to $units -units off]
433                }
434                # fix for the case when the user tries to
435                # compare values like minv=-500 nv=-0600
436                set nv [format "%g" $nv]
437                set minv [format "%g" $minv]
438
439                if {$nv < $minv} {
440                    error "Minimum value allowed here is $rawmin"
441                }
442            }
443
444            set rawmax [$_xmlobj get $path.max]
445            if {"" != $rawmax} {
446                set maxv $rawmax
447                if {"" != $units} {
448                    set maxv [Rappture::Units::convert \
449                        $maxv -context $units -to $units -units off]
450                    set nv [Rappture::Units::convert \
451                        $value -context $units -to $units -units off]
452                }
453                # fix for the case when the user tries to
454                # compare values like maxv=-500 nv=-0600
455                set nv [format "%g" $nv]
456                set maxv [format "%g" $maxv]
457
458                if {$nv > $maxv} {
459                    error "Maximum value allowed here is $rawmax"
460                }
461            }
462
463            return "ok"
464        }
465        put {
466            set path [lindex $args 0]
467            set value [lindex $args 1]
468            $_xmlobj put $path.current $value
469            _build
470        }
471        default {
472            error "bad option \"$option\": should be get or put"
473        }
474    }
475}
476
477# ----------------------------------------------------------------------
478# USAGE: hints ?<keyword>?
479#
480# Returns a list of key/value pairs for various hints about plotting
481# this field.  If a particular <keyword> is specified, then it returns
482# the hint for that <keyword>, if it exists.
483# ----------------------------------------------------------------------
484itcl::body Rappture::Field::hints {{keyword ""}} {
485    foreach {key path} {
486        group   about.group
487        label   about.label
488        color   about.color
489        style   about.style
490        scale   about.scale
491        units   units
492        updir   updir
493        camera  camera.position
494    } {
495        set str [$_field get $path]
496        if {"" != $str} {
497            set hints($key) $str
498        }
499    }
500
501    # to be compatible with curve objects
502    set hints(xlabel) "Position"
503
504    if {[info exists hints(group)] && [info exists hints(label)]} {
505        # pop-up help for each curve
506        set hints(tooltip) $hints(label)
507    }
508
509    if {$keyword != ""} {
510        if {[info exists hints($keyword)]} {
511            return $hints($keyword)
512        }
513        return ""
514    }
515    return [array get hints]
516}
517
518# ----------------------------------------------------------------------
519# USAGE: _build
520#
521# Used internally to build up the vector representation for the
522# field when the object is first constructed, or whenever the field
523# data changes.  Discards any existing vectors and builds everything
524# from scratch.
525# ----------------------------------------------------------------------
526itcl::body Rappture::Field::_build {} {
527    # discard any existing data
528    foreach name [array names _comp2xy] {
529        eval blt::vector destroy $_comp2xy($name)
530    }
531    foreach name [array names _comp2vtk] {
532        set mobj [lindex $_comp2vtk($name) 0]
533        set class [$mobj info class]
534        ${class}::release $mobj
535
536        set fobj [lindex $_comp2vtk($name) 1]
537        rename $fobj ""
538    }
539    foreach name [array names _comp2unirect2d] {
540        eval itcl::delete object $_comp2unirect2d($name)
541    }
542    foreach name [array names _comp2unirect3d] {
543        eval itcl::delete object $_comp2unirect3d($name)
544    }
545    catch {unset _comp2xy}
546    catch {unset _comp2vtk}
547    catch {unset _comp2dx}
548    catch {unset _comp2dims}
549    catch {unset _comp2style}
550    array unset _comp2unirect2d
551    array unset _comp2unirect3d
552    array unset _comp2extents
553    #
554    # Scan through the components of the field and create
555    # vectors for each part.
556    #
557    foreach cname [$_field children -type component] {
558        set type ""
559        if { ([$_field element $cname.constant] != "" &&
560            [$_field element $cname.domain] != "") ||
561            [$_field element $cname.xy] != ""} {
562            set type "1D"
563        } elseif {[$_field element $cname.mesh] != "" &&
564            [$_field element $cname.values] != ""} {
565            set type "points-on-mesh"
566        } elseif {[$_field element $cname.vtk] != ""} {
567            set type "vtk"
568        } elseif {[$_field element $cname.opendx] != ""} {
569            set type "opendx"
570        } elseif {[$_field element $cname.dx] != ""} {
571            set type "dx"
572        }
573        set _comp2style($cname) ""
574       
575        # Save the extents of the component
576        if { [$_field element $cname.extents] != "" } {
577            set extents [$_field get $cname.extents]
578        } else {
579            set extents 1
580        }
581        set _comp2extents($cname) $extents
582
583        if {$type == "1D"} {
584            #
585            # 1D data can be represented as 2 BLT vectors,
586            # one for x and the other for y.
587            #
588            set xv ""
589            set yv ""
590
591            set val [$_field get $cname.constant]
592            if {$val != ""} {
593                set domain [$_field get $cname.domain]
594                if {$domain == "" || ![info exists _limits($domain)]} {
595                    set z0 0
596                    set z1 $_zmax
597                } else {
598                    foreach {z0 z1} $_limits($domain) { break }
599                }
600                set xv [blt::vector create x$_counter]
601                $xv append $z0 $z1
602
603                foreach {val pcomp} [_getValue $val] break
604                set yv [blt::vector create y$_counter]
605                $yv append $val $val
606
607                if {$pcomp != ""} {
608                    set zm [expr {0.5*($z0+$z1)}]
609                    set _comp2cntls($cname) \
610                        [list $pcomp $zm $val "$val$_units"]
611                }
612            } else {
613                set xydata [$_field get $cname.xy]
614                if {"" != $xydata} {
615                    set xv [blt::vector create x$_counter]
616                    set yv [blt::vector create y$_counter]
617                    set tmp [blt::vector create \#auto]
618                    $tmp set $xydata
619                    $tmp split $xv $yv
620                    blt::vector destroy $tmp
621                }
622            }
623
624            if {$xv != "" && $yv != ""} {
625                # sort x-coords in increasing order
626                $xv sort $yv
627
628                set _comp2dims($cname) "1D"
629                set _comp2xy($cname) [list $xv $yv]
630                incr _counter
631            }
632        } elseif {$type == "points-on-mesh"} {
633            #
634            # More complex 2D/3D data is represented by a mesh
635            # object and an associated vtkFloatArray for field
636            # values.
637            #
638            set path [$_field get $cname.mesh]
639            if {[$_xmlobj element $path] != ""} {
640                set element [$_xmlobj element -as type $path]
641                puts stderr "element is $element"
642                if { $element == "unirect2d" } {
643                    set _comp2dims($cname) "2D"
644                    set _comp2unirect2d($cname) \
645                        [Rappture::Unirect2d \#auto $_xmlobj $_field $cname]
646                    set _comp2style($cname) [$_field get $cname.style]
647                    if {[$_field element $cname.flow] != ""} {
648                        set _comp2flowhints($cname) \
649                            [Rappture::FlowHints ::\#auto $_field $cname $_units]
650                    }
651                    incr _counter
652                } elseif { $element == "unirect3d" } {
653                    set _comp2dims($cname) "3D"
654                    set _comp2unirect3d($cname) \
655                        [Rappture::Unirect3d \#auto $_xmlobj $_field $cname]
656                    set _comp2style($cname) [$_field get $cname.style]
657                    if {[$_field element $cname.flow] != ""} {
658                        set _comp2flowhints($cname) \
659                            [Rappture::FlowHints ::\#auto $_field $cname $_units]
660                    }
661                    incr _counter
662                } elseif { $element == "cloud" || $element == "mesh" } {
663                    switch -- $element {
664                        cloud {
665                            set mobj [Rappture::Cloud::fetch $_xmlobj $path]
666                        }
667                        mesh {
668                            set mobj [Rappture::Mesh::fetch $_xmlobj $path]
669                        }
670                    }
671                    if {[$mobj dimensions] > 1} {
672                        #
673                        # 2D/3D data
674                        # Store cloud/field as components
675                        #
676                        set values [$_field get $cname.values]
677                        set farray [vtkFloatArray ::vals$_counter]
678
679                        foreach v $values {
680                            if {"" != $_units} {
681                                set v [Rappture::Units::convert $v \
682                                   -context $_units -to $_units -units off]
683                            }
684                            $farray InsertNextValue $v
685                        }
686
687                        set _comp2dims($cname) "[$mobj dimensions]D"
688                        set _comp2vtk($cname) [list $mobj $farray]
689                        set _comp2style($cname) [$_field get $cname.style]
690                        incr _counter
691                    } else {
692                        #
693                        # OOPS!  This is 1D data
694                        # Forget the cloud/field -- store BLT vectors
695                        #
696                        set xv [blt::vector create x$_counter]
697                        set yv [blt::vector create y$_counter]
698
699                        set vtkpts [$mobj points]
700                        set max [$vtkpts GetNumberOfPoints]
701                        for {set i 0} {$i < $max} {incr i} {
702                            set xval [lindex [$vtkpts GetPoint $i] 0]
703                            $xv append $xval
704                        }
705                        set class [$mobj info class]
706                        ${class}::release $mobj
707
708                        set values [$_field get $cname.values]
709                        foreach yval $values {
710                            if {"" != $_units} {
711                                set yval [Rappture::Units::convert $yval \
712                                      -context $_units -to $_units -units off]
713                            }
714                            $yv append $yval
715                        }
716
717                        # sort x-coords in increasing order
718                        $xv sort $yv
719
720                        set _comp2dims($cname) "1D"
721                        set _comp2xy($cname) [list $xv $yv]
722                        incr _counter
723                    }
724                }
725            } else {
726                puts "WARNING: can't find mesh $path for field component"
727            }
728        } elseif {$type == "vtk"} {
729            #
730            # Extract native vtk data from the XML and use a reader
731            # to load it.
732            #
733            vtkRectilinearGridReader $this-gr
734            $this-gr SetInputString [$_field get $cname.vtk]
735
736
737            set _comp2dims($cname) "[$mobj dimensions]D"
738            set _comp2vtk($cname) [list $mobj $farray]
739            set _comp2style($cname) [$_field get $cname.style]
740            incr _counter
741        } elseif {$type == "dx"} {
742            #
743            # HACK ALERT!  Extract gzipped, base64-encoded OpenDX
744            # data.  Assume that it's 3D.  Pass it straight
745            # off to the NanoVis visualizer.
746            #
747            set _comp2dims($cname) "3D"
748            set _comp2dx($cname)  [$_field get -decode no $cname.dx]
749            set _comp2style($cname) [$_field get $cname.style]
750            if {[$_field element $cname.flow] != ""} {
751                set _comp2flowhints($cname) \
752                    [Rappture::FlowHints ::\#auto $_field $cname $_units]
753            }
754            incr _counter
755        } elseif {$type == "opendx"} {
756            #
757            # HACK ALERT!  Extract gzipped, base64-encoded OpenDX
758            # data.  Assume that it's 3D.  Pass it straight
759            # off to the NanoVis visualizer.
760            #
761            set _comp2dims($cname) "3D"
762            set data [$_field get -decode yes $cname.opendx]
763            set data [Rappture::encoding::decode -as zb64 $data]
764
765            set data "<ODX>$data"
766            set data [Rappture::encoding::encode -as zb64 $data]
767            set _comp2dx($cname) $data
768            set _comp2style($cname) [$_field get $cname.style]
769            if {[$_field element $cname.flow] != ""} {
770                set _comp2flowhints($cname) \
771                    [Rapture::FlowHints ::\#auto $_field $cname $_units]
772            }
773            incr _counter
774        }
775    }
776}
777
778# ----------------------------------------------------------------------
779# USAGE: _getValue <expr>
780#
781# Used internally to get the value for an expression <expr>.  Returns
782# a list of the form {val parameterPath}, where val is the numeric
783# value of the expression, and parameterPath is the XML path to the
784# parameter representing the value, or "" if the <expr> does not
785# depend on any parameters.
786# ----------------------------------------------------------------------
787itcl::body Rappture::Field::_getValue {expr} {
788    #
789    # First, look for the expression among the <parameter>'s
790    # associated with the device.
791    #
792    set found 0
793    foreach pcomp [$_xmlobj children parameters] {
794        set id [$_xmlobj element -as id parameters.$pcomp]
795        if {[string equal $id $expr]} {
796            set val [$_xmlobj get parameters.$pcomp.current]
797            if {"" == $val} {
798                set val [$_xmlobj get parameters.$pcomp.default]
799            }
800            if {"" != $val} {
801                set expr $val
802                set found 1
803                break
804            }
805        }
806    }
807    if {$found} {
808        set pcomp "parameters.$pcomp"
809    } else {
810        set pcomp ""
811    }
812
813    if {$_units != ""} {
814        set expr [Rappture::Units::convert $expr \
815            -context $_units -to $_units -units off]
816    }
817
818    return [list $expr $pcomp]
819}
820
821#
822# isunirect2d  --
823#
824# Returns if the field is a unirect2d object. 
825#
826itcl::body Rappture::Field::isunirect2d { } {
827    return [expr [array size _comp2unirect2d] > 0]
828}
829
830#
831# isunirect3d  --
832#
833# Returns if the field is a unirect3d object. 
834#
835itcl::body Rappture::Field::isunirect3d { } {
836    return [expr [array size _comp2unirect3d] > 0]
837}
838
839#
840# flowhints  --
841#
842# Returns the hints associated with a flow vector field. 
843#
844itcl::body Rappture::Field::flowhints { cname } {
845    if { [info exists _comp2flowhints($cname)] } {
846        return $_comp2flowhints($cname)
847    }
848    return ""
849}
850
851#
852# extents --
853#
854# Returns if the field is a unirect2d object. 
855#
856itcl::body Rappture::Field::extents {{what -overall}} {
857    if {$what == "-overall" } {
858        set max 0
859        foreach cname [$_field children -type component] {
860            if { [info exists _comp2unirect3d($cname)] } {
861                set value [$_comp2unirect3d($cname) components]
862            } elseif { [info exists _comp2unirect2d($cname)] } {
863                set value [$_comp2unirect2d($cname) components]
864            } elseif { [info exists _comp2extents($cname)] } {
865                set value $_comp2extents($cname)
866            } else {
867                continue
868            }
869            if { $max < $value } {
870                set max $value
871            }
872        }
873        return $max
874    }
875    if { $what == "component0"} {
876        set what [lindex [components -name] 0]
877        if { [info exists _comp2unirect3d($what)] } {
878            return [$_comp2unirect3d($what) components]
879        } elseif { [info exists _comp2unirect2d($what)] } {
880            return [$_comp2unirect2d($what) components]
881        } elseif { [info exists _comp2extents($what)] } {
882            return $_comp2extents($what)
883        }
884    }
885    return $_comp2extents($what)
886}
Note: See TracBrowser for help on using the repository browser.