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

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

Added a capability to MainWin? to syncCutBuffer with the
application. The VNC Java client uses the cutbuffer
instead of the selection for Copy/Paste? to desktop, and
this mechanism keeps the two in sync so Copy/Paste? works
properly. Also, added Cut/Copy/Paste? menus to the right
mouse button of various widgets.

Fixed 3D plotting to work with the vtkCutter so it works
better. Also, added support for 3D meshes in addition
to clouds. Meshes store connectivity, so they are better
at representing holes in data. Fixed the 3D plotter so
that rotate is more intuitive, and added lights so you can
see your data better at any angle.

Fixed the loader so that it can load elements with the ""
value, and so that it doesn't duplicate entries found
more than once by *.xml pattern matching.

File size: 35.9 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
42blt::bitmap define ContourResult-xslice {
43#define x_width 12
44#define x_height 12
45static unsigned char x_bits[] = {
46   0x00, 0x00, 0x00, 0x00, 0x9c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00,
47   0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00};
48}
49
50blt::bitmap define ContourResult-yslice {
51#define y_width 12
52#define y_height 12
53static unsigned char y_bits[] = {
54   0x00, 0x00, 0x00, 0x00, 0x0e, 0x07, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00,
55   0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00};
56}
57blt::bitmap define ContourResult-zslice {
58#define z_width 12
59#define z_height 12
60static unsigned char z_bits[] = {
61   0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x84, 0x03, 0xc0, 0x01, 0xe0, 0x00,
62   0x70, 0x00, 0x38, 0x00, 0x1c, 0x02, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00};
63}
64
65option add *ContourResult.width 4i widgetDefault
66option add *ContourResult.height 4i widgetDefault
67option add *ContourResult.foreground black widgetDefault
68option add *ContourResult.controlBackground gray widgetDefault
69option add *ContourResult.controlDarkBackground #999999 widgetDefault
70option add *ContourResult.font \
71    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
72
73itcl::class Rappture::ContourResult {
74    inherit itk::Widget
75
76    itk_option define -foreground foreground Foreground ""
77    itk_option define -background background Background ""
78
79    constructor {args} { # defined below }
80    destructor { # defined below }
81
82    public method add {dataobj {settings ""}}
83    public method get {}
84    public method delete {args}
85    public method scale {args}
86
87    protected method _rebuild {}
88    protected method _clear {}
89    protected method _zoom {option}
90    protected method _move {option x y}
91    protected method _slice {option args}
92    protected method _3dView {theta phi}
93    protected method _fixLimits {}
94    protected method _color2rgb {color}
95
96    private variable _dlist ""     ;# list of data objects
97    private variable _dims ""      ;# dimensionality of data objects
98    private variable _obj2color    ;# maps dataobj => plotting color
99    private variable _obj2width    ;# maps dataobj => line width
100    private variable _obj2raise    ;# maps dataobj => raise flag 0/1
101    private variable _obj2vtk      ;# maps dataobj => vtk objects
102    private variable _actors       ;# list of actors for each renderer
103    private variable _lights       ;# list of lights for each renderer
104    private variable _click        ;# info used for _move operations
105    private variable _slicer       ;# vtk transform used for 3D slice plane
106    private variable _limits       ;# autoscale min/max for all axes
107    private variable _view         ;# view params for 3D view
108
109    private common _counter 0      ;# used for auto-generated names
110}
111
112itk::usual ContourResult {
113    keep -background -foreground -cursor -font
114}
115
116# ----------------------------------------------------------------------
117# CONSTRUCTOR
118# ----------------------------------------------------------------------
119itcl::body Rappture::ContourResult::constructor {args} {
120    option add hull.width hull.height
121    pack propagate $itk_component(hull) no
122
123    set _slicer(axis) ""
124    set _slicer(plane) ""
125    set _slicer(readout) ""
126    set _view(theta) 0
127    set _view(phi) 0
128
129    itk_component add controls {
130        frame $itk_interior.cntls
131    } {
132        usual
133        rename -background -controlbackground controlBackground Background
134    }
135    pack $itk_component(controls) -side right -fill y
136
137    itk_component add reset {
138        button $itk_component(controls).reset \
139            -borderwidth 1 -padx 1 -pady 1 \
140            -bitmap ContourResult-reset \
141            -command [itcl::code $this _zoom reset]
142    } {
143        usual
144        ignore -borderwidth
145        rename -highlightbackground -controlbackground controlBackground Background
146    }
147    pack $itk_component(reset) -padx 4 -pady 4
148    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
149
150    itk_component add zoomin {
151        button $itk_component(controls).zin \
152            -borderwidth 1 -padx 1 -pady 1 \
153            -bitmap ContourResult-zoomin \
154            -command [itcl::code $this _zoom in]
155    } {
156        usual
157        ignore -borderwidth
158        rename -highlightbackground -controlbackground controlBackground Background
159    }
160    pack $itk_component(zoomin) -padx 4 -pady 4
161    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
162
163    itk_component add zoomout {
164        button $itk_component(controls).zout \
165            -borderwidth 1 -padx 1 -pady 1 \
166            -bitmap ContourResult-zoomout \
167            -command [itcl::code $this _zoom out]
168    } {
169        usual
170        ignore -borderwidth
171        rename -highlightbackground -controlbackground controlBackground Background
172    }
173    pack $itk_component(zoomout) -padx 4 -pady 4
174    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
175
176    itk_component add xslice {
177        label $itk_component(controls).xslice \
178            -borderwidth 1 -relief raised -padx 1 -pady 1 \
179            -bitmap ContourResult-xslice
180    } {
181        usual
182        ignore -borderwidth
183        rename -highlightbackground -controlbackground controlBackground Background
184    }
185    bind $itk_component(xslice) <ButtonPress> \
186        [itcl::code $this _slice axis x]
187    Rappture::Tooltip::for $itk_component(xslice) "Slice along x-axis"
188
189    itk_component add yslice {
190        label $itk_component(controls).yslice \
191            -borderwidth 1 -relief raised -padx 1 -pady 1 \
192            -bitmap ContourResult-yslice
193    } {
194        usual
195        ignore -borderwidth
196        rename -highlightbackground -controlbackground controlBackground Background
197    }
198    bind $itk_component(yslice) <ButtonPress> \
199        [itcl::code $this _slice axis y]
200    Rappture::Tooltip::for $itk_component(yslice) "Slice along y-axis"
201
202    itk_component add zslice {
203        label $itk_component(controls).zslice \
204            -borderwidth 1 -relief raised -padx 1 -pady 1 \
205            -bitmap ContourResult-zslice
206    } {
207        usual
208        ignore -borderwidth
209        rename -highlightbackground -controlbackground controlBackground Background
210    }
211    bind $itk_component(zslice) <ButtonPress> \
212        [itcl::code $this _slice axis z]
213    Rappture::Tooltip::for $itk_component(zslice) "Slice along z-axis"
214
215    itk_component add slicer {
216        ::scale $itk_component(controls).slicer -from 100 -to 0 \
217            -width 10 -orient vertical -showvalue off \
218            -borderwidth 1 -highlightthickness 0 \
219            -command [itcl::code $this _slice move]
220    } {
221        usual
222        ignore -borderwidth
223        ignore -highlightthickness
224        rename -highlightbackground -controlbackground controlBackground Background
225        rename -troughcolor -controldarkbackground controlDarkBackground Background
226    }
227    pack $itk_component(slicer) -side bottom -padx 4 -pady 4
228    Rappture::Tooltip::for $itk_component(slicer) "Move the cut plane"
229
230    #
231    # RENDERING AREA
232    #
233    itk_component add area {
234        frame $itk_interior.area
235    }
236    pack $itk_component(area) -expand yes -fill both
237
238    vtkRenderer $this-ren
239    vtkRenderWindow $this-renWin
240    $this-renWin AddRenderer $this-ren
241    vtkRenderWindowInteractor $this-iren
242    $this-iren SetRenderWindow $this-renWin
243
244    itk_component add plot {
245        vtkTkRenderWidget $itk_component(area).plot -rw $this-renWin \
246            -width 1 -height 1
247    } {
248    }
249    pack $itk_component(plot) -expand yes -fill both
250
251
252    vtkRenderer $this-ren2
253    vtkRenderWindow $this-renWin2
254    $this-renWin2 AddRenderer $this-ren2
255    vtkRenderWindowInteractor $this-iren2
256    $this-iren2 SetRenderWindow $this-renWin2
257
258    itk_component add legend {
259        vtkTkRenderWidget $itk_component(area).legend -rw $this-renWin2 \
260            -width 1 -height 40
261    } {
262    }
263    pack $itk_component(legend) -side bottom -fill x
264
265    eval itk_initialize $args
266}
267
268# ----------------------------------------------------------------------
269# DESTRUCTOR
270# ----------------------------------------------------------------------
271itcl::body Rappture::ContourResult::destructor {} {
272    _clear
273    after cancel [itcl::code $this _rebuild]
274
275    rename $this-renWin ""
276    rename $this-ren ""
277    rename $this-iren ""
278
279    rename $this-renWin2 ""
280    rename $this-ren2 ""
281    rename $this-iren2 ""
282}
283
284# ----------------------------------------------------------------------
285# USAGE: add <dataobj> ?<settings>?
286#
287# Clients use this to add a data object to the plot.  The optional
288# <settings> are used to configure the plot.  Allowed settings are
289# -color, -brightness, -width, -linestyle, and -raise.
290# ----------------------------------------------------------------------
291itcl::body Rappture::ContourResult::add {dataobj {settings ""}} {
292    array set params {
293        -color black
294        -width 1
295        -linestyle solid
296        -brightness 0
297        -raise 0
298    }
299    foreach {opt val} $settings {
300        if {![info exists params($opt)]} {
301            error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
302        }
303        set params($opt) $val
304    }
305
306    set pos [lsearch -exact $dataobj $_dlist]
307    if {$pos < 0} {
308        lappend _dlist $dataobj
309        set _obj2color($dataobj) $params(-color)
310        set _obj2width($dataobj) $params(-width)
311        set _obj2raise($dataobj) $params(-raise)
312
313        after cancel [itcl::code $this _rebuild]
314        after idle [itcl::code $this _rebuild]
315    }
316}
317
318# ----------------------------------------------------------------------
319# USAGE: get
320#
321# Clients use this to query the list of objects being plotted, in
322# order from bottom to top of this result.
323# ----------------------------------------------------------------------
324itcl::body Rappture::ContourResult::get {} {
325    # put the dataobj list in order according to -raise options
326    set dlist $_dlist
327    foreach obj $dlist {
328        if {[info exists _obj2raise($obj)] && $_obj2raise($obj)} {
329            set i [lsearch -exact $dlist $obj]
330            if {$i >= 0} {
331                set dlist [lreplace $dlist $i $i]
332                lappend dlist $obj
333            }
334        }
335    }
336    return $dlist
337}
338
339# ----------------------------------------------------------------------
340# USAGE: delete ?<dataobj1> <dataobj2> ...?
341#
342# Clients use this to delete a dataobj from the plot.  If no dataobjs
343# are specified, then all dataobjs are deleted.
344# ----------------------------------------------------------------------
345itcl::body Rappture::ContourResult::delete {args} {
346    if {[llength $args] == 0} {
347        set args $_dlist
348    }
349
350    # delete all specified dataobjs
351    set changed 0
352    foreach dataobj $args {
353        set pos [lsearch -exact $_dlist $dataobj]
354        if {$pos >= 0} {
355            set _dlist [lreplace $_dlist $pos $pos]
356            catch {unset _obj2color($dataobj)}
357            catch {unset _obj2width($dataobj)}
358            catch {unset _obj2raise($dataobj)}
359            set changed 1
360        }
361    }
362
363    # if anything changed, then rebuild the plot
364    if {$changed} {
365        after cancel [itcl::code $this _rebuild]
366        after idle [itcl::code $this _rebuild]
367    }
368}
369
370# ----------------------------------------------------------------------
371# USAGE: scale ?<data1> <data2> ...?
372#
373# Sets the default limits for the overall plot according to the
374# limits of the data for all of the given <data> objects.  This
375# accounts for all objects--even those not showing on the screen.
376# Because of this, the limits are appropriate for all objects as
377# the user scans through data in the ResultSet viewer.
378# ----------------------------------------------------------------------
379itcl::body Rappture::ContourResult::scale {args} {
380    foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} {
381        set _limits($val) ""
382    }
383    foreach obj $args {
384        foreach axis {x y z v} {
385            foreach {min max} [$obj limits $axis] break
386            if {"" != $min && "" != $max} {
387                if {"" == $_limits(${axis}min)} {
388                    set _limits(${axis}min) $min
389                    set _limits(${axis}max) $max
390                } else {
391                    if {$min < $_limits(${axis}min)} {
392                        set _limits(${axis}min) $min
393                    }
394                    if {$max > $_limits(${axis}max)} {
395                        set _limits(${axis}max) $max
396                    }
397                }
398            }
399        }
400    }
401    _fixLimits
402}
403
404# ----------------------------------------------------------------------
405# USAGE: _rebuild
406#
407# Called automatically whenever something changes that affects the
408# data in the widget.  Clears any existing data and rebuilds the
409# widget to display new data.
410# ----------------------------------------------------------------------
411itcl::body Rappture::ContourResult::_rebuild {} {
412    _clear
413
414    # determine the dimensionality from the topmost (raised) object
415    set dlist [get]
416    set dataobj [lindex $dlist end]
417    if {$dataobj != ""} {
418        set _dims [$dataobj components -dimensions]
419    } else {
420        set _dims "0D"
421    }
422
423    # scan through all data objects and build the contours
424    set _counter 0
425    foreach dataobj [get] {
426        foreach comp [$dataobj components] {
427            #
428            # LOOKUP TABLE FOR COLOR CONTOURS
429            #
430            # use vmin/vmax if possible, otherwise get from data
431            if {$_limits(vmin) == "" || $_limits(vmax) == ""} {
432                foreach {v0 v1} [$pd GetScalarRange] break
433            } else {
434                set v0 $_limits(vmin)
435                set v1 $_limits(vmax)
436            }
437
438            set lu $this-lookup$_counter
439            vtkLookupTable $lu
440            $lu SetTableRange $v0 $v1
441            $lu SetHueRange 0.66667 0.0
442            $lu Build
443
444            lappend _obj2vtk($dataobj) $lu
445
446            #
447            # Add color contours.
448            #
449            if {$_counter == 0} {
450                if {$_dims == "3D"} {
451                    pack $itk_component(slicer) -side bottom -padx 4 -pady 4
452                    pack $itk_component(zslice) -side bottom -padx 4 -pady 4
453                    pack $itk_component(yslice) -side bottom -padx 4 -pady 4
454                    pack $itk_component(xslice) -side bottom -padx 4 -pady 4
455
456                    #
457                    # 3D LIGHTS (on both sides of all three axes)
458                    #
459                    set xm [expr {0.5*($_limits(xmax)+$_limits(xmin))}]
460                    set ym [expr {0.5*($_limits(ymax)+$_limits(ymin))}]
461                    set zm [expr {0.5*($_limits(zmax)+$_limits(zmin))}]
462                    set xr [expr {$_limits(xmax)-$_limits(xmin)}]
463                    set yr [expr {$_limits(ymax)-$_limits(ymin)}]
464                    set zr [expr {$_limits(zmax)-$_limits(zmin)}]
465
466                    set lt $this-lightxm$_counter
467                    vtkLight $lt
468                    $lt SetColor 1 1 1
469                    $lt SetAttenuationValues 0 0 0
470                    $lt SetFocalPoint $xm $ym $zm
471                    $lt SetPosition [expr {$xm-$xr}] 0 0
472                    $this-ren AddLight $lt
473                    lappend _lights($this-ren) $lt
474
475                    set lt $this-lightxp$_counter
476                    vtkLight $lt
477                    $lt SetColor 1 1 1
478                    $lt SetAttenuationValues 0 0 0
479                    $lt SetFocalPoint $xm $ym $zm
480                    $lt SetPosition [expr {$xm+$xr}] 0 0
481                    $this-ren AddLight $lt
482                    lappend _lights($this-ren) $lt
483
484                    set lt $this-lightym$_counter
485                    vtkLight $lt
486                    $lt SetColor 1 1 1
487                    $lt SetAttenuationValues 0 0 0
488                    $lt SetFocalPoint $xm $ym $zm
489                    $lt SetPosition 0 [expr {$ym-$yr}] 0
490                    $this-ren AddLight $lt
491                    lappend _lights($this-ren) $lt
492
493                    set lt $this-lightyp$_counter
494                    vtkLight $lt
495                    $lt SetColor 1 1 1
496                    $lt SetAttenuationValues 0 0 0
497                    $lt SetFocalPoint $xm $ym $zm
498                    $lt SetPosition 0 [expr {$ym+$yr}] 0
499                    $this-ren AddLight $lt
500                    lappend _lights($this-ren) $lt
501
502                    set lt $this-lightzm$_counter
503                    vtkLight $lt
504                    $lt SetColor 1 1 1
505                    $lt SetAttenuationValues 0 0 0
506                    $lt SetFocalPoint $xm $ym $zm
507                    $lt SetPosition 0 0 [expr {$zm-$zr}]
508                    $this-ren AddLight $lt
509                    lappend _lights($this-ren) $lt
510
511                    set lt $this-lightzp$_counter
512                    vtkLight $lt
513                    $lt SetColor 1 1 1
514                    $lt SetAttenuationValues 0 0 0
515                    $lt SetFocalPoint $xm $ym $zm
516                    $lt SetPosition 0 0 [expr {$zm+$zr}]
517                    $this-ren AddLight $lt
518                    lappend _lights($this-ren) $lt
519
520                    #
521                    # 3D DATA SET
522                    #
523                    set mesh [$dataobj mesh $comp]
524                    switch -- [$mesh GetClassName] {
525                      vtkPoints {
526                        # handle cloud of 3D points
527                        set pd $this-polydata$_counter
528                        vtkPolyData $pd
529                        $pd SetPoints $mesh
530                        [$pd GetPointData] SetScalars [$dataobj values $comp]
531
532                        set tr $this-triangles$_counter
533                        vtkDelaunay3D $tr
534                        $tr SetInput $pd
535                        $tr SetTolerance 0.0000000000001
536                        set source [$tr GetOutput]
537
538                        set mp $this-mapper$_counter
539                        vtkPolyDataMapper $mp
540
541                        lappend _obj2vtk($dataobj) $pd $tr $mp
542                      }
543                      vtkUnstructuredGrid {
544                        # handle 3D grid with connectivity
545                        set gr $this-grdata$_counter
546                        vtkUnstructuredGrid $gr
547                        $gr ShallowCopy $mesh
548                        [$gr GetPointData] SetScalars [$dataobj values $comp]
549                        set source $gr
550
551                        lappend _obj2vtk($dataobj) $gr
552                      }
553                      default {
554                        error "don't know how to handle [$mesh GetClassName] data"
555                      }
556                    }
557
558                    #
559                    # 3D CUT PLANE
560                    #
561                    set pl $this-cutplane$_counter
562                    vtkPlane $pl
563                    set _slicer(plane) $pl
564                    _slice axis "z"
565
566                    set ct $this-cutter$_counter
567                    vtkCutter $ct
568                    $ct SetInput $source
569                    $ct SetCutFunction $pl
570
571                    set mp $this-cutmapper$_counter
572                    vtkPolyDataMapper $mp
573                    $mp SetInput [$ct GetOutput]
574                    $mp SetScalarRange $v0 $v1
575                    $mp SetLookupTable $lu
576
577                    lappend _obj2vtk($dataobj) $pl $ct $mp
578
579                    set ac $this-actor$_counter
580                    vtkActor $ac
581                    $ac SetMapper $mp
582                    $ac SetPosition 0 0 0
583                    [$ac GetProperty] SetColor 0 0 0
584                    $this-ren AddActor $ac
585                    lappend _actors($this-ren) $ac
586                    lappend _obj2vtk($dataobj) $ac
587
588                    set olf $this-3dolfilter$_counter
589                    vtkOutlineFilter $olf
590                    $olf SetInput $source
591
592                    set olm $this-3dolmapper$_counter
593                    vtkPolyDataMapper $olm
594                    $olm SetInput [$olf GetOutput]
595
596                    set ola $this-3dolactor$_counter
597                    vtkActor $ola
598                    $ola SetMapper $olm
599                    eval [$ola GetProperty] SetColor 0 0 0
600                    $this-ren AddActor $ola
601                    lappend _actors($this-ren) $ola
602
603                    lappend _obj2vtk($dataobj) $olf $olm $ola
604
605                    #
606                    # CUT PLANE READOUT
607                    #
608                    set tx $this-text$_counter
609                    vtkTextMapper $tx
610                    set tp [$tx GetTextProperty]
611                    eval $tp SetColor [_color2rgb $itk_option(-foreground)]
612                    $tp SetVerticalJustificationToTop
613                    set _slicer(readout) $tx
614
615                    set txa $this-texta$_counter
616                    vtkActor2D $txa
617                    $txa SetMapper $tx
618                    [$txa GetPositionCoordinate] \
619                        SetCoordinateSystemToNormalizedDisplay
620                    [$txa GetPositionCoordinate] SetValue 0.02 0.98
621
622                    $this-ren AddActor $txa
623                    lappend _actors($this-ren) $txa
624
625                    lappend _obj2vtk($dataobj) $tx $txa
626                } else {
627                    pack forget $itk_component(xslice)
628                    pack forget $itk_component(yslice)
629                    pack forget $itk_component(zslice)
630                    pack forget $itk_component(slicer)
631
632                    set pd $this-polydata$_counter
633                    vtkPolyData $pd
634                    $pd SetPoints [$dataobj mesh $comp]
635                    [$pd GetPointData] SetScalars [$dataobj values $comp]
636
637                    set tr $this-triangles$_counter
638                    vtkDelaunay2D $tr
639                    $tr SetInput $pd
640                    $tr SetTolerance 0.0000000000001
641                    set source [$tr GetOutput]
642
643                    set mp $this-mapper$_counter
644                    vtkPolyDataMapper $mp
645                    $mp SetInput $source
646                    $mp SetScalarRange $v0 $v1
647                    $mp SetLookupTable $lu
648
649                    set ac $this-actor$_counter
650                    vtkActor $ac
651                    $ac SetMapper $mp
652                    $ac SetPosition 0 0 0
653                    [$ac GetProperty] SetColor 0 0 0
654                    $this-ren AddActor $ac
655                    lappend _actors($this-ren) $ac
656
657                    lappend _obj2vtk($dataobj) $pd $tr $mp $ac
658                }
659            }
660
661            #
662            # Add color lines
663            #
664            if {$_counter > 0} {
665                set cf $this-clfilter$_counter
666                vtkContourFilter $cf
667                $cf SetInput $source
668                $cf GenerateValues 20 $v0 $v1
669
670                set mp $this-clmapper$_counter
671                vtkPolyDataMapper $mp
672                $mp SetInput [$cf GetOutput]
673                $mp SetScalarRange $v0 $v1
674                $mp SetLookupTable $lu
675
676                set ac $this-clactor$_counter
677                vtkActor $ac
678                $ac SetMapper $mp
679                [$ac GetProperty] SetColor 1 1 1
680                $ac SetPosition 0 0 0
681                $this-ren AddActor $ac
682                lappend _actors($this-ren) $ac
683
684                lappend _obj2vtk($dataobj) $cf $mp $ac
685            }
686
687            #
688            # Add an outline around the data
689            #
690            set olf $this-olfilter$_counter
691            vtkOutlineFilter $olf
692            $olf SetInput $source
693
694            set olm $this-olmapper$_counter
695            vtkPolyDataMapper $olm
696            $olm SetInput [$olf GetOutput]
697
698            set ola $this-olactor$_counter
699            vtkActor $ola
700            $ola SetMapper $olm
701            eval [$ola GetProperty] SetColor 0 0 0
702            $this-ren AddActor $ola
703            lappend _actors($this-ren) $ola
704
705            lappend _obj2vtk($dataobj) $olf $olm $ola
706
707            #
708            # Add a legend with the scale.
709            #
710            set lg $this-legend$_counter
711            vtkScalarBarActor $lg
712            $lg SetLookupTable $lu
713            [$lg GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
714            [$lg GetPositionCoordinate] SetValue 0.1 0.1
715            $lg SetOrientationToHorizontal
716            $lg SetWidth 0.8
717            $lg SetHeight 1.0
718
719            set tp [$lg GetLabelTextProperty]
720            eval $tp SetColor [_color2rgb $itk_option(-foreground)]
721            $tp BoldOff
722            $tp ItalicOff
723            $tp ShadowOff
724            #eval $tp SetShadowColor [_color2rgb gray]
725
726            $this-ren2 AddActor2D $lg
727            lappend _actors($this-ren2) $lg
728            lappend _obj2vtk($dataobj) $lg
729
730            incr _counter
731        }
732    }
733    _fixLimits
734    _zoom reset
735
736    # prevent interactions -- use our own
737    blt::busy hold $itk_component(area) -cursor left_ptr
738    bind $itk_component(area)_Busy <ButtonPress> \
739        [itcl::code $this _move click %x %y]
740    bind $itk_component(area)_Busy <B1-Motion> \
741        [itcl::code $this _move drag %x %y]
742    bind $itk_component(area)_Busy <ButtonRelease> \
743        [itcl::code $this _move release %x %y]
744}
745
746# ----------------------------------------------------------------------
747# USAGE: _clear
748#
749# Used internally to clear the drawing area and tear down all vtk
750# objects in the current scene.
751# ----------------------------------------------------------------------
752itcl::body Rappture::ContourResult::_clear {} {
753    # clear out any old constructs
754    foreach ren [array names _actors] {
755        foreach actor $_actors($ren) {
756            $ren RemoveActor $actor
757        }
758        set _actors($ren) ""
759    }
760    foreach ren [array names _lights] {
761        foreach light $_lights($ren) {
762            $ren RemoveLight $light
763            rename $light ""
764        }
765        set _lights($ren) ""
766    }
767    foreach dataobj [array names _obj2vtk] {
768        foreach cmd $_obj2vtk($dataobj) {
769            rename $cmd ""
770        }
771        set _obj2vtk($dataobj) ""
772    }
773    set _slicer(axis) ""
774    set _slicer(plane) ""
775    set _slicer(readout) ""
776}
777
778# ----------------------------------------------------------------------
779# USAGE: _zoom in
780# USAGE: _zoom out
781# USAGE: _zoom reset
782#
783# Called automatically when the user clicks on one of the zoom
784# controls for this widget.  Changes the zoom for the current view.
785# ----------------------------------------------------------------------
786itcl::body Rappture::ContourResult::_zoom {option} {
787    switch -- $option {
788        in {
789            [$this-ren GetActiveCamera] Zoom 1.25
790            $this-renWin Render
791        }
792        out {
793            [$this-ren GetActiveCamera] Zoom 0.8
794            $this-renWin Render
795        }
796        reset {
797            if {$_dims == "3D"} {
798                [$this-ren GetActiveCamera] SetViewAngle 30
799                $this-ren ResetCamera
800                _3dView 45 45
801            } else {
802                $this-ren ResetCamera
803                [$this-ren GetActiveCamera] Zoom 1.5
804            }
805            $this-renWin Render
806            $this-renWin2 Render
807        }
808    }
809}
810
811# ----------------------------------------------------------------------
812# USAGE: _move click <x> <y>
813# USAGE: _move drag <x> <y>
814# USAGE: _move release <x> <y>
815#
816# Called automatically when the user clicks/drags/releases in the
817# plot area.  Moves the plot according to the user's actions.
818# ----------------------------------------------------------------------
819itcl::body Rappture::ContourResult::_move {option x y} {
820    switch -- $option {
821        click {
822            blt::busy configure $itk_component(area) -cursor fleur
823            set _click(x) $x
824            set _click(y) $y
825            set _click(theta) $_view(theta)
826            set _click(phi) $_view(phi)
827        }
828        drag {
829            if {[array size _click] == 0} {
830                _move click $x $y
831            } else {
832                set w [winfo width $itk_component(plot)]
833                set h [winfo height $itk_component(plot)]
834                set dx [expr {double($x-$_click(x))/$w}]
835                set dy [expr {double($y-$_click(y))/$h}]
836
837                if {$_dims == "2D"} {
838                    #
839                    # Shift the contour plot in 2D
840                    #
841                    foreach actor $_actors($this-ren) {
842                        foreach {ax ay az} [$actor GetPosition] break
843                        $actor SetPosition [expr {$ax+$dx}] [expr {$ay-$dy}] 0
844                    }
845                    $this-renWin Render
846                } elseif {$_dims == "3D"} {
847                    #
848                    # Rotate the camera in 3D
849                    #
850                    set theta [expr {$_view(theta) - $dy*180}]
851                    if {$theta < 2} { set theta 2 }
852                    if {$theta > 178} { set theta 178 }
853                    set phi [expr {$_view(phi) - $dx*360}]
854
855                    _3dView $theta $phi
856                    $this-renWin Render
857                }
858                set _click(x) $x
859                set _click(y) $y
860            }
861        }
862        release {
863            _move drag $x $y
864            blt::busy configure $itk_component(area) -cursor left_ptr
865            catch {unset _click}
866        }
867        default {
868            error "bad option \"$option\": should be click, drag, release"
869        }
870    }
871}
872
873# ----------------------------------------------------------------------
874# USAGE: _slice axis x|y|z
875# USAGE: _slice move <newval>
876#
877# Called automatically when the user drags the slider to move the
878# cut plane that slices 3D data.  Gets the current value from the
879# slider and moves the cut plane to the appropriate point in the
880# data set.
881# ----------------------------------------------------------------------
882itcl::body Rappture::ContourResult::_slice {option args} {
883    if {$_slicer(plane) == ""} {
884        # no slicer? then bail out!
885        return
886    }
887    switch -- $option {
888        axis {
889            if {[llength $args] != 1} {
890                error "wrong # args: should be \"_slice axis xyz\""
891            }
892            set axis [lindex $args 0]
893
894            switch -- $axis {
895                x { $_slicer(plane) SetNormal 1 0 0 }
896                y { $_slicer(plane) SetNormal 0 1 0 }
897                z { $_slicer(plane) SetNormal 0 0 1 }
898                default {
899                    error "bad axis \"$axis\": should be x, y, z"
900                }
901            }
902
903            set _slicer(axis) $axis
904            $itk_component(slicer) set 50
905            _slice move 50
906            $this-renWin Render
907
908            foreach a {x y z} {
909                $itk_component(${a}slice) configure -relief raised
910            }
911            $itk_component(${axis}slice) configure -relief sunken
912        }
913        move {
914            if {[llength $args] != 1} {
915                error "wrong # args: should be \"_slice move newval\""
916            }
917            set newval [lindex $args 0]
918
919            set xm [expr {0.5*($_limits(xmax)+$_limits(xmin))}]
920            set ym [expr {0.5*($_limits(ymax)+$_limits(ymin))}]
921            set zm [expr {0.5*($_limits(zmax)+$_limits(zmin))}]
922
923            set a $_slicer(axis)
924            set newval [expr {0.01*($newval-50)
925                *($_limits(${a}max)-$_limits(${a}min))
926                  + 0.5*($_limits(${a}max)+$_limits(${a}min))}]
927
928            # show the current value in the readout
929            if {$_slicer(readout) != ""} {
930                $_slicer(readout) SetInput "$a = $newval"
931            }
932
933            # keep a little inside the volume, or the slice will disappear!
934            if {$newval == $_limits(${a}min)} {
935                set range [expr {$_limits(${a}max)-$_limits(${a}min)}]
936                set newval [expr {$newval + 1e-6*$range}]
937            }
938
939            # xfer new value to the proper dimension and move the cut plane
940            set ${a}m $newval
941            $_slicer(plane) SetOrigin $xm $ym $zm
942
943            $this-renWin Render
944        }
945        default {
946            error "bad option \"$option\": should be axis or move"
947        }
948    }
949}
950
951# ----------------------------------------------------------------------
952# USAGE: _3dView <theta> <phi>
953#
954# Used internally to change the position of the camera for 3D data
955# sets.  Sets the camera according to the angles <theta> (angle from
956# the z-axis) and <phi> (angle from the x-axis in the x-y plane).
957# Both angles are in degrees.
958# ----------------------------------------------------------------------
959itcl::body Rappture::ContourResult::_3dView {theta phi} {
960    set deg2rad 0.0174532927778
961    set xn [expr {sin($theta*$deg2rad)*cos($phi*$deg2rad)}]
962    set yn [expr {sin($theta*$deg2rad)*sin($phi*$deg2rad)}]
963    set zn [expr {cos($theta*$deg2rad)}]
964
965    set xm [expr {0.5*($_limits(xmax)+$_limits(xmin))}]
966    set ym [expr {0.5*($_limits(ymax)+$_limits(ymin))}]
967    set zm [expr {0.5*($_limits(zmax)+$_limits(zmin))}]
968
969    set cam [$this-ren GetActiveCamera]
970    set zoom [$cam GetViewAngle]
971    $cam SetViewAngle 30
972
973    $cam SetFocalPoint $xm $ym $zm
974    $cam SetPosition [expr {$xm-$xn}] [expr {$ym-$yn}] [expr {$zm+$zn}]
975    $cam ComputeViewPlaneNormal
976    $cam SetViewUp 0 0 1  ;# z-dir is up
977    $cam OrthogonalizeViewUp
978    $this-ren ResetCamera
979    $cam SetViewAngle $zoom
980
981    set _view(theta) $theta
982    set _view(phi) $phi
983}
984
985# ----------------------------------------------------------------------
986# USAGE: _fixLimits
987#
988# Used internally to apply automatic limits to the axes for the
989# current plot.
990# ----------------------------------------------------------------------
991itcl::body Rappture::ContourResult::_fixLimits {} {
992    $this-ren ResetCamera
993    [$this-ren GetActiveCamera] Zoom 1.5
994    $this-renWin Render
995    $this-renWin2 Render
996}
997
998# ----------------------------------------------------------------------
999# USAGE: _color2rgb <color>
1000#
1001# Used internally to convert a color name to a set of {r g b} values
1002# needed for vtk.  Each r/g/b component is scaled in the range 0-1.
1003# ----------------------------------------------------------------------
1004itcl::body Rappture::ContourResult::_color2rgb {color} {
1005    foreach {r g b} [winfo rgb $itk_component(hull) $color] break
1006    set r [expr {$r/65535.0}]
1007    set g [expr {$g/65535.0}]
1008    set b [expr {$b/65535.0}]
1009    return [list $r $g $b]
1010}
1011
1012# ----------------------------------------------------------------------
1013# CONFIGURATION OPTION: -background
1014# ----------------------------------------------------------------------
1015itcl::configbody Rappture::ContourResult::background {
1016    foreach {r g b} [_color2rgb $itk_option(-background)] break
1017    $this-ren SetBackground $r $g $b
1018    $this-renWin Render
1019    $this-ren2 SetBackground $r $g $b
1020    $this-renWin2 Render
1021}
1022
1023# ----------------------------------------------------------------------
1024# CONFIGURATION OPTION: -foreground
1025# ----------------------------------------------------------------------
1026itcl::configbody Rappture::ContourResult::foreground {
1027    after cancel [itcl::code $this _rebuild]
1028    after idle [itcl::code $this _rebuild]
1029}
Note: See TracBrowser for help on using the repository browser.