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

Last change on this file since 1491 was 1491, checked in by gah, 15 years ago

update for flowvisviewer: speed controls, arrows, volume checkbutton

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                if { $element == "unirect2d" } {
642                    set _comp2dims($cname) "2D"
643                    set _comp2unirect2d($cname) \
644                        [Rappture::Unirect2d \#auto $_xmlobj $_field $cname]
645                    set _comp2style($cname) [$_field get $cname.style]
646                    if {[$_field element $cname.flow] != ""} {
647                        set _comp2flowhints($cname) \
648                            [Rappture::FlowHints ::\#auto $_field $cname $_units]
649                    }
650                    incr _counter
651                } elseif { $element == "unirect3d" } {
652                    set _comp2dims($cname) "3D"
653                    set _comp2unirect3d($cname) \
654                        [Rappture::Unirect3d \#auto $_xmlobj $_field $cname]
655                    set _comp2style($cname) [$_field get $cname.style]
656                    if {[$_field element $cname.flow] != ""} {
657                        set _comp2flowhints($cname) \
658                            [Rappture::FlowHints ::\#auto $_field $cname $_units]
659                    }
660                    incr _counter
661                } elseif { $element == "cloud" || $element == "mesh" } {
662                    switch -- $element {
663                        cloud {
664                            set mobj [Rappture::Cloud::fetch $_xmlobj $path]
665                        }
666                        mesh {
667                            set mobj [Rappture::Mesh::fetch $_xmlobj $path]
668                        }
669                    }
670                    if {[$mobj dimensions] > 1} {
671                        #
672                        # 2D/3D data
673                        # Store cloud/field as components
674                        #
675                        set values [$_field get $cname.values]
676                        set farray [vtkFloatArray ::vals$_counter]
677
678                        foreach v $values {
679                            if {"" != $_units} {
680                                set v [Rappture::Units::convert $v \
681                                   -context $_units -to $_units -units off]
682                            }
683                            $farray InsertNextValue $v
684                        }
685
686                        set _comp2dims($cname) "[$mobj dimensions]D"
687                        set _comp2vtk($cname) [list $mobj $farray]
688                        set _comp2style($cname) [$_field get $cname.style]
689                        incr _counter
690                    } else {
691                        #
692                        # OOPS!  This is 1D data
693                        # Forget the cloud/field -- store BLT vectors
694                        #
695                        set xv [blt::vector create x$_counter]
696                        set yv [blt::vector create y$_counter]
697
698                        set vtkpts [$mobj points]
699                        set max [$vtkpts GetNumberOfPoints]
700                        for {set i 0} {$i < $max} {incr i} {
701                            set xval [lindex [$vtkpts GetPoint $i] 0]
702                            $xv append $xval
703                        }
704                        set class [$mobj info class]
705                        ${class}::release $mobj
706
707                        set values [$_field get $cname.values]
708                        foreach yval $values {
709                            if {"" != $_units} {
710                                set yval [Rappture::Units::convert $yval \
711                                      -context $_units -to $_units -units off]
712                            }
713                            $yv append $yval
714                        }
715
716                        # sort x-coords in increasing order
717                        $xv sort $yv
718
719                        set _comp2dims($cname) "1D"
720                        set _comp2xy($cname) [list $xv $yv]
721                        incr _counter
722                    }
723                }
724            } else {
725                puts "WARNING: can't find mesh $path for field component"
726            }
727        } elseif {$type == "vtk"} {
728            #
729            # Extract native vtk data from the XML and use a reader
730            # to load it.
731            #
732            vtkRectilinearGridReader $this-gr
733            $this-gr SetInputString [$_field get $cname.vtk]
734
735
736            set _comp2dims($cname) "[$mobj dimensions]D"
737            set _comp2vtk($cname) [list $mobj $farray]
738            set _comp2style($cname) [$_field get $cname.style]
739            incr _counter
740        } elseif {$type == "dx"} {
741            #
742            # HACK ALERT!  Extract gzipped, base64-encoded OpenDX
743            # data.  Assume that it's 3D.  Pass it straight
744            # off to the NanoVis visualizer.
745            #
746            set _comp2dims($cname) "3D"
747            set _comp2dx($cname)  [$_field get -decode no $cname.dx]
748            set _comp2style($cname) [$_field get $cname.style]
749            if {[$_field element $cname.flow] != ""} {
750                set _comp2flowhints($cname) \
751                    [Rappture::FlowHints ::\#auto $_field $cname $_units]
752            }
753            incr _counter
754        } elseif {$type == "opendx"} {
755            #
756            # HACK ALERT!  Extract gzipped, base64-encoded OpenDX
757            # data.  Assume that it's 3D.  Pass it straight
758            # off to the NanoVis visualizer.
759            #
760            set _comp2dims($cname) "3D"
761            set data [$_field get -decode yes $cname.opendx]
762            set data [Rappture::encoding::decode -as zb64 $data]
763
764            set data "<ODX>$data"
765            set data [Rappture::encoding::encode -as zb64 $data]
766            set _comp2dx($cname) $data
767            set _comp2style($cname) [$_field get $cname.style]
768            if {[$_field element $cname.flow] != ""} {
769                set _comp2flowhints($cname) \
770                    [Rapture::FlowHints ::\#auto $_field $cname $_units]
771            }
772            incr _counter
773        }
774    }
775}
776
777# ----------------------------------------------------------------------
778# USAGE: _getValue <expr>
779#
780# Used internally to get the value for an expression <expr>.  Returns
781# a list of the form {val parameterPath}, where val is the numeric
782# value of the expression, and parameterPath is the XML path to the
783# parameter representing the value, or "" if the <expr> does not
784# depend on any parameters.
785# ----------------------------------------------------------------------
786itcl::body Rappture::Field::_getValue {expr} {
787    #
788    # First, look for the expression among the <parameter>'s
789    # associated with the device.
790    #
791    set found 0
792    foreach pcomp [$_xmlobj children parameters] {
793        set id [$_xmlobj element -as id parameters.$pcomp]
794        if {[string equal $id $expr]} {
795            set val [$_xmlobj get parameters.$pcomp.current]
796            if {"" == $val} {
797                set val [$_xmlobj get parameters.$pcomp.default]
798            }
799            if {"" != $val} {
800                set expr $val
801                set found 1
802                break
803            }
804        }
805    }
806    if {$found} {
807        set pcomp "parameters.$pcomp"
808    } else {
809        set pcomp ""
810    }
811
812    if {$_units != ""} {
813        set expr [Rappture::Units::convert $expr \
814            -context $_units -to $_units -units off]
815    }
816
817    return [list $expr $pcomp]
818}
819
820#
821# isunirect2d  --
822#
823# Returns if the field is a unirect2d object. 
824#
825itcl::body Rappture::Field::isunirect2d { } {
826    return [expr [array size _comp2unirect2d] > 0]
827}
828
829#
830# isunirect3d  --
831#
832# Returns if the field is a unirect3d object. 
833#
834itcl::body Rappture::Field::isunirect3d { } {
835    return [expr [array size _comp2unirect3d] > 0]
836}
837
838#
839# flowhints  --
840#
841# Returns the hints associated with a flow vector field. 
842#
843itcl::body Rappture::Field::flowhints { cname } {
844    if { [info exists _comp2flowhints($cname)] } {
845        return $_comp2flowhints($cname)
846    }
847    return ""
848}
849
850#
851# extents --
852#
853# Returns if the field is a unirect2d object. 
854#
855itcl::body Rappture::Field::extents {{what -overall}} {
856    if {$what == "-overall" } {
857        set max 0
858        foreach cname [$_field children -type component] {
859            if { [info exists _comp2unirect3d($cname)] } {
860                set value [$_comp2unirect3d($cname) components]
861            } elseif { [info exists _comp2unirect2d($cname)] } {
862                set value [$_comp2unirect2d($cname) components]
863            } elseif { [info exists _comp2extents($cname)] } {
864                set value $_comp2extents($cname)
865            } else {
866                continue
867            }
868            if { $max < $value } {
869                set max $value
870            }
871        }
872        return $max
873    }
874    if { $what == "component0"} {
875        set what [lindex [components -name] 0]
876        if { [info exists _comp2unirect3d($what)] } {
877            return [$_comp2unirect3d($what) components]
878        } elseif { [info exists _comp2unirect2d($what)] } {
879            return [$_comp2unirect2d($what) components]
880        } elseif { [info exists _comp2extents($what)] } {
881            return $_comp2extents($what)
882        }
883    }
884    return $_comp2extents($what)
885}
Note: See TracBrowser for help on using the repository browser.