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

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

merge (by hand) with Rappture1.2 branch

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