File: ImageInteractor.tcl

package info (click to toggle)
vtk7 7.1.1%2Bdfsg2-8
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 127,396 kB
  • sloc: cpp: 1,539,584; ansic: 124,382; python: 78,038; tcl: 47,013; xml: 8,142; yacc: 5,040; java: 4,439; perl: 3,132; lex: 1,926; sh: 1,500; makefile: 126; objc: 83
file content (192 lines) | stat: -rw-r--r-- 4,777 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# This example shows how to use the InteractorStyleImage and add your own
# event handling.  The InteractorStyleImage is a special interactor designed
# to be used with vtkImageActor in a rendering window context. It forces the
# camera to stay perpendicular to the x-y plane.

package require vtk
package require vtkinteraction

# Create the image
#
vtkPNGReader reader
  reader SetDataSpacing 0.8 0.8 1.5
  reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png"

vtkImageShiftScale shiftScale
  shiftScale SetInputConnection [reader GetOutputPort]
  shiftScale SetShift 0
  shiftScale SetScale 0.07
  shiftScale SetOutputScalarTypeToUnsignedChar

vtkImageActor ia
  [ia GetMapper] SetInputConnection [shiftScale GetOutputPort]

# Create the RenderWindow, Renderer and both Actors
vtkRenderer ren1
vtkRenderWindow renWin
    renWin AddRenderer ren1
vtkRenderWindowInteractor iren
    iren SetRenderWindow renWin

# Create an image interactor style and associate it with the
# interactive renderer. Then assign some callbacks with the
# appropriate events. THe callbacks are implemented as Tcl procs.
vtkInteractorStyleImage interactor
  iren SetInteractorStyle interactor
  interactor AddObserver LeftButtonPressEvent {StartZoom}
  interactor AddObserver MouseMoveEvent {MouseMove}
  interactor AddObserver LeftButtonReleaseEvent {EndZoom}

# Add the actors to the renderer, set the background and size
ren1 AddActor ia
ren1 SetBackground 0.1 0.2 0.4
renWin SetSize 400 400

# render the image
iren AddObserver UserEvent {wm deiconify .vtkInteract}
renWin Render

set cam1 [ren1 GetActiveCamera]

ren1 ResetCameraClippingRange
renWin Render

# prevent the tk window from showing up then start the event loop
wm withdraw .

### Supporting data for callbacks
vtkPoints pts
  pts SetNumberOfPoints 4
vtkCellArray lines
  lines InsertNextCell 5
  lines InsertCellPoint 0
  lines InsertCellPoint 1
  lines InsertCellPoint 2
  lines InsertCellPoint 3
  lines InsertCellPoint 0
vtkPolyData pd
  pd SetPoints pts
  pd SetLines lines
vtkPolyDataMapper2D bboxMapper
  bboxMapper SetInputData pd
vtkActor2D bboxActor
  bboxActor SetMapper bboxMapper
  [bboxActor GetProperty] SetColor 1 0 0
ren1 AddViewProp bboxActor

### Procedures for callbacks---------------------
set X 0
set Y 0
set bboxEnabled 0

proc StartZoom {} {
  global X Y bboxEnabled

  set xy [iren GetEventPosition]
  set X [lindex $xy 0]
  set Y [lindex $xy 1]

  pts SetPoint 0 $X $Y 0
  pts SetPoint 1 $X $Y 0
  pts SetPoint 2 $X $Y 0
  pts SetPoint 3 $X $Y 0

  set bboxEnabled 1
  bboxActor VisibilityOn
}

proc MouseMove {} {
  global X Y bboxEnabled

  if { $bboxEnabled } {
    set xy [iren GetEventPosition]
    set x [lindex $xy 0]
    set y [lindex $xy 1]

    pts SetPoint 1 $x $Y 0
    pts SetPoint 2 $x $y 0
    pts SetPoint 3 $X $y 0

    renWin Render
    }
}

#Do the hard stuff: pan and dolly
proc EndZoom {} {
  global bboxEnabled

  set p1 [pts GetPoint 0]
  set p2 [pts GetPoint 2]
  set x1 [lindex $p1 0]
  set y1 [lindex $p1 1]
  set x2 [lindex $p2 0]
  set y2 [lindex $p2 1]

  ren1 SetDisplayPoint $x1 $y1 0
  ren1 DisplayToWorld
  set p1 [ren1 GetWorldPoint]
  ren1 SetDisplayPoint $x2 $y2 0
  ren1 DisplayToWorld
  set p2 [ren1 GetWorldPoint]

  set p1X [lindex $p1 0]
  set p1Y [lindex $p1 1]
  set p1Z [lindex $p1 2]

  set p2X [lindex $p2 0]
  set p2Y [lindex $p2 1]
  set p2Z [lindex $p2 2]

  set camera [ren1 GetActiveCamera]
  set focalPt [$camera GetFocalPoint]
  set focalX [lindex $focalPt 0]
  set focalY [lindex $focalPt 1]
  set focalZ [lindex $focalPt 2]
  set position [$camera GetPosition]
  set positionX [lindex $position 0]
  set positionY [lindex $position 1]
  set positionZ [lindex $position 2]

  set deltaX [expr $focalX - ($p1X + $p2X)/2.0]
  set deltaY [expr $focalY - ($p1Y + $p2Y)/2.0]

  #Set camera focal point to the center of the box
  $camera SetFocalPoint [expr ($p1X + $p2X)/2.0] \
          [expr ($p1Y + $p2Y)/2.0] $focalZ
  $camera SetPosition [expr $positionX - $deltaX] \
          [expr $positionY - $deltaY] $positionZ

  #Now dolly the camera to fill the box
  #This is a half-assed hack for demonstration purposes
  if { $p1X > $p2X } {
      set deltaX [expr $p1X - $p2X]
  } else {
      set deltaX [expr $p2X - $p1X]
  }
  if { $p1Y > $p2Y } {
      set deltaY [expr $p1Y - $p2Y]
  } else {
      set deltaY [expr $p2Y - $p1Y]
  }

  set winSize [renWin GetSize]
  set winX [lindex $winSize 0]
  set winY [lindex $winSize 1]

  set sx [expr $deltaX / $winX]
  set sy [expr $deltaY / $winY]

  if { $sx > $sy } {
      set dolly [expr 1.0 + 1.0/(2.0*$sx)]
  } else {
      set dolly [expr 1.0 + 1.0/(2.0*$sy)]
  }
  $camera Dolly $dolly
  ren1 ResetCameraClippingRange

  set bboxEnabled 0
  bboxActor VisibilityOff
  renWin Render
}

iren Start