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

Last change on this file since 2035 was 1570, checked in by dkearney, 15 years ago

removing debug code which produced a dx file for each dx component.

File size: 30.8 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        return [$_comp2unirect2d($what) blob]
252    }
253    if {[info exists _comp2unirect3d($what)]} {
254        return [$_comp2unirect3d($what) blob]
255    }
256    error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]"
257}
258
259# ----------------------------------------------------------------------
260# USAGE: limits <axis>
261#
262# Returns a list {min max} representing the limits for the specified
263# axis.
264# ----------------------------------------------------------------------
265itcl::body Rappture::Field::limits {which} {
266    set min ""
267    set max ""
268
269    blt::vector create tmp zero
270    foreach comp [array names _comp2dims] {
271        switch -- $_comp2dims($comp) {
272            1D {
273                switch -- $which {
274                    x - xlin { set pos 0; set log 0; set axis xaxis }
275                    xlog { set pos 0; set log 1; set axis xaxis }
276                    y - ylin - v - vlin { set pos 1; set log 0; set axis yaxis }
277                    ylog - vlog { set pos 1; set log 1; set axis yaxis }
278                    default {
279                        error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog"
280                    }
281                }
282
283                set vname [lindex $_comp2xy($comp) $pos]
284                $vname variable vec
285
286                if {$log} {
287                    # on a log scale, use abs value and ignore 0's
288                    $vname dup tmp
289                    $vname dup zero
290                    zero expr {tmp == 0}            ;# find the 0's
291                    tmp expr {abs(tmp)}             ;# get the abs value
292                    tmp expr {tmp + zero*max(tmp)}  ;# replace 0's with abs max
293                    set vmin [blt::vector expr min(tmp)]
294                    set vmax [blt::vector expr max(tmp)]
295                } else {
296                    set vmin $vec(min)
297                    set vmax $vec(max)
298                }
299
300                if {"" == $min} {
301                    set min $vmin
302                } elseif {$vmin < $min} {
303                    set min $vmin
304                }
305                if {"" == $max} {
306                    set max $vmax
307                } elseif {$vmax > $max} {
308                    set max $vmax
309                }
310            }
311            2D - 3D {
312                if {[info exists _comp2unirect2d($comp)]} {
313                    set limits [$_comp2unirect2d($comp) limits $which]
314                    foreach {vmin vmax} $limits break
315                    set axis vaxis
316                } elseif {[info exists _comp2unirect3d($comp)]} {
317                    set limits [$_comp2unirect3d($comp) limits $which]
318                    foreach {vmin vmax} $limits break
319                    set axis vaxis
320                } elseif {[info exists _comp2vtk($comp)]} {
321                    foreach {xv yv} $_comp2vtk($comp) break
322                    switch -- $which {
323                        x - xlin - xlog {
324                            foreach {vmin vmax} [$xv limits x] break
325                            set axis xaxis
326                        }
327                        y - ylin - ylog {
328                            foreach {vmin vmax} [$xv limits y] break
329                            set axis yaxis
330                        }
331                        z - zlin - zlog {
332                            foreach {vmin vmax} [$xv limits z] break
333                            set axis zaxis
334                        }
335                        v - vlin - vlog {
336                            catch {unset style}
337                            array set style $_comp2style($comp)
338                            if {[info exists style(-min)] && [info exists style(-max)]} {
339                                # This component has its own hard-coded
340                                # min/max range.  Ignore it for overall limits.
341                                set vmin $min
342                                set vmax $max
343                            } else {
344                                foreach {vmin vmax} [$yv GetRange] break
345                            }
346                            set axis vaxis
347                        }
348                        default {
349                            error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog"
350                        }
351                    }
352                } else {
353                    set vmin 0  ;# HACK ALERT! must be OpenDX data
354                    set vmax 1
355                    set axis vaxis
356                }
357            }
358        }
359        if {"" == $min} {
360            set min $vmin
361        } elseif {$vmin < $min} {
362            set min $vmin
363        }
364        if {"" == $max} {
365            set max $vmax
366        } elseif {$vmax > $max} {
367            set max $vmax
368        }
369    }
370    blt::vector destroy tmp zero
371
372    set val [$_field get $axis.min]
373    if {"" != $val && "" != $min} {
374        if {$val > $min} {
375            # tool specified this min -- don't go any lower
376            set min $val
377        }
378    }
379
380    set val [$_field get $axis.max]
381    if {"" != $val && "" != $max} {
382        if {$val < $max} {
383            # tool specified this max -- don't go any higher
384            set max $val
385        }
386    }
387    return [list $min $max]
388}
389
390# ----------------------------------------------------------------------
391# USAGE: controls get ?<name>?
392# USAGE: controls validate <path> <value>
393# USAGE: controls put <path> <value>
394#
395# Returns a list {path1 x1 y1 val1  path2 x2 y2 val2 ...} representing
396# control points for the specified field component <name>.
397# ----------------------------------------------------------------------
398itcl::body Rappture::Field::controls {option args} {
399    switch -- $option {
400        get {
401            set what [lindex $args 0]
402            if {[info exists _comp2cntls($what)]} {
403                return $_comp2cntls($what)
404            }
405            return ""
406        }
407        validate {
408            set path [lindex $args 0]
409            set value [lindex $args 1]
410            set units [$_xmlobj get $path.units]
411
412            if {"" != $units} {
413                set nv [Rappture::Units::convert \
414                    $value -context $units -to $units -units off]
415            } else {
416                set nv $value
417            }
418            if {![string is double $nv]
419                  || [regexp -nocase {^(inf|nan)$} $nv]} {
420                error "Value out of range"
421            }
422
423            set rawmin [$_xmlobj get $path.min]
424            if {"" != $rawmin} {
425                set minv $rawmin
426                if {"" != $units} {
427                    set minv [Rappture::Units::convert \
428                        $minv -context $units -to $units -units off]
429                    set nv [Rappture::Units::convert \
430                        $value -context $units -to $units -units off]
431                }
432                # fix for the case when the user tries to
433                # compare values like minv=-500 nv=-0600
434                set nv [format "%g" $nv]
435                set minv [format "%g" $minv]
436
437                if {$nv < $minv} {
438                    error "Minimum value allowed here is $rawmin"
439                }
440            }
441
442            set rawmax [$_xmlobj get $path.max]
443            if {"" != $rawmax} {
444                set maxv $rawmax
445                if {"" != $units} {
446                    set maxv [Rappture::Units::convert \
447                        $maxv -context $units -to $units -units off]
448                    set nv [Rappture::Units::convert \
449                        $value -context $units -to $units -units off]
450                }
451                # fix for the case when the user tries to
452                # compare values like maxv=-500 nv=-0600
453                set nv [format "%g" $nv]
454                set maxv [format "%g" $maxv]
455
456                if {$nv > $maxv} {
457                    error "Maximum value allowed here is $rawmax"
458                }
459            }
460
461            return "ok"
462        }
463        put {
464            set path [lindex $args 0]
465            set value [lindex $args 1]
466            $_xmlobj put $path.current $value
467            _build
468        }
469        default {
470            error "bad option \"$option\": should be get or put"
471        }
472    }
473}
474
475# ----------------------------------------------------------------------
476# USAGE: hints ?<keyword>?
477#
478# Returns a list of key/value pairs for various hints about plotting
479# this field.  If a particular <keyword> is specified, then it returns
480# the hint for that <keyword>, if it exists.
481# ----------------------------------------------------------------------
482itcl::body Rappture::Field::hints {{keyword ""}} {
483    foreach {key path} {
484        group   about.group
485        label   about.label
486        color   about.color
487        style   about.style
488        scale   about.scale
489        units   units
490        updir   updir
491        camera  camera.position
492    } {
493        set str [$_field get $path]
494        if {"" != $str} {
495            set hints($key) $str
496        }
497    }
498
499    # to be compatible with curve objects
500    set hints(xlabel) "Position"
501
502    if {[info exists hints(group)] && [info exists hints(label)]} {
503        # pop-up help for each curve
504        set hints(tooltip) $hints(label)
505    }
506
507    if {$keyword != ""} {
508        if {[info exists hints($keyword)]} {
509            return $hints($keyword)
510        }
511        return ""
512    }
513    return [array get hints]
514}
515
516# ----------------------------------------------------------------------
517# USAGE: _build
518#
519# Used internally to build up the vector representation for the
520# field when the object is first constructed, or whenever the field
521# data changes.  Discards any existing vectors and builds everything
522# from scratch.
523# ----------------------------------------------------------------------
524itcl::body Rappture::Field::_build {} {
525    # discard any existing data
526    foreach name [array names _comp2xy] {
527        eval blt::vector destroy $_comp2xy($name)
528    }
529    foreach name [array names _comp2vtk] {
530        set mobj [lindex $_comp2vtk($name) 0]
531        set class [$mobj info class]
532        ${class}::release $mobj
533
534        set fobj [lindex $_comp2vtk($name) 1]
535        rename $fobj ""
536    }
537    foreach name [array names _comp2unirect2d] {
538        eval itcl::delete object $_comp2unirect2d($name)
539    }
540    foreach name [array names _comp2unirect3d] {
541        eval itcl::delete object $_comp2unirect3d($name)
542    }
543    catch {unset _comp2xy}
544    catch {unset _comp2vtk}
545    catch {unset _comp2dx}
546    catch {unset _comp2dims}
547    catch {unset _comp2style}
548    array unset _comp2unirect2d
549    array unset _comp2unirect3d
550    array unset _comp2extents
551    #
552    # Scan through the components of the field and create
553    # vectors for each part.
554    #
555    foreach cname [$_field children -type component] {
556        set type ""
557        if { ([$_field element $cname.constant] != "" &&
558            [$_field element $cname.domain] != "") ||
559            [$_field element $cname.xy] != ""} {
560            set type "1D"
561        } elseif {[$_field element $cname.mesh] != "" &&
562            [$_field element $cname.values] != ""} {
563            set type "points-on-mesh"
564        } elseif {[$_field element $cname.vtk] != ""} {
565            set type "vtk"
566        } elseif {[$_field element $cname.opendx] != ""} {
567            set type "opendx"
568        } elseif {[$_field element $cname.dx] != ""} {
569            set type "dx"
570        }
571        set _comp2style($cname) ""
572       
573        # Save the extents of the component
574        if { [$_field element $cname.extents] != "" } {
575            set extents [$_field get $cname.extents]
576        } else {
577            set extents 1
578        }
579        set _comp2extents($cname) $extents
580
581        if {$type == "1D"} {
582            #
583            # 1D data can be represented as 2 BLT vectors,
584            # one for x and the other for y.
585            #
586            set xv ""
587            set yv ""
588
589            set val [$_field get $cname.constant]
590            if {$val != ""} {
591                set domain [$_field get $cname.domain]
592                if {$domain == "" || ![info exists _limits($domain)]} {
593                    set z0 0
594                    set z1 $_zmax
595                } else {
596                    foreach {z0 z1} $_limits($domain) { break }
597                }
598                set xv [blt::vector create x$_counter]
599                $xv append $z0 $z1
600
601                foreach {val pcomp} [_getValue $val] break
602                set yv [blt::vector create y$_counter]
603                $yv append $val $val
604
605                if {$pcomp != ""} {
606                    set zm [expr {0.5*($z0+$z1)}]
607                    set _comp2cntls($cname) \
608                        [list $pcomp $zm $val "$val$_units"]
609                }
610            } else {
611                set xydata [$_field get $cname.xy]
612                if {"" != $xydata} {
613                    set xv [blt::vector create x$_counter]
614                    set yv [blt::vector create y$_counter]
615                    set tmp [blt::vector create \#auto]
616                    $tmp set $xydata
617                    $tmp split $xv $yv
618                    blt::vector destroy $tmp
619                }
620            }
621
622            if {$xv != "" && $yv != ""} {
623                # sort x-coords in increasing order
624                $xv sort $yv
625
626                set _comp2dims($cname) "1D"
627                set _comp2xy($cname) [list $xv $yv]
628                incr _counter
629            }
630        } elseif {$type == "points-on-mesh"} {
631            #
632            # More complex 2D/3D data is represented by a mesh
633            # object and an associated vtkFloatArray for field
634            # values.
635            #
636            set path [$_field get $cname.mesh]
637            if {[$_xmlobj element $path] != ""} {
638                set element [$_xmlobj element -as type $path]
639                if { $element == "unirect2d" } {
640                    set _comp2dims($cname) "2D"
641                    set _comp2unirect2d($cname) \
642                        [Rappture::Unirect2d \#auto $_xmlobj $_field $cname \
643                             $extents]
644                    set _comp2style($cname) [$_field get $cname.style]
645                    if {[$_field element $cname.flow] != ""} {
646                        set _comp2flowhints($cname) \
647                            [Rappture::FlowHints ::\#auto $_field $cname $_units]
648                    }
649                    incr _counter
650                } elseif { $element == "unirect3d" } {
651                    set _comp2dims($cname) "3D"
652                    set _comp2unirect3d($cname) \
653                        [Rappture::Unirect3d \#auto $_xmlobj $_field $cname \
654                            $extents]
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 "<ODX>$data"
763            set data [Rappture::encoding::encode -as zb64 $data]
764            set _comp2dx($cname) $data
765            set _comp2style($cname) [$_field get $cname.style]
766            if {[$_field element $cname.flow] != ""} {
767                set _comp2flowhints($cname) \
768                    [Rapture::FlowHints ::\#auto $_field $cname $_units]
769            }
770            incr _counter
771        }
772    }
773}
774
775# ----------------------------------------------------------------------
776# USAGE: _getValue <expr>
777#
778# Used internally to get the value for an expression <expr>.  Returns
779# a list of the form {val parameterPath}, where val is the numeric
780# value of the expression, and parameterPath is the XML path to the
781# parameter representing the value, or "" if the <expr> does not
782# depend on any parameters.
783# ----------------------------------------------------------------------
784itcl::body Rappture::Field::_getValue {expr} {
785    #
786    # First, look for the expression among the <parameter>'s
787    # associated with the device.
788    #
789    set found 0
790    foreach pcomp [$_xmlobj children parameters] {
791        set id [$_xmlobj element -as id parameters.$pcomp]
792        if {[string equal $id $expr]} {
793            set val [$_xmlobj get parameters.$pcomp.current]
794            if {"" == $val} {
795                set val [$_xmlobj get parameters.$pcomp.default]
796            }
797            if {"" != $val} {
798                set expr $val
799                set found 1
800                break
801            }
802        }
803    }
804    if {$found} {
805        set pcomp "parameters.$pcomp"
806    } else {
807        set pcomp ""
808    }
809
810    if {$_units != ""} {
811        set expr [Rappture::Units::convert $expr \
812            -context $_units -to $_units -units off]
813    }
814
815    return [list $expr $pcomp]
816}
817
818#
819# isunirect2d  --
820#
821# Returns if the field is a unirect2d object. 
822#
823itcl::body Rappture::Field::isunirect2d { } {
824    return [expr [array size _comp2unirect2d] > 0]
825}
826
827#
828# isunirect3d  --
829#
830# Returns if the field is a unirect3d object. 
831#
832itcl::body Rappture::Field::isunirect3d { } {
833    return [expr [array size _comp2unirect3d] > 0]
834}
835
836#
837# flowhints  --
838#
839# Returns the hints associated with a flow vector field. 
840#
841itcl::body Rappture::Field::flowhints { cname } {
842    if { [info exists _comp2flowhints($cname)] } {
843        return $_comp2flowhints($cname)
844    }
845    return ""
846}
847
848#
849# extents --
850#
851# Returns if the field is a unirect2d object. 
852#
853itcl::body Rappture::Field::extents {{what -overall}} {
854    if {$what == "-overall" } {
855        set max 0
856        foreach cname [$_field children -type component] {
857            if { ![info exists _comp2unirect3d($cname)] &&
858                 ![info exists _comp2extents($cname)] } {
859                continue
860            }
861            set value $_comp2extents($cname)
862            if { $max < $value } {
863                set max $value
864            }
865        }
866        return $max
867    }
868    if { $what == "component0"} {
869        set what [lindex [components -name] 0]
870    }
871    return $_comp2extents($what)
872}
Note: See TracBrowser for help on using the repository browser.