Commit 66fa5cd60953006d0c96842289ec66d8044f07db

Authored by tatiana
1 parent c6e7c193

ADD: Inserted cross that follows left mouse clicks on slices 2D

invesalius/constants.py
@@ -78,3 +78,10 @@ WINDOW_LEVEL = ({"Abdomen":(350,50), @@ -78,3 +78,10 @@ WINDOW_LEVEL = ({"Abdomen":(350,50),
78 "Vasculature - Hard":(240,80), 78 "Vasculature - Hard":(240,80),
79 "Vasculature - Soft":(650,160) 79 "Vasculature - Soft":(650,160)
80 }) 80 })
  81 +
  82 +ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red
  83 + 'CORONAL': (0,1,0), # Green
  84 + 'SAGITAL': (0,0,1)} # Blue
  85 +CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)}
  86 +CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)}
  87 +
invesalius/data/slice_.py
@@ -28,6 +28,8 @@ class Slice(object): @@ -28,6 +28,8 @@ class Slice(object):
28 ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected') 28 ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected')
29 ps.Publisher().subscribe(self.CreateSurfaceFromIndex, 29 ps.Publisher().subscribe(self.CreateSurfaceFromIndex,
30 'Create surface from index') 30 'Create surface from index')
  31 + ps.Publisher().subscribe(self.UpdateCursorPosition,
  32 + 'Update cursor position in slice')
31 33
32 def CreateSurfaceFromIndex(self, pubsub_evt): 34 def CreateSurfaceFromIndex(self, pubsub_evt):
33 mask_index = pubsub_evt.data 35 mask_index = pubsub_evt.data
@@ -116,7 +118,46 @@ class Slice(object): @@ -116,7 +118,46 @@ class Slice(object):
116 blend_imagedata.SetInput(1, imagedata_mask) 118 blend_imagedata.SetInput(1, imagedata_mask)
117 blend_imagedata.SetBlendModeToNormal() 119 blend_imagedata.SetBlendModeToNormal()
118 blend_imagedata.GetOutput().ReleaseDataFlagOn() 120 blend_imagedata.GetOutput().ReleaseDataFlagOn()
119 - self.blend_imagedata = blend_imagedata 121 + #self.blend_imagedata = blend_imagedata
  122 +
  123 +
  124 + #blend_imagedata.GetExtent()
  125 +
  126 + # global values
  127 + CURSOR_X = 0 # SAGITAL
  128 + CURSOR_Y = 0 # CORONAL
  129 + CURSOR_Z = 0 # AXIAL
  130 +
  131 + CURSOR_VALUE = 4095
  132 + CURSOR_RADIUS = 1000
  133 +
  134 + cross = vtk.vtkImageCursor3D()
  135 + cross.GetOutput().ReleaseDataFlagOn()
  136 + cross.SetInput(blend_imagedata.GetOutput())
  137 + cross.SetCursorPosition(CURSOR_X, CURSOR_Y, CURSOR_Z)
  138 + cross.SetCursorValue(CURSOR_VALUE)
  139 + cross.SetCursorRadius(CURSOR_RADIUS)
  140 + cross.Modified()
  141 + self.cross = cross
  142 +
  143 + cast = vtk.vtkImageCast()
  144 + cast.SetInput(cross.GetOutput())
  145 + cast.GetOutput().SetUpdateExtentToWholeExtent()
  146 + cast.SetOutputScalarTypeToUnsignedChar()
  147 + cast.Update()
  148 +
  149 + self.blend_imagedata = cast
  150 +
  151 +
  152 + def UpdateCursorPosition(self, pubsub_evt):
  153 +
  154 + new_pos = pubsub_evt.data
  155 + self.cross.SetCursorPosition(new_pos)
  156 + self.cross.Modified()
  157 + self.blend_imagedata.Update()
  158 + ps.Publisher().sendMessage('Update slice viewer', None)
  159 +
  160 +
120 161
121 def __create_background(self, imagedata): 162 def __create_background(self, imagedata):
122 163
invesalius/data/viewer_slice.py
@@ -24,35 +24,49 @@ import wx @@ -24,35 +24,49 @@ import wx
24 import wx.lib.pubsub as ps 24 import wx.lib.pubsub as ps
25 25
26 import data.slice_ as sl 26 import data.slice_ as sl
27 - 27 +import constants as const
28 import project 28 import project
29 29
30 class Viewer(wx.Panel): 30 class Viewer(wx.Panel):
31 31
32 def __init__(self, prnt, orientation='AXIAL'): 32 def __init__(self, prnt, orientation='AXIAL'):
33 wx.Panel.__init__(self, prnt, size=wx.Size(320, 300)) 33 wx.Panel.__init__(self, prnt, size=wx.Size(320, 300))
34 - 34 +
  35 + colour = [255*c for c in const.ORIENTATION_COLOUR[orientation]]
  36 + self.SetBackgroundColour(colour)
  37 +
35 self.__init_gui() 38 self.__init_gui()
36 - self.__config_interactor()  
37 39
38 self.orientation = orientation 40 self.orientation = orientation
39 self.slice_number = 0 41 self.slice_number = 0
40 42
  43 + # Interactor aditional style
  44 + self.mode = 'DEFAULT'
  45 + self.mouse_pressed = 0
  46 +
  47 + # VTK pipeline and actors
  48 + self.__config_interactor()
  49 + self.pick = vtk.vtkCellPicker()
  50 + #self.cursor =
  51 +
41 self.__bind_events() 52 self.__bind_events()
42 self.__bind_events_wx() 53 self.__bind_events_wx()
43 54
44 def __init_gui(self): 55 def __init_gui(self):
  56 +
45 interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize()) 57 interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize())
46 58
47 scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL) 59 scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
48 self.scroll = scroll 60 self.scroll = scroll
49 61
50 sizer = wx.BoxSizer(wx.HORIZONTAL) 62 sizer = wx.BoxSizer(wx.HORIZONTAL)
51 - self.SetSizer(sizer)  
52 -  
53 - sizer.Add(scroll, 0, wx.EXPAND|wx.GROW)  
54 sizer.Add(interactor, 1, wx.EXPAND|wx.GROW) 63 sizer.Add(interactor, 1, wx.EXPAND|wx.GROW)
55 - sizer.Fit(self) 64 +
  65 + background_sizer = wx.BoxSizer(wx.HORIZONTAL)
  66 + background_sizer.AddSizer(sizer, 1, wx.EXPAND|wx.GROW|wx.ALL, 2)
  67 + background_sizer.Add(scroll, 0, wx.EXPAND|wx.GROW)
  68 + self.SetSizer(background_sizer)
  69 + background_sizer.Fit(self)
56 70
57 self.Layout() 71 self.Layout()
58 self.Update() 72 self.Update()
@@ -61,7 +75,10 @@ class Viewer(wx.Panel): @@ -61,7 +75,10 @@ class Viewer(wx.Panel):
61 self.interactor = interactor 75 self.interactor = interactor
62 76
63 def __config_interactor(self): 77 def __config_interactor(self):
  78 +
64 style = vtk.vtkInteractorStyleImage() 79 style = vtk.vtkInteractorStyleImage()
  80 + self.style = style
  81 +
65 ren = vtk.vtkRenderer() 82 ren = vtk.vtkRenderer()
66 83
67 interactor = self.interactor 84 interactor = self.interactor
@@ -69,26 +86,116 @@ class Viewer(wx.Panel): @@ -69,26 +86,116 @@ class Viewer(wx.Panel):
69 interactor.GetRenderWindow().AddRenderer(ren) 86 interactor.GetRenderWindow().AddRenderer(ren)
70 87
71 self.cam = ren.GetActiveCamera() 88 self.cam = ren.GetActiveCamera()
72 -  
73 self.ren = ren 89 self.ren = ren
74 - 90 +
  91 + self.SetMode(self.mode)
  92 +
  93 + def SetMode(self, mode):
  94 + self.mode = mode
  95 + # All modes and bindings
  96 + action = {'DEFAULT': {
  97 + "MouseMoveEvent": self.OnCrossMove,
  98 + "LeftButtonPressEvent": self.OnMouseClick,
  99 + "LeftButtonReleaseEvent": self.OnMouseRelease
  100 + },
  101 + 'EDITOR': {
  102 + "MouseMoveEvent": self.OnBrushMove,
  103 + "LeftButtonPressEvent": self.OnBrushClick,
  104 + "LeftButtonReleaseEvent": self.OnMouseRelease
  105 + }
  106 + }
  107 +
  108 + # Bind method according to current mode
  109 + style = self.style
  110 + style.AddObserver("MouseMoveEvent", action[mode]["MouseMoveEvent"])
  111 + style.AddObserver("LeftButtonPressEvent", action[mode]["LeftButtonPressEvent"])
  112 + style.AddObserver("LeftButtonReleaseEvent", action[mode]["LeftButtonReleaseEvent"])
  113 +
  114 + def OnMouseClick(self, obj, evt_vtk):
  115 + self.mouse_pressed = 1
  116 +
  117 + def OnMouseRelease(self, obj, evt_vtk):
  118 + self.mouse_pressed = 0
  119 +
  120 + def OnBrushClick(self, obj, evt_vtk):
  121 + self.mouse_pressed = 1
  122 + coord = self.GetCoordinate()
  123 + print "Edit pixel region based on origin:", coord
  124 +
  125 + def OnBrushMove(self, obj, evt_vtk):
  126 + coord = self.GetCoordinate()
  127 + if self.mouse_pressed:
  128 + print "Edit pixel region based on origin:", coord
  129 +
  130 + def OnCrossMove(self, obj, evt_vtk):
  131 + coord = self.GetCoordinate()
  132 + # Update position in other slices
  133 + if self.mouse_pressed:
  134 + ps.Publisher().sendMessage('Update cursor position in slice', coord)
  135 + ps.Publisher().sendMessage(('Set scroll position', 'SAGITAL'), coord[0])
  136 + ps.Publisher().sendMessage(('Set scroll position', 'CORONAL'), coord[1])
  137 + ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'), coord[2])
  138 +
  139 + def GetCoordinate(self):
  140 +
  141 + # Find position
  142 + mouse_x, mouse_y = self.interactor.GetEventPosition()
  143 + self.pick.Pick(mouse_x, mouse_y, 0, self.ren)
  144 + x, y, z = self.pick.GetPickPosition()
  145 +
  146 + # First we fix the position origin, based on vtkActor bounds
  147 + bounds = self.actor.GetBounds()
  148 + bound_xi, bound_xf, bound_yi, bound_yf, bound_zi, bound_zf = bounds
  149 + x = float(x - bound_xi)
  150 + y = float(y - bound_yi)
  151 + z = float(z - bound_zi)
  152 +
  153 + # Then we fix the porpotion, based on vtkImageData spacing
  154 + spacing_x, spacing_y, spacing_z = self.imagedata.GetSpacing()
  155 + x = x/spacing_x
  156 + y = y/spacing_y
  157 + z = z/spacing_z
  158 +
  159 + # Based on the current orientation, we define 3D position
  160 + coordinates = {"SAGITAL": [self.slice_number, y, z],
  161 + "CORONAL": [x, self.slice_number, z],
  162 + "AXIAL": [x, y, self.slice_number]}
  163 + coord = [int(coord) for coord in coordinates[self.orientation]]
  164 +
  165 + # According to vtkImageData extent, we limit min and max value
  166 + # If this is not done, a VTK Error occurs when mouse is pressed outside
  167 + # vtkImageData extent
  168 + extent = self.imagedata.GetWholeExtent()
  169 + extent_min = extent[0], extent[2], extent[4]
  170 + extent_max = extent[1], extent[3], extent[5]
  171 + for index in xrange(3):
  172 + if coord[index] > extent_max[index]:
  173 + coord[index] = extent_max[index]
  174 + elif coord[index] < extent_min[index]:
  175 + coord[index] = extent_min[index]
  176 +
  177 + print "New coordinate: ", coord
  178 +
  179 + return coord
  180 +
75 def __bind_events(self): 181 def __bind_events(self):
76 ps.Publisher().subscribe(self.LoadImagedata, 'Load slice to viewer') 182 ps.Publisher().subscribe(self.LoadImagedata, 'Load slice to viewer')
77 ps.Publisher().subscribe(self.SetColour, 'Change mask colour') 183 ps.Publisher().subscribe(self.SetColour, 'Change mask colour')
78 ps.Publisher().subscribe(self.UpdateRender, 'Update slice viewer') 184 ps.Publisher().subscribe(self.UpdateRender, 'Update slice viewer')
79 - ps.Publisher().subscribe(self.SetScrollPosition, ('Set scroll position', 185 + ps.Publisher().subscribe(self.ChangeSliceNumber, ('Set scroll position',
80 self.orientation)) 186 self.orientation))
81 187
82 def __bind_events_wx(self): 188 def __bind_events_wx(self):
83 self.scroll.Bind(wx.EVT_SCROLL, self.OnScrollBar) 189 self.scroll.Bind(wx.EVT_SCROLL, self.OnScrollBar)
84 - #self.interactor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)  
85 190
86 def LoadImagedata(self, pubsub_evt): 191 def LoadImagedata(self, pubsub_evt):
87 imagedata = pubsub_evt.data 192 imagedata = pubsub_evt.data
88 self.SetInput(imagedata) 193 self.SetInput(imagedata)
89 194
90 def SetInput(self, imagedata): 195 def SetInput(self, imagedata):
  196 +
91 self.imagedata = imagedata 197 self.imagedata = imagedata
  198 +
92 ren = self.ren 199 ren = self.ren
93 interactor = self.interactor 200 interactor = self.interactor
94 201
@@ -101,77 +208,72 @@ class Viewer(wx.Panel): @@ -101,77 +208,72 @@ class Viewer(wx.Panel):
101 actor.SetInput(slice_.GetOutput()) 208 actor.SetInput(slice_.GetOutput())
102 self.actor = actor 209 self.actor = actor
103 210
  211 + colour = const.ORIENTATION_COLOUR[self.orientation]
  212 +
  213 + text_property = vtk.vtkTextProperty()
  214 + text_property.SetFontSize(16)
  215 + text_property.SetFontFamilyToArial()
  216 + text_property.BoldOn()
  217 + text_property.SetColor(colour)
  218 +
  219 + # Text related to slice number shown
  220 + text_mapper = vtk.vtkTextMapper()
  221 + text_mapper.SetInput("%d"%(self.slice_number))
  222 + text_mapper.GetTextProperty().ShallowCopy(text_property)
  223 + self.text_mapper = text_mapper
  224 +
  225 + text_actor = vtk.vtkActor2D()
  226 + text_actor.SetMapper(text_mapper)
  227 + text_actor.SetLayerNumber(1)
  228 + text_actor.GetPositionCoordinate().SetValue(self.GetSize()[0] - 80, 20)
  229 + text_actor.SetVisibility(1)
  230 +
104 ren.AddActor(actor) 231 ren.AddActor(actor)
  232 + ren.AddActor(text_actor)
105 self.__update_camera() 233 self.__update_camera()
106 234
107 max_slice_number = actor.GetSliceNumberMax() 235 max_slice_number = actor.GetSliceNumberMax()
108 self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, 236 self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
109 max_slice_number) 237 max_slice_number)
  238 + self.SetScrollPosition(0)
110 239
111 def SetOrientation(self, orientation): 240 def SetOrientation(self, orientation):
112 self.orientation = orientation 241 self.orientation = orientation
113 self.__update_camera() 242 self.__update_camera()
114 243
115 def __update_camera(self): 244 def __update_camera(self):
116 - cam = self.cam  
117 -  
118 orientation = self.orientation 245 orientation = self.orientation
119 246
120 - if orientation == "AXIAL":  
121 - cam.SetFocalPoint(0, 0, 0)  
122 - cam.SetPosition(0, 0, 1)  
123 - cam.ComputeViewPlaneNormal()  
124 - cam.SetViewUp(0, 1, 0)  
125 - elif orientation == "CORONAL":  
126 - cam.SetFocalPoint(0, 0, 0)  
127 - cam.SetPosition(0, -1, 0)  
128 - cam.ComputeViewPlaneNormal()  
129 - cam.SetViewUp(0, 0, 1)  
130 - elif orientation == "SAGITAL":  
131 - cam.SetFocalPoint(0, 0, 0)  
132 - cam.SetPosition(1, 0, 0)  
133 - cam.ComputeViewPlaneNormal()  
134 - cam.SetViewUp(0, 0, 1)  
135 - 247 + cam = self.cam
  248 + cam.SetFocalPoint(0, 0, 0)
  249 + cam.SetPosition(const.CAM_POSITION[self.orientation])
  250 + cam.SetViewUp(const.CAM_VIEW_UP[self.orientation])
  251 + cam.ComputeViewPlaneNormal()
136 cam.OrthogonalizeViewUp() 252 cam.OrthogonalizeViewUp()
  253 + cam.ParallelProjectionOn()
  254 +
137 self.__update_display_extent() 255 self.__update_display_extent()
138 - cam.ParallelProjectionOn() 256 +
139 self.ren.ResetCamera() 257 self.ren.ResetCamera()
140 self.ren.Render() 258 self.ren.Render()
141 259
142 def __update_display_extent(self): 260 def __update_display_extent(self):
143 - actor = self.actor  
144 - slice_number = self.slice_number  
145 - extent = self.imagedata.GetWholeExtent()  
146 - if self.orientation == "AXIAL":  
147 - xs = extent[1] - extent[0] + 1  
148 - ys = extent[3] - extent[2] + 1  
149 - actor.SetDisplayExtent(extent[0], extent[1],  
150 - extent[2], extent[3],  
151 - slice_number, slice_number)  
152 - elif self.orientation == "CORONAL":  
153 - xs = extent[1] - extent[0] + 1  
154 - ys = extent[5] - extent[4] + 1  
155 - actor.SetDisplayExtent(extent[0], extent[1],  
156 - slice_number,slice_number,  
157 - extent[4], extent[5])  
158 - elif self.orientation == "SAGITAL":  
159 - xs = extent[3] - extent[2] + 1  
160 - ys = extent[5] - extent[4] + 1  
161 - actor.SetDisplayExtent(slice_number, slice_number,  
162 - extent[2], extent[3],  
163 - extent[4], extent[5])  
164 261
  262 + pos = self.slice_number
  263 + e = self.imagedata.GetWholeExtent()
  264 +
  265 + new_extent = {"SAGITAL": (pos, pos, e[2], e[3], e[4], e[5]),
  266 + "CORONAL": (e[0], e[1], pos, pos, e[4], e[5]),
  267 + "AXIAL": (e[0], e[1], e[2], e[3], pos, pos)}
  268 +
  269 + self.actor.SetDisplayExtent(new_extent[self.orientation])
165 self.ren.ResetCameraClippingRange() 270 self.ren.ResetCameraClippingRange()
166 self.ren.Render() 271 self.ren.Render()
167 272
168 def UpdateRender(self, evt): 273 def UpdateRender(self, evt):
169 self.interactor.Render() 274 self.interactor.Render()
170 275
171 - def SetScrollPosition(self, pubsub_evt):  
172 - value = pubsub_evt.data  
173 - position = self.scroll.GetThumbPosition()  
174 - position += value 276 + def SetScrollPosition(self, position):
175 self.scroll.SetThumbPosition(position) 277 self.scroll.SetThumbPosition(position)
176 self.OnScrollBar() 278 self.OnScrollBar()
177 279
@@ -183,9 +285,16 @@ class Viewer(wx.Panel): @@ -183,9 +285,16 @@ class Viewer(wx.Panel):
183 evt.Skip() 285 evt.Skip()
184 286
185 def SetSliceNumber(self, index): 287 def SetSliceNumber(self, index):
  288 + self.text_mapper.SetInput(str(index))
186 self.slice_number = index 289 self.slice_number = index
187 self.__update_display_extent() 290 self.__update_display_extent()
188 291
  292 + def ChangeSliceNumber(self, pubsub_evt):
  293 + index = pubsub_evt.data
  294 + self.SetSliceNumber(index)
  295 + self.scroll.SetThumbPosition(index)
  296 + self.interactor.Render()
  297 +
189 def SetColour(self, pubsub_evt): 298 def SetColour(self, pubsub_evt):
190 colour_wx = pubsub_evt.data 299 colour_wx = pubsub_evt.data
191 colour_vtk = [colour/float(255) for colour in colour_wx] 300 colour_vtk = [colour/float(255) for colour in colour_wx]
invesalius/data/viewer_volume.py
@@ -61,6 +61,26 @@ class Viewer(wx.Panel): @@ -61,6 +61,26 @@ class Viewer(wx.Panel):
61 def __bind_events(self): 61 def __bind_events(self):
62 ps.Publisher().subscribe(self.LoadActor, 'Load surface actor into viewer') 62 ps.Publisher().subscribe(self.LoadActor, 'Load surface actor into viewer')
63 ps.Publisher().subscribe(self.UpdateRender, 'Render volume viewer') 63 ps.Publisher().subscribe(self.UpdateRender, 'Render volume viewer')
  64 + ps.Publisher().subscribe(self.ChangeBackgroundColour,
  65 + 'Change volume viewer background colour')
  66 + ps.Publisher().subscribe(self.ShowRaycastingVolume,
  67 + 'Show raycasting volume')
  68 + ps.Publisher().subscribe(self.HideRaycastingVolume,
  69 + 'Hide raycasting volume')
  70 +
  71 +
  72 + def ShowRaycastingVolume(self, pubsub_evt):
  73 + pass
  74 +
  75 + def HideRaycastingVolume(self, pubsub_evt):
  76 + pass
  77 +
  78 +
  79 +
  80 + def ChangeBackgroundColour(self, pubsub_evt):
  81 + colour = pubsub_evt.data
  82 + self.ren.SetBackground(colour)
  83 + self.UpdateRender()
64 84
65 def LoadActor(self, pubsub_evt): 85 def LoadActor(self, pubsub_evt):
66 actor = pubsub_evt.data 86 actor = pubsub_evt.data
@@ -76,7 +96,7 @@ class Viewer(wx.Panel): @@ -76,7 +96,7 @@ class Viewer(wx.Panel):
76 96
77 self.iren.Render() 97 self.iren.Render()
78 98
79 - def UpdateRender(self, evt_pubsub): 99 + def UpdateRender(self, evt_pubsub=None):
80 self.iren.Render() 100 self.iren.Render()
81 101
82 def CreatePlanes(self): 102 def CreatePlanes(self):
invesalius/gui/default_viewers.py
@@ -21,18 +21,6 @@ import wx.lib.agw.fourwaysplitter as fws @@ -21,18 +21,6 @@ import wx.lib.agw.fourwaysplitter as fws
21 import data.viewer_slice as slice_viewer 21 import data.viewer_slice as slice_viewer
22 import data.viewer_volume as volume_viewer 22 import data.viewer_volume as volume_viewer
23 23
24 -class SamplePane(wx.Panel):  
25 - """  
26 - Just a simple test window to put into the splitter.  
27 - """  
28 - def __init__(self, parent, colour, label):  
29 - wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN)  
30 - self.SetBackgroundColour(colour)  
31 - wx.StaticText(self, -1, label, (5,5))  
32 -  
33 - def SetOtherLabel(self, label):  
34 - wx.StaticText(self, -1, label, (5, 30))  
35 -  
36 24
37 class Panel(wx.Panel): 25 class Panel(wx.Panel):
38 def __init__(self, parent): 26 def __init__(self, parent):
@@ -89,7 +77,8 @@ class Panel(wx.Panel): @@ -89,7 +77,8 @@ class Panel(wx.Panel):
89 Name("Sagital Slice").Caption("Sagital slice"). 77 Name("Sagital Slice").Caption("Sagital slice").
90 MaximizeButton(True).CloseButton(False)) 78 MaximizeButton(True).CloseButton(False))
91 79
92 - self.aui_manager.AddPane(volume_viewer.Viewer(self), 80 + self.aui_manager.AddPane(VolumeViewerCover(self),
  81 + #self.aui_manager.AddPane(volume_viewer.Viewer(self)
93 wx.aui.AuiPaneInfo().Row(1).Name("Volume"). 82 wx.aui.AuiPaneInfo().Row(1).Name("Volume").
94 Bottom().Centre().Caption("Volume"). 83 Bottom().Centre().Caption("Volume").
95 MaximizeButton(True).CloseButton(False)) 84 MaximizeButton(True).CloseButton(False))
@@ -150,8 +139,8 @@ class Panel(wx.Panel): @@ -150,8 +139,8 @@ class Panel(wx.Panel):
150 Name("Sagittal Slice").Caption("Sagittal slice"). 139 Name("Sagittal Slice").Caption("Sagittal slice").
151 MaximizeButton(True).CloseButton(False)) 140 MaximizeButton(True).CloseButton(False))
152 141
153 - p4 = volume_viewer.Viewer(self)  
154 - aui_manager.AddPane(p4, 142 + #p4 = volume_viewer.Viewer(self)
  143 + aui_manager.AddPane(VolumeViewerCover,
155 wx.aui.AuiPaneInfo(). 144 wx.aui.AuiPaneInfo().
156 Name("Volume").Caption("Volume"). 145 Name("Volume").Caption("Volume").
157 MaximizeButton(True).CloseButton(False)) 146 MaximizeButton(True).CloseButton(False))
@@ -163,3 +152,50 @@ class Panel(wx.Panel): @@ -163,3 +152,50 @@ class Panel(wx.Panel):
163 152
164 153
165 aui_manager.Update() 154 aui_manager.Update()
  155 +
  156 +class VolumeViewerCover(wx.Panel):
  157 + def __init__(self, parent):
  158 + wx.Panel.__init__(self, parent)
  159 +
  160 + sizer = wx.BoxSizer(wx.HORIZONTAL)
  161 + sizer.Add(volume_viewer.Viewer(self), 1, wx.EXPAND|wx.GROW)
  162 + sizer.Add(VolumeToolPanel(self), 0, wx.EXPAND)
  163 + self.SetSizer(sizer)
  164 + sizer.Fit(self)
  165 +
  166 +#import wx.lib.platebtn as pbtn
  167 +import wx.lib.buttons as btn
  168 +import wx.lib.pubsub as ps
  169 +import wx.lib.colourselect as csel
  170 +
  171 +class VolumeToolPanel(wx.Panel):
  172 + def __init__(self, parent):
  173 + wx.Panel.__init__(self, parent, size = (8,100))
  174 +
  175 + BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", wx.BITMAP_TYPE_PNG)
  176 + BMP_RAYCASTING.SetWidth(22)
  177 + BMP_RAYCASTING.SetHeight(22)
  178 +
  179 + button_raycasting=btn.GenBitmapToggleButton(self, 1, BMP_RAYCASTING, size=(24,24))
  180 + button_raycasting.Bind(wx.EVT_BUTTON, self.OnToggleRaycasting)
  181 + self.button_raycasting = button_raycasting
  182 +
  183 + button_colour= csel.ColourSelect(self, 111,colour=(0,0,0),size=(24,24))
  184 + button_colour.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour)
  185 + self.button_colour = button_colour
  186 +
  187 + sizer = wx.BoxSizer(wx.VERTICAL)
  188 + sizer.Add(button_colour, 0, wx.ALL, 1)
  189 + sizer.Add(button_raycasting, 0, wx.ALL, 1)
  190 + self.SetSizer(sizer)
  191 + sizer.Fit(self)
  192 +
  193 + def OnSelectColour(self, evt):
  194 + colour = c = [i/255.0 for i in evt.GetValue()]
  195 + ps.Publisher().sendMessage('Change volume viewer background colour', colour)
  196 +
  197 + def OnToggleRaycasting(self, evt):
  198 + if self.button_raycasting.GetToggle():
  199 + ps.Publisher().sendMessage('Show raycasting volume')
  200 + else:
  201 + ps.Publisher().sendMessage('Hide raycasting volume')
invesalius/gui/frame.py
@@ -30,7 +30,8 @@ import default_viewers as viewers @@ -30,7 +30,8 @@ import default_viewers as viewers
30 class Frame(wx.Frame): 30 class Frame(wx.Frame):
31 def __init__(self, prnt): 31 def __init__(self, prnt):
32 wx.Frame.__init__(self, id=-1, name='', parent=prnt, 32 wx.Frame.__init__(self, id=-1, name='', parent=prnt,
33 - pos=wx.Point(0, 0), size=wx.Size(1024, 768), 33 + pos=wx.Point(0, 0),
  34 + size=wx.Size(1024, 768), #size = wx.DisplaySize(),
34 style=wx.DEFAULT_FRAME_STYLE, title='InVesalius 3.0') 35 style=wx.DEFAULT_FRAME_STYLE, title='InVesalius 3.0')
35 self.Center(wx.BOTH) 36 self.Center(wx.BOTH)
36 self.SetIcon(wx.Icon("../icons/invesalius.ico", wx.BITMAP_TYPE_ICO)) 37 self.SetIcon(wx.Icon("../icons/invesalius.ico", wx.BITMAP_TYPE_ICO))