Commit 32a72e8b400238d37779453dcf05084a5402256d

Authored by Paulo Henrique Junqueira Amorim
1 parent 7853c073

ENH: Cursor actor is being shown over slice. Not working when cursor is moved.

Showing 1 changed file with 75 additions and 60 deletions   Show diff stats
invesalius/data/viewer_slice.py
... ... @@ -29,34 +29,34 @@ import project
29 29 import cursor_actors as ca
30 30  
31 31 class Viewer(wx.Panel):
32   -
  32 +
33 33 def __init__(self, prnt, orientation='AXIAL'):
34 34 wx.Panel.__init__(self, prnt, size=wx.Size(320, 300))
35   -
  35 +
36 36 colour = [255*c for c in const.ORIENTATION_COLOUR[orientation]]
37 37 self.SetBackgroundColour(colour)
38   -
  38 +
39 39 # Interactor aditional style
40 40 self.modes = ['DEFAULT']
41 41 self.mouse_pressed = 0
42   -
  42 +
43 43 self.__init_gui()
44 44  
45 45 self.orientation = orientation
46 46 self.slice_number = 0
47   -
  47 +
48 48 self._brush_cursor_op = 'Draw'
49 49 self.brush_cursor_size = 30
50   -
  50 + self.cursor = None
51 51 # VTK pipeline and actors
52 52 self.__config_interactor()
53 53 self.pick = vtk.vtkCellPicker()
54   -
  54 +
55 55 self.__bind_events()
56 56 self.__bind_events_wx()
57 57  
58 58 def __init_gui(self):
59   -
  59 +
60 60 interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize())
61 61  
62 62 scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
... ... @@ -78,7 +78,7 @@ class Viewer(wx.Panel):
78 78 self.interactor = interactor
79 79  
80 80 def __config_interactor(self):
81   -
  81 +
82 82 ren = vtk.vtkRenderer()
83 83  
84 84 interactor = self.interactor
... ... @@ -86,14 +86,13 @@ class Viewer(wx.Panel):
86 86  
87 87 self.cam = ren.GetActiveCamera()
88 88 self.ren = ren
89   -
90   - self.AppendMode('EDITOR')
91   -
  89 +
  90 +
92 91 def AppendMode(self, mode):
93   -
  92 +
94 93 # Retrieve currently set modes
95 94 self.modes.append(mode)
96   -
  95 +
97 96 # All modes and bindings
98 97 action = {'DEFAULT': {
99 98 "MouseMoveEvent": self.OnCrossMove,
... ... @@ -111,7 +110,7 @@ class Viewer(wx.Panel):
111 110 style = vtk.vtkInteractorStyleImage()
112 111 self.style = style
113 112 self.interactor.SetInteractorStyle(style)
114   -
  113 +
115 114 # Check all modes set by user
116 115 for mode in self.modes:
117 116 # Check each event available for each mode
... ... @@ -120,17 +119,7 @@ class Viewer(wx.Panel):
120 119 style.AddObserver(event,
121 120 action[mode][event])
122 121  
123   - # Insert cursor
124   - cursor = ca.CursorCircle()
125   - cursor.SetOrientation(self.orientation)
126   - coordinates = {"SAGITAL": [self.slice_number, 0, 0],
127   - "CORONAL": [0, self.slice_number, 0],
128   - "AXIAL": [0, 0, self.slice_number]}
129   - cursor.SetPosition(coordinates[self.orientation])
130   - self.ren.AddActor(cursor.actor)
131   - self.ren.Render()
132   -
133   - self.cursor = cursor
  122 +
134 123  
135 124 def ChangeBrushSize(self, pubsub_evt):
136 125 size = pubsub_evt.data
... ... @@ -140,23 +129,24 @@ class Viewer(wx.Panel):
140 129 self.interactor.Render()
141 130  
142 131 def ChangeBrushColour(self, pubsub_evt):
143   - vtk_colour = pubsub_evt.data[3]
144   - self.cursor.SetColour(vtk_colour)
145   - self._brush_cursor_colour = vtk_colour
146   - self.ren.Render()
147   - self.interactor.Render()
148   -
  132 + if (self.cursor):
  133 + vtk_colour = pubsub_evt.data[3]
  134 + self.cursor.SetColour(vtk_colour)
  135 + self._brush_cursor_colour = vtk_colour
  136 + self.ren.Render()
  137 + self.interactor.Render()
  138 +
149 139  
150 140 def ChangeBrushActor(self, pubsub_evt):
151 141 brush_type = pubsub_evt.data
152 142 self.ren.RemoveActor(self.cursor.actor)
153   -
  143 +
154 144 if brush_type == 'square':
155 145 cursor = ca.CursorRectangle()
156 146 elif brush_type == 'circle':
157 147 cursor = ca.CursorCircle()
158 148 self.cursor = cursor
159   -
  149 +
160 150 cursor.SetOrientation(self.orientation)
161 151 coordinates = {"SAGITAL": [self.slice_number, 0, 0],
162 152 "CORONAL": [0, self.slice_number, 0],
... ... @@ -187,21 +177,21 @@ class Viewer(wx.Panel):
187 177 self.cursor.SetPosition(coord)
188 178 self.cursor.SetEditionPosition(self.GetCoordinateCursorEdition())
189 179 self.ren.Render()
190   -
  180 +
191 181 if self._brush_cursor_op == 'Erase':
192 182 evt_msg = 'Erase mask pixel'
193 183 elif self._brush_cursor_op == 'Draw':
194 184 evt_msg = 'Add mask pixel'
195 185 elif self._brush_cursor_op == 'Threshold':
196 186 evt_msg = 'Edit mask pixel'
197   -
  187 +
198 188 if self.mouse_pressed:
199 189 print "Edit pixel region based on origin:", coord
200 190 pixels = self.cursor.GetPixels()
201 191 for coord in pixels:
202 192 ps.Publisher().sendMessage(evt_msg, coord)
203 193 self.interactor.Render()
204   -
  194 +
205 195 def OnCrossMove(self, obj, evt_vtk):
206 196 coord = self.GetCoordinate()
207 197 # Update position in other slices
... ... @@ -214,34 +204,34 @@ class Viewer(wx.Panel):
214 204 coord[1])
215 205 ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'),
216 206 coord[2])
217   -
218   -
  207 +
  208 +
219 209 def GetCoordinate(self):
220   -
  210 +
221 211 # Find position
222 212 mouse_x, mouse_y = self.interactor.GetEventPosition()
223 213 self.pick.Pick(mouse_x, mouse_y, 0, self.ren)
224 214 x, y, z = self.pick.GetPickPosition()
225   -
  215 +
226 216 # First we fix the position origin, based on vtkActor bounds
227 217 bounds = self.actor.GetBounds()
228 218 bound_xi, bound_xf, bound_yi, bound_yf, bound_zi, bound_zf = bounds
229 219 x = float(x - bound_xi)
230 220 y = float(y - bound_yi)
231 221 z = float(z - bound_zi)
232   -
  222 +
233 223 # Then we fix the porpotion, based on vtkImageData spacing
234 224 spacing_x, spacing_y, spacing_z = self.imagedata.GetSpacing()
235 225 x = x/spacing_x
236 226 y = y/spacing_y
237 227 z = z/spacing_z
238   -
  228 +
239 229 # Based on the current orientation, we define 3D position
240 230 coordinates = {"SAGITAL": [self.slice_number, y, z],
241 231 "CORONAL": [x, self.slice_number, z],
242 232 "AXIAL": [x, y, self.slice_number]}
243 233 coord = [int(coord) for coord in coordinates[self.orientation]]
244   -
  234 +
245 235 # According to vtkImageData extent, we limit min and max value
246 236 # If this is not done, a VTK Error occurs when mouse is pressed outside
247 237 # vtkImageData extent
... ... @@ -254,24 +244,24 @@ class Viewer(wx.Panel):
254 244 elif coord[index] < extent_min[index]:
255 245 coord[index] = extent_min[index]
256 246 #print "New coordinate: ", coord
257   -
  247 +
258 248 return coord
259   -
  249 +
260 250 def GetCoordinateCursor(self):
261   -
  251 +
262 252 # Find position
263 253 mouse_x, mouse_y = self.interactor.GetEventPosition()
264 254 self.pick.Pick(mouse_x, mouse_y, 0, self.ren)
265 255 x, y, z = self.pick.GetPickPosition()
266 256 return x, y, z
267   -
  257 +
268 258 def GetCoordinateCursorEdition(self):
269   -
  259 +
270 260 # Find position
271 261 mouse_x, mouse_y = self.interactor.GetEventPosition()
272 262 self.pick.Pick(mouse_x, mouse_y, 0, self.ren)
273 263 x, y, z = self.pick.GetPickPosition()
274   -
  264 +
275 265 # First we fix the position origin, based on vtkActor bounds
276 266 bounds = self.actor.GetBounds()
277 267 bound_xi, bound_xf, bound_yi, bound_yf, bound_zi, bound_zf = bounds
... ... @@ -299,21 +289,21 @@ class Viewer(wx.Panel):
299 289 z = self.slice_number
300 290  
301 291 return x,y,z
302   -
  292 +
303 293 def __bind_events(self):
304 294 ps.Publisher().subscribe(self.LoadImagedata, 'Load slice to viewer')
305 295 ps.Publisher().subscribe(self.SetColour, 'Change mask colour')
306 296 ps.Publisher().subscribe(self.UpdateRender, 'Update slice viewer')
307   - ps.Publisher().subscribe(self.ChangeSliceNumber, ('Set scroll position',
  297 + ps.Publisher().subscribe(self.ChangeSliceNumber, ('Set scroll position',
308 298 self.orientation))
309   -
  299 +
310 300 ###
311 301 ps.Publisher().subscribe(self.ChangeBrushSize,'Set edition brush size')
312 302 ps.Publisher().subscribe(self.ChangeBrushColour, 'Add mask')
313 303 ps.Publisher().subscribe(self.ChangeBrushActor, 'Set brush format')
314 304 ps.Publisher().subscribe(self.ChangeBrushOperation, 'Set edition operation')
315   -
316   -
  305 +
  306 +
317 307 def ChangeBrushOperation(self, pubsub_evt):
318 308 print pubsub_evt.data
319 309 self._brush_cursor_op = pubsub_evt.data
... ... @@ -339,6 +329,7 @@ class Viewer(wx.Panel):
339 329  
340 330 actor = vtk.vtkImageActor()
341 331 actor.SetInput(slice_.GetOutput())
  332 + actor_bound = actor.GetBounds()
342 333 self.actor = actor
343 334  
344 335 colour = const.ORIENTATION_COLOUR[self.orientation]
... ... @@ -363,7 +354,30 @@ class Viewer(wx.Panel):
363 354 self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
364 355 max_slice_number)
365 356 self.SetScrollPosition(0)
366   - self.cursor.SetSpacing(imagedata.GetSpacing())
  357 +
  358 + actor_bound = actor.GetBounds()
  359 +
  360 + # Insert cursor
  361 + cursor = ca.CursorCircle()
  362 + cursor.SetOrientation(self.orientation)
  363 + self.__update_cursor_position()
  364 + cursor.SetSpacing(imagedata.GetSpacing())
  365 + self.ren.AddActor(cursor.actor)
  366 + self.ren.Render()
  367 +
  368 + self.cursor = cursor
  369 +
  370 + self.AppendMode('EDITOR')
  371 +
  372 + def __update_cursor_position(self, position = None):
  373 +
  374 + if (self.cursor):
  375 + slice_number = self.slice_number
  376 + actor_bound = self.actor.GetBounds()
  377 + coordinates = {"SAGITAL": [actor_bound[1] + 1 + slice_number, actor_bound[3], actor_bound[5]],
  378 + "CORONAL": [actor_bound[1], actor_bound[3] + 1 + slice_number, actor_bound[5]],
  379 + "AXIAL": [actor_bound[1], actor_bound[3], actor_bound[5] + 1 + slice_number]}
  380 + self.cursor.SetPosition(coordinates[self.orientation])
367 381  
368 382 def SetOrientation(self, orientation):
369 383 self.orientation = orientation
... ... @@ -378,10 +392,10 @@ class Viewer(wx.Panel):
378 392 cam.SetViewUp(const.CAM_VIEW_UP[self.orientation])
379 393 cam.ComputeViewPlaneNormal()
380 394 cam.OrthogonalizeViewUp()
381   - cam.ParallelProjectionOn()
  395 + cam.ParallelProjectionOn()
382 396  
383 397 self.__update_display_extent()
384   -
  398 +
385 399 self.ren.ResetCamera()
386 400 self.ren.Render()
387 401  
... ... @@ -389,11 +403,11 @@ class Viewer(wx.Panel):
389 403  
390 404 pos = self.slice_number
391 405 e = self.imagedata.GetWholeExtent()
392   -
  406 +
393 407 new_extent = {"SAGITAL": (pos, pos, e[2], e[3], e[4], e[5]),
394 408 "CORONAL": (e[0], e[1], pos, pos, e[4], e[5]),
395 409 "AXIAL": (e[0], e[1], e[2], e[3], pos, pos)}
396   -
  410 +
397 411 self.actor.SetDisplayExtent(new_extent[self.orientation])
398 412 self.ren.ResetCameraClippingRange()
399 413 self.ren.Render()
... ... @@ -416,6 +430,7 @@ class Viewer(wx.Panel):
416 430 self.text_actor.SetInput(str(index))
417 431 self.slice_number = index
418 432 self.__update_display_extent()
  433 + self.__update_cursor_position()
419 434  
420 435 def ChangeSliceNumber(self, pubsub_evt):
421 436 index = pubsub_evt.data
... ...