Commit 66fa5cd60953006d0c96842289ec66d8044f07db
1 parent
c6e7c193
Exists in
master
and in
68 other branches
ADD: Inserted cross that follows left mouse clicks on slices 2D
Showing
6 changed files
with
287 additions
and
73 deletions
Show diff stats
invesalius/constants.py
| ... | ... | @@ -78,3 +78,10 @@ WINDOW_LEVEL = ({"Abdomen":(350,50), |
| 78 | 78 | "Vasculature - Hard":(240,80), |
| 79 | 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 | 28 | ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected') |
| 29 | 29 | ps.Publisher().subscribe(self.CreateSurfaceFromIndex, |
| 30 | 30 | 'Create surface from index') |
| 31 | + ps.Publisher().subscribe(self.UpdateCursorPosition, | |
| 32 | + 'Update cursor position in slice') | |
| 31 | 33 | |
| 32 | 34 | def CreateSurfaceFromIndex(self, pubsub_evt): |
| 33 | 35 | mask_index = pubsub_evt.data |
| ... | ... | @@ -116,7 +118,46 @@ class Slice(object): |
| 116 | 118 | blend_imagedata.SetInput(1, imagedata_mask) |
| 117 | 119 | blend_imagedata.SetBlendModeToNormal() |
| 118 | 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 | 162 | def __create_background(self, imagedata): |
| 122 | 163 | ... | ... |
invesalius/data/viewer_slice.py
| ... | ... | @@ -24,35 +24,49 @@ import wx |
| 24 | 24 | import wx.lib.pubsub as ps |
| 25 | 25 | |
| 26 | 26 | import data.slice_ as sl |
| 27 | - | |
| 27 | +import constants as const | |
| 28 | 28 | import project |
| 29 | 29 | |
| 30 | 30 | class Viewer(wx.Panel): |
| 31 | 31 | |
| 32 | 32 | def __init__(self, prnt, orientation='AXIAL'): |
| 33 | 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 | 38 | self.__init_gui() |
| 36 | - self.__config_interactor() | |
| 37 | 39 | |
| 38 | 40 | self.orientation = orientation |
| 39 | 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 | 52 | self.__bind_events() |
| 42 | 53 | self.__bind_events_wx() |
| 43 | 54 | |
| 44 | 55 | def __init_gui(self): |
| 56 | + | |
| 45 | 57 | interactor = wxVTKRenderWindowInteractor(self, -1, size=self.GetSize()) |
| 46 | 58 | |
| 47 | 59 | scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL) |
| 48 | 60 | self.scroll = scroll |
| 49 | 61 | |
| 50 | 62 | sizer = wx.BoxSizer(wx.HORIZONTAL) |
| 51 | - self.SetSizer(sizer) | |
| 52 | - | |
| 53 | - sizer.Add(scroll, 0, wx.EXPAND|wx.GROW) | |
| 54 | 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 | 71 | self.Layout() |
| 58 | 72 | self.Update() |
| ... | ... | @@ -61,7 +75,10 @@ class Viewer(wx.Panel): |
| 61 | 75 | self.interactor = interactor |
| 62 | 76 | |
| 63 | 77 | def __config_interactor(self): |
| 78 | + | |
| 64 | 79 | style = vtk.vtkInteractorStyleImage() |
| 80 | + self.style = style | |
| 81 | + | |
| 65 | 82 | ren = vtk.vtkRenderer() |
| 66 | 83 | |
| 67 | 84 | interactor = self.interactor |
| ... | ... | @@ -69,26 +86,116 @@ class Viewer(wx.Panel): |
| 69 | 86 | interactor.GetRenderWindow().AddRenderer(ren) |
| 70 | 87 | |
| 71 | 88 | self.cam = ren.GetActiveCamera() |
| 72 | - | |
| 73 | 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 | 181 | def __bind_events(self): |
| 76 | 182 | ps.Publisher().subscribe(self.LoadImagedata, 'Load slice to viewer') |
| 77 | 183 | ps.Publisher().subscribe(self.SetColour, 'Change mask colour') |
| 78 | 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 | 186 | self.orientation)) |
| 81 | 187 | |
| 82 | 188 | def __bind_events_wx(self): |
| 83 | 189 | self.scroll.Bind(wx.EVT_SCROLL, self.OnScrollBar) |
| 84 | - #self.interactor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) | |
| 85 | 190 | |
| 86 | 191 | def LoadImagedata(self, pubsub_evt): |
| 87 | 192 | imagedata = pubsub_evt.data |
| 88 | 193 | self.SetInput(imagedata) |
| 89 | 194 | |
| 90 | 195 | def SetInput(self, imagedata): |
| 196 | + | |
| 91 | 197 | self.imagedata = imagedata |
| 198 | + | |
| 92 | 199 | ren = self.ren |
| 93 | 200 | interactor = self.interactor |
| 94 | 201 | |
| ... | ... | @@ -101,77 +208,72 @@ class Viewer(wx.Panel): |
| 101 | 208 | actor.SetInput(slice_.GetOutput()) |
| 102 | 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 | 231 | ren.AddActor(actor) |
| 232 | + ren.AddActor(text_actor) | |
| 105 | 233 | self.__update_camera() |
| 106 | 234 | |
| 107 | 235 | max_slice_number = actor.GetSliceNumberMax() |
| 108 | 236 | self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, |
| 109 | 237 | max_slice_number) |
| 238 | + self.SetScrollPosition(0) | |
| 110 | 239 | |
| 111 | 240 | def SetOrientation(self, orientation): |
| 112 | 241 | self.orientation = orientation |
| 113 | 242 | self.__update_camera() |
| 114 | 243 | |
| 115 | 244 | def __update_camera(self): |
| 116 | - cam = self.cam | |
| 117 | - | |
| 118 | 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 | 252 | cam.OrthogonalizeViewUp() |
| 253 | + cam.ParallelProjectionOn() | |
| 254 | + | |
| 137 | 255 | self.__update_display_extent() |
| 138 | - cam.ParallelProjectionOn() | |
| 256 | + | |
| 139 | 257 | self.ren.ResetCamera() |
| 140 | 258 | self.ren.Render() |
| 141 | 259 | |
| 142 | 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 | 270 | self.ren.ResetCameraClippingRange() |
| 166 | 271 | self.ren.Render() |
| 167 | 272 | |
| 168 | 273 | def UpdateRender(self, evt): |
| 169 | 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 | 277 | self.scroll.SetThumbPosition(position) |
| 176 | 278 | self.OnScrollBar() |
| 177 | 279 | |
| ... | ... | @@ -183,9 +285,16 @@ class Viewer(wx.Panel): |
| 183 | 285 | evt.Skip() |
| 184 | 286 | |
| 185 | 287 | def SetSliceNumber(self, index): |
| 288 | + self.text_mapper.SetInput(str(index)) | |
| 186 | 289 | self.slice_number = index |
| 187 | 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 | 298 | def SetColour(self, pubsub_evt): |
| 190 | 299 | colour_wx = pubsub_evt.data |
| 191 | 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 | 61 | def __bind_events(self): |
| 62 | 62 | ps.Publisher().subscribe(self.LoadActor, 'Load surface actor into viewer') |
| 63 | 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 | 85 | def LoadActor(self, pubsub_evt): |
| 66 | 86 | actor = pubsub_evt.data |
| ... | ... | @@ -76,7 +96,7 @@ class Viewer(wx.Panel): |
| 76 | 96 | |
| 77 | 97 | self.iren.Render() |
| 78 | 98 | |
| 79 | - def UpdateRender(self, evt_pubsub): | |
| 99 | + def UpdateRender(self, evt_pubsub=None): | |
| 80 | 100 | self.iren.Render() |
| 81 | 101 | |
| 82 | 102 | def CreatePlanes(self): | ... | ... |
invesalius/gui/default_viewers.py
| ... | ... | @@ -21,18 +21,6 @@ import wx.lib.agw.fourwaysplitter as fws |
| 21 | 21 | import data.viewer_slice as slice_viewer |
| 22 | 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 | 25 | class Panel(wx.Panel): |
| 38 | 26 | def __init__(self, parent): |
| ... | ... | @@ -89,7 +77,8 @@ class Panel(wx.Panel): |
| 89 | 77 | Name("Sagital Slice").Caption("Sagital slice"). |
| 90 | 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 | 82 | wx.aui.AuiPaneInfo().Row(1).Name("Volume"). |
| 94 | 83 | Bottom().Centre().Caption("Volume"). |
| 95 | 84 | MaximizeButton(True).CloseButton(False)) |
| ... | ... | @@ -150,8 +139,8 @@ class Panel(wx.Panel): |
| 150 | 139 | Name("Sagittal Slice").Caption("Sagittal slice"). |
| 151 | 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 | 144 | wx.aui.AuiPaneInfo(). |
| 156 | 145 | Name("Volume").Caption("Volume"). |
| 157 | 146 | MaximizeButton(True).CloseButton(False)) |
| ... | ... | @@ -163,3 +152,50 @@ class Panel(wx.Panel): |
| 163 | 152 | |
| 164 | 153 | |
| 165 | 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 | 30 | class Frame(wx.Frame): |
| 31 | 31 | def __init__(self, prnt): |
| 32 | 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 | 35 | style=wx.DEFAULT_FRAME_STYLE, title='InVesalius 3.0') |
| 35 | 36 | self.Center(wx.BOTH) |
| 36 | 37 | self.SetIcon(wx.Icon("../icons/invesalius.ico", wx.BITMAP_TYPE_ICO)) | ... | ... |