[11] | 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 |
---|
[115] | 10 | # Copyright (c) 2004-2005 Purdue Research Foundation |
---|
| 11 | # |
---|
| 12 | # See the file "license.terms" for information on usage and |
---|
| 13 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
[11] | 14 | # ====================================================================== |
---|
| 15 | package require Itk |
---|
| 16 | package require vtk |
---|
| 17 | package require vtkinteraction |
---|
| 18 | package require BLT |
---|
[193] | 19 | package require Img |
---|
[11] | 20 | |
---|
| 21 | option add *ContourResult.width 4i widgetDefault |
---|
| 22 | option add *ContourResult.height 4i widgetDefault |
---|
| 23 | option add *ContourResult.foreground black widgetDefault |
---|
| 24 | option add *ContourResult.controlBackground gray widgetDefault |
---|
[16] | 25 | option add *ContourResult.controlDarkBackground #999999 widgetDefault |
---|
[136] | 26 | option add *ContourResult.plotBackground black widgetDefault |
---|
| 27 | option add *ContourResult.plotForeground white widgetDefault |
---|
[11] | 28 | option add *ContourResult.font \ |
---|
[676] | 29 | -*-helvetica-medium-r-normal-*-12-* widgetDefault |
---|
[11] | 30 | |
---|
| 31 | itcl::class Rappture::ContourResult { |
---|
| 32 | inherit itk::Widget |
---|
| 33 | |
---|
[136] | 34 | itk_option define -plotforeground plotForeground Foreground "" |
---|
| 35 | itk_option define -plotbackground plotBackground Background "" |
---|
[11] | 36 | |
---|
| 37 | constructor {args} { # defined below } |
---|
| 38 | destructor { # defined below } |
---|
| 39 | |
---|
| 40 | public method add {dataobj {settings ""}} |
---|
[13] | 41 | public method get {} |
---|
[11] | 42 | public method delete {args} |
---|
| 43 | public method scale {args} |
---|
[766] | 44 | public method parameters {title args} { # do nothing } |
---|
[464] | 45 | public method download {option args} |
---|
[11] | 46 | |
---|
| 47 | protected method _rebuild {} |
---|
[17] | 48 | protected method _clear {} |
---|
[11] | 49 | protected method _zoom {option} |
---|
| 50 | protected method _move {option x y} |
---|
[16] | 51 | protected method _slice {option args} |
---|
[17] | 52 | protected method _3dView {theta phi} |
---|
[11] | 53 | protected method _fixLimits {} |
---|
[136] | 54 | protected method _slicertip {axis} |
---|
[11] | 55 | protected method _color2rgb {color} |
---|
| 56 | |
---|
| 57 | private variable _dlist "" ;# list of data objects |
---|
[17] | 58 | private variable _dims "" ;# dimensionality of data objects |
---|
[11] | 59 | private variable _obj2color ;# maps dataobj => plotting color |
---|
| 60 | private variable _obj2width ;# maps dataobj => line width |
---|
| 61 | private variable _obj2raise ;# maps dataobj => raise flag 0/1 |
---|
| 62 | private variable _obj2vtk ;# maps dataobj => vtk objects |
---|
| 63 | private variable _actors ;# list of actors for each renderer |
---|
[17] | 64 | private variable _lights ;# list of lights for each renderer |
---|
[11] | 65 | private variable _click ;# info used for _move operations |
---|
[16] | 66 | private variable _slicer ;# vtk transform used for 3D slice plane |
---|
| 67 | private variable _limits ;# autoscale min/max for all axes |
---|
[17] | 68 | private variable _view ;# view params for 3D view |
---|
[193] | 69 | private variable _download "" ;# snapshot for download |
---|
[11] | 70 | } |
---|
| 71 | |
---|
| 72 | itk::usual ContourResult { |
---|
| 73 | keep -background -foreground -cursor -font |
---|
[136] | 74 | keep -plotbackground -plotforeground |
---|
[11] | 75 | } |
---|
| 76 | |
---|
| 77 | # ---------------------------------------------------------------------- |
---|
| 78 | # CONSTRUCTOR |
---|
| 79 | # ---------------------------------------------------------------------- |
---|
| 80 | itcl::body Rappture::ContourResult::constructor {args} { |
---|
| 81 | option add hull.width hull.height |
---|
| 82 | pack propagate $itk_component(hull) no |
---|
| 83 | |
---|
[136] | 84 | set _slicer(xplane) "" |
---|
| 85 | set _slicer(yplane) "" |
---|
| 86 | set _slicer(zplane) "" |
---|
| 87 | set _slicer(xslice) "" |
---|
| 88 | set _slicer(yslice) "" |
---|
| 89 | set _slicer(zslice) "" |
---|
[16] | 90 | set _slicer(readout) "" |
---|
[17] | 91 | set _view(theta) 0 |
---|
| 92 | set _view(phi) 0 |
---|
[16] | 93 | |
---|
[739] | 94 | foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} { |
---|
[1342] | 95 | set _limits($val) "" |
---|
[739] | 96 | } |
---|
| 97 | |
---|
[11] | 98 | itk_component add controls { |
---|
[1342] | 99 | frame $itk_interior.cntls |
---|
[11] | 100 | } { |
---|
[1342] | 101 | usual |
---|
| 102 | rename -background -controlbackground controlBackground Background |
---|
[11] | 103 | } |
---|
| 104 | pack $itk_component(controls) -side right -fill y |
---|
| 105 | |
---|
[136] | 106 | itk_component add zoom { |
---|
[1342] | 107 | frame $itk_component(controls).zoom |
---|
[136] | 108 | } { |
---|
[1342] | 109 | usual |
---|
| 110 | rename -background -controlbackground controlBackground Background |
---|
[136] | 111 | } |
---|
| 112 | pack $itk_component(zoom) -side top |
---|
| 113 | |
---|
[11] | 114 | itk_component add reset { |
---|
[1342] | 115 | button $itk_component(zoom).reset \ |
---|
| 116 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
| 117 | -bitmap [Rappture::icon reset] \ |
---|
| 118 | -command [itcl::code $this _zoom reset] |
---|
[11] | 119 | } { |
---|
[1342] | 120 | usual |
---|
| 121 | ignore -borderwidth |
---|
| 122 | rename -highlightbackground -controlbackground controlBackground Background |
---|
[11] | 123 | } |
---|
| 124 | pack $itk_component(reset) -padx 4 -pady 4 |
---|
| 125 | Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level" |
---|
| 126 | |
---|
| 127 | itk_component add zoomin { |
---|
[1342] | 128 | button $itk_component(zoom).zin \ |
---|
| 129 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
| 130 | -bitmap [Rappture::icon zoomin] \ |
---|
| 131 | -command [itcl::code $this _zoom in] |
---|
[11] | 132 | } { |
---|
[1342] | 133 | usual |
---|
| 134 | ignore -borderwidth |
---|
| 135 | rename -highlightbackground -controlbackground controlBackground Background |
---|
[11] | 136 | } |
---|
| 137 | pack $itk_component(zoomin) -padx 4 -pady 4 |
---|
| 138 | Rappture::Tooltip::for $itk_component(zoomin) "Zoom in" |
---|
| 139 | |
---|
| 140 | itk_component add zoomout { |
---|
[1342] | 141 | button $itk_component(zoom).zout \ |
---|
| 142 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
| 143 | -bitmap [Rappture::icon zoomout] \ |
---|
| 144 | -command [itcl::code $this _zoom out] |
---|
[11] | 145 | } { |
---|
[1342] | 146 | usual |
---|
| 147 | ignore -borderwidth |
---|
| 148 | rename -highlightbackground -controlbackground controlBackground Background |
---|
[11] | 149 | } |
---|
| 150 | pack $itk_component(zoomout) -padx 4 -pady 4 |
---|
| 151 | Rappture::Tooltip::for $itk_component(zoomout) "Zoom out" |
---|
| 152 | |
---|
[136] | 153 | # |
---|
| 154 | # Create slicer controls... |
---|
| 155 | # |
---|
| 156 | itk_component add slicers { |
---|
[1342] | 157 | frame $itk_component(controls).slicers |
---|
[136] | 158 | } { |
---|
[1342] | 159 | usual |
---|
| 160 | rename -background -controlbackground controlBackground Background |
---|
[136] | 161 | } |
---|
| 162 | pack $itk_component(slicers) -side bottom -padx 4 -pady 4 |
---|
| 163 | grid rowconfigure $itk_component(slicers) 1 -weight 1 |
---|
| 164 | |
---|
| 165 | # |
---|
| 166 | # X-value slicer... |
---|
| 167 | # |
---|
[16] | 168 | itk_component add xslice { |
---|
[1342] | 169 | label $itk_component(slicers).xslice \ |
---|
| 170 | -borderwidth 1 -relief raised -padx 1 -pady 1 \ |
---|
| 171 | -bitmap [Rappture::icon x] |
---|
[16] | 172 | } { |
---|
[1342] | 173 | usual |
---|
| 174 | ignore -borderwidth |
---|
| 175 | rename -highlightbackground -controlbackground controlBackground Background |
---|
[16] | 176 | } |
---|
| 177 | bind $itk_component(xslice) <ButtonPress> \ |
---|
[1342] | 178 | [itcl::code $this _slice axis x toggle] |
---|
[136] | 179 | Rappture::Tooltip::for $itk_component(xslice) \ |
---|
[1342] | 180 | "Toggle the X cut plane on/off" |
---|
[136] | 181 | grid $itk_component(xslice) -row 0 -column 0 -sticky ew -padx 1 |
---|
[16] | 182 | |
---|
[136] | 183 | itk_component add xslicer { |
---|
[1342] | 184 | ::scale $itk_component(slicers).xval -from 100 -to 0 \ |
---|
| 185 | -width 10 -orient vertical -showvalue off -state disabled \ |
---|
| 186 | -borderwidth 1 -highlightthickness 0 \ |
---|
| 187 | -command [itcl::code $this _slice move x] |
---|
[136] | 188 | } { |
---|
[1342] | 189 | usual |
---|
| 190 | ignore -borderwidth |
---|
| 191 | ignore -highlightthickness |
---|
| 192 | rename -highlightbackground -controlbackground controlBackground Background |
---|
| 193 | rename -troughcolor -controldarkbackground controlDarkBackground Background |
---|
[136] | 194 | } |
---|
| 195 | grid $itk_component(xslicer) -row 1 -column 0 -padx 1 |
---|
| 196 | Rappture::Tooltip::for $itk_component(xslicer) \ |
---|
[1342] | 197 | "@[itcl::code $this _slicertip x]" |
---|
[136] | 198 | |
---|
| 199 | # |
---|
| 200 | # Y-value slicer... |
---|
| 201 | # |
---|
[16] | 202 | itk_component add yslice { |
---|
[1342] | 203 | label $itk_component(slicers).yslice \ |
---|
| 204 | -borderwidth 1 -relief raised -padx 1 -pady 1 \ |
---|
| 205 | -bitmap [Rappture::icon y] |
---|
[16] | 206 | } { |
---|
[1342] | 207 | usual |
---|
| 208 | ignore -borderwidth |
---|
| 209 | rename -highlightbackground -controlbackground controlBackground Background |
---|
[16] | 210 | } |
---|
| 211 | bind $itk_component(yslice) <ButtonPress> \ |
---|
[1342] | 212 | [itcl::code $this _slice axis y toggle] |
---|
[136] | 213 | Rappture::Tooltip::for $itk_component(yslice) \ |
---|
[1342] | 214 | "Toggle the Y cut plane on/off" |
---|
[136] | 215 | grid $itk_component(yslice) -row 0 -column 1 -sticky ew -padx 1 |
---|
[16] | 216 | |
---|
[136] | 217 | itk_component add yslicer { |
---|
[1342] | 218 | ::scale $itk_component(slicers).yval -from 100 -to 0 \ |
---|
| 219 | -width 10 -orient vertical -showvalue off -state disabled \ |
---|
| 220 | -borderwidth 1 -highlightthickness 0 \ |
---|
| 221 | -command [itcl::code $this _slice move y] |
---|
[136] | 222 | } { |
---|
[1342] | 223 | usual |
---|
| 224 | ignore -borderwidth |
---|
| 225 | ignore -highlightthickness |
---|
| 226 | rename -highlightbackground -controlbackground controlBackground Background |
---|
| 227 | rename -troughcolor -controldarkbackground controlDarkBackground Background |
---|
[136] | 228 | } |
---|
| 229 | grid $itk_component(yslicer) -row 1 -column 1 -padx 1 |
---|
| 230 | Rappture::Tooltip::for $itk_component(yslicer) \ |
---|
[1342] | 231 | "@[itcl::code $this _slicertip y]" |
---|
[136] | 232 | |
---|
| 233 | # |
---|
| 234 | # Z-value slicer... |
---|
| 235 | # |
---|
[16] | 236 | itk_component add zslice { |
---|
[1342] | 237 | label $itk_component(slicers).zslice \ |
---|
| 238 | -borderwidth 1 -relief raised -padx 1 -pady 1 \ |
---|
| 239 | -bitmap [Rappture::icon z] |
---|
[16] | 240 | } { |
---|
[1342] | 241 | usual |
---|
| 242 | ignore -borderwidth |
---|
| 243 | rename -highlightbackground -controlbackground controlBackground Background |
---|
[16] | 244 | } |
---|
[136] | 245 | grid $itk_component(zslice) -row 0 -column 2 -sticky ew -padx 1 |
---|
[16] | 246 | bind $itk_component(zslice) <ButtonPress> \ |
---|
[1342] | 247 | [itcl::code $this _slice axis z toggle] |
---|
[136] | 248 | Rappture::Tooltip::for $itk_component(zslice) \ |
---|
[1342] | 249 | "Toggle the Z cut plane on/off" |
---|
[16] | 250 | |
---|
[136] | 251 | itk_component add zslicer { |
---|
[1342] | 252 | ::scale $itk_component(slicers).zval -from 100 -to 0 \ |
---|
| 253 | -width 10 -orient vertical -showvalue off -state disabled \ |
---|
| 254 | -borderwidth 1 -highlightthickness 0 \ |
---|
| 255 | -command [itcl::code $this _slice move z] |
---|
[16] | 256 | } { |
---|
[1342] | 257 | usual |
---|
| 258 | ignore -borderwidth |
---|
| 259 | ignore -highlightthickness |
---|
| 260 | rename -highlightbackground -controlbackground controlBackground Background |
---|
| 261 | rename -troughcolor -controldarkbackground controlDarkBackground Background |
---|
[16] | 262 | } |
---|
[136] | 263 | grid $itk_component(zslicer) -row 1 -column 2 -padx 1 |
---|
| 264 | Rappture::Tooltip::for $itk_component(zslicer) \ |
---|
[1342] | 265 | "@[itcl::code $this _slicertip z]" |
---|
[16] | 266 | |
---|
| 267 | # |
---|
| 268 | # RENDERING AREA |
---|
| 269 | # |
---|
[11] | 270 | itk_component add area { |
---|
[1342] | 271 | frame $itk_interior.area |
---|
[11] | 272 | } |
---|
| 273 | pack $itk_component(area) -expand yes -fill both |
---|
| 274 | |
---|
| 275 | vtkRenderer $this-ren |
---|
| 276 | vtkRenderWindow $this-renWin |
---|
| 277 | $this-renWin AddRenderer $this-ren |
---|
[136] | 278 | $this-renWin LineSmoothingOn |
---|
| 279 | $this-renWin PolygonSmoothingOn |
---|
[11] | 280 | vtkRenderWindowInteractor $this-iren |
---|
| 281 | $this-iren SetRenderWindow $this-renWin |
---|
| 282 | |
---|
| 283 | itk_component add plot { |
---|
[1342] | 284 | vtkTkRenderWidget $itk_component(area).plot -rw $this-renWin \ |
---|
| 285 | -width 1 -height 1 |
---|
[11] | 286 | } { |
---|
| 287 | } |
---|
| 288 | pack $itk_component(plot) -expand yes -fill both |
---|
| 289 | |
---|
| 290 | |
---|
| 291 | vtkRenderer $this-ren2 |
---|
| 292 | vtkRenderWindow $this-renWin2 |
---|
| 293 | $this-renWin2 AddRenderer $this-ren2 |
---|
| 294 | vtkRenderWindowInteractor $this-iren2 |
---|
| 295 | $this-iren2 SetRenderWindow $this-renWin2 |
---|
| 296 | |
---|
| 297 | itk_component add legend { |
---|
[1342] | 298 | vtkTkRenderWidget $itk_component(area).legend -rw $this-renWin2 \ |
---|
| 299 | -width 1 -height 40 |
---|
[11] | 300 | } { |
---|
| 301 | } |
---|
| 302 | pack $itk_component(legend) -side bottom -fill x |
---|
| 303 | |
---|
[193] | 304 | # |
---|
| 305 | # Create a photo for download snapshots |
---|
| 306 | # |
---|
| 307 | set _download [image create photo] |
---|
| 308 | |
---|
[11] | 309 | eval itk_initialize $args |
---|
| 310 | } |
---|
| 311 | |
---|
| 312 | # ---------------------------------------------------------------------- |
---|
| 313 | # DESTRUCTOR |
---|
| 314 | # ---------------------------------------------------------------------- |
---|
| 315 | itcl::body Rappture::ContourResult::destructor {} { |
---|
[17] | 316 | _clear |
---|
| 317 | after cancel [itcl::code $this _rebuild] |
---|
| 318 | |
---|
[11] | 319 | rename $this-renWin "" |
---|
| 320 | rename $this-ren "" |
---|
| 321 | rename $this-iren "" |
---|
| 322 | |
---|
| 323 | rename $this-renWin2 "" |
---|
| 324 | rename $this-ren2 "" |
---|
| 325 | rename $this-iren2 "" |
---|
[193] | 326 | |
---|
| 327 | image delete $_download |
---|
[11] | 328 | } |
---|
| 329 | |
---|
| 330 | # ---------------------------------------------------------------------- |
---|
| 331 | # USAGE: add <dataobj> ?<settings>? |
---|
| 332 | # |
---|
| 333 | # Clients use this to add a data object to the plot. The optional |
---|
| 334 | # <settings> are used to configure the plot. Allowed settings are |
---|
[13] | 335 | # -color, -brightness, -width, -linestyle, and -raise. |
---|
[11] | 336 | # ---------------------------------------------------------------------- |
---|
| 337 | itcl::body Rappture::ContourResult::add {dataobj {settings ""}} { |
---|
| 338 | array set params { |
---|
[1342] | 339 | -color auto |
---|
| 340 | -width 1 |
---|
| 341 | -linestyle solid |
---|
| 342 | -brightness 0 |
---|
| 343 | -raise 0 |
---|
| 344 | -description "" |
---|
| 345 | -param "" |
---|
[11] | 346 | } |
---|
| 347 | foreach {opt val} $settings { |
---|
[1342] | 348 | if {![info exists params($opt)]} { |
---|
| 349 | error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]" |
---|
| 350 | } |
---|
| 351 | set params($opt) $val |
---|
[11] | 352 | } |
---|
[64] | 353 | if {$params(-color) == "auto" || $params(-color) == "autoreset"} { |
---|
[1342] | 354 | # can't handle -autocolors yet |
---|
| 355 | set params(-color) black |
---|
[64] | 356 | } |
---|
[11] | 357 | |
---|
| 358 | set pos [lsearch -exact $dataobj $_dlist] |
---|
| 359 | if {$pos < 0} { |
---|
[1342] | 360 | lappend _dlist $dataobj |
---|
| 361 | set _obj2color($dataobj) $params(-color) |
---|
| 362 | set _obj2width($dataobj) $params(-width) |
---|
| 363 | set _obj2raise($dataobj) $params(-raise) |
---|
[11] | 364 | |
---|
[1342] | 365 | after cancel [itcl::code $this _rebuild] |
---|
| 366 | after idle [itcl::code $this _rebuild] |
---|
[11] | 367 | } |
---|
| 368 | } |
---|
| 369 | |
---|
| 370 | # ---------------------------------------------------------------------- |
---|
[13] | 371 | # USAGE: get |
---|
| 372 | # |
---|
| 373 | # Clients use this to query the list of objects being plotted, in |
---|
| 374 | # order from bottom to top of this result. |
---|
| 375 | # ---------------------------------------------------------------------- |
---|
| 376 | itcl::body Rappture::ContourResult::get {} { |
---|
| 377 | # put the dataobj list in order according to -raise options |
---|
| 378 | set dlist $_dlist |
---|
| 379 | foreach obj $dlist { |
---|
[1342] | 380 | if {[info exists _obj2raise($obj)] && $_obj2raise($obj)} { |
---|
| 381 | set i [lsearch -exact $dlist $obj] |
---|
| 382 | if {$i >= 0} { |
---|
| 383 | set dlist [lreplace $dlist $i $i] |
---|
| 384 | lappend dlist $obj |
---|
| 385 | } |
---|
| 386 | } |
---|
[13] | 387 | } |
---|
| 388 | return $dlist |
---|
| 389 | } |
---|
| 390 | |
---|
| 391 | # ---------------------------------------------------------------------- |
---|
[11] | 392 | # USAGE: delete ?<dataobj1> <dataobj2> ...? |
---|
| 393 | # |
---|
| 394 | # Clients use this to delete a dataobj from the plot. If no dataobjs |
---|
| 395 | # are specified, then all dataobjs are deleted. |
---|
| 396 | # ---------------------------------------------------------------------- |
---|
| 397 | itcl::body Rappture::ContourResult::delete {args} { |
---|
| 398 | if {[llength $args] == 0} { |
---|
[1342] | 399 | set args $_dlist |
---|
[11] | 400 | } |
---|
| 401 | |
---|
| 402 | # delete all specified dataobjs |
---|
| 403 | set changed 0 |
---|
| 404 | foreach dataobj $args { |
---|
[1342] | 405 | set pos [lsearch -exact $_dlist $dataobj] |
---|
| 406 | if {$pos >= 0} { |
---|
| 407 | set _dlist [lreplace $_dlist $pos $pos] |
---|
| 408 | catch {unset _obj2color($dataobj)} |
---|
| 409 | catch {unset _obj2width($dataobj)} |
---|
| 410 | catch {unset _obj2raise($dataobj)} |
---|
| 411 | set changed 1 |
---|
| 412 | } |
---|
[11] | 413 | } |
---|
| 414 | |
---|
| 415 | # if anything changed, then rebuild the plot |
---|
| 416 | if {$changed} { |
---|
[1342] | 417 | after cancel [itcl::code $this _rebuild] |
---|
| 418 | after idle [itcl::code $this _rebuild] |
---|
[11] | 419 | } |
---|
| 420 | } |
---|
| 421 | |
---|
| 422 | # ---------------------------------------------------------------------- |
---|
| 423 | # USAGE: scale ?<data1> <data2> ...? |
---|
| 424 | # |
---|
| 425 | # Sets the default limits for the overall plot according to the |
---|
| 426 | # limits of the data for all of the given <data> objects. This |
---|
| 427 | # accounts for all objects--even those not showing on the screen. |
---|
| 428 | # Because of this, the limits are appropriate for all objects as |
---|
| 429 | # the user scans through data in the ResultSet viewer. |
---|
| 430 | # ---------------------------------------------------------------------- |
---|
| 431 | itcl::body Rappture::ContourResult::scale {args} { |
---|
[16] | 432 | foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} { |
---|
[1342] | 433 | set _limits($val) "" |
---|
[16] | 434 | } |
---|
[11] | 435 | foreach obj $args { |
---|
[1342] | 436 | foreach axis {x y z v} { |
---|
| 437 | foreach {min max} [$obj limits $axis] break |
---|
| 438 | if {"" != $min && "" != $max} { |
---|
| 439 | if {"" == $_limits(${axis}min)} { |
---|
| 440 | set _limits(${axis}min) $min |
---|
| 441 | set _limits(${axis}max) $max |
---|
| 442 | } else { |
---|
| 443 | if {$min < $_limits(${axis}min)} { |
---|
| 444 | set _limits(${axis}min) $min |
---|
| 445 | } |
---|
| 446 | if {$max > $_limits(${axis}max)} { |
---|
| 447 | set _limits(${axis}max) $max |
---|
| 448 | } |
---|
| 449 | } |
---|
| 450 | } |
---|
| 451 | } |
---|
[11] | 452 | } |
---|
| 453 | _fixLimits |
---|
| 454 | } |
---|
| 455 | |
---|
| 456 | # ---------------------------------------------------------------------- |
---|
[193] | 457 | # USAGE: download coming |
---|
[464] | 458 | # USAGE: download controls <downloadCommand> |
---|
[193] | 459 | # USAGE: download now |
---|
[50] | 460 | # |
---|
| 461 | # Clients use this method to create a downloadable representation |
---|
| 462 | # of the plot. Returns a list of the form {ext string}, where |
---|
| 463 | # "ext" is the file extension (indicating the type of data) and |
---|
| 464 | # "string" is the data itself. |
---|
| 465 | # ---------------------------------------------------------------------- |
---|
[464] | 466 | itcl::body Rappture::ContourResult::download {option args} { |
---|
[193] | 467 | switch $option { |
---|
[1342] | 468 | coming { |
---|
| 469 | if {[catch {blt::winop snap $itk_component(area) $_download}]} { |
---|
| 470 | $_download configure -width 1 -height 1 |
---|
| 471 | $_download put #000000 |
---|
| 472 | } |
---|
| 473 | } |
---|
| 474 | controls { |
---|
| 475 | # no controls for this download yet |
---|
| 476 | return "" |
---|
| 477 | } |
---|
| 478 | now { |
---|
[1343] | 479 | # Get the image data (as base64) and decode it back to binary. |
---|
| 480 | # This is better than writing to temporary files. When we switch |
---|
| 481 | # to the BLT picture image it won't be necessary to decode the |
---|
| 482 | # image data. |
---|
[1342] | 483 | set bytes [$_download data -format "jpeg -quality 100"] |
---|
| 484 | set bytes [Rappture::encoding::decode -as b64 $bytes] |
---|
| 485 | return [list .jpg $bytes] |
---|
| 486 | } |
---|
| 487 | default { |
---|
| 488 | error "bad option \"$option\": should be coming, controls, now" |
---|
| 489 | } |
---|
[193] | 490 | } |
---|
[50] | 491 | } |
---|
| 492 | |
---|
| 493 | # ---------------------------------------------------------------------- |
---|
[11] | 494 | # USAGE: _rebuild |
---|
| 495 | # |
---|
| 496 | # Called automatically whenever something changes that affects the |
---|
| 497 | # data in the widget. Clears any existing data and rebuilds the |
---|
| 498 | # widget to display new data. |
---|
| 499 | # ---------------------------------------------------------------------- |
---|
| 500 | itcl::body Rappture::ContourResult::_rebuild {} { |
---|
[17] | 501 | _clear |
---|
[136] | 502 | set id 0 |
---|
[11] | 503 | |
---|
[16] | 504 | # determine the dimensionality from the topmost (raised) object |
---|
| 505 | set dlist [get] |
---|
| 506 | set dataobj [lindex $dlist end] |
---|
| 507 | if {$dataobj != ""} { |
---|
[1342] | 508 | set _dims [lindex [lsort [$dataobj components -dimensions]] end] |
---|
[16] | 509 | } else { |
---|
[1342] | 510 | set _dims "0D" |
---|
[16] | 511 | } |
---|
| 512 | |
---|
[136] | 513 | # |
---|
| 514 | # LOOKUP TABLE FOR COLOR CONTOURS |
---|
| 515 | # |
---|
| 516 | # use vmin/vmax if possible, otherwise get from data |
---|
| 517 | if {$_limits(vmin) == "" || $_limits(vmax) == ""} { |
---|
[1342] | 518 | set v0 0 |
---|
| 519 | set v1 1 |
---|
| 520 | if {[info exists _obj2vtk($dataobj)]} { |
---|
| 521 | set pd [lindex $_obj2vtk($dataobj) 0] |
---|
| 522 | if {"" != $pd} { |
---|
| 523 | foreach {v0 v1} [$pd GetScalarRange] break |
---|
| 524 | } |
---|
| 525 | } |
---|
[136] | 526 | } else { |
---|
[1342] | 527 | set v0 $_limits(vmin) |
---|
| 528 | set v1 $_limits(vmax) |
---|
[136] | 529 | } |
---|
| 530 | |
---|
| 531 | set lu $this-lookup$id |
---|
| 532 | vtkLookupTable $lu |
---|
| 533 | $lu SetTableRange $v0 $v1 |
---|
| 534 | $lu SetHueRange 0.66667 0.0 |
---|
| 535 | $lu Build |
---|
| 536 | |
---|
| 537 | lappend _obj2vtk($dataobj) $lu |
---|
| 538 | |
---|
| 539 | if {$_dims == "3D"} { |
---|
[1342] | 540 | # |
---|
| 541 | # 3D LIGHTS (on both sides of all three axes) |
---|
| 542 | # |
---|
| 543 | set x0 $_limits(xmin) |
---|
| 544 | set x1 $_limits(xmax) |
---|
| 545 | set xm [expr {0.5*($x0+$x1)}] |
---|
| 546 | set y0 $_limits(ymin) |
---|
| 547 | set y1 $_limits(ymax) |
---|
| 548 | set ym [expr {0.5*($y0+$y1)}] |
---|
| 549 | set z0 $_limits(zmin) |
---|
| 550 | set z1 $_limits(zmax) |
---|
| 551 | set zm [expr {0.5*($z0+$z1)}] |
---|
| 552 | set xr [expr {$x1-$x0}] |
---|
| 553 | set yr [expr {$y1-$y0}] |
---|
| 554 | set zr [expr {$z1-$z0}] |
---|
[136] | 555 | |
---|
[1342] | 556 | set lt $this-light$id |
---|
| 557 | vtkLight $lt |
---|
| 558 | $lt SetColor 1 1 1 |
---|
| 559 | $lt SetAttenuationValues 0 0 0 |
---|
| 560 | $lt SetFocalPoint $xm $ym $zm |
---|
| 561 | $lt SetLightTypeToHeadlight |
---|
| 562 | $this-ren AddLight $lt |
---|
| 563 | lappend _lights($this-ren) $lt |
---|
[136] | 564 | |
---|
| 565 | } else { |
---|
| 566 | } |
---|
| 567 | |
---|
[11] | 568 | # scan through all data objects and build the contours |
---|
[136] | 569 | set firstobj 1 |
---|
[13] | 570 | foreach dataobj [get] { |
---|
[1342] | 571 | foreach comp [$dataobj components] { |
---|
| 572 | # |
---|
| 573 | # Add color contours. |
---|
| 574 | # |
---|
| 575 | if {$firstobj} { |
---|
| 576 | if {$_dims == "3D"} { |
---|
| 577 | pack $itk_component(slicers) -side bottom -padx 4 -pady 4 |
---|
| 578 | pack $itk_component(reset) -side left |
---|
| 579 | pack $itk_component(zoomin) -side left |
---|
| 580 | pack $itk_component(zoomout) -side left |
---|
[11] | 581 | |
---|
[1342] | 582 | # |
---|
| 583 | # 3D DATA SET |
---|
| 584 | # |
---|
| 585 | set mesh [$dataobj mesh $comp] |
---|
| 586 | if {"" == $mesh} { |
---|
| 587 | set x [expr {[winfo rootx $itk_component(area)]+10}] |
---|
| 588 | set y [expr {[winfo rooty $itk_component(area)]+10}] |
---|
| 589 | Rappture::Tooltip::cue @$x,$y "This data requires the visualization server, and that appears to be down. Please try your simulation again later." |
---|
| 590 | return |
---|
| 591 | } |
---|
| 592 | switch -- [$mesh GetClassName] { |
---|
| 593 | vtkPoints { |
---|
| 594 | # handle cloud of 3D points |
---|
| 595 | set pd $this-polydata$id |
---|
| 596 | vtkPolyData $pd |
---|
| 597 | $pd SetPoints $mesh |
---|
| 598 | [$pd GetPointData] SetScalars [$dataobj values $comp] |
---|
[17] | 599 | |
---|
[1342] | 600 | set tr $this-triangles$id |
---|
| 601 | vtkDelaunay3D $tr |
---|
| 602 | $tr SetInput $pd |
---|
| 603 | $tr SetTolerance 0.0000000000001 |
---|
| 604 | set source [$tr GetOutput] |
---|
[17] | 605 | |
---|
[1342] | 606 | set mp $this-mapper$id |
---|
| 607 | vtkPolyDataMapper $mp |
---|
[17] | 608 | |
---|
[1342] | 609 | lappend _obj2vtk($dataobj) $pd $tr $mp |
---|
| 610 | } |
---|
| 611 | vtkUnstructuredGrid { |
---|
| 612 | # handle 3D grid with connectivity |
---|
| 613 | set gr $this-grdata$id |
---|
| 614 | vtkUnstructuredGrid $gr |
---|
| 615 | $gr ShallowCopy $mesh |
---|
| 616 | [$gr GetPointData] SetScalars [$dataobj values $comp] |
---|
| 617 | set source $gr |
---|
[17] | 618 | |
---|
[1342] | 619 | lappend _obj2vtk($dataobj) $gr |
---|
| 620 | } |
---|
| 621 | vtkRectilinearGrid { |
---|
| 622 | # handle 3D grid with connectivity |
---|
| 623 | set gr $this-grdata$id |
---|
| 624 | vtkRectilinearGrid $gr |
---|
| 625 | $gr ShallowCopy $mesh |
---|
| 626 | [$gr GetPointData] SetScalars [$dataobj values $comp] |
---|
| 627 | set source $gr |
---|
[136] | 628 | |
---|
[1342] | 629 | lappend _obj2vtk($dataobj) $gr |
---|
| 630 | } |
---|
| 631 | default { |
---|
| 632 | error "don't know how to handle [$mesh GetClassName] data" |
---|
| 633 | } |
---|
| 634 | } |
---|
[17] | 635 | |
---|
[1342] | 636 | # |
---|
| 637 | # 3D ISOSURFACES |
---|
| 638 | # |
---|
| 639 | set iso $this-iso$id |
---|
| 640 | vtkContourFilter $iso |
---|
| 641 | $iso SetInput $source |
---|
[16] | 642 | |
---|
[1342] | 643 | set mp $this-isomap$id |
---|
| 644 | vtkPolyDataMapper $mp |
---|
| 645 | $mp SetInput [$iso GetOutput] |
---|
[16] | 646 | |
---|
[1342] | 647 | set ac $this-isoactor$id |
---|
| 648 | vtkActor $ac |
---|
| 649 | $ac SetMapper $mp |
---|
| 650 | [$ac GetProperty] SetOpacity 0.3 |
---|
| 651 | [$ac GetProperty] SetDiffuse 0.5 |
---|
| 652 | [$ac GetProperty] SetAmbient 0.7 |
---|
| 653 | [$ac GetProperty] SetSpecular 10.0 |
---|
| 654 | [$ac GetProperty] SetSpecularPower 200.0 |
---|
| 655 | $this-ren AddActor $ac |
---|
[136] | 656 | |
---|
[1342] | 657 | lappend _obj2vtk($dataobj) $iso $mp $ac |
---|
| 658 | lappend _actors($this-ren) $ac |
---|
[16] | 659 | |
---|
[1342] | 660 | catch {unset style} |
---|
| 661 | array set style [lindex [$dataobj components -style $comp] 0] |
---|
| 662 | if {[info exists style(-color)]} { |
---|
| 663 | $mp ScalarVisibilityOff ;# take color from actor |
---|
| 664 | eval [$ac GetProperty] SetColor [_color2rgb $style(-color)] |
---|
| 665 | } |
---|
[16] | 666 | |
---|
[1342] | 667 | if {[info exists style(-opacity)]} { |
---|
| 668 | [$ac GetProperty] SetOpacity $style(-opacity) |
---|
| 669 | } |
---|
[16] | 670 | |
---|
[1342] | 671 | set levels 5 |
---|
| 672 | if {[info exists style(-levels)]} { |
---|
| 673 | set levels $style(-levels) |
---|
| 674 | } |
---|
| 675 | if {$levels == 1} { |
---|
| 676 | $iso SetValue 0 [expr {0.5*($v1-$v0)+$v0}] |
---|
| 677 | } else { |
---|
| 678 | $iso GenerateValues [expr {$levels+2}] $v0 $v1 |
---|
| 679 | } |
---|
[16] | 680 | |
---|
[1342] | 681 | # |
---|
| 682 | # 3D CUT PLANES |
---|
| 683 | # |
---|
| 684 | if {$id == 0} { |
---|
| 685 | foreach axis {x y z} norm {{1 0 0} {0 1 0} {0 0 1}} { |
---|
| 686 | set pl $this-${axis}cutplane$id |
---|
| 687 | vtkPlane $pl |
---|
| 688 | eval $pl SetNormal $norm |
---|
| 689 | set _slicer(${axis}plane) $pl |
---|
[16] | 690 | |
---|
[1342] | 691 | set ct $this-${axis}cutter$id |
---|
| 692 | vtkCutter $ct |
---|
| 693 | $ct SetInput $source |
---|
| 694 | $ct SetCutFunction $pl |
---|
[16] | 695 | |
---|
[1342] | 696 | set mp $this-${axis}cutmapper$id |
---|
| 697 | vtkPolyDataMapper $mp |
---|
| 698 | $mp SetInput [$ct GetOutput] |
---|
| 699 | $mp SetScalarRange $v0 $v1 |
---|
| 700 | $mp SetLookupTable $lu |
---|
[16] | 701 | |
---|
[1342] | 702 | lappend _obj2vtk($dataobj) $pl $ct $mp |
---|
[136] | 703 | |
---|
[1342] | 704 | set ac $this-${axis}actor$id |
---|
| 705 | vtkActor $ac |
---|
| 706 | $ac VisibilityOff |
---|
| 707 | $ac SetMapper $mp |
---|
| 708 | $ac SetPosition 0 0 0 |
---|
| 709 | [$ac GetProperty] SetColor 0 0 0 |
---|
| 710 | set _slicer(${axis}slice) $ac |
---|
[136] | 711 | |
---|
[1342] | 712 | $this-ren AddActor $ac |
---|
| 713 | lappend _actors($this-ren) $ac |
---|
| 714 | lappend _obj2vtk($dataobj) $ac |
---|
| 715 | } |
---|
[136] | 716 | |
---|
[1342] | 717 | # |
---|
| 718 | # CUT PLANE READOUT |
---|
| 719 | # |
---|
| 720 | set tx $this-text$id |
---|
| 721 | vtkTextMapper $tx |
---|
| 722 | set tp [$tx GetTextProperty] |
---|
| 723 | eval $tp SetColor [_color2rgb $itk_option(-plotforeground)] |
---|
| 724 | $tp SetVerticalJustificationToTop |
---|
| 725 | set _slicer(readout) $tx |
---|
[136] | 726 | |
---|
[1342] | 727 | set txa $this-texta$id |
---|
| 728 | vtkActor2D $txa |
---|
| 729 | $txa SetMapper $tx |
---|
| 730 | [$txa GetPositionCoordinate] \ |
---|
| 731 | SetCoordinateSystemToNormalizedDisplay |
---|
| 732 | [$txa GetPositionCoordinate] SetValue 0.02 0.98 |
---|
[136] | 733 | |
---|
[1342] | 734 | $this-ren AddActor $txa |
---|
| 735 | lappend _actors($this-ren) $txa |
---|
[136] | 736 | |
---|
[1342] | 737 | lappend _obj2vtk($dataobj) $tx $txa |
---|
[136] | 738 | |
---|
[1342] | 739 | # turn off all slicers by default |
---|
| 740 | foreach axis {x y z} { |
---|
| 741 | $itk_component(${axis}slicer) configure -state normal |
---|
| 742 | $itk_component(${axis}slicer) set 50 |
---|
| 743 | _slice move $axis 50 |
---|
| 744 | _slice axis $axis off |
---|
| 745 | } |
---|
| 746 | } |
---|
[136] | 747 | |
---|
[1342] | 748 | } else { |
---|
| 749 | pack forget $itk_component(slicers) |
---|
| 750 | pack $itk_component(reset) -side top |
---|
| 751 | pack $itk_component(zoomin) -side top |
---|
| 752 | pack $itk_component(zoomout) -side top |
---|
[16] | 753 | |
---|
[1342] | 754 | set pd $this-polydata$id |
---|
| 755 | vtkPolyData $pd |
---|
| 756 | $pd SetPoints [$dataobj mesh $comp] |
---|
| 757 | [$pd GetPointData] SetScalars [$dataobj values $comp] |
---|
[17] | 758 | |
---|
[1342] | 759 | set tr $this-triangles$id |
---|
| 760 | vtkDelaunay2D $tr |
---|
| 761 | $tr SetInput $pd |
---|
| 762 | $tr SetTolerance 0.0000000000001 |
---|
| 763 | set source [$tr GetOutput] |
---|
[17] | 764 | |
---|
[1342] | 765 | set mp $this-mapper$id |
---|
| 766 | vtkPolyDataMapper $mp |
---|
| 767 | $mp SetInput $source |
---|
| 768 | $mp SetScalarRange $v0 $v1 |
---|
| 769 | $mp SetLookupTable $lu |
---|
[16] | 770 | |
---|
[1342] | 771 | set ac $this-actor$id |
---|
| 772 | vtkActor $ac |
---|
| 773 | $ac SetMapper $mp |
---|
| 774 | $ac SetPosition 0 0 0 |
---|
| 775 | [$ac GetProperty] SetColor 0 0 0 |
---|
| 776 | $this-ren AddActor $ac |
---|
| 777 | lappend _actors($this-ren) $ac |
---|
[16] | 778 | |
---|
[1342] | 779 | lappend _obj2vtk($dataobj) $pd $tr $mp $ac |
---|
| 780 | } |
---|
| 781 | } else { |
---|
| 782 | # |
---|
| 783 | # Add color lines |
---|
| 784 | # |
---|
| 785 | set cf $this-clfilter$id |
---|
| 786 | vtkContourFilter $cf |
---|
| 787 | $cf SetInput $source |
---|
| 788 | $cf GenerateValues 20 $v0 $v1 |
---|
[11] | 789 | |
---|
[1342] | 790 | set mp $this-clmapper$id |
---|
| 791 | vtkPolyDataMapper $mp |
---|
| 792 | $mp SetInput [$cf GetOutput] |
---|
| 793 | $mp SetScalarRange $v0 $v1 |
---|
| 794 | $mp SetLookupTable $lu |
---|
[11] | 795 | |
---|
[1342] | 796 | set ac $this-clactor$id |
---|
| 797 | vtkActor $ac |
---|
| 798 | $ac SetMapper $mp |
---|
| 799 | [$ac GetProperty] SetColor 1 1 1 |
---|
| 800 | $ac SetPosition 0 0 0 |
---|
| 801 | $this-ren AddActor $ac |
---|
| 802 | lappend _actors($this-ren) $ac |
---|
[11] | 803 | |
---|
[1342] | 804 | lappend _obj2vtk($dataobj) $cf $mp $ac |
---|
| 805 | } |
---|
[11] | 806 | |
---|
[1342] | 807 | # |
---|
| 808 | # Add an outline around the data |
---|
| 809 | # |
---|
| 810 | if {$id == 0} { |
---|
| 811 | set olf $this-olfilter$id |
---|
| 812 | vtkOutlineFilter $olf |
---|
| 813 | $olf SetInput $source |
---|
[11] | 814 | |
---|
[1342] | 815 | set olm $this-olmapper$id |
---|
| 816 | vtkPolyDataMapper $olm |
---|
| 817 | $olm SetInput [$olf GetOutput] |
---|
[11] | 818 | |
---|
[1342] | 819 | set ola $this-olactor$id |
---|
| 820 | vtkActor $ola |
---|
| 821 | $ola SetMapper $olm |
---|
| 822 | eval [$ola GetProperty] SetColor [_color2rgb $itk_option(-plotforeground)] |
---|
| 823 | $this-ren AddActor $ola |
---|
| 824 | lappend _actors($this-ren) $ola |
---|
[11] | 825 | |
---|
[1342] | 826 | lappend _obj2vtk($dataobj) $olf $olm $ola |
---|
[11] | 827 | |
---|
[1342] | 828 | if {$_dims == "3D"} { |
---|
| 829 | # pick a good scale factor for text |
---|
| 830 | if {$xr < $yr} { |
---|
| 831 | set tscale [expr {0.1*$xr}] |
---|
| 832 | } else { |
---|
| 833 | set tscale [expr {0.1*$yr}] |
---|
| 834 | } |
---|
[136] | 835 | |
---|
[1342] | 836 | foreach {i axis px py pz rx ry rz} { |
---|
| 837 | 0 x $xm 0 0 90 0 0 |
---|
| 838 | 1 y 0 $ym 0 90 -90 0 |
---|
| 839 | 2 z $x1 0 $zm 90 0 -45 |
---|
| 840 | } { |
---|
| 841 | set length "[expr {[set ${axis}1]-[set ${axis}0]}]" |
---|
[136] | 842 | |
---|
[1342] | 843 | set vtx $this-${axis}label$id |
---|
| 844 | vtkVectorText $vtx |
---|
| 845 | $vtx SetText "$axis" |
---|
[136] | 846 | |
---|
[1342] | 847 | set vmp $this-${axis}lmap$id |
---|
| 848 | vtkPolyDataMapper $vmp |
---|
| 849 | $vmp SetInput [$vtx GetOutput] |
---|
[136] | 850 | |
---|
[1342] | 851 | set vac $this-${axis}lact$id |
---|
| 852 | vtkActor $vac |
---|
| 853 | $vac SetMapper $vmp |
---|
| 854 | $vac SetPosition [expr $px] [expr $py] [expr $pz] |
---|
| 855 | $vac SetOrientation $rx $ry $rz |
---|
| 856 | $vac SetScale $tscale |
---|
| 857 | $this-ren AddActor $vac |
---|
[136] | 858 | |
---|
[1342] | 859 | lappend _obj2vtk($dataobj) $vtx $vmp $vac |
---|
| 860 | lappend _actors($this-ren) $vac |
---|
[136] | 861 | |
---|
[1342] | 862 | $vmp Update |
---|
| 863 | foreach {xx0 xx1 yy0 yy1 zz0 zz1} [$vac GetBounds] break |
---|
| 864 | switch -- $axis { |
---|
| 865 | x { |
---|
| 866 | set dx [expr {-0.5*($xx1-$xx0)}] |
---|
| 867 | set dy 0 |
---|
| 868 | set dz [expr {1.3*($zz0-$zz1)}] |
---|
| 869 | } |
---|
| 870 | y { |
---|
| 871 | set dx 0 |
---|
| 872 | set dy [expr {0.5*($yy1-$yy0)}] |
---|
| 873 | set dz [expr {$zz0-$zz1}] |
---|
| 874 | } |
---|
| 875 | z { |
---|
| 876 | set dx [expr {0.2*$tscale}] |
---|
| 877 | set dy $dx |
---|
| 878 | set dz [expr {-0.5*($zz1-$zz0)}] |
---|
| 879 | } |
---|
| 880 | } |
---|
| 881 | $vac AddPosition $dx $dy $dz |
---|
| 882 | } |
---|
| 883 | } |
---|
| 884 | } |
---|
[136] | 885 | |
---|
[1342] | 886 | # |
---|
| 887 | # Add a legend with the scale. |
---|
| 888 | # |
---|
| 889 | if {$id == 0} { |
---|
| 890 | set lg $this-legend$id |
---|
| 891 | vtkScalarBarActor $lg |
---|
| 892 | $lg SetLookupTable $lu |
---|
| 893 | [$lg GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport |
---|
| 894 | [$lg GetPositionCoordinate] SetValue 0.1 0.1 |
---|
| 895 | $lg SetOrientationToHorizontal |
---|
| 896 | $lg SetWidth 0.8 |
---|
| 897 | $lg SetHeight 1.0 |
---|
[11] | 898 | |
---|
[1342] | 899 | set tp [$lg GetLabelTextProperty] |
---|
| 900 | eval $tp SetColor [_color2rgb $itk_option(-plotforeground)] |
---|
| 901 | $tp BoldOff |
---|
| 902 | $tp ItalicOff |
---|
| 903 | $tp ShadowOff |
---|
| 904 | #eval $tp SetShadowColor [_color2rgb gray] |
---|
[11] | 905 | |
---|
[1342] | 906 | $this-ren2 AddActor2D $lg |
---|
| 907 | lappend _actors($this-ren2) $lg |
---|
| 908 | lappend _obj2vtk($dataobj) $lg |
---|
| 909 | } |
---|
[11] | 910 | |
---|
[1342] | 911 | incr id |
---|
| 912 | } |
---|
| 913 | set firstobj 0 |
---|
[11] | 914 | } |
---|
| 915 | _fixLimits |
---|
[16] | 916 | _zoom reset |
---|
| 917 | |
---|
[645] | 918 | # |
---|
| 919 | # HACK ALERT! A single ResetCamera doesn't seem to work for |
---|
| 920 | # some contour data. You have to do it multiple times to |
---|
| 921 | # get to the right zoom factor on data. I hope 20 times is |
---|
| 922 | # enough. I hate Vtk sometimes... |
---|
| 923 | # |
---|
| 924 | for {set i 0} {$i < 20} {incr i} { |
---|
[1342] | 925 | $this-ren ResetCamera |
---|
| 926 | [$this-ren GetActiveCamera] Zoom 1.5 |
---|
[645] | 927 | } |
---|
| 928 | |
---|
[17] | 929 | # prevent interactions -- use our own |
---|
| 930 | blt::busy hold $itk_component(area) -cursor left_ptr |
---|
| 931 | bind $itk_component(area)_Busy <ButtonPress> \ |
---|
[1342] | 932 | [itcl::code $this _move click %x %y] |
---|
[17] | 933 | bind $itk_component(area)_Busy <B1-Motion> \ |
---|
[1342] | 934 | [itcl::code $this _move drag %x %y] |
---|
[17] | 935 | bind $itk_component(area)_Busy <ButtonRelease> \ |
---|
[1342] | 936 | [itcl::code $this _move release %x %y] |
---|
[17] | 937 | } |
---|
| 938 | |
---|
| 939 | # ---------------------------------------------------------------------- |
---|
| 940 | # USAGE: _clear |
---|
| 941 | # |
---|
| 942 | # Used internally to clear the drawing area and tear down all vtk |
---|
| 943 | # objects in the current scene. |
---|
| 944 | # ---------------------------------------------------------------------- |
---|
| 945 | itcl::body Rappture::ContourResult::_clear {} { |
---|
| 946 | # clear out any old constructs |
---|
| 947 | foreach ren [array names _actors] { |
---|
[1342] | 948 | foreach actor $_actors($ren) { |
---|
| 949 | $ren RemoveActor $actor |
---|
| 950 | } |
---|
| 951 | set _actors($ren) "" |
---|
[16] | 952 | } |
---|
[17] | 953 | foreach ren [array names _lights] { |
---|
[1342] | 954 | foreach light $_lights($ren) { |
---|
| 955 | $ren RemoveLight $light |
---|
| 956 | rename $light "" |
---|
| 957 | } |
---|
| 958 | set _lights($ren) "" |
---|
[17] | 959 | } |
---|
| 960 | foreach dataobj [array names _obj2vtk] { |
---|
[1342] | 961 | foreach cmd $_obj2vtk($dataobj) { |
---|
| 962 | rename $cmd "" |
---|
| 963 | } |
---|
| 964 | set _obj2vtk($dataobj) "" |
---|
[17] | 965 | } |
---|
[136] | 966 | set _slicer(xplane) "" |
---|
| 967 | set _slicer(yplane) "" |
---|
| 968 | set _slicer(zplane) "" |
---|
| 969 | set _slicer(xslice) "" |
---|
| 970 | set _slicer(yslice) "" |
---|
| 971 | set _slicer(zslice) "" |
---|
[17] | 972 | set _slicer(readout) "" |
---|
[11] | 973 | } |
---|
| 974 | |
---|
| 975 | # ---------------------------------------------------------------------- |
---|
| 976 | # USAGE: _zoom in |
---|
| 977 | # USAGE: _zoom out |
---|
| 978 | # USAGE: _zoom reset |
---|
| 979 | # |
---|
| 980 | # Called automatically when the user clicks on one of the zoom |
---|
| 981 | # controls for this widget. Changes the zoom for the current view. |
---|
| 982 | # ---------------------------------------------------------------------- |
---|
| 983 | itcl::body Rappture::ContourResult::_zoom {option} { |
---|
| 984 | switch -- $option { |
---|
[1342] | 985 | in { |
---|
| 986 | [$this-ren GetActiveCamera] Zoom 1.25 |
---|
| 987 | $this-renWin Render |
---|
| 988 | } |
---|
| 989 | out { |
---|
| 990 | [$this-ren GetActiveCamera] Zoom 0.8 |
---|
| 991 | $this-renWin Render |
---|
| 992 | } |
---|
| 993 | reset { |
---|
| 994 | if {$_dims == "3D"} { |
---|
| 995 | [$this-ren GetActiveCamera] SetViewAngle 30 |
---|
| 996 | $this-ren ResetCamera |
---|
| 997 | _3dView 45 45 |
---|
| 998 | } else { |
---|
| 999 | $this-ren ResetCamera |
---|
| 1000 | [$this-ren GetActiveCamera] Zoom 1.5 |
---|
| 1001 | } |
---|
| 1002 | $this-renWin Render |
---|
| 1003 | $this-renWin2 Render |
---|
| 1004 | } |
---|
[11] | 1005 | } |
---|
| 1006 | } |
---|
| 1007 | |
---|
| 1008 | # ---------------------------------------------------------------------- |
---|
| 1009 | # USAGE: _move click <x> <y> |
---|
| 1010 | # USAGE: _move drag <x> <y> |
---|
| 1011 | # USAGE: _move release <x> <y> |
---|
| 1012 | # |
---|
| 1013 | # Called automatically when the user clicks/drags/releases in the |
---|
| 1014 | # plot area. Moves the plot according to the user's actions. |
---|
| 1015 | # ---------------------------------------------------------------------- |
---|
| 1016 | itcl::body Rappture::ContourResult::_move {option x y} { |
---|
| 1017 | switch -- $option { |
---|
[1342] | 1018 | click { |
---|
| 1019 | blt::busy configure $itk_component(area) -cursor fleur |
---|
| 1020 | set _click(x) $x |
---|
| 1021 | set _click(y) $y |
---|
| 1022 | set _click(theta) $_view(theta) |
---|
| 1023 | set _click(phi) $_view(phi) |
---|
| 1024 | } |
---|
| 1025 | drag { |
---|
| 1026 | if {[array size _click] == 0} { |
---|
| 1027 | _move click $x $y |
---|
| 1028 | } else { |
---|
| 1029 | set w [winfo width $itk_component(plot)] |
---|
| 1030 | set h [winfo height $itk_component(plot)] |
---|
| 1031 | set scalex [expr {$_limits(xmax)-$_limits(xmin)}] |
---|
| 1032 | set scaley [expr {$_limits(ymax)-$_limits(ymin)}] |
---|
| 1033 | set dx [expr {double($x-$_click(x))/$w*$scalex}] |
---|
| 1034 | set dy [expr {double($y-$_click(y))/$h*$scaley}] |
---|
[17] | 1035 | |
---|
[1342] | 1036 | if {$_dims == "2D"} { |
---|
| 1037 | # |
---|
| 1038 | # Shift the contour plot in 2D |
---|
| 1039 | # |
---|
| 1040 | foreach actor $_actors($this-ren) { |
---|
| 1041 | foreach {ax ay az} [$actor GetPosition] break |
---|
| 1042 | $actor SetPosition [expr {$ax+$dx}] [expr {$ay-$dy}] 0 |
---|
| 1043 | } |
---|
| 1044 | $this-renWin Render |
---|
| 1045 | } elseif {$_dims == "3D"} { |
---|
| 1046 | # |
---|
| 1047 | # Rotate the camera in 3D |
---|
| 1048 | # |
---|
| 1049 | set theta [expr {$_view(theta) - $dy*180}] |
---|
| 1050 | if {$theta < 2} { set theta 2 } |
---|
| 1051 | if {$theta > 178} { set theta 178 } |
---|
| 1052 | set phi [expr {$_view(phi) - $dx*360}] |
---|
[17] | 1053 | |
---|
[1342] | 1054 | _3dView $theta $phi |
---|
| 1055 | $this-renWin Render |
---|
| 1056 | } |
---|
| 1057 | set _click(x) $x |
---|
| 1058 | set _click(y) $y |
---|
| 1059 | } |
---|
| 1060 | } |
---|
| 1061 | release { |
---|
| 1062 | _move drag $x $y |
---|
| 1063 | blt::busy configure $itk_component(area) -cursor left_ptr |
---|
| 1064 | catch {unset _click} |
---|
| 1065 | } |
---|
| 1066 | default { |
---|
| 1067 | error "bad option \"$option\": should be click, drag, release" |
---|
| 1068 | } |
---|
[11] | 1069 | } |
---|
| 1070 | } |
---|
| 1071 | |
---|
| 1072 | # ---------------------------------------------------------------------- |
---|
[136] | 1073 | # USAGE: _slice axis x|y|z ?on|off|toggle? |
---|
| 1074 | # USAGE: _slice move x|y|z <newval> |
---|
[16] | 1075 | # |
---|
| 1076 | # Called automatically when the user drags the slider to move the |
---|
| 1077 | # cut plane that slices 3D data. Gets the current value from the |
---|
| 1078 | # slider and moves the cut plane to the appropriate point in the |
---|
| 1079 | # data set. |
---|
| 1080 | # ---------------------------------------------------------------------- |
---|
| 1081 | itcl::body Rappture::ContourResult::_slice {option args} { |
---|
[136] | 1082 | if {$_slicer(xplane) == ""} { |
---|
[1342] | 1083 | # no slicer? then bail out! |
---|
| 1084 | return |
---|
[16] | 1085 | } |
---|
| 1086 | switch -- $option { |
---|
[1342] | 1087 | axis { |
---|
| 1088 | if {[llength $args] < 1 || [llength $args] > 2} { |
---|
| 1089 | error "wrong # args: should be \"_slice axis x|y|z ?on|off|toggle?\"" |
---|
| 1090 | } |
---|
| 1091 | set axis [lindex $args 0] |
---|
| 1092 | set op [lindex $args 1] |
---|
| 1093 | if {$op == ""} { set op "on" } |
---|
[16] | 1094 | |
---|
[1342] | 1095 | if {[$itk_component(${axis}slice) cget -relief] == "raised"} { |
---|
| 1096 | set current "off" |
---|
| 1097 | } else { |
---|
| 1098 | set current "on" |
---|
| 1099 | } |
---|
[17] | 1100 | |
---|
[1342] | 1101 | if {$op == "toggle"} { |
---|
| 1102 | if {$current == "on"} { set op "off" } else { set op "on" } |
---|
| 1103 | } |
---|
[16] | 1104 | |
---|
[1342] | 1105 | if {$op} { |
---|
| 1106 | $itk_component(${axis}slicer) configure -state normal |
---|
| 1107 | $_slicer(${axis}slice) VisibilityOn |
---|
| 1108 | $itk_component(${axis}slice) configure -relief sunken |
---|
| 1109 | } else { |
---|
| 1110 | $itk_component(${axis}slicer) configure -state disabled |
---|
| 1111 | $_slicer(${axis}slice) VisibilityOff |
---|
| 1112 | $itk_component(${axis}slice) configure -relief raised |
---|
| 1113 | } |
---|
| 1114 | $this-renWin Render |
---|
| 1115 | } |
---|
| 1116 | move { |
---|
| 1117 | if {[llength $args] != 2} { |
---|
| 1118 | error "wrong # args: should be \"_slice move x|y|z newval\"" |
---|
| 1119 | } |
---|
| 1120 | set axis [lindex $args 0] |
---|
| 1121 | set newval [lindex $args 1] |
---|
[16] | 1122 | |
---|
[1342] | 1123 | set xm [expr {0.5*($_limits(xmax)+$_limits(xmin))}] |
---|
| 1124 | set ym [expr {0.5*($_limits(ymax)+$_limits(ymin))}] |
---|
| 1125 | set zm [expr {0.5*($_limits(zmax)+$_limits(zmin))}] |
---|
[16] | 1126 | |
---|
[1342] | 1127 | set newval [expr {0.01*($newval-50) |
---|
| 1128 | *($_limits(${axis}max)-$_limits(${axis}min)) |
---|
| 1129 | + 0.5*($_limits(${axis}max)+$_limits(${axis}min))}] |
---|
[16] | 1130 | |
---|
[1342] | 1131 | # show the current value in the readout |
---|
| 1132 | if {$_slicer(readout) != ""} { |
---|
| 1133 | $_slicer(readout) SetInput "$axis = $newval" |
---|
| 1134 | } |
---|
[16] | 1135 | |
---|
[1342] | 1136 | # keep a little inside the volume, or the slice will disappear! |
---|
| 1137 | if {$newval == $_limits(${axis}min)} { |
---|
| 1138 | set range [expr {$_limits(${axis}max)-$_limits(${axis}min)}] |
---|
| 1139 | set newval [expr {$newval + 1e-6*$range}] |
---|
| 1140 | } |
---|
[17] | 1141 | |
---|
[1342] | 1142 | # xfer new value to the proper dimension and move the cut plane |
---|
| 1143 | set ${axis}m $newval |
---|
| 1144 | $_slicer(${axis}plane) SetOrigin $xm $ym $zm |
---|
[17] | 1145 | |
---|
[1342] | 1146 | $this-renWin Render |
---|
| 1147 | } |
---|
| 1148 | default { |
---|
| 1149 | error "bad option \"$option\": should be axis or move" |
---|
| 1150 | } |
---|
[16] | 1151 | } |
---|
| 1152 | } |
---|
| 1153 | |
---|
| 1154 | # ---------------------------------------------------------------------- |
---|
[17] | 1155 | # USAGE: _3dView <theta> <phi> |
---|
| 1156 | # |
---|
| 1157 | # Used internally to change the position of the camera for 3D data |
---|
| 1158 | # sets. Sets the camera according to the angles <theta> (angle from |
---|
| 1159 | # the z-axis) and <phi> (angle from the x-axis in the x-y plane). |
---|
| 1160 | # Both angles are in degrees. |
---|
| 1161 | # ---------------------------------------------------------------------- |
---|
| 1162 | itcl::body Rappture::ContourResult::_3dView {theta phi} { |
---|
| 1163 | set deg2rad 0.0174532927778 |
---|
| 1164 | set xn [expr {sin($theta*$deg2rad)*cos($phi*$deg2rad)}] |
---|
| 1165 | set yn [expr {sin($theta*$deg2rad)*sin($phi*$deg2rad)}] |
---|
| 1166 | set zn [expr {cos($theta*$deg2rad)}] |
---|
| 1167 | |
---|
| 1168 | set xm [expr {0.5*($_limits(xmax)+$_limits(xmin))}] |
---|
| 1169 | set ym [expr {0.5*($_limits(ymax)+$_limits(ymin))}] |
---|
| 1170 | set zm [expr {0.5*($_limits(zmax)+$_limits(zmin))}] |
---|
| 1171 | |
---|
| 1172 | set cam [$this-ren GetActiveCamera] |
---|
| 1173 | set zoom [$cam GetViewAngle] |
---|
| 1174 | $cam SetViewAngle 30 |
---|
| 1175 | |
---|
| 1176 | $cam SetFocalPoint $xm $ym $zm |
---|
| 1177 | $cam SetPosition [expr {$xm-$xn}] [expr {$ym-$yn}] [expr {$zm+$zn}] |
---|
| 1178 | $cam ComputeViewPlaneNormal |
---|
| 1179 | $cam SetViewUp 0 0 1 ;# z-dir is up |
---|
| 1180 | $cam OrthogonalizeViewUp |
---|
| 1181 | $this-ren ResetCamera |
---|
| 1182 | $cam SetViewAngle $zoom |
---|
| 1183 | |
---|
| 1184 | set _view(theta) $theta |
---|
| 1185 | set _view(phi) $phi |
---|
| 1186 | } |
---|
| 1187 | |
---|
| 1188 | # ---------------------------------------------------------------------- |
---|
[11] | 1189 | # USAGE: _fixLimits |
---|
| 1190 | # |
---|
| 1191 | # Used internally to apply automatic limits to the axes for the |
---|
| 1192 | # current plot. |
---|
| 1193 | # ---------------------------------------------------------------------- |
---|
| 1194 | itcl::body Rappture::ContourResult::_fixLimits {} { |
---|
| 1195 | $this-ren ResetCamera |
---|
| 1196 | [$this-ren GetActiveCamera] Zoom 1.5 |
---|
| 1197 | $this-renWin Render |
---|
| 1198 | $this-renWin2 Render |
---|
| 1199 | } |
---|
| 1200 | |
---|
| 1201 | # ---------------------------------------------------------------------- |
---|
[136] | 1202 | # USAGE: _slicertip <axis> |
---|
| 1203 | # |
---|
| 1204 | # Used internally to generate a tooltip for the x/y/z slicer controls. |
---|
| 1205 | # Returns a message that includes the current slicer value. |
---|
| 1206 | # ---------------------------------------------------------------------- |
---|
| 1207 | itcl::body Rappture::ContourResult::_slicertip {axis} { |
---|
| 1208 | set val [$itk_component(${axis}slicer) get] |
---|
| 1209 | set val [expr {0.01*($val-50) |
---|
[1342] | 1210 | *($_limits(${axis}max)-$_limits(${axis}min)) |
---|
| 1211 | + 0.5*($_limits(${axis}max)+$_limits(${axis}min))}] |
---|
[136] | 1212 | return "Move the [string toupper $axis] cut plane.\nCurrently: $axis = $val" |
---|
| 1213 | } |
---|
| 1214 | |
---|
| 1215 | # ---------------------------------------------------------------------- |
---|
[11] | 1216 | # USAGE: _color2rgb <color> |
---|
| 1217 | # |
---|
| 1218 | # Used internally to convert a color name to a set of {r g b} values |
---|
| 1219 | # needed for vtk. Each r/g/b component is scaled in the range 0-1. |
---|
| 1220 | # ---------------------------------------------------------------------- |
---|
| 1221 | itcl::body Rappture::ContourResult::_color2rgb {color} { |
---|
| 1222 | foreach {r g b} [winfo rgb $itk_component(hull) $color] break |
---|
| 1223 | set r [expr {$r/65535.0}] |
---|
| 1224 | set g [expr {$g/65535.0}] |
---|
| 1225 | set b [expr {$b/65535.0}] |
---|
| 1226 | return [list $r $g $b] |
---|
| 1227 | } |
---|
| 1228 | |
---|
| 1229 | # ---------------------------------------------------------------------- |
---|
[136] | 1230 | # CONFIGURATION OPTION: -plotbackground |
---|
[11] | 1231 | # ---------------------------------------------------------------------- |
---|
[136] | 1232 | itcl::configbody Rappture::ContourResult::plotbackground { |
---|
| 1233 | foreach {r g b} [_color2rgb $itk_option(-plotbackground)] break |
---|
[11] | 1234 | $this-ren SetBackground $r $g $b |
---|
| 1235 | $this-renWin Render |
---|
| 1236 | $this-ren2 SetBackground $r $g $b |
---|
| 1237 | $this-renWin2 Render |
---|
| 1238 | } |
---|
| 1239 | |
---|
| 1240 | # ---------------------------------------------------------------------- |
---|
[136] | 1241 | # CONFIGURATION OPTION: -plotforeground |
---|
[11] | 1242 | # ---------------------------------------------------------------------- |
---|
[136] | 1243 | itcl::configbody Rappture::ContourResult::plotforeground { |
---|
[11] | 1244 | after cancel [itcl::code $this _rebuild] |
---|
| 1245 | after idle [itcl::code $this _rebuild] |
---|
| 1246 | } |
---|