source: trunk/gui/scripts/contourresult.tcl @ 13

Last change on this file since 13 was 13, checked in by mmc, 16 years ago

Many improvements, including a new energy level viewer
for Huckel-IV. Added support for a new <boolean> type.
Fixed the cloud/field stuff so that when a cloud is 1D,
it reverts to BLT vectors so it will plot correctly.
Fixed the install script to work better on Windows.

File size: 19.6 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: contourresult - contour plot in a ResultSet
3#
4#  This widget is a contour plot for 2D meshes with a scalar value.
5#  It is normally used in the ResultViewer to show results from the
6#  run of a Rappture tool.  Use the "add" and "delete" methods to
7#  control the dataobjs showing on the plot.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2005
11#  Purdue Research Foundation, West Lafayette, IN
12# ======================================================================
13package require Itk
14package require vtk
15package require vtkinteraction
16package require BLT
17
18blt::bitmap define ContourResult-reset {
19#define reset_width 12
20#define reset_height 12
21static unsigned char reset_bits[] = {
22   0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02,
23   0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00};
24}
25
26blt::bitmap define ContourResult-zoomin {
27#define zoomin_width 12
28#define zoomin_height 12
29static unsigned char zoomin_bits[] = {
30   0x7c, 0x00, 0x82, 0x00, 0x11, 0x01, 0x11, 0x01, 0x7d, 0x01, 0x11, 0x01,
31   0x11, 0x01, 0x82, 0x03, 0xfc, 0x07, 0x80, 0x0f, 0x00, 0x0f, 0x00, 0x06};
32}
33
34blt::bitmap define ContourResult-zoomout {
35#define zoomout_width 12
36#define zoomout_height 12
37static unsigned char zoomout_bits[] = {
38   0x7c, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x7d, 0x01, 0x01, 0x01,
39   0x01, 0x01, 0x82, 0x03, 0xfc, 0x07, 0x80, 0x0f, 0x00, 0x0f, 0x00, 0x06};
40}
41
42option add *ContourResult.width 4i widgetDefault
43option add *ContourResult.height 4i widgetDefault
44option add *ContourResult.foreground black widgetDefault
45option add *ContourResult.controlBackground gray widgetDefault
46option add *ContourResult.font \
47    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
48
49itcl::class Rappture::ContourResult {
50    inherit itk::Widget
51
52    itk_option define -foreground foreground Foreground ""
53    itk_option define -background background Background ""
54
55    constructor {args} { # defined below }
56    destructor { # defined below }
57
58    public method add {dataobj {settings ""}}
59    public method get {}
60    public method delete {args}
61    public method scale {args}
62
63    protected method _rebuild {}
64    protected method _zoom {option}
65    protected method _move {option x y}
66    protected method _fixLimits {}
67    protected method _color2rgb {color}
68
69    private variable _dlist ""     ;# list of data objects
70    private variable _obj2color    ;# maps dataobj => plotting color
71    private variable _obj2width    ;# maps dataobj => line width
72    private variable _obj2raise    ;# maps dataobj => raise flag 0/1
73    private variable _obj2vtk      ;# maps dataobj => vtk objects
74    private variable _actors       ;# list of actors for each renderer
75    private variable _click        ;# info used for _move operations
76    private variable _xmin ""      ;# autoscale min for x-axis
77    private variable _xmax ""      ;# autoscale max for x-axis
78    private variable _ymin ""      ;# autoscale min for y-axis
79    private variable _ymax ""      ;# autoscale max for y-axis
80    private variable _zmin ""      ;# autoscale min for z-axis
81    private variable _zmax ""      ;# autoscale max for z-axis
82
83    private common _counter 0      ;# used for auto-generated names
84}
85
86itk::usual ContourResult {
87    keep -background -foreground -cursor -font
88}
89
90# ----------------------------------------------------------------------
91# CONSTRUCTOR
92# ----------------------------------------------------------------------
93itcl::body Rappture::ContourResult::constructor {args} {
94    option add hull.width hull.height
95    pack propagate $itk_component(hull) no
96
97    itk_component add controls {
98        frame $itk_interior.cntls
99    } {
100        usual
101        rename -background -controlbackground controlBackground Background
102    }
103    pack $itk_component(controls) -side right -fill y
104
105    itk_component add reset {
106        button $itk_component(controls).reset \
107            -borderwidth 1 -padx 1 -pady 1 \
108            -bitmap ContourResult-reset \
109            -command [itcl::code $this _zoom reset]
110    } {
111        usual
112        ignore -borderwidth
113        rename -highlightbackground -controlbackground controlBackground Background
114    }
115    pack $itk_component(reset) -padx 4 -pady 4
116    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
117
118    itk_component add zoomin {
119        button $itk_component(controls).zin \
120            -borderwidth 1 -padx 1 -pady 1 \
121            -bitmap ContourResult-zoomin \
122            -command [itcl::code $this _zoom in]
123    } {
124        usual
125        ignore -borderwidth
126        rename -highlightbackground -controlbackground controlBackground Background
127    }
128    pack $itk_component(zoomin) -padx 4 -pady 4
129    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
130
131    itk_component add zoomout {
132        button $itk_component(controls).zout \
133            -borderwidth 1 -padx 1 -pady 1 \
134            -bitmap ContourResult-zoomout \
135            -command [itcl::code $this _zoom out]
136    } {
137        usual
138        ignore -borderwidth
139        rename -highlightbackground -controlbackground controlBackground Background
140    }
141    pack $itk_component(zoomout) -padx 4 -pady 4
142    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
143
144    itk_component add area {
145        frame $itk_interior.area
146    }
147    pack $itk_component(area) -expand yes -fill both
148
149    vtkRenderer $this-ren
150    vtkRenderWindow $this-renWin
151    $this-renWin AddRenderer $this-ren
152    vtkRenderWindowInteractor $this-iren
153    $this-iren SetRenderWindow $this-renWin
154
155    itk_component add plot {
156        vtkTkRenderWidget $itk_component(area).plot -rw $this-renWin \
157            -width 1 -height 1
158    } {
159    }
160    pack $itk_component(plot) -expand yes -fill both
161
162
163    vtkRenderer $this-ren2
164    vtkRenderWindow $this-renWin2
165    $this-renWin2 AddRenderer $this-ren2
166    vtkRenderWindowInteractor $this-iren2
167    $this-iren2 SetRenderWindow $this-renWin2
168
169    itk_component add legend {
170        vtkTkRenderWidget $itk_component(area).legend -rw $this-renWin2 \
171            -width 1 -height 40
172    } {
173    }
174    pack $itk_component(legend) -side bottom -fill x
175
176    eval itk_initialize $args
177
178    blt::busy hold $itk_component(area) -cursor left_ptr
179    bind $itk_component(area)_Busy <ButtonPress> \
180        [itcl::code $this _move click %x %y]
181    bind $itk_component(area)_Busy <B1-Motion> \
182        [itcl::code $this _move drag %x %y]
183    bind $itk_component(area)_Busy <ButtonRelease> \
184        [itcl::code $this _move release %x %y]
185}
186
187# ----------------------------------------------------------------------
188# DESTRUCTOR
189# ----------------------------------------------------------------------
190itcl::body Rappture::ContourResult::destructor {} {
191    rename $this-renWin ""
192    rename $this-ren ""
193    rename $this-iren ""
194
195    rename $this-renWin2 ""
196    rename $this-ren2 ""
197    rename $this-iren2 ""
198
199    after cancel [itcl::code $this _rebuild]
200}
201
202# ----------------------------------------------------------------------
203# USAGE: add <dataobj> ?<settings>?
204#
205# Clients use this to add a data object to the plot.  The optional
206# <settings> are used to configure the plot.  Allowed settings are
207# -color, -brightness, -width, -linestyle, and -raise.
208# ----------------------------------------------------------------------
209itcl::body Rappture::ContourResult::add {dataobj {settings ""}} {
210    array set params {
211        -color black
212        -width 1
213        -linestyle solid
214        -brightness 0
215        -raise 0
216    }
217    foreach {opt val} $settings {
218        if {![info exists params($opt)]} {
219            error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
220        }
221        set params($opt) $val
222    }
223
224    set pos [lsearch -exact $dataobj $_dlist]
225    if {$pos < 0} {
226        lappend _dlist $dataobj
227        set _obj2color($dataobj) $params(-color)
228        set _obj2width($dataobj) $params(-width)
229        set _obj2raise($dataobj) $params(-raise)
230
231        after cancel [itcl::code $this _rebuild]
232        after idle [itcl::code $this _rebuild]
233    }
234}
235
236# ----------------------------------------------------------------------
237# USAGE: get
238#
239# Clients use this to query the list of objects being plotted, in
240# order from bottom to top of this result.
241# ----------------------------------------------------------------------
242itcl::body Rappture::ContourResult::get {} {
243    # put the dataobj list in order according to -raise options
244    set dlist $_dlist
245    foreach obj $dlist {
246        if {[info exists _obj2raise($obj)] && $_obj2raise($obj)} {
247            set i [lsearch -exact $dlist $obj]
248            if {$i >= 0} {
249                set dlist [lreplace $dlist $i $i]
250                lappend dlist $obj
251            }
252        }
253    }
254    return $dlist
255}
256
257# ----------------------------------------------------------------------
258# USAGE: delete ?<dataobj1> <dataobj2> ...?
259#
260# Clients use this to delete a dataobj from the plot.  If no dataobjs
261# are specified, then all dataobjs are deleted.
262# ----------------------------------------------------------------------
263itcl::body Rappture::ContourResult::delete {args} {
264    if {[llength $args] == 0} {
265        set args $_dlist
266    }
267
268    # delete all specified dataobjs
269    set changed 0
270    foreach dataobj $args {
271        set pos [lsearch -exact $_dlist $dataobj]
272        if {$pos >= 0} {
273            set _dlist [lreplace $_dlist $pos $pos]
274            catch {unset _obj2color($dataobj)}
275            catch {unset _obj2width($dataobj)}
276            catch {unset _obj2raise($dataobj)}
277            set changed 1
278        }
279    }
280
281    # if anything changed, then rebuild the plot
282    if {$changed} {
283        after cancel [itcl::code $this _rebuild]
284        after idle [itcl::code $this _rebuild]
285    }
286}
287
288# ----------------------------------------------------------------------
289# USAGE: scale ?<data1> <data2> ...?
290#
291# Sets the default limits for the overall plot according to the
292# limits of the data for all of the given <data> objects.  This
293# accounts for all objects--even those not showing on the screen.
294# Because of this, the limits are appropriate for all objects as
295# the user scans through data in the ResultSet viewer.
296# ----------------------------------------------------------------------
297itcl::body Rappture::ContourResult::scale {args} {
298    set _xmin ""
299    set _xmax ""
300    set _ymin ""
301    set _ymax ""
302    set _zmin ""
303    set _zmax ""
304    foreach obj $args {
305        foreach axis {x y z} {
306            foreach {min max} [$obj limits $axis] break
307            if {"" != $min && "" != $max} {
308                if {"" == [set _${axis}min]} {
309                    set _${axis}min $min
310                    set _${axis}max $max
311                } else {
312                    if {$min < [set _${axis}min]} {
313                        set _${axis}min $min
314                    }
315                    if {$max > [set _${axis}max]} {
316                        set _${axis}max $max
317                    }
318                }
319            }
320        }
321    }
322    _fixLimits
323}
324
325# ----------------------------------------------------------------------
326# USAGE: _rebuild
327#
328# Called automatically whenever something changes that affects the
329# data in the widget.  Clears any existing data and rebuilds the
330# widget to display new data.
331# ----------------------------------------------------------------------
332itcl::body Rappture::ContourResult::_rebuild {} {
333    # clear out any old constructs
334    foreach ren [array names _actors] {
335        foreach actor $_actors($ren) {
336            $ren RemoveActor $actor
337        }
338        set _actors($ren) ""
339    }
340    foreach dataobj [array names _obj2vtk] {
341        foreach cmd $_obj2vtk($dataobj) {
342            rename $cmd ""
343        }
344        set _obj2vtk($dataobj) ""
345    }
346
347    # scan through all data objects and build the contours
348    set _counter 0
349    foreach dataobj [get] {
350        foreach comp [$dataobj components] {
351            set pd $this-polydata$_counter
352            vtkPolyData $pd
353            $pd SetPoints [$dataobj mesh $comp]
354            [$pd GetPointData] SetScalars [$dataobj values $comp]
355
356            # use _zmin/_zmax if possible, otherwise get from data
357            if {$_zmin == "" || $_zmax == ""} {
358                foreach {z0 z1} [$pd GetScalarRange] break
359            } else {
360                set z0 $_zmin
361                set z1 $_zmax
362            }
363
364            set tr $this-triangles$_counter
365            vtkDelaunay2D $tr
366            $tr SetInput $pd
367            $tr SetTolerance 0.0000000000001
368
369            set lu $this-lookup$_counter
370            vtkLookupTable $lu
371            $lu SetTableRange $z0 $z1
372            $lu SetHueRange 0.66667 0.0
373            $lu Build
374
375            lappend _obj2vtk($dataobj) $pd $tr $lu
376
377            #
378            # Add color contours.
379            #
380            if {$_counter == 0} {
381                set mp $this-mapper$_counter
382                vtkPolyDataMapper $mp
383                $mp SetInput [$tr GetOutput]
384                $mp SetScalarRange $z0 $z1
385                $mp SetLookupTable $lu
386
387                set ac $this-actor$_counter
388                vtkActor $ac
389                $ac SetMapper $mp
390                $ac SetPosition 0 0 0
391                [$ac GetProperty] SetColor 0 0 0
392                $this-ren AddActor $ac
393                lappend _actors($this-ren) $ac
394
395                lappend _obj2vtk($dataobj) $mp $ac
396            }
397
398            #
399            # Add color lines
400            #
401            if {$_counter > 0} {
402                set cf $this-clfilter$_counter
403                vtkContourFilter $cf
404                $cf SetInput [$tr GetOutput]
405                $cf GenerateValues 20 $z0 $z1
406
407                set mp $this-clmapper$_counter
408                vtkPolyDataMapper $mp
409                $mp SetInput [$cf GetOutput]
410                $mp SetScalarRange $z0 $z1
411                $mp SetLookupTable $lu
412
413                set ac $this-clactor$_counter
414                vtkActor $ac
415                $ac SetMapper $mp
416                [$ac GetProperty] SetColor 1 1 1
417                $ac SetPosition 0 0 0
418                $this-ren AddActor $ac
419                lappend _actors($this-ren) $ac
420
421                lappend _obj2vtk($dataobj) $cf $mp $ac
422            }
423
424            #
425            # Add an outline around the data
426            #
427            set olf $this-olfilter$_counter
428            vtkOutlineFilter $olf
429            $olf SetInput [$tr GetOutput]
430
431            set olm $this-olmapper$_counter
432            vtkPolyDataMapper $olm
433            $olm SetInput [$olf GetOutput]
434
435            set ola $this-olactor$_counter
436            vtkActor $ola
437            $ola SetMapper $olm
438            eval [$ola GetProperty] SetColor 0 0 0
439            $this-ren AddActor $ola
440            lappend _actors($this-ren) $ola
441
442            lappend _obj2vtk($dataobj) $olf $olm $ola
443
444            #
445            # Add a legend with the scale.
446            #
447            set lg $this-legend$_counter
448            vtkScalarBarActor $lg
449            $lg SetLookupTable $lu
450            [$lg GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
451            [$lg GetPositionCoordinate] SetValue 0.1 0.1
452            $lg SetOrientationToHorizontal
453            $lg SetWidth 0.8
454            $lg SetHeight 1.0
455
456            set tp [$lg GetLabelTextProperty]
457            eval $tp SetColor [_color2rgb $itk_option(-foreground)]
458            $tp BoldOff
459            $tp ItalicOff
460            $tp ShadowOff
461            #eval $tp SetShadowColor [_color2rgb gray]
462
463            $this-ren2 AddActor2D $lg
464            lappend _actors($this-ren2) $lg
465            lappend _obj2vtk($dataobj) $lg
466
467            incr _counter
468        }
469    }
470    _fixLimits
471}
472
473# ----------------------------------------------------------------------
474# USAGE: _zoom in
475# USAGE: _zoom out
476# USAGE: _zoom reset
477#
478# Called automatically when the user clicks on one of the zoom
479# controls for this widget.  Changes the zoom for the current view.
480# ----------------------------------------------------------------------
481itcl::body Rappture::ContourResult::_zoom {option} {
482    switch -- $option {
483        in {
484            set camera [$this-ren GetActiveCamera]
485            set zoom [$camera Zoom 1.25]
486            $this-renWin Render
487        }
488        out {
489            set camera [$this-ren GetActiveCamera]
490            set zoom [$camera Zoom 0.8]
491            $this-renWin Render
492        }
493        reset {
494            $this-ren ResetCamera
495            [$this-ren GetActiveCamera] Zoom 1.5
496            $this-renWin Render
497            $this-renWin2 Render
498        }
499    }
500}
501
502# ----------------------------------------------------------------------
503# USAGE: _move click <x> <y>
504# USAGE: _move drag <x> <y>
505# USAGE: _move release <x> <y>
506#
507# Called automatically when the user clicks/drags/releases in the
508# plot area.  Moves the plot according to the user's actions.
509# ----------------------------------------------------------------------
510itcl::body Rappture::ContourResult::_move {option x y} {
511    switch -- $option {
512        click {
513            blt::busy configure $itk_component(area) -cursor fleur
514            set _click(x) $x
515            set _click(y) $y
516        }
517        drag {
518            if {[array size _click] == 0} {
519                _move click $x $y
520            } else {
521                set w [winfo width $itk_component(plot)]
522                set h [winfo height $itk_component(plot)]
523                set dx [expr {double($x-$_click(x))/$w}]
524                set dy [expr {double($y-$_click(y))/$h}]
525                foreach actor $_actors($this-ren) {
526                    foreach {ax ay az} [$actor GetPosition] break
527                    $actor SetPosition [expr {$ax+$dx}] [expr {$ay-$dy}] 0
528                }
529                $this-renWin Render
530
531                set _click(x) $x
532                set _click(y) $y
533            }
534        }
535        release {
536            _move drag $x $y
537            blt::busy configure $itk_component(area) -cursor left_ptr
538            catch {unset _click}
539        }
540        default {
541            error "bad option \"$option\": should be click, drag, release"
542        }
543    }
544}
545
546# ----------------------------------------------------------------------
547# USAGE: _fixLimits
548#
549# Used internally to apply automatic limits to the axes for the
550# current plot.
551# ----------------------------------------------------------------------
552itcl::body Rappture::ContourResult::_fixLimits {} {
553    $this-ren ResetCamera
554    [$this-ren GetActiveCamera] Zoom 1.5
555    $this-renWin Render
556    $this-renWin2 Render
557}
558
559# ----------------------------------------------------------------------
560# USAGE: _color2rgb <color>
561#
562# Used internally to convert a color name to a set of {r g b} values
563# needed for vtk.  Each r/g/b component is scaled in the range 0-1.
564# ----------------------------------------------------------------------
565itcl::body Rappture::ContourResult::_color2rgb {color} {
566    foreach {r g b} [winfo rgb $itk_component(hull) $color] break
567    set r [expr {$r/65535.0}]
568    set g [expr {$g/65535.0}]
569    set b [expr {$b/65535.0}]
570    return [list $r $g $b]
571}
572
573# ----------------------------------------------------------------------
574# CONFIGURATION OPTION: -background
575# ----------------------------------------------------------------------
576itcl::configbody Rappture::ContourResult::background {
577    foreach {r g b} [_color2rgb $itk_option(-background)] break
578    $this-ren SetBackground $r $g $b
579    $this-renWin Render
580    $this-ren2 SetBackground $r $g $b
581    $this-renWin2 Render
582}
583
584# ----------------------------------------------------------------------
585# CONFIGURATION OPTION: -foreground
586# ----------------------------------------------------------------------
587itcl::configbody Rappture::ContourResult::foreground {
588    after cancel [itcl::code $this _rebuild]
589    after idle [itcl::code $this _rebuild]
590}
Note: See TracBrowser for help on using the repository browser.