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

Last change on this file since 2395 was 2144, checked in by gah, 14 years ago

vtk-contour-viewer additions: still experimental

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        type    about.type
493    } {
494        set str [$_field get $path]
495        if {"" != $str} {
496            set hints($key) $str
497        }
498    }
499
500    # to be compatible with curve objects
501    set hints(xlabel) "Position"
502
503    if {[info exists hints(group)] && [info exists hints(label)]} {
504        # pop-up help for each curve
505        set hints(tooltip) $hints(label)
506    }
507
508    if {$keyword != ""} {
509        if {[info exists hints($keyword)]} {
510            return $hints($keyword)
511        }
512        return ""
513    }
514    return [array get hints]
515}
516
517# ----------------------------------------------------------------------
518# USAGE: _build
519#
520# Used internally to build up the vector representation for the
521# field when the object is first constructed, or whenever the field
522# data changes.  Discards any existing vectors and builds everything
523# from scratch.
524# ----------------------------------------------------------------------
525itcl::body Rappture::Field::_build {} {
526    # discard any existing data
527    foreach name [array names _comp2xy] {
528        eval blt::vector destroy $_comp2xy($name)
529    }
530    foreach name [array names _comp2vtk] {
531        set mobj [lindex $_comp2vtk($name) 0]
532        set class [$mobj info class]
533        ${class}::release $mobj
534
535        set fobj [lindex $_comp2vtk($name) 1]
536        rename $fobj ""
537    }
538    foreach name [array names _comp2unirect2d] {
539        eval itcl::delete object $_comp2unirect2d($name)
540    }
541    foreach name [array names _comp2unirect3d] {
542        eval itcl::delete object $_comp2unirect3d($name)
543    }
544    catch {unset _comp2xy}
545    catch {unset _comp2vtk}
546    catch {unset _comp2dx}
547    catch {unset _comp2dims}
548    catch {unset _comp2style}
549    array unset _comp2unirect2d
550    array unset _comp2unirect3d
551    array unset _comp2extents
552    #
553    # Scan through the components of the field and create
554    # vectors for each part.
555    #
556    foreach cname [$_field children -type component] {
557        set type ""
558        if { ([$_field element $cname.constant] != "" &&
559            [$_field element $cname.domain] != "") ||
560            [$_field element $cname.xy] != ""} {
561            set type "1D"
562        } elseif {[$_field element $cname.mesh] != "" &&
563            [$_field element $cname.values] != ""} {
564            set type "points-on-mesh"
565        } elseif {[$_field element $cname.vtk] != ""} {
566            set type "vtk"
567        } elseif {[$_field element $cname.opendx] != ""} {
568            set type "opendx"
569        } elseif {[$_field element $cname.dx] != ""} {
570            set type "dx"
571        }
572        set _comp2style($cname) ""
573       
574        # Save the extents of the component
575        if { [$_field element $cname.extents] != "" } {
576            set extents [$_field get $cname.extents]
577        } else {
578            set extents 1
579        }
580        set _comp2extents($cname) $extents
581
582        if {$type == "1D"} {
583            #
584            # 1D data can be represented as 2 BLT vectors,
585            # one for x and the other for y.
586            #
587            set xv ""
588            set yv ""
589
590            set val [$_field get $cname.constant]
591            if {$val != ""} {
592                set domain [$_field get $cname.domain]
593                if {$domain == "" || ![info exists _limits($domain)]} {
594                    set z0 0
595                    set z1 $_zmax
596                } else {
597                    foreach {z0 z1} $_limits($domain) { break }
598                }
599                set xv [blt::vector create x$_counter]
600                $xv append $z0 $z1
601
602                foreach {val pcomp} [_getValue $val] break
603                set yv [blt::vector create y$_counter]
604                $yv append $val $val
605
606                if {$pcomp != ""} {
607                    set zm [expr {0.5*($z0+$z1)}]
608                    set _comp2cntls($cname) \
609                        [list $pcomp $zm $val "$val$_units"]
610                }
611            } else {
612                set xydata [$_field get $cname.xy]
613                if {"" != $xydata} {
614                    set xv [blt::vector create x$_counter]
615                    set yv [blt::vector create y$_counter]
616                    set tmp [blt::vector create \#auto]
617                    $tmp set $xydata
618                    $tmp split $xv $yv
619                    blt::vector destroy $tmp
620                }
621            }
622
623            if {$xv != "" && $yv != ""} {
624                # sort x-coords in increasing order
625                $xv sort $yv
626
627                set _comp2dims($cname) "1D"
628                set _comp2xy($cname) [list $xv $yv]
629                incr _counter
630            }
631        } elseif {$type == "points-on-mesh"} {
632            #
633            # More complex 2D/3D data is represented by a mesh
634            # object and an associated vtkFloatArray for field
635            # values.
636            #
637            set path [$_field get $cname.mesh]
638            if {[$_xmlobj element $path] != ""} {
639                set element [$_xmlobj element -as type $path]
640                if { $element == "unirect2d" } {
641                    set _comp2dims($cname) "2D"
642                    set _comp2unirect2d($cname) \
643                        [Rappture::Unirect2d \#auto $_xmlobj $_field $cname \
644                             $extents]
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                            $extents]
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 "<ODX>$data"
764            set data [Rappture::encoding::encode -as zb64 $data]
765            set _comp2dx($cname) $data
766            set _comp2style($cname) [$_field get $cname.style]
767            if {[$_field element $cname.flow] != ""} {
768                set _comp2flowhints($cname) \
769                    [Rapture::FlowHints ::\#auto $_field $cname $_units]
770            }
771            incr _counter
772        }
773    }
774}
775
776# ----------------------------------------------------------------------
777# USAGE: _getValue <expr>
778#
779# Used internally to get the value for an expression <expr>.  Returns
780# a list of the form {val parameterPath}, where val is the numeric
781# value of the expression, and parameterPath is the XML path to the
782# parameter representing the value, or "" if the <expr> does not
783# depend on any parameters.
784# ----------------------------------------------------------------------
785itcl::body Rappture::Field::_getValue {expr} {
786    #
787    # First, look for the expression among the <parameter>'s
788    # associated with the device.
789    #
790    set found 0
791    foreach pcomp [$_xmlobj children parameters] {
792        set id [$_xmlobj element -as id parameters.$pcomp]
793        if {[string equal $id $expr]} {
794            set val [$_xmlobj get parameters.$pcomp.current]
795            if {"" == $val} {
796                set val [$_xmlobj get parameters.$pcomp.default]
797            }
798            if {"" != $val} {
799                set expr $val
800                set found 1
801                break
802            }
803        }
804    }
805    if {$found} {
806        set pcomp "parameters.$pcomp"
807    } else {
808        set pcomp ""
809    }
810
811    if {$_units != ""} {
812        set expr [Rappture::Units::convert $expr \
813            -context $_units -to $_units -units off]
814    }
815
816    return [list $expr $pcomp]
817}
818
819#
820# isunirect2d  --
821#
822# Returns if the field is a unirect2d object. 
823#
824itcl::body Rappture::Field::isunirect2d { } {
825    return [expr [array size _comp2unirect2d] > 0]
826}
827
828#
829# isunirect3d  --
830#
831# Returns if the field is a unirect3d object. 
832#
833itcl::body Rappture::Field::isunirect3d { } {
834    return [expr [array size _comp2unirect3d] > 0]
835}
836
837#
838# flowhints  --
839#
840# Returns the hints associated with a flow vector field. 
841#
842itcl::body Rappture::Field::flowhints { cname } {
843    if { [info exists _comp2flowhints($cname)] } {
844        return $_comp2flowhints($cname)
845    }
846    return ""
847}
848
849#
850# extents --
851#
852# Returns if the field is a unirect2d object. 
853#
854itcl::body Rappture::Field::extents {{what -overall}} {
855    if {$what == "-overall" } {
856        set max 0
857        foreach cname [$_field children -type component] {
858            if { ![info exists _comp2unirect3d($cname)] &&
859                 ![info exists _comp2extents($cname)] } {
860                continue
861            }
862            set value $_comp2extents($cname)
863            if { $max < $value } {
864                set max $value
865            }
866        }
867        return $max
868    }
869    if { $what == "component0"} {
870        set what [lindex [components -name] 0]
871    }
872    return $_comp2extents($what)
873}
Note: See TracBrowser for help on using the repository browser.