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

Last change on this file since 1441 was 1441, checked in by gah, 12 years ago

added flow detection and flow hints

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