source: trunk/gui/scripts/cloud.tcl @ 3582

Last change on this file since 3582 was 3571, checked in by gah, 11 years ago

These was are all related to the omenwire example.

o Added validity test for fields, meshes, clouds, and unirect2ds. There is

now a "isvalid" method that viewers should use to verify that the data object
can be plotted.

In some cases with fields this means that the widget won't even be created.
The resultviewer tests for the dimensionality which is by default 0.

o Thanks to Leif for pointing this out, it's not enough to check if the field

is valid. Individual components of the field may be invalid. Added check so
that viewers are never passed the names of invalid field components.

o Changed many "error" commands to just print to stderr and tolerantly deal

with the error.

File size: 8.5 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2# ----------------------------------------------------------------------
3#  COMPONENT: cloud - represents the mesh for a cloud of points
4#
5#  This object represents the mesh for a cloud of points in an XML
6#  description of a device.  It simplifies the process of extracting
7#  data that represent the mesh.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itcl
16
17namespace eval Rappture { # forward declaration }
18
19itcl::class Rappture::Cloud {
20    private variable _xmlobj "";        # ref to XML obj with device data
21    private variable _cloud "";         # lib obj representing this cloud
22    private variable _units "m m m" ;   # system of units for x, y, z
23    private variable _limits;           # limits x, y, z
24    private common _xp2obj ;            # Used for fetch/release ref counting
25    private common _obj2ref ;           # Used for fetch/release ref counting
26    private variable _numPoints 0
27    private variable _vtkdata ""
28    private variable _points ""
29    private variable _dim 0
30    private variable _isValid 0;        # Indicates if the data is valid.
31
32    constructor {xmlobj path} {
33        # defined below
34    }
35    destructor {
36        # defined below
37    }
38    public method points {}
39    public method mesh {}
40    public method vtkdata {}
41    public method size {}
42    public method dimensions {}
43    public method limits {which}
44    public method hints {{key ""}}
45    public method numpoints {} {
46        return $_numPoints
47    }
48    public method isvalid {} {
49        return $_isValid
50    }
51    public proc fetch {xmlobj path}
52    public proc release {obj}
53}
54
55# ----------------------------------------------------------------------
56# USAGE: Rappture::Cloud::fetch <xmlobj> <path>
57#
58# Clients use this instead of a constructor to fetch the Cloud for
59# a particular <path> in the <xmlobj>.  When the client is done with
60# the cloud, he calls "release" to decrement the reference count.
61# When the cloud is no longer needed, it is cleaned up automatically.
62# ----------------------------------------------------------------------
63itcl::body Rappture::Cloud::fetch {xmlobj path} {
64    set handle "$xmlobj|$path"
65    if {[info exists _xp2obj($handle)]} {
66        set obj $_xp2obj($handle)
67        incr _obj2ref($obj)
68        return $obj
69    }
70
71    set obj [Rappture::Cloud ::#auto $xmlobj $path]
72    set _xp2obj($handle) $obj
73    set _obj2ref($obj) 1
74    return $obj
75}
76
77# ----------------------------------------------------------------------
78# USAGE: Rappture::Cloud::release <obj>
79#
80# Clients call this when they're no longer using a Cloud fetched
81# previously by the "fetch" proc.  This decrements the reference
82# count for the cloud and destroys the object when it is no longer
83# in use.
84# ----------------------------------------------------------------------
85itcl::body Rappture::Cloud::release {obj} {
86    if {[info exists _obj2ref($obj)]} {
87        incr _obj2ref($obj) -1
88        if {$_obj2ref($obj) <= 0} {
89            unset _obj2ref($obj)
90            foreach handle [array names _xp2obj] {
91                if {$_xp2obj($handle) == $obj} {
92                    unset _xp2obj($handle)
93                }
94            }
95            itcl::delete object $obj
96        }
97    } else {
98        error "can't find reference count for $obj"
99    }
100}
101
102# ----------------------------------------------------------------------
103# CONSTRUCTOR
104# ----------------------------------------------------------------------
105itcl::body Rappture::Cloud::constructor {xmlobj path} {
106    if {![Rappture::library isvalid $xmlobj]} {
107        error "bad value \"$xmlobj\": should be Rappture::library"
108    }
109    set _xmlobj $xmlobj
110    set _cloud [$xmlobj element -as object $path]
111
112    set u [$_cloud get units]
113    if {"" != $u} {
114        while {[llength $u] < 3} {
115            lappend u [lindex $u end]
116        }
117        set _units $u
118    }
119
120    set _numPoints 0
121    set _points {}
122    foreach line [split [$xmlobj get $path.points] \n] {
123        if {"" == [string trim $line]} {
124            continue
125        }
126
127        set _dim [llength $line]
128        # make sure we have x,y,z
129        while {[llength $line] < 3} {
130            lappend line "0"
131        }
132
133        # Extract each point and add it to the points list
134        foreach {x y z} $line break
135        foreach axis {x y z} units $_units {
136            set value [Rappture::Units::convert [set $axis] \
137                -context $units -to $units -units off]
138
139            set $axis $value;           # Set the (x/y/z) coordinate to
140                                        # converted value.
141            if { ![info exists _limits($axis)] } {
142                set _limits($axis) [list $value $value]
143            } else {
144                foreach { min max } $_limits($axis) break
145                if {$value < $min} {
146                    set min $value
147                }
148                if {$value > $max} {
149                    set max $value
150                }
151                set _limits($axis) [list $min $max]
152            }
153        }
154        append _points "$x $y $z\n"
155        incr _numPoints
156    }
157    append out "DATASET POLYDATA\n"
158    append out "POINTS $_numPoints double\n"
159    append out $_points
160    set _vtkdata $out
161    if { $_numPoints == 0 } {
162        return
163    }
164    # Check each axis to verify that data exists
165    foreach { xmin xmax } $_limits(x) break
166    if { $xmin >= $xmax } {
167        return
168    }
169    if { $_dim > 1 } {
170        foreach { ymin ymax } $_limits(y) break
171        if { $ymin >= $ymax } {
172            return
173        }
174    }
175    if { $_dim > 2 } {
176        foreach { zmin zmax } $_limits(z) break
177        if { $zmin >= $zmax } {
178            return
179        }
180    }
181    set _isValid 1
182}
183
184# ----------------------------------------------------------------------
185# DESTRUCTOR
186# ----------------------------------------------------------------------
187itcl::body Rappture::Cloud::destructor {} {
188    # don't destroy the _xmlobj! we don't own it!
189    itcl::delete object $_cloud
190}
191
192# ----------------------------------------------------------------------
193# USAGE: points
194#
195# Returns the vtk object containing the points for this mesh.
196# ----------------------------------------------------------------------
197itcl::body Rappture::Cloud::points {} {
198    return $_points
199}
200
201# ----------------------------------------------------------------------
202# USAGE: mesh
203#
204# Returns the vtk object representing the mesh.
205# ----------------------------------------------------------------------
206itcl::body Rappture::Cloud::mesh {} {
207    return $_points
208}
209
210# ----------------------------------------------------------------------
211# USAGE: size
212#
213# Returns the number of points in this cloud.
214# ----------------------------------------------------------------------
215itcl::body Rappture::Cloud::size {} {
216    return $_numPoints
217}
218
219# ----------------------------------------------------------------------
220# USAGE: dimensions
221#
222# Returns the number of dimensions for this object: 1, 2, or 3.
223# ----------------------------------------------------------------------
224itcl::body Rappture::Cloud::dimensions {} {
225    return $_dim
226}
227
228# ----------------------------------------------------------------------
229# USAGE: limits x|y|z
230#
231# Returns the {min max} values for the limits of the specified axis.
232# ----------------------------------------------------------------------
233itcl::body Rappture::Cloud::limits { axis } {
234    if { ![info exists _limits($axis)] } {
235        error "bad axis \"$axis\": should be x, y, z"
236    }
237    return $_limits($axis)
238}
239
240# ----------------------------------------------------------------------
241# USAGE: hints ?<keyword>?
242#
243# Returns a list of key/value pairs for various hints about plotting
244# this field.  If a particular <keyword> is specified, then it returns
245# the hint for that <keyword>, if it exists.
246# ----------------------------------------------------------------------
247itcl::body Rappture::Cloud::hints {{keyword ""}} {
248    foreach key {label color units} {
249        set str [$_cloud get $key]
250        if {"" != $str} {
251            set hints($key) $str
252        }
253    }
254
255    if {$keyword != ""} {
256        if {[info exists hints($keyword)]} {
257            return $hints($keyword)
258        }
259        return ""
260    }
261    return [array get hints]
262}
263
264itcl::body Rappture::Cloud::vtkdata {} {
265    return $_vtkdata
266}
Note: See TracBrowser for help on using the repository browser.