Changeset 3330 for trunk/gui/scripts/field.tcl
- Timestamp:
- Feb 24, 2013 1:11:18 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gui/scripts/field.tcl
r3177 r3330 1 # -*- mode: tcl; indent-tabs-mode: nil -*- 1 2 2 3 # ---------------------------------------------------------------------- … … 16 17 package require BLT 17 18 18 namespace eval Rappture { # forward declaration } 19 19 namespace eval Rappture { 20 # forward declaration 21 } 22 23 # 24 # Possible field dataset types: 25 # 26 # 2D Datasets 27 # vtk (range of z-axis is zero). 28 # unirect2d (deprecated except where extents > 1) 29 # cloud (x,y point coordinates) (deprecated) 30 # mesh 31 # 3D Datasets 32 # vtk 33 # unirect3d 34 # cloud (x,y,z coordinates) (deprecated) 35 # mesh 36 # dx (FIXME: make dx-to-vtk converter work) 37 # ucd avs 38 # 39 # Viewers: 40 # Format Dim Description Viewer Server 41 # vtk 2 vtk file data. contour vtkvis 42 # vtk 3 vtk file data. isosurface vtkvis 43 # mesh 2 points-on-mesh heightmap vtkvis 44 # mesh 3 points-on-mesh isosurface vtkvis 45 # dx 3 DX volume nanovis 46 # unirect2d 2 unirect3d + extents > 1 flow flow nanovis 47 # unirect3d 3 unirect2d + extents > 1 flow flow nanovis 48 # 49 # The goal should be any 3D dataset can view a isosurface, volume, 50 # streamlines, or flow (if extents > 1). Any 2D dataset can view a 51 # contour, heightmap, streamlines, or flow (if extents > 1). 52 # 53 # 20 54 itcl::class Rappture::Field { 21 constructor {xmlobj path} { # defined below } 22 destructor { # defined below } 23 55 private variable _dim 0; # Dimension of the mesh 56 private variable _xmlobj "" ; # ref to XML obj with field data 57 private variable _limits ; # maps box name => {z0 z1} limits 58 private variable _field "" 59 private variable _fieldNames "" ; # list of field names. 60 private variable _fieldUnits "" ; # list of units of each field name. 61 private variable _fieldLabels "" ; # list of labels of each field name. 62 private variable _viewer "" 63 private variable _hints 64 65 constructor {xmlobj path} { 66 # defined below 67 } 68 destructor { 69 # defined below 70 } 24 71 public method components {args} 25 public method mesh {{ what-overall}}26 public method values {{ what-overall}}27 public method blob {{ what-overall}}72 public method mesh {{cname -overall}} 73 public method values {{cname -overall}} 74 public method blob {{cname -overall}} 28 75 public method limits {axis} 29 76 public method controls {option args} … … 32 79 public method isunirect2d {} 33 80 public method isunirect3d {} 34 public method extents {{ what-overall}}81 public method extents {{cname -overall}} 35 82 public method flowhints { cname } 36 83 public method type {} 37 public method vtkdata {{what -overall}} 38 39 protected method _build {} 84 public method viewer {} { 85 return $_viewer 86 } 87 public method vtkdata {cname} 88 89 protected method Build {} 40 90 protected method _getValue {expr} 41 91 42 private variable _xmlobj "" ; # ref to XML obj with device data43 92 private variable _path ""; # Path of this object in the XML 44 93 private variable _units "" ; # system of units for this field 45 private variable _limits ;# maps box name => {z0 z1} limits46 94 private variable _zmax 0 ;# length of the device 47 95 48 private variable _field "" ;# lib obj representing this field49 96 private variable _comp2dims ;# maps component name => dimensionality 50 97 private variable _comp2xy ;# maps component name => x,y vectors 51 private variable _comp2vtk ;# maps component name => vtkFloatArray 52 private variable _comp2vtkstreamlines ;# maps component name => vtkFloatArray 53 private variable _comp2vtkcontour ;# maps component name => vtkFloatArray 54 private variable _comp2vtkvolume ;# maps component name => vtkFloatArray 55 private variable _comp2volume ;# maps component name => vtkFloatArray 98 private variable _comp2vtk ;# maps component name => vtk file data 56 99 private variable _comp2dx ;# maps component name => OpenDX data 57 100 private variable _comp2unirect2d ;# maps component name => unirect2d obj … … 60 103 private variable _comp2cntls ;# maps component name => x,y control points 61 104 private variable _comp2extents 62 private variable _comp2limits 105 private variable _comp2limits; # Array of limits per component 63 106 private variable _type "" 64 107 private variable _comp2flowhints 108 private variable _comp2mesh 65 109 private common _counter 0 ;# counter for unique vector names 66 110 111 private method BuildPointsOnMesh { cname } 67 112 private method ConvertToVtkData { cname } 68 113 private method ReadVtkDataSet { cname contents } 69 private variable _fields {}70 private variable _ isVtk114 private method AvsToVtk { cname contents } 115 private variable _values "" 71 116 } 72 117 … … 111 156 112 157 # build up vectors for various components of the field 113 _build158 Build 114 159 } 115 160 … … 124 169 eval blt::vector destroy $_comp2xy($name) 125 170 } 126 foreach name [array names _comp2vtk] {127 set mobj [lindex $_comp2vtk($name) 0]128 set class [$mobj info class]129 ${class}::release $mobj130 131 set fobj [lindex $_comp2vtk($name) 1]132 rename $fobj ""133 }134 171 foreach name [array names _comp2unirect2d] { 135 172 itcl::delete object $_comp2unirect2d($name) … … 140 177 foreach name [array names _comp2flowhints] { 141 178 itcl::delete object $_comp2flowhints($name) 179 } 180 foreach name [array names _comp2mesh] { 181 # Data is in the form of a mesh and a vector. 182 foreach { mesh vector } $_comp2mesh($name) break 183 # Release the mesh (may be shared) 184 set class [$mesh info class] 185 ${class}::release $mesh 186 # Destroy the vector 187 blt::vector destroy $vector 142 188 } 143 189 } … … 193 239 # overall field (sum of all components). 194 240 # ---------------------------------------------------------------------- 195 itcl::body Rappture::Field::mesh {{what -overall}} { 196 if {$what == "-overall" || $what == "component0"} { 197 set what [lindex [components -name] 0] 198 } 199 if {[info exists _comp2xy($what)]} { 200 return [lindex $_comp2xy($what) 0] ;# return xv 201 } 202 if { [info exists _comp2vtkstreamlines($what)] } { 203 error "mesh: not implemented for streamlines" 241 itcl::body Rappture::Field::mesh {{cname -overall}} { 242 if {$cname == "-overall" || $cname == "component0"} { 243 set cname [lindex [components -name] 0] 244 } 245 if {[info exists _comp2xy($cname)]} { 246 return [lindex $_comp2xy($cname) 0] ;# return xv 247 } 248 if { [info exists _comp2vtk($cname)] } { 249 # FIXME: extract mesh from VTK file data. 250 error "method \"mesh\" is not implemented for VTK file data" 251 } 252 if {[info exists _comp2dx($cname)]} { 253 return "" ;# no mesh -- it's embedded in the value data 254 } 255 if {[info exists _comp2mesh($cname)]} { 256 return "" ;# no mesh -- it's embedded in the value data 257 } 258 if {[info exists _comp2unirect2d($cname)]} { 259 set mobj [lindex $_comp2unirect2d($cname) 0] 204 260 return [$mobj mesh] 205 261 } 206 if { [info exists _comp2vtkcontour($what)] } { 207 error "method \"mesh\" is not implemented for vtkcontour" 208 } 209 if { [info exists _comp2vtk($what)] } { 210 set mobj [lindex $_comp2vtk($what) 0] 262 if {[info exists _comp2unirect3d($cname)]} { 263 set mobj [lindex $_comp2unirect3d($cname) 0] 211 264 return [$mobj mesh] 212 265 } 213 if {[info exists _comp2dx($what)]} { 214 return "" ;# no mesh -- it's embedded in the value data 215 } 216 if {[info exists _comp2vtkvolume($what)]} { 217 return "" ;# no mesh -- it's embedded in the value data 218 } 219 if {[info exists _comp2unirect2d($what)]} { 220 set mobj [lindex $_comp2unirect2d($what) 0] 221 return [$mobj mesh] 222 } 223 if {[info exists _comp2unirect3d($what)]} { 224 set mobj [lindex $_comp2unirect3d($what) 0] 225 return [$mobj mesh] 226 } 227 error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]" 266 error "bad option \"$cname\": should be [join [lsort [array names _comp2dims]] {, }]" 228 267 } 229 268 … … 235 274 # overall field (sum of all components). 236 275 # ---------------------------------------------------------------------- 237 itcl::body Rappture::Field::values {{what -overall}} { 238 if {$what == "component0"} { 239 set what "component" 240 } 241 if {[info exists _comp2xy($what)]} { 242 return [lindex $_comp2xy($what) 1] ;# return yv 243 } 244 if { [info exists _comp2vtkcontour($what)] } { 245 error "method \"values\" is not implemented for vtkcontour" 246 } 247 if { [info exists _comp2vtkstreamlines($what)] } { 248 # FIXME: Need to process the vtk file data to pull out the field's 249 # values. 250 error "vtkstreamlines: values not implemented" 251 return [lindex $_comp2vtkstreamlines($what) 1] 252 } 253 if { [info exists _comp2vtk($what)] } { 254 return [lindex $_comp2vtk($what) 1] ;# return vtkFloatArray 255 } 256 if {[info exists _comp2dx($what)]} { 257 return $_comp2dx($what) ;# return gzipped, base64-encoded DX data 258 } 259 if {[info exists _comp2unirect2d($what)]} { 260 return [$_comp2unirect2d($what) values] 261 } 262 if {[info exists _comp2unirect3d($what)]} { 263 return [$_comp2unirect3d($what) blob] 264 } 265 error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]" 276 itcl::body Rappture::Field::values {{cname -overall}} { 277 if {$cname == "component0"} { 278 set cname "component" 279 } 280 if {[info exists _comp2xy($cname)]} { 281 return [lindex $_comp2xy($cname) 1] ;# return yv 282 } 283 # VTK file data 284 if { [info exists _comp2vtk($cname)] } { 285 # FIXME: extract the values from the VTK file data 286 error "method \"values\" is not implemented for vtk file data" 287 } 288 # Points-on-mesh 289 if { [info exists _comp2mesh($cname)] } { 290 set vector [lindex $_comp2mesh($cname) 1] 291 return [$vector range 0 end] 292 } 293 if {[info exists _comp2dx($cname)]} { 294 return $_comp2dx($cname) ;# return gzipped, base64-encoded DX data 295 } 296 if {[info exists _comp2unirect2d($cname)]} { 297 return [$_comp2unirect2d($cname) values] 298 } 299 if {[info exists _comp2unirect3d($cname)]} { 300 return [$_comp2unirect3d($cname) blob] 301 } 302 error "bad option \"$cname\": should be [join [lsort [array names _comp2dims]] {, }]" 266 303 } 267 304 … … 271 308 # Returns a string representing the blob of data for the mesh and values. 272 309 # ---------------------------------------------------------------------- 273 itcl::body Rappture::Field::blob {{ what-overall}} {274 if {$ what== "component0"} {275 set what"component"276 } 277 if {[info exists _comp2xy($ what)]} {310 itcl::body Rappture::Field::blob {{cname -overall}} { 311 if {$cname == "component0"} { 312 set cname "component" 313 } 314 if {[info exists _comp2xy($cname)]} { 278 315 return "" 279 316 } 280 if { [info exists _comp2vtk($what)] } { 281 return "" 282 } 283 if { [info exists _comp2vtkvolume($what)] } { 284 return $_comp2vtkvolume($what) 285 } 286 if { [info exists _comp2vtkcontour($what)] } { 287 return $_comp2vtkcontour($what) 288 } 289 if { [info exists _comp2vtkstreamlines($what)] } { 290 # Return the contents of the vtk file. 291 return $_comp2vtkstreamlines($what) 292 } 293 if {[info exists _comp2dx($what)]} { 294 return $_comp2dx($what) ;# return gzipped, base64-encoded DX data 295 } 296 if {[info exists _comp2unirect2d($what)]} { 297 return [$_comp2unirect2d($what) blob] 298 } 299 if {[info exists _comp2unirect3d($what)]} { 300 return [$_comp2unirect3d($what) blob] 301 } 302 error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]" 317 if { [info exists _comp2vtk($cname)] } { 318 error "blob not implemented for VTK file data" 319 } 320 if {[info exists _comp2dx($cname)]} { 321 return $_comp2dx($cname) ;# return gzipped, base64-encoded DX data 322 } 323 if {[info exists _comp2unirect2d($cname)]} { 324 return [$_comp2unirect2d($cname) blob] 325 } 326 if {[info exists _comp2unirect3d($cname)]} { 327 return [$_comp2unirect3d($cname) blob] 328 } 329 error "bad option \"$cname\": should be [join [lsort [array names _comp2dims]] {, }]" 303 330 } 304 331 … … 312 339 set min "" 313 340 set max "" 314 315 341 blt::vector tmp zero 316 foreach comp [array names _comp2dims] { 317 switch -- $_comp2dims($comp) { 342 343 foreach cname [array names _comp2dims] { 344 switch -- $_comp2dims($cname) { 318 345 1D { 319 346 switch -- $which { 320 x - xlin { set pos 0; set log 0; set axis xaxis } 321 xlog { set pos 0; set log 1; set axis xaxis } 322 y - ylin - v - vlin { set pos 1; set log 0; set axis yaxis } 323 ylog - vlog { set pos 1; set log 1; set axis yaxis } 347 x - xlin { 348 set pos 0; set log 0; set axis x 349 } 350 xlog { 351 set pos 0; set log 1; set axis x 352 } 353 y - ylin - v - vlin { 354 set pos 1; set log 0; set axis y 355 } 356 ylog - vlog { 357 set pos 1; set log 1; set axis y 358 } 324 359 default { 325 360 error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog" … … 327 362 } 328 363 329 set vname [lindex $_comp2xy($c omp) $pos]364 set vname [lindex $_comp2xy($cname) $pos] 330 365 $vname variable vec 331 366 … … 337 372 tmp expr {abs(tmp)} ;# get the abs value 338 373 tmp expr {tmp + zero*max(tmp)} ;# replace 0's with abs max 339 set vmin [blt::vector expr min(tmp)]340 set vmax [blt::vector expr max(tmp)]374 set axisMin [blt::vector expr min(tmp)] 375 set axisMax [blt::vector expr max(tmp)] 341 376 } else { 342 set vmin $vec(min)343 set vmax $vec(max)377 set axisMin $vec(min) 378 set axisMax $vec(max) 344 379 } 345 380 346 381 if {"" == $min} { 347 set min $ vmin348 } elseif {$ vmin < $min} {349 set min $ vmin382 set min $axisMin 383 } elseif {$axisMin < $min} { 384 set min $axisMin 350 385 } 351 386 if {"" == $max} { 352 set max $ vmax353 } elseif {$ vmax > $max} {354 set max $ vmax387 set max $axisMax 388 } elseif {$axisMax > $max} { 389 set max $axisMax 355 390 } 356 391 } 357 392 2D - 3D { 358 if {[info exists _comp2unirect2d($c omp)]} {359 set limits [$_comp2unirect2d($c omp) limits $which]360 foreach { vmin vmax} $limits break361 set axis v axis362 } elseif {[info exists _comp2unirect3d($c omp)]} {363 set limits [$_comp2unirect3d($c omp) limits $which]364 foreach { vmin vmax} $limits break365 set axis v axis366 } elseif {[info exists _comp2 vtk($comp)]} {367 foreach {xv yv} $_comp2vtk($comp) break 368 393 if {[info exists _comp2unirect2d($cname)]} { 394 set limits [$_comp2unirect2d($cname) limits $which] 395 foreach {axisMin axisMax} $limits break 396 set axis v 397 } elseif {[info exists _comp2unirect3d($cname)]} { 398 set limits [$_comp2unirect3d($cname) limits $which] 399 foreach {axisMin axisMax} $limits break 400 set axis v 401 } elseif {[info exists _comp2limits($cname)]} { 402 array set limits $_comp2limits($cname) 403 switch -- $which { 369 404 x - xlin - xlog { 370 foreach {vmin vmax} [$xv limits x] break371 set axis xaxis 405 set axis x 406 foreach {axisMin axisMax} $limits(x) break 372 407 } 373 408 y - ylin - ylog { 374 foreach {vmin vmax} [$xv limits y] break375 set axis yaxis 409 set axis y 410 foreach {axisMin axisMax} $limits(y) break 376 411 } 377 412 z - zlin - zlog { 378 foreach {vmin vmax} [$xv limits z] break379 set axis zaxis 413 set axis y 414 foreach {axisMin axisMax} $limits(z) break 380 415 } 381 416 v - vlin - vlog { 382 catch {unset style} 383 array set style $_comp2style($comp) 384 if {[info exists style(-min)] && [info exists style(-max)]} { 385 # This component has its own hard-coded 386 # min/max range. Ignore it for overall limits. 387 set vmin $min 388 set vmax $max 389 } else { 390 foreach {vmin vmax} [$yv GetRange] break 391 } 392 set axis vaxis 393 } 394 default { 395 error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog" 396 } 397 } 417 set axis v 418 foreach {axisMin axisMax} $limits(v) break 419 } 420 default { 421 if { ![info exists limits($which)] } { 422 error "limits: unknown axis \"$which\"" 423 } 424 set axis v 425 foreach {axisMin axisMax} $limits($which) break 426 } 427 } 398 428 } else { 399 set vmin 0 ;# HACK ALERT! must be OpenDX data400 set vmax 1401 set axis v axis429 set axisMin 0 ;# HACK ALERT! must be OpenDX data 430 set axisMax 1 431 set axis v 402 432 } 403 433 } 404 434 } 405 if {"" == $min} { 406 set min $vmin 407 } elseif {$vmin < $min} { 408 set min $vmin 409 } 410 if {"" == $max} { 411 set max $vmax 412 } elseif {$vmax > $max} { 413 set max $vmax 435 if { "" == $min || $axisMin < $min } { 436 set min $axisMin 437 } 438 if { "" == $max || $axisMax > $max } { 439 set max $axisMax 414 440 } 415 441 } 416 442 blt::vector destroy tmp zero 417 418 set val [$_field get $axis.min] 443 set val [$_field get "${axis}axis.min"] 419 444 if {"" != $val && "" != $min} { 420 445 if {$val > $min} { … … 423 448 } 424 449 } 425 426 set val [$_field get $axis.max] 450 set val [$_field get "${axis}axis.max"] 427 451 if {"" != $val && "" != $max} { 428 452 if {$val < $max} { … … 445 469 switch -- $option { 446 470 get { 447 set what[lindex $args 0]448 if {[info exists _comp2cntls($ what)]} {449 return $_comp2cntls($ what)471 set cname [lindex $args 0] 472 if {[info exists _comp2cntls($cname)]} { 473 return $_comp2cntls($cname) 450 474 } 451 475 return "" … … 511 535 set value [lindex $args 1] 512 536 $_xmlobj put $path.current $value 513 _build537 Build 514 538 } 515 539 default { … … 527 551 # ---------------------------------------------------------------------- 528 552 itcl::body Rappture::Field::hints {{keyword ""}} { 529 foreach {key path} { 530 camera camera.position 531 color about.color 532 default about.default 533 group about.group 534 label about.label 535 scalars about.scalars 536 scale about.scale 537 seeds about.seeds 538 style about.style 539 toolId tool.id 540 toolName tool.name 541 toolRevision tool.version.application.revision 542 type about.type 543 units units 544 updir updir 545 vectors about.vectors 546 } { 547 set str [$_field get $path] 548 if {"" != $str} { 549 set hints($key) $str 550 } 551 } 552 # Set tool and path hints 553 set hints(tool) [$_xmlobj get tool.name] 554 set hints(path) $_path 555 if 0 { 556 # to be compatible with curve objects 557 set hints(xlabel) "Position" 558 } 559 if {[info exists hints(group)] && [info exists hints(label)]} { 560 # pop-up help for each curve 561 set hints(tooltip) $hints(label) 562 } 563 564 if {$keyword != ""} { 565 if {[info exists hints($keyword)]} { 566 return $hints($keyword) 553 if { ![info exists _hints] } { 554 set _hints(fieldnames) $_fieldNames 555 set _hints(fieldunits) $_fieldUnits 556 set _hints(fieldlabels) $_fieldLabels 557 foreach {key path} { 558 camera camera.position 559 color about.color 560 default about.default 561 group about.group 562 label about.label 563 fieldnames about.fieldnames 564 fieldunits about.fieldunits 565 fieldlabels about.fieldlabels 566 scale about.scale 567 seeds about.seeds 568 style about.style 569 type about.type 570 xlabel about.xaxis.label 571 ylabel about.yaxis.label 572 zlabel about.zaxis.label 573 xunits about.xaxis.units 574 yunits about.yaxis.units 575 zunits about.zaxis.units 576 units units 577 updir updir 578 vectors about.vectors 579 } { 580 set str [$_field get $path] 581 if { "" != $str } { 582 set _hints($key) $str 583 } 584 } 585 foreach {key path} { 586 toolid tool.id 587 toolname tool.name 588 toolcommand tool.execute 589 tooltitle tool.title 590 toolrevision tool.version.application.revision 591 } { 592 set str [$_xmlobj get $path] 593 if { "" != $str } { 594 set _hints($key) $str 595 } 596 } 597 # Set toolip and path hints 598 set _hints(path) $_path 599 if { [info exists _hints(group)] && [info exists _hints(label)] } { 600 # pop-up help for each curve 601 set _hints(tooltip) $_hints(label) 602 } 603 } 604 if { $keyword != "" } { 605 if {[info exists _hints($keyword)]} { 606 return $_hints($keyword) 567 607 } 568 608 return "" 569 609 } 570 return [array get hints]571 } 572 573 # ---------------------------------------------------------------------- 574 # USAGE: _build610 return [array get _hints] 611 } 612 613 # ---------------------------------------------------------------------- 614 # USAGE: Build 575 615 # 576 616 # Used internally to build up the vector representation for the … … 579 619 # from scratch. 580 620 # ---------------------------------------------------------------------- 581 itcl::body Rappture::Field::_build {} { 582 # discard any existing data 621 itcl::body Rappture::Field::Build {} { 622 623 # Discard any existing data 583 624 foreach name [array names _comp2xy] { 584 625 eval blt::vector destroy $_comp2xy($name) 585 626 } 586 foreach name [array names _comp2vtk] { 587 set mobj [lindex $_comp2vtk($name) 0] 588 set class [$mobj info class] 589 ${class}::release $mobj 590 591 set fobj [lindex $_comp2vtk($name) 1] 592 rename $fobj "" 593 } 627 array unset _comp2vtk 594 628 foreach name [array names _comp2unirect2d] { 595 629 eval itcl::delete object $_comp2unirect2d($name) … … 599 633 } 600 634 catch {unset _comp2xy} 601 catch {unset _comp2vtk}602 635 catch {unset _comp2dx} 603 636 catch {unset _comp2dims} 604 637 catch {unset _comp2style} 605 array unset _comp2volume606 array unset _comp2vtkstreamlines607 array unset _comp2vtkcontour608 638 array unset _comp2unirect2d 609 639 array unset _comp2unirect3d … … 617 647 set type "" 618 648 if { ([$_field element $cname.constant] != "" && 619 620 [$_field element $cname.xy] != ""} {649 [$_field element $cname.domain] != "") || 650 [$_field element $cname.xy] != "" } { 621 651 set type "1D" 622 } elseif { [$_field element $cname.mesh] != "" &&623 652 } elseif { [$_field element $cname.mesh] != "" && 653 [$_field element $cname.values] != ""} { 624 654 set type "points-on-mesh" 625 } elseif {[$_field element $cname.vtk] != ""} { 626 set _isVtkData($cname) 1 627 if { [$_field get "about.view"] == "streamlines" } { 628 set type "vtkstreamlines" 629 } elseif { [$_field get "about.view"] == "contour" } { 630 set type "vtkcontour" 631 } else { 632 set type "vtk" 633 } 655 } elseif { [$_field element $cname.vtk] != ""} { 656 set viewer [$_field get "about.view"] 657 set type "vtk" 658 if { $viewer != "" } { 659 set _viewer $viewer 660 } 634 661 } elseif {[$_field element $cname.opendx] != ""} { 635 662 global env … … 646 673 set type "dx" 647 674 } 648 675 } 649 676 set _comp2style($cname) "" 650 677 … … 701 728 # sort x-coords in increasing order 702 729 $xv sort $yv 703 704 730 set _comp2dims($cname) "1D" 705 731 set _comp2xy($cname) [list $xv $yv] … … 707 733 } 708 734 } elseif {$type == "points-on-mesh"} { 709 # 710 # More complex 2D/3D data is represented by a mesh 711 # object and an associated vtkFloatArray for field 712 # values. 713 # 714 set path [$_field get $cname.mesh] 715 if {[$_xmlobj element $path] != ""} { 716 set element [$_xmlobj element -as type $path] 717 if { $element == "unirect2d" } { 718 set _comp2dims($cname) "2D" 719 set _comp2unirect2d($cname) \ 720 [Rappture::Unirect2d \#auto $_xmlobj $_field $cname \ 721 $extents] 722 set _comp2style($cname) [$_field get $cname.style] 723 if {[$_field element $cname.flow] != ""} { 724 set _comp2flowhints($cname) \ 725 [Rappture::FlowHints ::\#auto $_field $cname $_units] 726 } 727 incr _counter 728 } elseif { $element == "unirect3d" } { 729 set _comp2dims($cname) "3D" 730 set _comp2unirect3d($cname) \ 731 [Rappture::Unirect3d \#auto $_xmlobj $_field $cname \ 732 $extents] 733 set _comp2style($cname) [$_field get $cname.style] 734 if {[$_field element $cname.flow] != ""} { 735 set _comp2flowhints($cname) \ 736 [Rappture::FlowHints ::\#auto $_field $cname $_units] 737 } 738 incr _counter 739 } elseif { $element == "cloud" || $element == "mesh" } { 740 switch -- $element { 741 cloud { 742 set mobj [Rappture::Cloud::fetch $_xmlobj $path] 743 } 744 mesh { 745 set mobj [Rappture::Mesh::fetch $_xmlobj $path] 746 } 747 } 748 if {[$mobj dimensions] > 1} { 749 # 750 # 2D/3D data 751 # Store cloud/field as components 752 # 753 set values [$_field get $cname.values] 754 set farray [vtkFloatArray ::vals$_counter] 755 756 foreach v $values { 757 if {"" != $_units} { 758 set v [Rappture::Units::convert $v \ 759 -context $_units -to $_units -units off] 760 } 761 $farray InsertNextValue $v 762 } 763 764 set _comp2dims($cname) "[$mobj dimensions]D" 765 set _comp2vtk($cname) [list $mobj $farray] 766 set _comp2style($cname) [$_field get $cname.style] 767 incr _counter 768 } else { 769 # 770 # OOPS! This is 1D data 771 # Forget the cloud/field -- store BLT vectors 772 # 773 set xv [blt::vector create x$_counter] 774 set yv [blt::vector create y$_counter] 775 776 set vtkpts [$mobj points] 777 set max [$vtkpts GetNumberOfPoints] 778 for {set i 0} {$i < $max} {incr i} { 779 set xval [lindex [$vtkpts GetPoint $i] 0] 780 $xv append $xval 781 } 782 set class [$mobj info class] 783 ${class}::release $mobj 784 785 set values [$_field get $cname.values] 786 foreach yval $values { 787 if {"" != $_units} { 788 set yval [Rappture::Units::convert $yval \ 789 -context $_units -to $_units -units off] 790 } 791 $yv append $yval 792 } 793 794 # sort x-coords in increasing order 795 $xv sort $yv 796 797 set _comp2dims($cname) "1D" 798 set _comp2xy($cname) [list $xv $yv] 799 incr _counter 800 } 801 } 802 } else { 803 puts "WARNING: can't find mesh $path for field component" 804 } 735 BuildPointsOnMesh $cname 805 736 } elseif {$type == "vtk"} { 806 #807 # Extract native vtk data from the XML and use a reader808 # to load it.809 #810 vtkRectilinearGridReader $this-gr811 $this-gr SetInputString [$_field get $cname.vtk]812 813 814 set _comp2dims($cname) "[$mobj dimensions]D"815 set _comp2vtk($cname) [list $mobj $farray]816 set _comp2style($cname) [$_field get $cname.style]817 incr _counter818 } elseif {$type == "vtkstreamlines"} {819 set _comp2dims($cname) "3D"820 # Allow redirects to another element.821 737 set vtkdata [$_field get $cname.vtk] 822 set _comp2vtkstreamlines($cname) $vtkdata 823 set _comp2style($cname) [$_field get $cname.style] 824 incr _counter 825 } elseif {$type == "vtkcontour"} { 826 set _comp2dims($cname) "2D" 827 # Allow redirects to another element. 828 829 set data [$_field get $cname.vtk] 830 ReadVtkDataSet $cname $data 831 set _comp2vtkcontour($cname) $data 832 set _comp2style($cname) [$_field get $cname.style] 833 incr _counter 834 } elseif {$type == "vtkvolume"} { 835 set _comp2dims($cname) "3D" 836 # Allow redirects to another element. 837 set data [$_field get -decode no $cname.dx] 838 set data [Rappture::encoding::decode -as zb64 $data] 839 if 1 { 840 set file "/tmp/$cname.dx" 841 set f [open $file "w"] 842 puts $f $data 843 close $f 844 } 845 set data [Rappture::ConvertDxToVtk $data] 846 if 1 { 847 set file "/tmp/$cname.vtk" 848 set f [open $file "w"] 849 puts $f $data 850 close $f 851 } 852 set _comp2vtkvolume($cname) $data 853 set _comp2style($cname) [$_field get $cname.style] 854 incr _counter 855 } elseif {$type == "vtkstreamlines2"} { 856 set _comp2dims($cname) "3D" 857 set _comp2vtkstreamlines($cname) [$_field get $cname.vtk] 738 ReadVtkDataSet $cname $vtkdata 739 set _comp2vtk($cname) $vtkdata 858 740 set _comp2style($cname) [$_field get $cname.style] 859 741 incr _counter … … 864 746 # off to the NanoVis visualizer. 865 747 # 748 set _viewer "nanovis" 866 749 set _comp2dims($cname) "3D" 867 750 set _comp2dx($cname) [$_field get -decode no $cname.dx] … … 890 773 # off to the NanoVis visualizer. 891 774 # 775 set _viewer "nanovis" 892 776 set _comp2dims($cname) "3D" 893 777 set data [$_field get -decode yes $cname.opendx] … … 901 785 } 902 786 incr _counter 787 } elseif {[$_field element $cname.ucd] != ""} { 788 set _viewer "isosurface" 789 set _comp2dims($cname) "3D" 790 set contents [$_field get $cname.ucd] 791 set vtkdata [AvsToVtk $cname $contents] 792 ReadVtkDataSet $cname $vtkdata 793 set _comp2vtk($cname) $vtkdata 794 set _comp2style($cname) [$_field get $cname.style] 795 incr _counter 796 } 797 } 798 # Sanity check. Verify that all components of the field have the same 799 # dimension. 800 set dim "" 801 foreach cname [array names _comp2dims] { 802 if { $dim == "" } { 803 set dim $_comp2dims($cname) 804 continue 805 } 806 if { $dim != $_comp2dims($cname) } { 807 error "field can't have components of different dimensions: [join [array get _comp2dims] ,]" 903 808 } 904 809 } … … 1004 909 # Returns if the field is a unirect2d object. 1005 910 # 1006 itcl::body Rappture::Field::extents {{ what-overall}} {1007 if {$ what== "-overall" } {911 itcl::body Rappture::Field::extents {{cname -overall}} { 912 if {$cname == "-overall" } { 1008 913 set max 0 1009 914 foreach cname [$_field children -type component] { … … 1019 924 return $max 1020 925 } 1021 if { $what == "component0"} { 1022 set what [lindex [components -name] 0] 1023 } 1024 return $_comp2extents($what) 1025 } 1026 1027 # ---------------------------------------------------------------------- 1028 # USAGE: blob ?<name>? 1029 # 1030 # Returns a string representing the blob of data for the mesh and values. 1031 # ---------------------------------------------------------------------- 1032 itcl::body Rappture::Field::vtkdata {{what -overall}} { 1033 if {$what == "component0"} { 1034 set what "component" 1035 } 1036 if {[info exists _comp2xy($what)]} { 1037 return "" 1038 } 1039 if { [info exists _comp2vtk($what)] } { 1040 return "" 1041 } 1042 if { [info exists _comp2vtkcontour($what)] } { 1043 return $_comp2contour($what) 1044 } 1045 if { [info exists _comp2vtkstreamlines($what)] } { 1046 return $_comp2vtkstreamlines($what) 1047 } 1048 if { [info exists _comp2vtkvolume($what)] } { 1049 return $_comp2vtkvolume($what) 1050 } 1051 if {[info exists _comp2dx($what)]} { 1052 return $_comp2dx($what) 1053 } 1054 if {[info exists _comp2unirect2d($what)]} { 1055 return [$_comp2unirect2d($what) blob] 1056 } 1057 if {[info exists _comp2unirect3d($what)]} { 1058 return [$_comp2unirect3d($what) blob] 1059 } 1060 error "bad option \"$what\": should be [join [lsort [array names _comp2dims]] {, }]" 1061 } 1062 1063 itcl::body Rappture::Field::ConvertToVtkData { comp } { 926 if { $cname == "component0"} { 927 set cname [lindex [components -name] 0] 928 } 929 return $_comp2extents($cname) 930 } 931 932 itcl::body Rappture::Field::ConvertToVtkData { cname } { 1064 933 set ds "" 1065 switch -- [typeof $c omp] {934 switch -- [typeof $cname] { 1066 935 "unirect2d" { 1067 foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $c omp] break936 foreach { x1 x2 xN y1 y2 yN } [$dataobj mesh $cname] break 1068 937 set spacingX [expr {double($x2 - $x1)/double($xN - 1)}] 1069 938 set spacingY [expr {double($y2 - $y1)/double($yN - 1)}] … … 1074 943 $ds SetSpacing $spacingX $spacingY 0 1075 944 set arr [vtkDoubleArray $this-arrTemp] 1076 foreach {val} [$dataobj values $c omp] {945 foreach {val} [$dataobj values $cname] { 1077 946 $arr InsertNextValue $val 1078 947 } … … 1080 949 } 1081 950 "unirect3d" { 1082 foreach { x1 x2 xN y1 y2 yN z1 z2 zN } [$dataobj mesh $c omp] break951 foreach { x1 x2 xN y1 y2 yN z1 z2 zN } [$dataobj mesh $cname] break 1083 952 set spacingX [expr {double($x2 - $x1)/double($xN - 1)}] 1084 953 set spacingY [expr {double($y2 - $y1)/double($yN - 1)}] … … 1090 959 $ds SetSpacing $spacingX $spacingY $spacingZ 1091 960 set arr [vtkDoubleArray $this-arrTemp] 1092 foreach {val} [$dataobj values $c omp] {961 foreach {val} [$dataobj values $cname] { 1093 962 $arr InsertNextValue $val 1094 963 } 1095 964 [$ds GetPointData] SetScalars $val 1096 965 } 1097 " vtkcontour" {1098 return [$dataobj blob $c omp]966 "contour" { 967 return [$dataobj blob $cname] 1099 968 } 1100 969 "dx" { 1101 return [Rappture::ConvertDxToVtk $_comp2dx($ what)]970 return [Rappture::ConvertDxToVtk $_comp2dx($cname)] 1102 971 } 1103 972 default { 1104 set mesh [$dataobj mesh $c omp]973 set mesh [$dataobj mesh $cname] 1105 974 switch -- [$mesh GetClassName] { 1106 975 vtkPoints { … … 1108 977 set ds [vtkPolyData $this-polydataTemp] 1109 978 $ds SetPoints $mesh 1110 [$ds GetPointData] SetScalars [$dataobj values $c omp]979 [$ds GetPointData] SetScalars [$dataobj values $cname] 1111 980 } 1112 981 vtkPolyData { 1113 982 set ds [vtkPolyData $this-polydataTemp] 1114 983 $ds ShallowCopy $mesh 1115 [$ds GetPointData] SetScalars [$dataobj values $c omp]984 [$ds GetPointData] SetScalars [$dataobj values $cname] 1116 985 } 1117 986 vtkUnstructuredGrid { … … 1119 988 set ds [vtkUnstructuredGrid $this-grdataTemp] 1120 989 $ds ShallowCopy $mesh 1121 [$ds GetPointData] SetScalars [$dataobj values $c omp]990 [$ds GetPointData] SetScalars [$dataobj values $cname] 1122 991 } 1123 992 vtkRectilinearGrid { … … 1125 994 set ds [vtkRectilinearGrid $this-grdataTemp] 1126 995 $ds ShallowCopy $mesh 1127 [$ds GetPointData] SetScalars [$dataobj values $c omp]996 [$ds GetPointData] SetScalars [$dataobj values $cname] 1128 997 } 1129 998 default { … … 1152 1021 } 1153 1022 1154 itcl::body Rappture::Field::ReadVtkDataSet { c ompcontents } {1023 itcl::body Rappture::Field::ReadVtkDataSet { cname contents } { 1155 1024 package require vtk 1156 1025 … … 1172 1041 set limits {} 1173 1042 foreach {xmin xmax ymin ymax zmin zmax} [$dataset GetBounds] break 1174 lappend limits xmin $xmin xmax $xmax ymin $ymin ymax $ymax 1043 # Figure out the dimension of the mesh from the bounds. 1044 set _dim 0 1045 if { $xmax > $xmin } { 1046 incr _dim 1047 } 1048 if { $ymax > $ymin } { 1049 incr _dim 1050 } 1051 if { $zmax > $zmin } { 1052 incr _dim 1053 } 1054 if { $_viewer == "" } { 1055 if { $_dim == 2 } { 1056 set _viewer contour 1057 } else { 1058 set _viewer isosurface 1059 } 1060 } 1061 set _comp2dims($cname) ${_dim}D 1062 lappend limits x [list $xmin $xmax] 1063 lappend limits y [list $ymin $ymax] 1064 lappend limits z [list $zmin $zmax] 1175 1065 set dataAttrs [$dataset GetPointData] 1176 1066 if { $dataAttrs == ""} { 1177 1067 puts stderr "No point data" 1178 1068 } 1179 for {set i 0} {$i < [$dataAttrs GetNumberOfArrays] } {incr i} { 1180 set array [$dataAttrs GetArray $i] 1181 set name [$dataAttrs GetArrayName $i] 1182 foreach {min max} [$array GetRange] break 1183 lappend limits $name-min $min $name-max $max 1184 lappend _fields $name 1185 } 1186 set _comp2limits($comp) $limits 1187 puts stderr limits=$limits 1069 set vmin 0 1070 set vmax 1 1071 set numArrays [$dataAttrs GetNumberOfArrays] 1072 if { $numArrays > 0 } { 1073 set array [$dataAttrs GetArray 0] 1074 foreach {vmin vmax} [$array GetRange] break 1075 1076 for {set i 0} {$i < [$dataAttrs GetNumberOfArrays] } {incr i} { 1077 set array [$dataAttrs GetArray $i] 1078 set name [$dataAttrs GetArrayName $i] 1079 foreach {min max} [$array GetRange] break 1080 lappend limits $name [list $min $max] 1081 lappend _fieldNames $name 1082 lappend _fieldUnits "" 1083 lappend _fieldLabels $name 1084 } 1085 } 1086 lappend limits v [list $vmin $vmax] 1087 set _comp2limits($cname) $limits 1188 1088 $reader Delete 1189 1089 file delete $tmpfile 1190 1090 } 1191 1091 1092 # 1093 # vtkdata -- 1094 # 1095 # Returns a string representing the mesh and field data for a specific 1096 # component in the legacy VTK file format. 1097 # 1098 itcl::body Rappture::Field::vtkdata {cname} { 1099 if {$cname == "component0"} { 1100 set cname "component" 1101 } 1102 # DX: Convert DX to VTK 1103 if {[info exists _comp2dx($cname)]} { 1104 return [Rappture::ConvertDxToVtk $_comp2dx($cname)] 1105 } 1106 # Unirect3d: isosurface 1107 if {[info exists _comp2unirect3d($cname)]} { 1108 return [$_comp2unirect3d($cname) vtkdata] 1109 } 1110 # VTK file data: 1111 if { [info exists _comp2vtk($cname)] } { 1112 return $_comp2vtk($cname) 1113 } 1114 # Points on mesh: Construct VTK file output. 1115 if { [info exists _comp2mesh($cname)] } { 1116 # Data is in the form mesh and vector 1117 foreach {mesh vector} $_comp2mesh($cname) break 1118 set label [hints zlabel] 1119 if { $label == "" } { 1120 set label $cname 1121 } else { 1122 regsub -all { } $label {_} label 1123 } 1124 append out "# vtk DataFile Version 3.0\n" 1125 append out "[hints label]\n" 1126 append out "ASCII\n" 1127 append out [$mesh vtkdata] 1128 append out "POINT_DATA [$vector length]\n" 1129 append out "SCALARS $label float\n" 1130 append out "LOOKUP_TABLE default\n" 1131 append out "[$vector range 0 end]\n" 1132 return $out 1133 } 1134 error "can't find vtkdata for $cname. This method should only be called by the vtkheightmap widget" 1135 } 1136 1137 # 1138 # BuildPointsOnMesh -- 1139 # 1140 # Parses the field XML description to build a mesh and values vector 1141 # representing the field. Right now we handle the deprecated types 1142 # of "cloud", "unirect2d", and "unirect3d" (mostly for flows). 1143 # 1144 itcl::body Rappture::Field::BuildPointsOnMesh {cname} { 1145 # 1146 # More complex 2D/3D data is represented by a mesh 1147 # object and an associated vector for field values. 1148 # 1149 set path [$_field get $cname.mesh] 1150 if {[$_xmlobj element $path] == ""} { 1151 # Unknown mesh designated. 1152 return 1153 } 1154 set element [$_xmlobj element -as type $path] 1155 lappend _fieldNames $cname 1156 lappend _fieldLabels $cname 1157 lappend _fieldUnits "" 1158 1159 # Handle bizarre cases that hopefully will be deprecated. 1160 if { $element == "unirect3d" } { 1161 # Special case: unirect3d (should be deprecated) + flow. 1162 if { [$_field element $cname.extents] != "" } { 1163 set extents [$_field get $cname.extents] 1164 } else { 1165 set extents 1 1166 } 1167 set _dim 3 1168 set _viewer flowvis 1169 set _comp2dims($cname) "3D" 1170 set _comp2unirect3d($cname) \ 1171 [Rappture::Unirect3d \#auto $_xmlobj $_field $cname $extents] 1172 set _comp2style($cname) [$_field get $cname.style] 1173 if {[$_field element $cname.flow] != ""} { 1174 set _comp2flowhints($cname) \ 1175 [Rappture::FlowHints ::\#auto $_field $cname $_units] 1176 } 1177 incr _counter 1178 return 1179 } 1180 if { $element == "unirect2d" && [$_field element $cname.flow] != "" } { 1181 # Special case: unirect2d (normally deprecated) + flow. 1182 if { [$_field element $cname.extents] != "" } { 1183 set extents [$_field get $cname.extents] 1184 } else { 1185 set extents 1 1186 } 1187 set _dim 2 1188 set _viewer "flowvis" 1189 set _comp2dims($cname) "2D" 1190 set _comp2unirect2d($cname) \ 1191 [Rappture::Unirect2d \#auto $_xmlobj $path] 1192 set _comp2style($cname) [$_field get $cname.style] 1193 set _comp2flowhints($cname) \ 1194 [Rappture::FlowHints ::\#auto $_field $cname $_units] 1195 set _values [$_field element $cname.values] 1196 incr _counter 1197 return 1198 } 1199 set _viewer "contour" 1200 switch -- $element { 1201 "cloud" { 1202 set mesh [Rappture::Cloud::fetch $_xmlobj $path] 1203 } 1204 "mesh" { 1205 set mesh [Rappture::Mesh::fetch $_xmlobj $path] 1206 } 1207 "unirect2d" { 1208 set mesh [Rappture::Unirect2d::fetch $_xmlobj $path] 1209 set _viewer "heightmap" 1210 } 1211 } 1212 set _dim [$mesh dimensions] 1213 if {$_dim == 1} { 1214 # Is this used anywhere? 1215 # 1216 # OOPS! This is 1D data 1217 # Forget the cloud/field -- store BLT vectors 1218 # 1219 # Is there a natural growth path in generating output from 1D to 1220 # higher dimensions? If there isn't, let's kill this in favor 1221 # or explicitly using a <curve> instead. Otherwise, the features 1222 # (methods such as xmarkers) or the <curve> need to be added 1223 # to the <field>. 1224 # 1225 set xv [blt::vector create x$_counter] 1226 set yv [blt::vector create y$_counter] 1227 1228 $yv set [$mesh points] 1229 $xv seq 0 1 [$yv length] 1230 # sort x-coords in increasing order 1231 $xv sort $yv 1232 1233 set _comp2dims($cname) "1D" 1234 set _comp2xy($cname) [list $xv $yv] 1235 incr _counter 1236 return 1237 } elseif {$_dim == 2} { 1238 set _type "heightmap" 1239 set vector [blt::vector create \#auto] 1240 $vector set [$_field get $cname.values] 1241 set _comp2dims($cname) "[$mesh dimensions]D" 1242 set _comp2mesh($cname) [list $mesh $vector] 1243 set _comp2style($cname) [$_field get $cname.style] 1244 incr _counter 1245 set label [hints zlabel] 1246 if { $label != "" } { 1247 set _fieldLabels $label 1248 set _fieldNames $label 1249 regsub -all { } $_fieldNames {_} _fieldNames 1250 } 1251 set units [hints zunits] 1252 if { $units != "" } { 1253 set _fieldUnits $units 1254 } 1255 array unset _comp2limits $cname 1256 lappend _comp2limits($cname) x [$mesh limits x] 1257 lappend _comp2limits($cname) y [$mesh limits y] 1258 lappend _comp2limits($cname) $label [$vector limits] 1259 lappend _comp2limits($cname) v [$vector limits] 1260 return 1261 } elseif {$_dim == 3} { 1262 # 1263 # 3D data: Store cloud/field as components 1264 # 1265 set values [$_field get $cname.values] 1266 set farray [vtkFloatArray ::vals$_counter] 1267 foreach v $values { 1268 if {"" != $_units} { 1269 set v [Rappture::Units::convert $v \ 1270 -context $_units -to $_units -units off] 1271 } 1272 $farray InsertNextValue $v 1273 } 1274 set _viewer "isosurface" 1275 set _type "isosurface" 1276 set vector [blt::vector create \#auto] 1277 $vector set [$_field get $cname.values] 1278 set _comp2dims($cname) "[$mesh dimensions]D" 1279 set _comp2mesh($cname) [list $mesh $vector] 1280 set _comp2style($cname) [$_field get $cname.style] 1281 incr _counter 1282 set label [hints zlabel] 1283 if { $label != "" } { 1284 set _fieldNames $label 1285 regsub -all { } $_fieldNames {_} _fieldNames 1286 set _fieldLabels $label 1287 } 1288 set units [hints zunits] 1289 if { $units != "" } { 1290 set _fieldUnits $units 1291 } 1292 lappend _comp2limits($cname) x [$mesh limits x] 1293 lappend _comp2limits($cname) y [$mesh limits y] 1294 lappend _comp2limits($cname) z [$mesh limits z] 1295 lappend _comp2limits($cname) $label [$vector limits] 1296 lappend _comp2limits($cname) v [$vector limits] 1297 return 1298 } 1299 error "unhandled case in field" 1300 } 1301 1302 itcl::body Rappture::Field::AvsToVtk { comp contents } { 1303 package require vtk 1304 1305 set reader $this-datasetreader 1306 vtkAVSucdReader $reader 1307 1308 # Write the contents to a file just in case it's binary. 1309 set tmpfile file[pid].vtk 1310 set f [open "$tmpfile" "w"] 1311 fconfigure $f -translation binary -encoding binary 1312 puts $f $contents 1313 close $f 1314 $reader SetFileName $tmpfile 1315 $reader Update 1316 file delete $tmpfile 1317 1318 set output [$reader GetOutput] 1319 set pointData [$output GetPointData] 1320 set _scalars {} 1321 for { set i 0 } { $i < [$pointData GetNumberOfArrays] } { incr i } { 1322 set name [$pointData GetArrayName $i] 1323 lappend _scalars $name $name "???" 1324 } 1325 set writer $this-datasetwriter 1326 vtkDataSetWriter $writer 1327 $writer SetInputConnection [$reader GetOutputPort] 1328 $writer SetFileName $tmpfile 1329 $writer Write 1330 rename $reader "" 1331 rename $writer "" 1332 set f [open "$tmpfile" "r"] 1333 fconfigure $f -translation binary -encoding binary 1334 set vtkdata [read $f] 1335 close $f 1336 file delete $tmpfile 1337 return $vtkdata 1338 }
Note: See TracChangeset
for help on using the changeset viewer.