From ce93f68d9e711956b1ff1ba555c866708ca8820e Mon Sep 17 00:00:00 2001 From: tatiana Date: Thu, 13 Aug 2009 19:32:50 +0000 Subject: [PATCH] ADD: GUI related to multiple raycasting projections --- invesalius/constants.py | 56 +++++++++++++++++++++++++++++++++++--------------------- invesalius/data/viewer_volume.py | 30 +++++++++++++++--------------- invesalius/data/volume.py | 9 +++------ invesalius/gui/default_viewers.py | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------ 4 files changed, 141 insertions(+), 114 deletions(-) diff --git a/invesalius/constants.py b/invesalius/constants.py index bbd1de5..4485cd0 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -1,4 +1,5 @@ import os.path +import wx from project import Project # Slice orientation @@ -27,27 +28,36 @@ SLICE_POSITION = {AXIAL:[AXIAL_SLICE_CAM_VIEW_UP, AXIAL_SLICE_CAM_POSITION], SAGITAL:[SAGITAL_SLICE_CAM_VIEW_UP, SAGITAL_SLICE_CAM_POSITION], CORONAL:[CORONAL_SLICE_CAM_VIEW_UP, CORONAL_SLICE_CAM_POSITION]} +# Volume view angle +VOL_FRONT = wx.NewId() +VOL_BACK = wx.NewId() +VOL_RIGHT = wx.NewId() +VOL_LEFT = wx.NewId() +VOL_TOP = wx.NewId() +VOL_BOTTOM = wx.NewId() +VOL_ISO = wx.NewId() + # Camera according to volume's orientation -AXIAL_VOLUME_CAM_VIEW_UP = {"FRONT":(0,0,1), "BACK":(0,0,1), "RIGHT":(0,0,1),\ - "LEFT":(0,0,1), "TOP":(0,1,0), "BOTTOM":(0,-1,0),\ - "ISOMETRIC":(0,0,1)} -AXIAL_VOLUME_CAM_POSITION = {"FRONT":(0,-1,0), "BACK":(0,1,0), "RIGHT":(-1,0,0),\ - "LEFT":(1,0,0), "TOP":(0,0,1), "BOTTOM":(0,0,-1),\ - "ISOMETRIC":(0.5,-1,0.5)} - -SAGITAL_VOLUME_CAM_VIEW_UP = {"FRONT":(0,-1,0), "BACK":(0,-1,0), "RIGHT":(0,-1,1),\ - "LEFT":(0,-1,1), "TOP":(1,-1,0), "BOTTOM":(-1,1,0),\ - "ISOMETRIC":(0,-1,0)} -SAGITAL_VOLUME_CAM_POSITION = {"FRONT":(-1,0,0), "BACK":(1,0,0), "RIGHT":(0,0,1),\ - "LEFT":(0,0,-1), "TOP":(0,-1,0), "BOTTOM":(0,1,0),\ - "ISOMETRIC":(-1,-0.5,-0.5)} - -CORONAL_VOLUME_CAM_VIEW_UP = {"FRONT":(0,-1,0), "BACK":(0,-1,0), "RIGHT":(0,-1,0),\ - "LEFT":(0,-1,0), "TOP":(0,1,0), "BOTTOM":(0,-1,0),\ - "ISOMETRIC":(0,-1,0)} -CORONAL_VOLUME_CAM_POSITION = {"FRONT":(0,0,-1), "BACK":(0,0,1), "RIGHT":(-1,0,0),\ - "LEFT":(1,0,0), "TOP":(0,-1,0), "BOTTOM":(0,1,0),\ - "ISOMETRIC":(0.5,-0.5,-1)} +AXIAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,0,1), VOL_BACK:(0,0,1), VOL_RIGHT:(0,0,1),\ + VOL_LEFT:(0,0,1), VOL_TOP:(0,1,0), VOL_BOTTOM:(0,-1,0),\ + VOL_ISO:(0,0,1)} +AXIAL_VOLUME_CAM_POSITION = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,1,0), VOL_RIGHT:(-1,0,0),\ + VOL_LEFT:(1,0,0), VOL_TOP:(0,0,1), VOL_BOTTOM:(0,0,-1),\ + VOL_ISO:(0.5,-1,0.5)} + +SAGITAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,-1,0), VOL_RIGHT:(0,-1,1),\ + VOL_LEFT:(0,-1,1), VOL_TOP:(1,-1,0), VOL_BOTTOM:(-1,1,0),\ + VOL_ISO:(0,-1,0)} +SAGITAL_VOLUME_CAM_POSITION = {VOL_FRONT:(-1,0,0), VOL_BACK:(1,0,0), VOL_RIGHT:(0,0,1),\ + VOL_LEFT:(0,0,-1), VOL_TOP:(0,-1,0), VOL_BOTTOM:(0,1,0),\ + VOL_ISO:(-1,-0.5,-0.5)} + +CORONAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,-1,0), VOL_RIGHT:(0,-1,0),\ + VOL_LEFT:(0,-1,0), VOL_TOP:(0,1,0), VOL_BOTTOM:(0,-1,0),\ + VOL_ISO:(0,-1,0)} +CORONAL_VOLUME_CAM_POSITION = {VOL_FRONT:(0,0,-1), VOL_BACK:(0,0,1), VOL_RIGHT:(-1,0,0),\ + VOL_LEFT:(1,0,0), VOL_TOP:(0,-1,0), VOL_BOTTOM:(0,1,0),\ + VOL_ISO:(0.5,-0.5,-1)} VOLUME_POSITION = {AXIAL: [AXIAL_VOLUME_CAM_VIEW_UP, AXIAL_VOLUME_CAM_POSITION], SAGITAL: [SAGITAL_VOLUME_CAM_VIEW_UP, SAGITAL_VOLUME_CAM_POSITION], @@ -137,4 +147,8 @@ REDUCE_IMAGEDATA_QUALITY = 1 # if 1, use vtkVolumeRaycastMapper, if 0, use vtkFixedPointVolumeRayCastMapper TYPE_RAYCASTING_MAPPER = 0 -RAYCASTING_PRESETS_DIRECTORY= os.path.join("..", "presets", "raycasting") +folder=RAYCASTING_PRESETS_DIRECTORY= os.path.join("..", "presets", "raycasting") + +RAYCASTING_TYPES = [filename.split(".")[0] for filename in + os.listdir(folder) if + os.path.isfile(os.path.join(folder,filename))] diff --git a/invesalius/data/viewer_volume.py b/invesalius/data/viewer_volume.py index eb83142..0c983f5 100755 --- a/invesalius/data/viewer_volume.py +++ b/invesalius/data/viewer_volume.py @@ -60,7 +60,7 @@ class Viewer(wx.Panel): self.__bind_events() self.__bind_events_wx() - self.first_reposition_actor = 0 + self.view_angle = None def __bind_events(self): ps.Publisher().subscribe(self.LoadActor, 'Load surface actor into viewer') @@ -69,8 +69,10 @@ class Viewer(wx.Panel): 'Change volume viewer background colour') ps.Publisher().subscribe(self.LoadVolume, 'Load volume into viewer') ps.Publisher().subscribe(self.AppendActor,'AppendActor') - ps.Publisher().subscribe(self.SetWidgetInteractor, 'Set Widget Interactor') - ps.Publisher().subscribe(self.RepositionActor, 'Reposition Actor') + ps.Publisher().subscribe(self.SetWidgetInteractor, + 'Set Widget Interactor') + ps.Publisher().subscribe(self.OnSetViewAngle, + 'Set volume view angle') def __bind_events_wx(self): @@ -90,9 +92,8 @@ class Viewer(wx.Panel): volume, colour = pubsub_evt.data self.light = self.ren.GetLights().GetNextItem() self.ren.AddVolume(volume) - if not (self.first_reposition_actor): - self.RepositionActor() - self.first_reposition_actor = 1 + if not (self.view_angle): + self.SetViewAngle(const.VOL_FRONT) else: ren.ResetCamera() ren.ResetCameraClippingRange() @@ -118,21 +119,20 @@ class Viewer(wx.Panel): self.iren.Render() - def RepositionActor(self, evt_pubsub=None): + def OnSetViewAngle(self, evt_pubsub): + view = evt_pubsub.data + self.SetViewAngle(view) + + def SetViewAngle(self, view): - if (evt_pubsub): - position = evt_pubsub.data - else: - position = "FRONT" - cam = self.ren.GetActiveCamera() cam.SetFocalPoint(0,0,0) proj = prj.Project() orig_orien = proj.original_orientation - xv,yv,zv = const.VOLUME_POSITION[orig_orien][0][position] - xp,yp,zp = const.VOLUME_POSITION[orig_orien][1][position] + xv,yv,zv = const.VOLUME_POSITION[orig_orien][0][view] + xp,yp,zp = const.VOLUME_POSITION[orig_orien][1][view] cam.SetViewUp(xv,yv,zv) cam.SetPosition(xp,yp,zp) @@ -179,4 +179,4 @@ class Viewer(wx.Panel): evt_pubsub.data.SetInteractor(self.iren._Iren) def AppendActor(self, evt_pubsub=None): - self.ren.AddActor(evt_pubsub.data) \ No newline at end of file + self.ren.AddActor(evt_pubsub.data) diff --git a/invesalius/data/volume.py b/invesalius/data/volume.py index 138ab30..f977063 100755 --- a/invesalius/data/volume.py +++ b/invesalius/data/volume.py @@ -64,9 +64,6 @@ SHADING = { } } -PRESETS = ["Airways", "Airways II", "Bone + Skin", "Bone + Skin II", "Dark Bone", -"Gold Bone", "Skin On Blue", "Skin On Blue II", "Soft + Skin", "Soft + Skin II", -"Soft + Skin III", "Yellow Bone"] class Volume(): @@ -101,9 +98,9 @@ class Volume(): if not label: label = "Skin On Blue" - path = os.path.join("..", "presets", "raycasting", - label+".plist") - label = plistlib.readPlist(path) + path = os.path.join("..", "presets", "raycasting", + label+".plist") + label = plistlib.readPlist(path) self.config = label #print path diff --git a/invesalius/gui/default_viewers.py b/invesalius/gui/default_viewers.py index 7e8294c..8ce761e 100755 --- a/invesalius/gui/default_viewers.py +++ b/invesalius/gui/default_viewers.py @@ -163,6 +163,32 @@ class Panel(wx.Panel): aui_manager.Update() + + + + + + +import wx.lib.platebtn as pbtn +import wx.lib.buttons as btn +import wx.lib.pubsub as ps +import wx.lib.colourselect as csel +import constants as const + +[BUTTON_RAYCASTING, BUTTON_VIEW] = [wx.NewId() for num in xrange(2)] + + +ID_TO_BMP = {const.VOL_FRONT: ["Front", "../icons/view_front.png"], + const.VOL_BACK: ["Back", "../icons/view_back.png"], + const.VOL_TOP: ["Top", "../icons/view_top.png"], + const.VOL_BOTTOM: ["Bottom", "../icons/view_bottom.png"], + const.VOL_RIGHT: ["Right", "../icons/view_right.png"], + const.VOL_LEFT: ["Left", "../icons/view_left.png"], + const.VOL_ISO:["Isometric","../icons/view_isometric.png"] + } + +ID_TO_NAME = {} + class VolumeViewerCover(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) @@ -173,100 +199,90 @@ class VolumeViewerCover(wx.Panel): self.SetSizer(sizer) sizer.Fit(self) -import wx.lib.platebtn as pbtn -import wx.lib.buttons as btn -import wx.lib.pubsub as ps -import wx.lib.colourselect as csel - class VolumeToolPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, size = (8,100)) - BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", wx.BITMAP_TYPE_PNG) - BMP_RAYCASTING.SetWidth(22) - BMP_RAYCASTING.SetHeight(22) + # VOLUME RAYCASTING BUTTON + BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", + wx.BITMAP_TYPE_PNG) - FRONT_BMP = wx.Bitmap("../icons/view_front.png", wx.BITMAP_TYPE_PNG) - - button_raycasting=btn.GenBitmapToggleButton(self, 1, BMP_RAYCASTING, size=(24,24)) - button_raycasting.Bind(wx.EVT_BUTTON, self.OnToggleRaycasting) + menu = wx.Menu() + for name in const.RAYCASTING_TYPES: + id = wx.NewId() + item = wx.MenuItem(menu, id, name) + menu.AppendItem(item) + ID_TO_NAME[id] = name + self.menu_raycasting = menu + menu.Bind(wx.EVT_MENU, self.OnMenuRaycasting) + + #button_raycasting=btn.GenBitmapToggleButton(self, 1, BMP_RAYCASTING, size=(24,24)) + self.button_raycasting_toggle = 0 + button_raycasting = pbtn.PlateButton(self, BUTTON_RAYCASTING,"", + BMP_RAYCASTING, style=pbtn.PB_STYLE_SQUARE, + size=(24,24)) + self.Bind(wx.EVT_BUTTON, self.OnToggleRaycasting) + button_raycasting.SetMenu(menu) + self.button_raycasting = button_raycasting + # VOLUME VIEW ANGLE BUTTON menu = wx.Menu() - - item = wx.MenuItem(menu, 0, "Front") - item.SetBitmap(FRONT_BMP) - - BACK_BMP = wx.Bitmap("../icons/view_back.png", wx.BITMAP_TYPE_PNG) - item2 = wx.MenuItem(menu, 1, "Back") - item2.SetBitmap(BACK_BMP) - - TOP_BMP = wx.Bitmap("../icons/view_top.png", wx.BITMAP_TYPE_PNG) - item3 = wx.MenuItem(menu, 2, "Top") - item3.SetBitmap(TOP_BMP) - - BOTTOM_BMP = wx.Bitmap("../icons/view_bottom.png", wx.BITMAP_TYPE_PNG) - item4 = wx.MenuItem(menu, 3, "Bottom") - item4.SetBitmap(BOTTOM_BMP) - - RIGHT_BMP = wx.Bitmap("../icons/view_right.png", wx.BITMAP_TYPE_PNG) - item5 = wx.MenuItem(menu, 4, "Right") - item5.SetBitmap(RIGHT_BMP) - - LEFT_BMP = wx.Bitmap("../icons/view_left.png", wx.BITMAP_TYPE_PNG) - item6 = wx.MenuItem(menu, 5, "Left") - item6.SetBitmap(LEFT_BMP) - - ISOMETRIC_BMP = wx.Bitmap("../icons/view_isometric.png", wx.BITMAP_TYPE_PNG) - item7 = wx.MenuItem(menu, 6, "Isometric") - item7.SetBitmap(ISOMETRIC_BMP) - - self.Bind(wx.EVT_MENU, self.OnMenu) - - menu.AppendItem(item) - menu.AppendItem(item2) - menu.AppendItem(item3) - menu.AppendItem(item4) - menu.AppendItem(item5) - menu.AppendItem(item6) - menu.AppendItem(item7) - self.menu = menu - - button_position = pbtn.PlateButton(self, wx.ID_ANY,"", FRONT_BMP, - style=pbtn.PB_STYLE_SQUARE, size=(24,24)) - - button_position.SetMenu(menu) - self.button_position = button_position - - button_colour= csel.ColourSelect(self, 111,colour=(0,0,0),size=(24,24)) + for id in ID_TO_BMP: + bmp = wx.Bitmap(ID_TO_BMP[id][1], wx.BITMAP_TYPE_PNG) + item = wx.MenuItem(menu, id, ID_TO_BMP[id][0]) + item.SetBitmap(bmp) + menu.AppendItem(item) + menu.Bind(wx.EVT_MENU, self.OnMenuView) + self.menu_view = menu + + BMP_FRONT = wx.Bitmap(ID_TO_BMP[const.VOL_FRONT][1], + wx.BITMAP_TYPE_PNG) + button_view = pbtn.PlateButton(self, BUTTON_VIEW, "", + BMP_FRONT, size=(24,24), + style=pbtn.PB_STYLE_SQUARE) + button_view.SetMenu(menu) + self.button_view = button_view + + # VOLUME COLOUR BUTTOM + button_colour= csel.ColourSelect(self, 111,colour=(0,0,0), + size=(24,24)) button_colour.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) self.button_colour = button_colour + # SIZER TO ORGANIZE ALL sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(button_colour, 0, wx.ALL, 1) sizer.Add(button_raycasting, 0, wx.ALL, 1) - sizer.Add(button_position, 0, wx.ALL, 1) + sizer.Add(button_view, 0, wx.ALL, 1) self.SetSizer(sizer) sizer.Fit(self) - self.orientations = {0:("FRONT", FRONT_BMP), 1:("BACK", BACK_BMP),\ - 2:("TOP",TOP_BMP), 3:("BOTTOM",BOTTOM_BMP),\ - 4:("RIGHT",RIGHT_BMP), 5:("LEFT", LEFT_BMP),\ - 6:("ISOMETRIC",ISOMETRIC_BMP)} - - def OnMenu(self, evt): + def OnMenuRaycasting(self, evt): + """Events from button menus.""" + ps.Publisher().sendMessage('Set raycasting preset', + ID_TO_NAME[evt.GetId()]) + ps.Publisher().sendMessage('Render volume viewer') - self.button_position.SetBitmapSelected(self.orientations[evt.GetId()][1]) - ps.Publisher().sendMessage('Reposition Actor',\ - self.orientations[evt.GetId()][0]) + def OnMenuView(self, evt): + """Events from button menus.""" + self.button_view.SetBitmapSelected(ID_TO_BMP[evt.GetId()][1]) + ps.Publisher().sendMessage('Set volume view angle', + ID_TO_BMP[evt.GetId()][0]) def OnSelectColour(self, evt): colour = c = [i/255.0 for i in evt.GetValue()] ps.Publisher().sendMessage('Change volume viewer background colour', colour) def OnToggleRaycasting(self, evt): - if self.button_raycasting.GetToggle(): - #ps.Publisher().sendMessage('Create volume raycasting') - ps.Publisher().sendMessage('Show raycasting volume') - else: + print "oi" + if self.button_raycasting_toggle: ps.Publisher().sendMessage('Hide raycasting volume') + self.button_raycasting.SetBackgroundColour(self.GetParent().GetBackgroundColour()) + #self.button_raycasting.SetBitmapSelected(ID_TO_BMP2[0]) + self.button_raycasting_toggle = 0 + else: + ps.Publisher().sendMessage('Show raycasting volume') + self.button_raycasting_toggle = 1 + #self.button_raycasting.SetBitmapSelected(ID_TO_BMP2[1]) + self.button_raycasting.SetBackgroundColour((255,255,255)) -- libgit2 0.21.2