Commit 29f9d5189f0e55a7d7520a78b5e7458b653b5c51
1 parent
46b26413
Exists in
master
and in
68 other branches
ADD: Plane with slices
Showing
3 changed files
with
102 additions
and
37 deletions
Show diff stats
invesalius/control.py
@@ -116,7 +116,8 @@ class Controller(): | @@ -116,7 +116,8 @@ class Controller(): | ||
116 | ps.Publisher().sendMessage('Show content panel') | 116 | ps.Publisher().sendMessage('Show content panel') |
117 | 117 | ||
118 | ps.Publisher().sendMessage('Update AUI') | 118 | ps.Publisher().sendMessage('Update AUI') |
119 | - | 119 | + |
120 | + ps.Publisher().sendMessage('Load slice plane') | ||
120 | 121 | ||
121 | def LoadImagedataInfo(self): | 122 | def LoadImagedataInfo(self): |
122 | proj = prj.Project() | 123 | proj = prj.Project() |
invesalius/data/viewer_volume.py
@@ -72,6 +72,7 @@ class Viewer(wx.Panel): | @@ -72,6 +72,7 @@ class Viewer(wx.Panel): | ||
72 | self.__bind_events() | 72 | self.__bind_events() |
73 | self.__bind_events_wx() | 73 | self.__bind_events_wx() |
74 | 74 | ||
75 | + | ||
75 | 76 | ||
76 | def OnMove(self, obj, evt): | 77 | def OnMove(self, obj, evt): |
77 | if self.onclick and self.raycasting_volume: | 78 | if self.onclick and self.raycasting_volume: |
@@ -157,8 +158,18 @@ class Viewer(wx.Panel): | @@ -157,8 +158,18 @@ class Viewer(wx.Panel): | ||
157 | ps.Publisher().subscribe(self.OnDisableBrightContrast, | 158 | ps.Publisher().subscribe(self.OnDisableBrightContrast, |
158 | ('Set interaction mode', | 159 | ('Set interaction mode', |
159 | const.MODE_SLICE_EDITOR)) | 160 | const.MODE_SLICE_EDITOR)) |
160 | - | 161 | + |
161 | ps.Publisher().subscribe(self.OnExportSurface, 'Export surface to file') | 162 | ps.Publisher().subscribe(self.OnExportSurface, 'Export surface to file') |
163 | + | ||
164 | + ps.Publisher().subscribe(self.LoadSlicePlane, 'Load slice plane') | ||
165 | + | ||
166 | + ps.Publisher().subscribe(self.ResetCamClippingRange, 'Reset cam clipping range') | ||
167 | + | ||
168 | + | ||
169 | + def ResetCamClippingRange(self, pubsub_evt): | ||
170 | + self.ren.ResetCamera() | ||
171 | + self.ren.ResetCameraClippingRange() | ||
172 | + | ||
162 | 173 | ||
163 | def OnExportSurface(self, pubsub_evt): | 174 | def OnExportSurface(self, pubsub_evt): |
164 | filename, filetype = pubsub_evt.data | 175 | filename, filetype = pubsub_evt.data |
@@ -243,11 +254,8 @@ class Viewer(wx.Panel): | @@ -243,11 +254,8 @@ class Viewer(wx.Panel): | ||
243 | 254 | ||
244 | self.UpdateRender() | 255 | self.UpdateRender() |
245 | 256 | ||
246 | - def LoadPlane(self): | ||
247 | - self.plane = SlicePlane() | ||
248 | - self.plane.EnableX() | ||
249 | - self.plane.EnableY() | ||
250 | - self.plane.EnableZ() | 257 | + def LoadSlicePlane(self, pubsub_evt): |
258 | + self.slice_plane = SlicePlane() | ||
251 | 259 | ||
252 | def ChangeBackgroundColour(self, pubsub_evt): | 260 | def ChangeBackgroundColour(self, pubsub_evt): |
253 | colour = pubsub_evt.data | 261 | colour = pubsub_evt.data |
@@ -308,12 +316,7 @@ class Viewer(wx.Panel): | @@ -308,12 +316,7 @@ class Viewer(wx.Panel): | ||
308 | class SlicePlane: | 316 | class SlicePlane: |
309 | 317 | ||
310 | def __init__(self): | 318 | def __init__(self): |
311 | - | ||
312 | self.Create() | 319 | self.Create() |
313 | - self.__bind_events() | ||
314 | - | ||
315 | - def __bind_events(self): | ||
316 | - self.plane_x.AddObserver("InteractionEvent", self.Update) | ||
317 | 320 | ||
318 | def Create(self): | 321 | def Create(self): |
319 | 322 | ||
@@ -352,35 +355,55 @@ class SlicePlane: | @@ -352,35 +355,55 @@ class SlicePlane: | ||
352 | prop1.SetColor(1, 0, 0) | 355 | prop1.SetColor(1, 0, 0) |
353 | cursor_property = plane_z.GetCursorProperty() | 356 | cursor_property = plane_z.GetCursorProperty() |
354 | cursor_property.SetOpacity(0) | 357 | cursor_property.SetOpacity(0) |
355 | - | 358 | + |
356 | ps.Publisher().sendMessage('Set Widget Interactor', plane_x) | 359 | ps.Publisher().sendMessage('Set Widget Interactor', plane_x) |
357 | ps.Publisher().sendMessage('Set Widget Interactor', plane_y) | 360 | ps.Publisher().sendMessage('Set Widget Interactor', plane_y) |
358 | ps.Publisher().sendMessage('Set Widget Interactor', plane_z) | 361 | ps.Publisher().sendMessage('Set Widget Interactor', plane_z) |
359 | 362 | ||
360 | - def EnableX(self, evt_pubsub=None): | ||
361 | - self.plane_x.On() | ||
362 | - self.Update() | ||
363 | - | ||
364 | - def EnableY(self, evt_pubsub=None): | ||
365 | - self.plane_y.On() | ||
366 | - self.Update() | ||
367 | - | ||
368 | - def EnableZ(self, evt_pubsub=None): | ||
369 | - self.plane_z.On() | ||
370 | - self.Update() | 363 | + ps.Publisher().subscribe(self.Enable, 'Enable plane') |
364 | + ps.Publisher().subscribe(self.Disable, 'Disable plane') | ||
371 | 365 | ||
372 | - def DisableX(self, evt_pubsub=None): | ||
373 | - self.plane_x.Off() | ||
374 | - self.Update() | 366 | + self.Enable() |
367 | + self.Disable() | ||
368 | + | ||
369 | + self.Render() | ||
370 | + | ||
371 | + def Enable(self, evt_pubsub=None): | ||
372 | + if (evt_pubsub): | ||
373 | + label = evt_pubsub.data | ||
374 | + | ||
375 | + if(label == "Axial"): | ||
376 | + self.plane_z.On() | ||
377 | + elif(label == "Coronal"): | ||
378 | + self.plane_x.On() | ||
379 | + elif(label == "Sagital"): | ||
380 | + self.plane_y.On() | ||
381 | + | ||
382 | + else: | ||
383 | + self.plane_z.On() | ||
384 | + self.plane_x.On() | ||
385 | + self.plane_y.On() | ||
386 | + ps.Publisher().sendMessage('Set volume view angle', const.VOL_ISO) | ||
387 | + self.Render() | ||
388 | + | ||
389 | + def Disable(self, evt_pubsub=None): | ||
390 | + if (evt_pubsub): | ||
391 | + label = evt_pubsub.data | ||
392 | + | ||
393 | + if(label == "Axial"): | ||
394 | + self.plane_z.Off() | ||
395 | + elif(label == "Coronal"): | ||
396 | + self.plane_x.Off() | ||
397 | + elif(label == "Sagital"): | ||
398 | + self.plane_y.Off() | ||
399 | + else: | ||
400 | + self.plane_z.Off() | ||
401 | + self.plane_x.Off() | ||
402 | + self.plane_y.Off() | ||
375 | 403 | ||
376 | - def DisableY(self, evt_pubsub=None): | ||
377 | - self.plane_y.Off() | ||
378 | - self.Update() | 404 | + self.Render() |
379 | 405 | ||
380 | - def DisableZ(self, evt_pubsub=None): | ||
381 | - self.plane_z.Off() | ||
382 | - self.Update() | ||
383 | 406 | ||
384 | - def Update(self, obj, evt): | ||
385 | - ps.Publisher().sendMessage('Render volume viewer', None) | 407 | + def Render(self): |
408 | + ps.Publisher().sendMessage('Render volume viewer') | ||
386 | 409 | ||
387 | \ No newline at end of file | 410 | \ No newline at end of file |
invesalius/gui/default_viewers.py
@@ -248,7 +248,7 @@ import wx.lib.pubsub as ps | @@ -248,7 +248,7 @@ import wx.lib.pubsub as ps | ||
248 | import wx.lib.colourselect as csel | 248 | import wx.lib.colourselect as csel |
249 | import constants as const | 249 | import constants as const |
250 | 250 | ||
251 | -[BUTTON_RAYCASTING, BUTTON_VIEW] = [wx.NewId() for num in xrange(2)] | 251 | +[BUTTON_RAYCASTING, BUTTON_VIEW, BUTTON_SLICE_PLANE] = [wx.NewId() for num in xrange(3)] |
252 | RAYCASTING_TOOLS = wx.NewId() | 252 | RAYCASTING_TOOLS = wx.NewId() |
253 | 253 | ||
254 | ID_TO_BMP = {const.VOL_FRONT: ["Front", "../icons/view_front.png"], | 254 | ID_TO_BMP = {const.VOL_FRONT: ["Front", "../icons/view_front.png"], |
@@ -264,6 +264,7 @@ ID_TO_NAME = {} | @@ -264,6 +264,7 @@ ID_TO_NAME = {} | ||
264 | ID_TO_TOOL = {} | 264 | ID_TO_TOOL = {} |
265 | ID_TO_TOOL_ITEM = {} | 265 | ID_TO_TOOL_ITEM = {} |
266 | TOOL_STATE = {} | 266 | TOOL_STATE = {} |
267 | +ID_TO_ITEMSLICEMENU = {} | ||
267 | 268 | ||
268 | class VolumeViewerCover(wx.Panel): | 269 | class VolumeViewerCover(wx.Panel): |
269 | def __init__(self, parent): | 270 | def __init__(self, parent): |
@@ -286,10 +287,19 @@ class VolumeToolPanel(wx.Panel): | @@ -286,10 +287,19 @@ class VolumeToolPanel(wx.Panel): | ||
286 | BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", | 287 | BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", |
287 | wx.BITMAP_TYPE_PNG) | 288 | wx.BITMAP_TYPE_PNG) |
288 | 289 | ||
290 | + BMP_SLICE_PLANE = wx.Bitmap("../icons/slice_plane.png", | ||
291 | + wx.BITMAP_TYPE_PNG) | ||
292 | + | ||
289 | 293 | ||
290 | button_raycasting = pbtn.PlateButton(self, BUTTON_RAYCASTING,"", | 294 | button_raycasting = pbtn.PlateButton(self, BUTTON_RAYCASTING,"", |
291 | BMP_RAYCASTING, style=pbtn.PB_STYLE_SQUARE, | 295 | BMP_RAYCASTING, style=pbtn.PB_STYLE_SQUARE, |
292 | size=(24,24)) | 296 | size=(24,24)) |
297 | + | ||
298 | + button_slice_plane = self.button_slice_plane = pbtn.PlateButton(self, BUTTON_SLICE_PLANE,"", | ||
299 | + BMP_SLICE_PLANE, style=pbtn.PB_STYLE_SQUARE, | ||
300 | + size=(24,24)) | ||
301 | + button_slice_plane.Bind(wx.EVT_LEFT_DOWN, self.OnButtonSlicePlane) | ||
302 | + | ||
293 | self.button_raycasting = button_raycasting | 303 | self.button_raycasting = button_raycasting |
294 | self.button_raycasting.Bind(wx.EVT_LEFT_DOWN, self.OnButtonRaycasting) | 304 | self.button_raycasting.Bind(wx.EVT_LEFT_DOWN, self.OnButtonRaycasting) |
295 | 305 | ||
@@ -321,6 +331,7 @@ class VolumeToolPanel(wx.Panel): | @@ -321,6 +331,7 @@ class VolumeToolPanel(wx.Panel): | ||
321 | sizer.Add(button_colour, 0, wx.ALL, sp) | 331 | sizer.Add(button_colour, 0, wx.ALL, sp) |
322 | sizer.Add(button_raycasting, 0, wx.TOP|wx.BOTTOM, 1) | 332 | sizer.Add(button_raycasting, 0, wx.TOP|wx.BOTTOM, 1) |
323 | sizer.Add(button_view, 0, wx.TOP|wx.BOTTOM, 1) | 333 | sizer.Add(button_view, 0, wx.TOP|wx.BOTTOM, 1) |
334 | + sizer.Add(button_slice_plane, 0, wx.TOP|wx.BOTTOM, 1) | ||
324 | 335 | ||
325 | sizer.Fit(self) | 336 | sizer.Fit(self) |
326 | 337 | ||
@@ -343,6 +354,9 @@ class VolumeToolPanel(wx.Panel): | @@ -343,6 +354,9 @@ class VolumeToolPanel(wx.Panel): | ||
343 | 354 | ||
344 | def OnButtonView(self, evt): | 355 | def OnButtonView(self, evt): |
345 | self.button_view.PopupMenu(self.menu_view) | 356 | self.button_view.PopupMenu(self.menu_view) |
357 | + | ||
358 | + def OnButtonSlicePlane(self, evt): | ||
359 | + self.button_slice_plane.PopupMenu(self.slice_plane_menu) | ||
346 | 360 | ||
347 | def __init_menus(self, pubsub_evt=None): | 361 | def __init_menus(self, pubsub_evt=None): |
348 | # MENU RELATED TO RAYCASTING TYPES | 362 | # MENU RELATED TO RAYCASTING TYPES |
@@ -386,10 +400,37 @@ class VolumeToolPanel(wx.Panel): | @@ -386,10 +400,37 @@ class VolumeToolPanel(wx.Panel): | ||
386 | menu.AppendItem(item) | 400 | menu.AppendItem(item) |
387 | menu.Bind(wx.EVT_MENU, self.OnMenuView) | 401 | menu.Bind(wx.EVT_MENU, self.OnMenuView) |
388 | self.menu_view = menu | 402 | self.menu_view = menu |
389 | - | 403 | + |
404 | + #SLICE PLANES BUTTON | ||
405 | + self.slice_plane_menu = slice_plane_menu = wx.Menu() | ||
406 | + itens = ["Axial", "Coronal", "Sagital"] | ||
407 | + | ||
408 | + for value in itens: | ||
409 | + new_id = wx.NewId() | ||
410 | + | ||
411 | + item = wx.MenuItem(slice_plane_menu, new_id, value, | ||
412 | + kind = wx.ITEM_CHECK) | ||
413 | + ID_TO_ITEMSLICEMENU[new_id] = item | ||
414 | + slice_plane_menu.AppendItem(item) | ||
415 | + | ||
416 | + slice_plane_menu.Bind(wx.EVT_MENU, self.OnMenuPlaneSlice) | ||
417 | + | ||
390 | self.Fit() | 418 | self.Fit() |
391 | self.Update() | 419 | self.Update() |
420 | + | ||
421 | + def OnMenuPlaneSlice(self, evt): | ||
422 | + | ||
423 | + id = evt.GetId() | ||
424 | + item = ID_TO_ITEMSLICEMENU[id] | ||
425 | + checked = item.IsChecked() | ||
426 | + label = item.GetLabel() | ||
427 | + | ||
428 | + if not (checked): | ||
429 | + ps.Publisher().sendMessage('Disable plane', label) | ||
430 | + else: | ||
431 | + ps.Publisher().sendMessage('Enable plane', label) | ||
392 | 432 | ||
433 | + | ||
393 | def ChangeButtonColour(self, pubsub_evt): | 434 | def ChangeButtonColour(self, pubsub_evt): |
394 | colour = [i*255 for i in pubsub_evt.data] | 435 | colour = [i*255 for i in pubsub_evt.data] |
395 | self.button_colour.SetColour(colour) | 436 | self.button_colour.SetColour(colour) |