Commit ce93f68d9e711956b1ff1ba555c866708ca8820e
1 parent
8fa40bf2
Exists in
master
and in
68 other branches
ADD: GUI related to multiple raycasting projections
Showing
4 changed files
with
141 additions
and
114 deletions
Show diff stats
invesalius/constants.py
1 | 1 | import os.path |
2 | +import wx | |
2 | 3 | from project import Project |
3 | 4 | |
4 | 5 | # Slice orientation |
... | ... | @@ -27,27 +28,36 @@ SLICE_POSITION = {AXIAL:[AXIAL_SLICE_CAM_VIEW_UP, AXIAL_SLICE_CAM_POSITION], |
27 | 28 | SAGITAL:[SAGITAL_SLICE_CAM_VIEW_UP, SAGITAL_SLICE_CAM_POSITION], |
28 | 29 | CORONAL:[CORONAL_SLICE_CAM_VIEW_UP, CORONAL_SLICE_CAM_POSITION]} |
29 | 30 | |
31 | +# Volume view angle | |
32 | +VOL_FRONT = wx.NewId() | |
33 | +VOL_BACK = wx.NewId() | |
34 | +VOL_RIGHT = wx.NewId() | |
35 | +VOL_LEFT = wx.NewId() | |
36 | +VOL_TOP = wx.NewId() | |
37 | +VOL_BOTTOM = wx.NewId() | |
38 | +VOL_ISO = wx.NewId() | |
39 | + | |
30 | 40 | # Camera according to volume's orientation |
31 | -AXIAL_VOLUME_CAM_VIEW_UP = {"FRONT":(0,0,1), "BACK":(0,0,1), "RIGHT":(0,0,1),\ | |
32 | - "LEFT":(0,0,1), "TOP":(0,1,0), "BOTTOM":(0,-1,0),\ | |
33 | - "ISOMETRIC":(0,0,1)} | |
34 | -AXIAL_VOLUME_CAM_POSITION = {"FRONT":(0,-1,0), "BACK":(0,1,0), "RIGHT":(-1,0,0),\ | |
35 | - "LEFT":(1,0,0), "TOP":(0,0,1), "BOTTOM":(0,0,-1),\ | |
36 | - "ISOMETRIC":(0.5,-1,0.5)} | |
37 | - | |
38 | -SAGITAL_VOLUME_CAM_VIEW_UP = {"FRONT":(0,-1,0), "BACK":(0,-1,0), "RIGHT":(0,-1,1),\ | |
39 | - "LEFT":(0,-1,1), "TOP":(1,-1,0), "BOTTOM":(-1,1,0),\ | |
40 | - "ISOMETRIC":(0,-1,0)} | |
41 | -SAGITAL_VOLUME_CAM_POSITION = {"FRONT":(-1,0,0), "BACK":(1,0,0), "RIGHT":(0,0,1),\ | |
42 | - "LEFT":(0,0,-1), "TOP":(0,-1,0), "BOTTOM":(0,1,0),\ | |
43 | - "ISOMETRIC":(-1,-0.5,-0.5)} | |
44 | - | |
45 | -CORONAL_VOLUME_CAM_VIEW_UP = {"FRONT":(0,-1,0), "BACK":(0,-1,0), "RIGHT":(0,-1,0),\ | |
46 | - "LEFT":(0,-1,0), "TOP":(0,1,0), "BOTTOM":(0,-1,0),\ | |
47 | - "ISOMETRIC":(0,-1,0)} | |
48 | -CORONAL_VOLUME_CAM_POSITION = {"FRONT":(0,0,-1), "BACK":(0,0,1), "RIGHT":(-1,0,0),\ | |
49 | - "LEFT":(1,0,0), "TOP":(0,-1,0), "BOTTOM":(0,1,0),\ | |
50 | - "ISOMETRIC":(0.5,-0.5,-1)} | |
41 | +AXIAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,0,1), VOL_BACK:(0,0,1), VOL_RIGHT:(0,0,1),\ | |
42 | + VOL_LEFT:(0,0,1), VOL_TOP:(0,1,0), VOL_BOTTOM:(0,-1,0),\ | |
43 | + VOL_ISO:(0,0,1)} | |
44 | +AXIAL_VOLUME_CAM_POSITION = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,1,0), VOL_RIGHT:(-1,0,0),\ | |
45 | + VOL_LEFT:(1,0,0), VOL_TOP:(0,0,1), VOL_BOTTOM:(0,0,-1),\ | |
46 | + VOL_ISO:(0.5,-1,0.5)} | |
47 | + | |
48 | +SAGITAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,-1,0), VOL_RIGHT:(0,-1,1),\ | |
49 | + VOL_LEFT:(0,-1,1), VOL_TOP:(1,-1,0), VOL_BOTTOM:(-1,1,0),\ | |
50 | + VOL_ISO:(0,-1,0)} | |
51 | +SAGITAL_VOLUME_CAM_POSITION = {VOL_FRONT:(-1,0,0), VOL_BACK:(1,0,0), VOL_RIGHT:(0,0,1),\ | |
52 | + VOL_LEFT:(0,0,-1), VOL_TOP:(0,-1,0), VOL_BOTTOM:(0,1,0),\ | |
53 | + VOL_ISO:(-1,-0.5,-0.5)} | |
54 | + | |
55 | +CORONAL_VOLUME_CAM_VIEW_UP = {VOL_FRONT:(0,-1,0), VOL_BACK:(0,-1,0), VOL_RIGHT:(0,-1,0),\ | |
56 | + VOL_LEFT:(0,-1,0), VOL_TOP:(0,1,0), VOL_BOTTOM:(0,-1,0),\ | |
57 | + VOL_ISO:(0,-1,0)} | |
58 | +CORONAL_VOLUME_CAM_POSITION = {VOL_FRONT:(0,0,-1), VOL_BACK:(0,0,1), VOL_RIGHT:(-1,0,0),\ | |
59 | + VOL_LEFT:(1,0,0), VOL_TOP:(0,-1,0), VOL_BOTTOM:(0,1,0),\ | |
60 | + VOL_ISO:(0.5,-0.5,-1)} | |
51 | 61 | |
52 | 62 | VOLUME_POSITION = {AXIAL: [AXIAL_VOLUME_CAM_VIEW_UP, AXIAL_VOLUME_CAM_POSITION], |
53 | 63 | SAGITAL: [SAGITAL_VOLUME_CAM_VIEW_UP, SAGITAL_VOLUME_CAM_POSITION], |
... | ... | @@ -137,4 +147,8 @@ REDUCE_IMAGEDATA_QUALITY = 1 |
137 | 147 | # if 1, use vtkVolumeRaycastMapper, if 0, use vtkFixedPointVolumeRayCastMapper |
138 | 148 | TYPE_RAYCASTING_MAPPER = 0 |
139 | 149 | |
140 | -RAYCASTING_PRESETS_DIRECTORY= os.path.join("..", "presets", "raycasting") | |
150 | +folder=RAYCASTING_PRESETS_DIRECTORY= os.path.join("..", "presets", "raycasting") | |
151 | + | |
152 | +RAYCASTING_TYPES = [filename.split(".")[0] for filename in | |
153 | + os.listdir(folder) if | |
154 | + os.path.isfile(os.path.join(folder,filename))] | ... | ... |
invesalius/data/viewer_volume.py
... | ... | @@ -60,7 +60,7 @@ class Viewer(wx.Panel): |
60 | 60 | self.__bind_events() |
61 | 61 | self.__bind_events_wx() |
62 | 62 | |
63 | - self.first_reposition_actor = 0 | |
63 | + self.view_angle = None | |
64 | 64 | |
65 | 65 | def __bind_events(self): |
66 | 66 | ps.Publisher().subscribe(self.LoadActor, 'Load surface actor into viewer') |
... | ... | @@ -69,8 +69,10 @@ class Viewer(wx.Panel): |
69 | 69 | 'Change volume viewer background colour') |
70 | 70 | ps.Publisher().subscribe(self.LoadVolume, 'Load volume into viewer') |
71 | 71 | ps.Publisher().subscribe(self.AppendActor,'AppendActor') |
72 | - ps.Publisher().subscribe(self.SetWidgetInteractor, 'Set Widget Interactor') | |
73 | - ps.Publisher().subscribe(self.RepositionActor, 'Reposition Actor') | |
72 | + ps.Publisher().subscribe(self.SetWidgetInteractor, | |
73 | + 'Set Widget Interactor') | |
74 | + ps.Publisher().subscribe(self.OnSetViewAngle, | |
75 | + 'Set volume view angle') | |
74 | 76 | |
75 | 77 | |
76 | 78 | def __bind_events_wx(self): |
... | ... | @@ -90,9 +92,8 @@ class Viewer(wx.Panel): |
90 | 92 | volume, colour = pubsub_evt.data |
91 | 93 | self.light = self.ren.GetLights().GetNextItem() |
92 | 94 | self.ren.AddVolume(volume) |
93 | - if not (self.first_reposition_actor): | |
94 | - self.RepositionActor() | |
95 | - self.first_reposition_actor = 1 | |
95 | + if not (self.view_angle): | |
96 | + self.SetViewAngle(const.VOL_FRONT) | |
96 | 97 | else: |
97 | 98 | ren.ResetCamera() |
98 | 99 | ren.ResetCameraClippingRange() |
... | ... | @@ -118,21 +119,20 @@ class Viewer(wx.Panel): |
118 | 119 | |
119 | 120 | self.iren.Render() |
120 | 121 | |
121 | - def RepositionActor(self, evt_pubsub=None): | |
122 | + def OnSetViewAngle(self, evt_pubsub): | |
123 | + view = evt_pubsub.data | |
124 | + self.SetViewAngle(view) | |
125 | + | |
126 | + def SetViewAngle(self, view): | |
122 | 127 | |
123 | - if (evt_pubsub): | |
124 | - position = evt_pubsub.data | |
125 | - else: | |
126 | - position = "FRONT" | |
127 | - | |
128 | 128 | cam = self.ren.GetActiveCamera() |
129 | 129 | cam.SetFocalPoint(0,0,0) |
130 | 130 | |
131 | 131 | proj = prj.Project() |
132 | 132 | orig_orien = proj.original_orientation |
133 | 133 | |
134 | - xv,yv,zv = const.VOLUME_POSITION[orig_orien][0][position] | |
135 | - xp,yp,zp = const.VOLUME_POSITION[orig_orien][1][position] | |
134 | + xv,yv,zv = const.VOLUME_POSITION[orig_orien][0][view] | |
135 | + xp,yp,zp = const.VOLUME_POSITION[orig_orien][1][view] | |
136 | 136 | |
137 | 137 | cam.SetViewUp(xv,yv,zv) |
138 | 138 | cam.SetPosition(xp,yp,zp) |
... | ... | @@ -179,4 +179,4 @@ class Viewer(wx.Panel): |
179 | 179 | evt_pubsub.data.SetInteractor(self.iren._Iren) |
180 | 180 | |
181 | 181 | def AppendActor(self, evt_pubsub=None): |
182 | - self.ren.AddActor(evt_pubsub.data) | |
183 | 182 | \ No newline at end of file |
183 | + self.ren.AddActor(evt_pubsub.data) | ... | ... |
invesalius/data/volume.py
... | ... | @@ -64,9 +64,6 @@ SHADING = { |
64 | 64 | } |
65 | 65 | } |
66 | 66 | |
67 | -PRESETS = ["Airways", "Airways II", "Bone + Skin", "Bone + Skin II", "Dark Bone", | |
68 | -"Gold Bone", "Skin On Blue", "Skin On Blue II", "Soft + Skin", "Soft + Skin II", | |
69 | -"Soft + Skin III", "Yellow Bone"] | |
70 | 67 | |
71 | 68 | class Volume(): |
72 | 69 | |
... | ... | @@ -101,9 +98,9 @@ class Volume(): |
101 | 98 | if not label: |
102 | 99 | label = "Skin On Blue" |
103 | 100 | |
104 | - path = os.path.join("..", "presets", "raycasting", | |
105 | - label+".plist") | |
106 | - label = plistlib.readPlist(path) | |
101 | + path = os.path.join("..", "presets", "raycasting", | |
102 | + label+".plist") | |
103 | + label = plistlib.readPlist(path) | |
107 | 104 | self.config = label |
108 | 105 | #print path |
109 | 106 | ... | ... |
invesalius/gui/default_viewers.py
... | ... | @@ -163,6 +163,32 @@ class Panel(wx.Panel): |
163 | 163 | |
164 | 164 | aui_manager.Update() |
165 | 165 | |
166 | + | |
167 | + | |
168 | + | |
169 | + | |
170 | + | |
171 | + | |
172 | +import wx.lib.platebtn as pbtn | |
173 | +import wx.lib.buttons as btn | |
174 | +import wx.lib.pubsub as ps | |
175 | +import wx.lib.colourselect as csel | |
176 | +import constants as const | |
177 | + | |
178 | +[BUTTON_RAYCASTING, BUTTON_VIEW] = [wx.NewId() for num in xrange(2)] | |
179 | + | |
180 | + | |
181 | +ID_TO_BMP = {const.VOL_FRONT: ["Front", "../icons/view_front.png"], | |
182 | + const.VOL_BACK: ["Back", "../icons/view_back.png"], | |
183 | + const.VOL_TOP: ["Top", "../icons/view_top.png"], | |
184 | + const.VOL_BOTTOM: ["Bottom", "../icons/view_bottom.png"], | |
185 | + const.VOL_RIGHT: ["Right", "../icons/view_right.png"], | |
186 | + const.VOL_LEFT: ["Left", "../icons/view_left.png"], | |
187 | + const.VOL_ISO:["Isometric","../icons/view_isometric.png"] | |
188 | + } | |
189 | + | |
190 | +ID_TO_NAME = {} | |
191 | + | |
166 | 192 | class VolumeViewerCover(wx.Panel): |
167 | 193 | def __init__(self, parent): |
168 | 194 | wx.Panel.__init__(self, parent) |
... | ... | @@ -173,100 +199,90 @@ class VolumeViewerCover(wx.Panel): |
173 | 199 | self.SetSizer(sizer) |
174 | 200 | sizer.Fit(self) |
175 | 201 | |
176 | -import wx.lib.platebtn as pbtn | |
177 | -import wx.lib.buttons as btn | |
178 | -import wx.lib.pubsub as ps | |
179 | -import wx.lib.colourselect as csel | |
180 | - | |
181 | 202 | class VolumeToolPanel(wx.Panel): |
182 | 203 | def __init__(self, parent): |
183 | 204 | wx.Panel.__init__(self, parent, size = (8,100)) |
184 | 205 | |
185 | - BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", wx.BITMAP_TYPE_PNG) | |
186 | - BMP_RAYCASTING.SetWidth(22) | |
187 | - BMP_RAYCASTING.SetHeight(22) | |
206 | + # VOLUME RAYCASTING BUTTON | |
207 | + BMP_RAYCASTING = wx.Bitmap("../icons/volume_raycasting.png", | |
208 | + wx.BITMAP_TYPE_PNG) | |
188 | 209 | |
189 | - FRONT_BMP = wx.Bitmap("../icons/view_front.png", wx.BITMAP_TYPE_PNG) | |
190 | - | |
191 | - button_raycasting=btn.GenBitmapToggleButton(self, 1, BMP_RAYCASTING, size=(24,24)) | |
192 | - button_raycasting.Bind(wx.EVT_BUTTON, self.OnToggleRaycasting) | |
210 | + menu = wx.Menu() | |
211 | + for name in const.RAYCASTING_TYPES: | |
212 | + id = wx.NewId() | |
213 | + item = wx.MenuItem(menu, id, name) | |
214 | + menu.AppendItem(item) | |
215 | + ID_TO_NAME[id] = name | |
216 | + self.menu_raycasting = menu | |
217 | + menu.Bind(wx.EVT_MENU, self.OnMenuRaycasting) | |
218 | + | |
219 | + #button_raycasting=btn.GenBitmapToggleButton(self, 1, BMP_RAYCASTING, size=(24,24)) | |
220 | + self.button_raycasting_toggle = 0 | |
221 | + button_raycasting = pbtn.PlateButton(self, BUTTON_RAYCASTING,"", | |
222 | + BMP_RAYCASTING, style=pbtn.PB_STYLE_SQUARE, | |
223 | + size=(24,24)) | |
224 | + self.Bind(wx.EVT_BUTTON, self.OnToggleRaycasting) | |
225 | + button_raycasting.SetMenu(menu) | |
226 | + | |
193 | 227 | self.button_raycasting = button_raycasting |
194 | 228 | |
229 | + # VOLUME VIEW ANGLE BUTTON | |
195 | 230 | menu = wx.Menu() |
196 | - | |
197 | - item = wx.MenuItem(menu, 0, "Front") | |
198 | - item.SetBitmap(FRONT_BMP) | |
199 | - | |
200 | - BACK_BMP = wx.Bitmap("../icons/view_back.png", wx.BITMAP_TYPE_PNG) | |
201 | - item2 = wx.MenuItem(menu, 1, "Back") | |
202 | - item2.SetBitmap(BACK_BMP) | |
203 | - | |
204 | - TOP_BMP = wx.Bitmap("../icons/view_top.png", wx.BITMAP_TYPE_PNG) | |
205 | - item3 = wx.MenuItem(menu, 2, "Top") | |
206 | - item3.SetBitmap(TOP_BMP) | |
207 | - | |
208 | - BOTTOM_BMP = wx.Bitmap("../icons/view_bottom.png", wx.BITMAP_TYPE_PNG) | |
209 | - item4 = wx.MenuItem(menu, 3, "Bottom") | |
210 | - item4.SetBitmap(BOTTOM_BMP) | |
211 | - | |
212 | - RIGHT_BMP = wx.Bitmap("../icons/view_right.png", wx.BITMAP_TYPE_PNG) | |
213 | - item5 = wx.MenuItem(menu, 4, "Right") | |
214 | - item5.SetBitmap(RIGHT_BMP) | |
215 | - | |
216 | - LEFT_BMP = wx.Bitmap("../icons/view_left.png", wx.BITMAP_TYPE_PNG) | |
217 | - item6 = wx.MenuItem(menu, 5, "Left") | |
218 | - item6.SetBitmap(LEFT_BMP) | |
219 | - | |
220 | - ISOMETRIC_BMP = wx.Bitmap("../icons/view_isometric.png", wx.BITMAP_TYPE_PNG) | |
221 | - item7 = wx.MenuItem(menu, 6, "Isometric") | |
222 | - item7.SetBitmap(ISOMETRIC_BMP) | |
223 | - | |
224 | - self.Bind(wx.EVT_MENU, self.OnMenu) | |
225 | - | |
226 | - menu.AppendItem(item) | |
227 | - menu.AppendItem(item2) | |
228 | - menu.AppendItem(item3) | |
229 | - menu.AppendItem(item4) | |
230 | - menu.AppendItem(item5) | |
231 | - menu.AppendItem(item6) | |
232 | - menu.AppendItem(item7) | |
233 | - self.menu = menu | |
234 | - | |
235 | - button_position = pbtn.PlateButton(self, wx.ID_ANY,"", FRONT_BMP, | |
236 | - style=pbtn.PB_STYLE_SQUARE, size=(24,24)) | |
237 | - | |
238 | - button_position.SetMenu(menu) | |
239 | - self.button_position = button_position | |
240 | - | |
241 | - button_colour= csel.ColourSelect(self, 111,colour=(0,0,0),size=(24,24)) | |
231 | + for id in ID_TO_BMP: | |
232 | + bmp = wx.Bitmap(ID_TO_BMP[id][1], wx.BITMAP_TYPE_PNG) | |
233 | + item = wx.MenuItem(menu, id, ID_TO_BMP[id][0]) | |
234 | + item.SetBitmap(bmp) | |
235 | + menu.AppendItem(item) | |
236 | + menu.Bind(wx.EVT_MENU, self.OnMenuView) | |
237 | + self.menu_view = menu | |
238 | + | |
239 | + BMP_FRONT = wx.Bitmap(ID_TO_BMP[const.VOL_FRONT][1], | |
240 | + wx.BITMAP_TYPE_PNG) | |
241 | + button_view = pbtn.PlateButton(self, BUTTON_VIEW, "", | |
242 | + BMP_FRONT, size=(24,24), | |
243 | + style=pbtn.PB_STYLE_SQUARE) | |
244 | + button_view.SetMenu(menu) | |
245 | + self.button_view = button_view | |
246 | + | |
247 | + # VOLUME COLOUR BUTTOM | |
248 | + button_colour= csel.ColourSelect(self, 111,colour=(0,0,0), | |
249 | + size=(24,24)) | |
242 | 250 | button_colour.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) |
243 | 251 | self.button_colour = button_colour |
244 | 252 | |
253 | + # SIZER TO ORGANIZE ALL | |
245 | 254 | sizer = wx.BoxSizer(wx.VERTICAL) |
246 | 255 | sizer.Add(button_colour, 0, wx.ALL, 1) |
247 | 256 | sizer.Add(button_raycasting, 0, wx.ALL, 1) |
248 | - sizer.Add(button_position, 0, wx.ALL, 1) | |
257 | + sizer.Add(button_view, 0, wx.ALL, 1) | |
249 | 258 | self.SetSizer(sizer) |
250 | 259 | sizer.Fit(self) |
251 | 260 | |
252 | - self.orientations = {0:("FRONT", FRONT_BMP), 1:("BACK", BACK_BMP),\ | |
253 | - 2:("TOP",TOP_BMP), 3:("BOTTOM",BOTTOM_BMP),\ | |
254 | - 4:("RIGHT",RIGHT_BMP), 5:("LEFT", LEFT_BMP),\ | |
255 | - 6:("ISOMETRIC",ISOMETRIC_BMP)} | |
256 | - | |
257 | - def OnMenu(self, evt): | |
261 | + def OnMenuRaycasting(self, evt): | |
262 | + """Events from button menus.""" | |
263 | + ps.Publisher().sendMessage('Set raycasting preset', | |
264 | + ID_TO_NAME[evt.GetId()]) | |
265 | + ps.Publisher().sendMessage('Render volume viewer') | |
258 | 266 | |
259 | - self.button_position.SetBitmapSelected(self.orientations[evt.GetId()][1]) | |
260 | - ps.Publisher().sendMessage('Reposition Actor',\ | |
261 | - self.orientations[evt.GetId()][0]) | |
267 | + def OnMenuView(self, evt): | |
268 | + """Events from button menus.""" | |
269 | + self.button_view.SetBitmapSelected(ID_TO_BMP[evt.GetId()][1]) | |
270 | + ps.Publisher().sendMessage('Set volume view angle', | |
271 | + ID_TO_BMP[evt.GetId()][0]) | |
262 | 272 | |
263 | 273 | def OnSelectColour(self, evt): |
264 | 274 | colour = c = [i/255.0 for i in evt.GetValue()] |
265 | 275 | ps.Publisher().sendMessage('Change volume viewer background colour', colour) |
266 | 276 | |
267 | 277 | def OnToggleRaycasting(self, evt): |
268 | - if self.button_raycasting.GetToggle(): | |
269 | - #ps.Publisher().sendMessage('Create volume raycasting') | |
270 | - ps.Publisher().sendMessage('Show raycasting volume') | |
271 | - else: | |
278 | + print "oi" | |
279 | + if self.button_raycasting_toggle: | |
272 | 280 | ps.Publisher().sendMessage('Hide raycasting volume') |
281 | + self.button_raycasting.SetBackgroundColour(self.GetParent().GetBackgroundColour()) | |
282 | + #self.button_raycasting.SetBitmapSelected(ID_TO_BMP2[0]) | |
283 | + self.button_raycasting_toggle = 0 | |
284 | + else: | |
285 | + ps.Publisher().sendMessage('Show raycasting volume') | |
286 | + self.button_raycasting_toggle = 1 | |
287 | + #self.button_raycasting.SetBitmapSelected(ID_TO_BMP2[1]) | |
288 | + self.button_raycasting.SetBackgroundColour((255,255,255)) | ... | ... |