[3941] | 1 | # -*- mode: tcl; indent-tabs-mode: nil -*- |
---|
| 2 | |
---|
| 3 | # ---------------------------------------------------------------------- |
---|
| 4 | # COMPONENT: transferfunctioneditor - Rudimentary editor for 3D volume |
---|
| 5 | # transfer functions |
---|
| 6 | # |
---|
| 7 | # This class is used to modify transfer functions used in volume rendering |
---|
| 8 | # on 3D scalar/vector datasets. |
---|
| 9 | # |
---|
| 10 | # ====================================================================== |
---|
| 11 | # AUTHOR: Michael McLennan, Purdue University |
---|
| 12 | # Copyright (c) 2004-2012 HUBzero Foundation, LLC |
---|
| 13 | # |
---|
| 14 | # See the file "license.terms" for information on usage and |
---|
| 15 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
| 16 | # ====================================================================== |
---|
| 17 | package require Itk |
---|
| 18 | package require BLT |
---|
| 19 | package require Img |
---|
| 20 | |
---|
| 21 | itcl::class Rappture::TransferFunctionEditor { |
---|
| 22 | private variable _nextId 0; # Used to create unique marker names |
---|
| 23 | private variable _values; # Relative values for each marker. |
---|
| 24 | private variable _limits; # Over limits of transfer function. |
---|
| 25 | private variable _labels; # Label id for each marker. |
---|
| 26 | private variable _ticks; # Tick id for each marker. |
---|
| 27 | private variable _canvas "" |
---|
| 28 | private variable _name ""; # Name of transfer function. |
---|
| 29 | private variable _activeMotion 0 |
---|
| 30 | private variable _activePress 0 |
---|
| 31 | private variable _id2name |
---|
| 32 | private common _normalIcon [Rappture::icon nvlegendmark] |
---|
| 33 | private common _activeIcon [Rappture::icon nvlegendmark2] |
---|
| 34 | public variable command "" |
---|
| 35 | |
---|
| 36 | private method SetAbsoluteValue { name x } |
---|
| 37 | private method GetAbsoluteValue { name } |
---|
| 38 | private method ContinueDrag { name x y } |
---|
| 39 | private method EnterTick { name } |
---|
| 40 | private method GetOverlappingMarkers { x y } |
---|
| 41 | private method GetScreenPosition { name } |
---|
| 42 | private method LeaveTick { name } |
---|
| 43 | private method SetRelativeValue { name x } |
---|
| 44 | private method GetRelativeValue { name } |
---|
| 45 | private method RemoveDuplicateMarkers {name x y} |
---|
| 46 | private method SetScreenPosition { name } |
---|
| 47 | private method SetVisibility { name bool } |
---|
| 48 | private method StartDrag { name x y } |
---|
| 49 | private method StopDrag { name x y } |
---|
| 50 | private method Activate { name } |
---|
| 51 | private method Deactivate { name } |
---|
| 52 | private method UpdateViewer {} |
---|
| 53 | |
---|
| 54 | constructor {c name args} {} |
---|
| 55 | destructor {} |
---|
| 56 | public method limits { min max } |
---|
| 57 | public method names {} |
---|
| 58 | public method name {} |
---|
| 59 | public method values {} |
---|
| 60 | public method absoluteValues {} |
---|
| 61 | public method removeMarkers { list } |
---|
| 62 | public method addMarkers { values } |
---|
[4088] | 63 | public method newMarker { x y state } |
---|
| 64 | public method deleteMarker { x y } |
---|
[3941] | 65 | public method hideMarkers { {list {}} } |
---|
| 66 | public method showMarkers { {limits {}} } |
---|
| 67 | } |
---|
| 68 | |
---|
| 69 | itcl::body Rappture::TransferFunctionEditor::constructor {c name args} { |
---|
| 70 | set _canvas $c |
---|
| 71 | set _name $name |
---|
| 72 | set _limits [list 0.0 1.0] |
---|
| 73 | eval configure $args |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | itcl::body Rappture::TransferFunctionEditor::limits { min max } { |
---|
| 77 | set _limits [list $min $max] |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | itcl::body Rappture::TransferFunctionEditor::names {} { |
---|
| 81 | return [lsort [array names _values]] |
---|
| 82 | } |
---|
| 83 | |
---|
| 84 | itcl::body Rappture::TransferFunctionEditor::values {} { |
---|
| 85 | set list {} |
---|
| 86 | foreach name [array names _ticks] { |
---|
| 87 | lappend list [GetRelativeValue $name] |
---|
| 88 | } |
---|
| 89 | return [lsort -real $list] |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | itcl::body Rappture::TransferFunctionEditor::absoluteValues {} { |
---|
| 93 | set list {} |
---|
| 94 | foreach name [array names _values] { |
---|
| 95 | lappend list [GetAbsoluteValue $name] |
---|
| 96 | } |
---|
| 97 | return $list |
---|
| 98 | } |
---|
| 99 | |
---|
[4088] | 100 | itcl::body Rappture::TransferFunctionEditor::deleteMarker { x y } { |
---|
| 101 | foreach marker [GetOverlappingMarkers $x $y] { |
---|
| 102 | $_canvas delete $_ticks($marker) |
---|
| 103 | $_canvas delete $_labels($marker) |
---|
| 104 | array unset _ticks $marker |
---|
| 105 | array unset _labels $marker |
---|
| 106 | array unset _values $marker |
---|
| 107 | bell |
---|
| 108 | UpdateViewer |
---|
| 109 | } |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | itcl::body Rappture::TransferFunctionEditor::newMarker { x y state } { |
---|
[3984] | 113 | foreach id [$_canvas find overlapping \ |
---|
| 114 | [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5]] { |
---|
| 115 | if { [info exists _id2name($id)] } { |
---|
| 116 | puts stderr "Too close to existing marker" |
---|
| 117 | return; # Too close to existing marker |
---|
| 118 | } |
---|
| 119 | } |
---|
[3941] | 120 | set name "tick[incr _nextId]" |
---|
| 121 | set w [winfo width $_canvas] |
---|
| 122 | set h [winfo height $_canvas] |
---|
| 123 | |
---|
| 124 | set _ticks($name) [$_canvas create image 0 $h \ |
---|
| 125 | -image $_normalIcon -anchor s \ |
---|
[3970] | 126 | -tags "tick $_name $this" -state $state] |
---|
[3941] | 127 | set _labels($name) [$_canvas create text 0 $h \ |
---|
| 128 | -anchor n -fill white -font "Helvetica 8" \ |
---|
[3970] | 129 | -tags "$this $_name" -state $state] |
---|
[3941] | 130 | set _id2name($_ticks($name)) $name |
---|
| 131 | $_canvas bind $_ticks($name) <Enter> [itcl::code $this EnterTick $name] |
---|
| 132 | $_canvas bind $_ticks($name) <Leave> [itcl::code $this LeaveTick $name] |
---|
| 133 | $_canvas bind $_ticks($name) <ButtonPress-1> \ |
---|
| 134 | [itcl::code $this StartDrag $name %x %y] |
---|
| 135 | $_canvas bind $_ticks($name) <B1-Motion> \ |
---|
| 136 | [itcl::code $this ContinueDrag $name %x %y] |
---|
| 137 | $_canvas bind $_ticks($name) <ButtonRelease-1> \ |
---|
| 138 | [itcl::code $this StopDrag $name %x %y] |
---|
| 139 | |
---|
| 140 | SetRelativeValue $name [expr {double($x-10)/($w-20)}] |
---|
[3984] | 141 | if { $state == "normal" } { |
---|
| 142 | UpdateViewer |
---|
| 143 | } |
---|
[3941] | 144 | return $name |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | itcl::body Rappture::TransferFunctionEditor::destructor {} { |
---|
| 148 | $_canvas delete $_name |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | itcl::body Rappture::TransferFunctionEditor::name {} { |
---|
| 152 | return $_name |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | itcl::body Rappture::TransferFunctionEditor::Activate { name } { |
---|
| 156 | if { $_activePress || $_activeMotion } { |
---|
| 157 | $_canvas itemconfigure $_labels($name) -state normal |
---|
| 158 | $_canvas itemconfigure $_ticks($name) -image $_activeIcon |
---|
| 159 | $_canvas itemconfigure title -state hidden |
---|
| 160 | } |
---|
| 161 | } |
---|
| 162 | |
---|
| 163 | itcl::body Rappture::TransferFunctionEditor::Deactivate { name } { |
---|
| 164 | if { $_activePress || $_activeMotion } { |
---|
[3970] | 165 | #puts stderr "do nothing for Deactivate" |
---|
[3941] | 166 | } else { |
---|
| 167 | $_canvas itemconfigure $_labels($name) -state hidden |
---|
| 168 | $_canvas itemconfigure $_ticks($name) -image $_normalIcon |
---|
| 169 | $_canvas itemconfigure title -state normal |
---|
| 170 | } |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | itcl::body Rappture::TransferFunctionEditor::SetVisibility { name bool } { |
---|
| 174 | if { $bool } { |
---|
| 175 | $_canvas itemconfigure $_ticks($name) -state normal |
---|
| 176 | $_canvas raise $_ticks($name) |
---|
| 177 | } else { |
---|
| 178 | $_canvas itemconfigure $_ticks($name) -state hidden |
---|
| 179 | } |
---|
| 180 | } |
---|
| 181 | |
---|
| 182 | itcl::body Rappture::TransferFunctionEditor::GetScreenPosition { name } { |
---|
| 183 | set x [GetRelativeValue $name] |
---|
| 184 | if { $x < 0.0 } { |
---|
| 185 | set x 0.0 |
---|
| 186 | } elseif { $x > 1.0 } { |
---|
| 187 | set x 1.0 |
---|
| 188 | } |
---|
| 189 | set low 10 |
---|
| 190 | set w [winfo width $_canvas] |
---|
| 191 | set high [expr {$w - 10}] |
---|
| 192 | set x [expr {round($x*($high - $low) + $low)}] |
---|
| 193 | return $x |
---|
| 194 | } |
---|
| 195 | |
---|
| 196 | itcl::body Rappture::TransferFunctionEditor::SetScreenPosition { name } { |
---|
| 197 | set value $_values($name) |
---|
| 198 | set x [GetScreenPosition $name] |
---|
| 199 | set absval [GetAbsoluteValue $name] |
---|
| 200 | set y 31 |
---|
| 201 | $_canvas itemconfigure $_labels($name) -text [format %.2g $absval] |
---|
| 202 | $_canvas coords $_ticks($name) $x [expr {$y+3}] |
---|
| 203 | $_canvas coords $_labels($name) $x [expr {$y+5}] |
---|
| 204 | } |
---|
| 205 | |
---|
| 206 | itcl::body Rappture::TransferFunctionEditor::GetAbsoluteValue { name } { |
---|
| 207 | foreach {min max} $_limits break |
---|
| 208 | return [expr {($_values($name) * ($max - $min)) + $min}] |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | itcl::body Rappture::TransferFunctionEditor::SetAbsoluteValue { name value } { |
---|
| 212 | foreach {min max} $_limits break |
---|
| 213 | set absval $value |
---|
| 214 | set relval [expr {($absval - $min) / ($max - $min)}] |
---|
| 215 | set _values($name) $relval |
---|
| 216 | set y 31 |
---|
| 217 | $_canvas itemconfigure $_label -text [format %.2g $absval] |
---|
| 218 | set x [GetScreenPosition $name] |
---|
| 219 | $_canvas coords $_ticks($name) $x [expr {$y+3}] |
---|
| 220 | $_canvas coords $_labels($name) $x [expr {$y+5}] |
---|
| 221 | return $absval |
---|
| 222 | } |
---|
| 223 | |
---|
| 224 | itcl::body Rappture::TransferFunctionEditor::GetRelativeValue { name } { |
---|
| 225 | return $_values($name) |
---|
| 226 | } |
---|
| 227 | |
---|
| 228 | itcl::body Rappture::TransferFunctionEditor::SetRelativeValue { name value } { |
---|
| 229 | set _values($name) $value |
---|
| 230 | set x [GetScreenPosition $name] |
---|
| 231 | set y 31 |
---|
| 232 | set absval [GetAbsoluteValue $name] |
---|
| 233 | $_canvas itemconfigure $_labels($name) -text [format %.2g $absval] |
---|
| 234 | $_canvas coords $_ticks($name) $x [expr {$y+3}] |
---|
| 235 | $_canvas coords $_labels($name) $x [expr {$y+5}] |
---|
| 236 | } |
---|
| 237 | |
---|
| 238 | itcl::body Rappture::TransferFunctionEditor::EnterTick { name } { |
---|
| 239 | set _activeMotion 1 |
---|
| 240 | Activate $name |
---|
| 241 | $_canvas raise $_ticks($name) |
---|
| 242 | } |
---|
| 243 | |
---|
| 244 | itcl::body Rappture::TransferFunctionEditor::LeaveTick { name } { |
---|
| 245 | set _activeMotion 0 |
---|
| 246 | Deactivate $name |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | itcl::body Rappture::TransferFunctionEditor::StartDrag { name x y } { |
---|
| 250 | $_canvas raise $_ticks($name) |
---|
| 251 | set _activePress 1 |
---|
| 252 | Activate $name |
---|
| 253 | $_canvas itemconfigure limits -state hidden |
---|
| 254 | $_canvas itemconfigure title -state hidden |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | itcl::body Rappture::TransferFunctionEditor::StopDrag { name x y } { |
---|
| 258 | ContinueDrag $name $x $y |
---|
| 259 | RemoveDuplicateMarkers $name $x $y |
---|
| 260 | set _activePress 0 |
---|
| 261 | Deactivate $name |
---|
| 262 | $_canvas itemconfigure limits -state normal |
---|
| 263 | $_canvas itemconfigure title -state normal |
---|
| 264 | } |
---|
| 265 | |
---|
| 266 | itcl::body Rappture::TransferFunctionEditor::ContinueDrag { name x y } { |
---|
| 267 | set w [winfo width $_canvas] |
---|
| 268 | SetRelativeValue $name [expr {double($x-10)/($w-20)}] |
---|
| 269 | UpdateViewer |
---|
| 270 | $_canvas raise $_ticks($name) |
---|
| 271 | set _activePress 1 |
---|
| 272 | Activate $name |
---|
| 273 | $_canvas itemconfigure limits -state hidden |
---|
| 274 | $_canvas itemconfigure title -state hidden |
---|
| 275 | } |
---|
| 276 | |
---|
| 277 | itcl::body Rappture::TransferFunctionEditor::GetOverlappingMarkers { x y } { |
---|
| 278 | set list {} |
---|
| 279 | foreach id [$_canvas find overlapping $x $y $x $y] { |
---|
| 280 | if { [info exists _id2name($id)] } { |
---|
| 281 | lappend list $_id2name($id) |
---|
| 282 | } |
---|
| 283 | } |
---|
| 284 | return $list |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | itcl::body Rappture::TransferFunctionEditor::hideMarkers { {list {}} } { |
---|
| 288 | if { $list == "" } { |
---|
| 289 | set list [array names _values] |
---|
| 290 | } |
---|
| 291 | foreach name $list { |
---|
| 292 | SetVisibility $name 0 |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | |
---|
| 296 | itcl::body Rappture::TransferFunctionEditor::showMarkers { {limits {}} } { |
---|
| 297 | if { $limits != "" } { |
---|
| 298 | set _limits $limits |
---|
| 299 | foreach name [array names _values] { |
---|
| 300 | SetScreenPosition $name |
---|
| 301 | } |
---|
| 302 | } |
---|
| 303 | foreach name [array names _values] { |
---|
| 304 | SetVisibility $name 1 |
---|
| 305 | } |
---|
| 306 | } |
---|
| 307 | |
---|
| 308 | itcl::body Rappture::TransferFunctionEditor::RemoveDuplicateMarkers {name x y} { |
---|
| 309 | foreach marker [GetOverlappingMarkers $x $y] { |
---|
| 310 | if { $marker != $name } { |
---|
| 311 | Activate $marker |
---|
| 312 | set markerx [GetScreenPosition $marker] |
---|
| 313 | if { ($x < ($markerx-3)) || ($x > ($markerx+3)) } { |
---|
| 314 | continue |
---|
| 315 | } |
---|
| 316 | $_canvas delete $_ticks($marker) |
---|
| 317 | $_canvas delete $_labels($marker) |
---|
| 318 | array unset _ticks $marker |
---|
| 319 | array unset _labels $marker |
---|
| 320 | array unset _values $marker |
---|
| 321 | bell |
---|
| 322 | } |
---|
| 323 | } |
---|
| 324 | } |
---|
| 325 | |
---|
| 326 | itcl::body Rappture::TransferFunctionEditor::addMarkers { values } { |
---|
| 327 | foreach value $values { |
---|
[4088] | 328 | set name [newMarker 0 0 hidden] |
---|
[3941] | 329 | SetRelativeValue $name $value |
---|
| 330 | } |
---|
| 331 | } |
---|
| 332 | |
---|
| 333 | itcl::body Rappture::TransferFunctionEditor::removeMarkers { names } { |
---|
| 334 | if { $names == "" } { |
---|
| 335 | set names [array names _values] |
---|
| 336 | } |
---|
| 337 | foreach name $names { |
---|
| 338 | $_canvas delete $_ticks($name) |
---|
| 339 | $_canvas delete $_labels($name) |
---|
| 340 | array unset _ticks $name |
---|
| 341 | array unset _labels $name |
---|
| 342 | array unset _values $name |
---|
| 343 | } |
---|
| 344 | UpdateViewer |
---|
| 345 | } |
---|
| 346 | |
---|
| 347 | itcl::body Rappture::TransferFunctionEditor::UpdateViewer {} { |
---|
| 348 | # Tell the nanovis/flowvis client to update its transfer functions |
---|
| 349 | # now that a marker position has changed. |
---|
| 350 | if { $command != "" } { |
---|
| 351 | eval uplevel \#0 $command |
---|
| 352 | } |
---|
| 353 | } |
---|