source: trunk/gui/scripts/mesh.tcl @ 14

Last change on this file since 14 was 14, checked in by mmc, 19 years ago

Added a new <mesh> type and a viewer for mesh geometries.
Needed this for Prophet, and it's a little hard-coded to
their test case. Hack job, but it works. Also fixed the
tooltips so they don't hang around in strange cases.

File size: 8.5 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: mesh - represents a structured mesh for a device
3#
4#  This object represents a mesh in an XML description of simulator
5#  output.  A mesh is a structured arrangement of points, as elements
6#  composed of nodes representing coordinates.  This is a little
7#  different from a cloud, which is an unstructured arrangement
8#  (shotgun blast) of points.
9# ======================================================================
10#  AUTHOR:  Michael McLennan, Purdue University
11#  Copyright (c) 2004-2005
12#  Purdue Research Foundation, West Lafayette, IN
13# ======================================================================
14package require Itcl
15package require vtk
16
17namespace eval Rappture { # forward declaration }
18
19itcl::class Rappture::Mesh {
20    constructor {xmlobj path} { # defined below }
21    destructor { # defined below }
22
23    public method points {}
24    public method elements {}
25    public method size {}
26    public method dimensions {}
27    public method limits {which}
28    public method hints {{key ""}}
29
30    public proc fetch {xmlobj path}
31    public proc release {obj}
32
33    private variable _xmlobj ""  ;# ref to XML obj with device data
34    private variable _mesh ""    ;# lib obj representing this mesh
35
36    private variable _units "m"  ;# system of units for this mesh
37    private variable _limits     ;# limits xmin, xmax, ymin, ymax, ...
38    private variable _npts 0     ;# number of points
39    private variable _nelems 0   ;# number of elements
40
41    private common _xp2obj       ;# used for fetch/release ref counting
42    private common _obj2ref      ;# used for fetch/release ref counting
43}
44
45# ----------------------------------------------------------------------
46# USAGE: Rappture::Mesh::fetch <xmlobj> <path>
47#
48# Clients use this instead of a constructor to fetch the Mesh for
49# a particular <path> in the <xmlobj>.  When the client is done with
50# the mesh, he calls "release" to decrement the reference count.
51# When the mesh is no longer needed, it is cleaned up automatically.
52# ----------------------------------------------------------------------
53itcl::body Rappture::Mesh::fetch {xmlobj path} {
54    set handle "$xmlobj|$path"
55    if {[info exists _xp2obj($handle)]} {
56        set obj $_xp2obj($handle)
57        incr _obj2ref($obj)
58        return $obj
59    }
60
61    set obj [Rappture::Mesh ::#auto $xmlobj $path]
62    set _xp2obj($handle) $obj
63    set _obj2ref($obj) 1
64    return $obj
65}
66
67# ----------------------------------------------------------------------
68# USAGE: Rappture::Mesh::release <obj>
69#
70# Clients call this when they're no longer using a Mesh fetched
71# previously by the "fetch" proc.  This decrements the reference
72# count for the mesh and destroys the object when it is no longer
73# in use.
74# ----------------------------------------------------------------------
75itcl::body Rappture::Mesh::release {obj} {
76    if {[info exists _obj2ref($obj)]} {
77        incr _obj2ref($obj) -1
78        if {$_obj2ref($obj) <= 0} {
79            unset _obj2ref($obj)
80            foreach handle [array names _xp2obj] {
81                if {$_xp2obj($handle) == $obj} {
82                    unset _xp2obj($handle)
83                }
84            }
85            itcl::delete object $obj
86        }
87    } else {
88        error "can't find reference count for $obj"
89    }
90}
91
92# ----------------------------------------------------------------------
93# CONSTRUCTOR
94# ----------------------------------------------------------------------
95itcl::body Rappture::Mesh::constructor {xmlobj path} {
96    if {![Rappture::library isvalid $xmlobj]} {
97        error "bad value \"$xmlobj\": should be Rappture::library"
98    }
99    set _xmlobj $xmlobj
100    set _mesh [$xmlobj element -as object $path]
101
102    set u [$_mesh get units]
103    if {"" != $u} {
104        set _units $u
105    }
106
107    foreach lim {xmin xmax ymin ymax zmin zmax} {
108        set _limits($lim) ""
109    }
110
111    foreach comp [$xmlobj children -type node $path] {
112        set xyz [$xmlobj get $path.$comp]
113
114        # make sure we have x,y,z
115        while {[llength $xyz] < 3} {
116            lappend xyz "0"
117        }
118
119        # extract each point and add it to the points list
120        foreach {x y z} $xyz break
121        foreach dim {x y z} {
122            set v [Rappture::Units::convert [set $dim] \
123                -context $_units -to $_units -units off]
124
125            set $dim $v  ;# save back to real x/y/z variable
126
127            if {"" == $_limits(${dim}min)} {
128                set _limits(${dim}min) $v
129                set _limits(${dim}max) $v
130            } else {
131                if {$v < $_limits(${dim}min)} { set _limits(${dim}min) $v }
132                if {$v > $_limits(${dim}max)} { set _limits(${dim}max) $v }
133            }
134        }
135        incr _npts
136    }
137    set _nelems [llength [$xmlobj children -type element $path]]
138}
139
140# ----------------------------------------------------------------------
141# DESTRUCTOR
142# ----------------------------------------------------------------------
143itcl::body Rappture::Mesh::destructor {} {
144    # don't destroy the _xmlobj! we don't own it!
145    itcl::delete object $_mesh
146}
147
148# ----------------------------------------------------------------------
149# USAGE: points
150#
151# Returns the vtk object containing the points for this mesh.
152# ----------------------------------------------------------------------
153itcl::body Rappture::Mesh::points {} {
154    # not implemented
155    return ""
156}
157
158# ----------------------------------------------------------------------
159# USAGE: elements
160#
161# Returns a list of the form {plist r plist r ...} for each element
162# in this mesh.  Each plist is a list of {x y x y ...} coordinates
163# for the mesh.
164# ----------------------------------------------------------------------
165itcl::body Rappture::Mesh::elements {} {
166    # build a map for region number => region type
167    foreach comp [$_mesh children -type region] {
168        set id [$_mesh element -as id $comp]
169        set regions($id) [$_mesh get $comp]
170    }
171    set regions() "unknown"
172
173    set rlist ""
174    foreach comp [$_mesh children -type element] {
175        set rid [$_mesh get $comp.region]
176
177        #
178        # HACK ALERT!
179        #
180        # Prophet puts out nodes in a funny "Z" shaped order,
181        # not in proper clockwise fashion.  Switch the last
182        # two nodes for now to make them correct.
183        #
184        set nlist [$_mesh get $comp.nodes]
185        set n2 [lindex $nlist 2]
186        set n3 [lindex $nlist 3]
187        set nlist [lreplace $nlist 2 3 $n3 $n2]
188        lappend nlist [lindex $nlist 0]
189
190        set plist ""
191        foreach nid $nlist {
192            eval lappend plist [$_mesh get node($nid)]
193        }
194        lappend rlist $plist $regions($rid)
195    }
196    return $rlist
197}
198
199# ----------------------------------------------------------------------
200# USAGE: size
201#
202# Returns the number of points in this mesh.
203# ----------------------------------------------------------------------
204itcl::body Rappture::Mesh::size {} {
205    return $_npts
206}
207
208# ----------------------------------------------------------------------
209# USAGE: dimensions
210#
211# Returns the number of dimensions for this object: 1, 2, or 3.
212# ----------------------------------------------------------------------
213itcl::body Rappture::Mesh::dimensions {} {
214    # count the dimensions with real limits
215    set dims 0
216    foreach d {x y z} {
217        if {$_limits(${d}min) != $_limits(${d}max)} {
218            incr dims
219        }
220    }
221    return $dims
222}
223
224# ----------------------------------------------------------------------
225# USAGE: limits x|y|z
226#
227# Returns the {min max} values for the limits of the specified axis.
228# ----------------------------------------------------------------------
229itcl::body Rappture::Mesh::limits {which} {
230    if {![info exists _limits(${which}min)]} {
231        error "bad axis \"$which\": should be x, y, z"
232    }
233    return [list $_limits(${which}min) $_limits(${which}max)]
234}
235
236# ----------------------------------------------------------------------
237# USAGE: hints ?<keyword>?
238#
239# Returns a list of key/value pairs for various hints about plotting
240# this field.  If a particular <keyword> is specified, then it returns
241# the hint for that <keyword>, if it exists.
242# ----------------------------------------------------------------------
243itcl::body Rappture::Mesh::hints {{keyword ""}} {
244    foreach key {label color units} {
245        set str [$_mesh get $key]
246        if {"" != $str} {
247            set hints($key) $str
248        }
249    }
250
251    if {$keyword != ""} {
252        if {[info exists hints($keyword)]} {
253            return $hints($keyword)
254        }
255        return ""
256    }
257    return [array get hints]
258}
Note: See TracBrowser for help on using the repository browser.