Commit 9ab9d4847b311144cbf72bb0ddd8cb08b21c4382

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent f6b001eb

Using Canvas to render text over the vtkrenderer

* Using wx to show slice number

* Setting weight to bold

* Orientation renderer text using wx

* Improvements

Author:    Thiago Franco de Moraes <totonixsame@gmail.com>

* Improvements

* Better cleaning on closing project

* Using antialising in mac
invesalius/data/measures.py
... ... @@ -66,6 +66,13 @@ class MeasureData:
66 66  
67 67 self._list_measures.append(m)
68 68  
  69 + def clean(self):
  70 + self.measures = {const.SURFACE: {},
  71 + const.AXIAL: {},
  72 + const.CORONAL: {},
  73 + const.SAGITAL: {}}
  74 + self._list_measures = []
  75 +
69 76 def get(self, location, slice_number):
70 77 return self.measures[map_locations_id[location]].get(slice_number, [])
71 78  
... ... @@ -110,6 +117,7 @@ class MeasurementManager(object):
110 117 Publisher.subscribe(self._rm_incomplete_measurements,
111 118 "Remove incomplete measurements")
112 119 Publisher.subscribe(self._change_measure_point_pos, 'Change measurement point position')
  120 + Publisher.subscribe(self.OnCloseProject, 'Close project data')
113 121  
114 122 def _load_measurements(self, pubsub_evt):
115 123 try:
... ... @@ -340,6 +348,9 @@ class MeasurementManager(object):
340 348 # self.measures.pop()
341 349 self.current = None
342 350  
  351 + def OnCloseProject(self, pubsub_evt):
  352 + self.measures.clean()
  353 +
343 354  
344 355 class Measurement():
345 356 general_index = -1
... ...
invesalius/data/slice_data.py
... ... @@ -17,6 +17,7 @@
17 17 # detalhes.
18 18 #--------------------------------------------------------------------------
19 19 import vtk
  20 +import wx
20 21  
21 22 import invesalius.constants as const
22 23 import invesalius.data.vtk_utils as vu
... ... @@ -50,6 +51,7 @@ class SliceData(object):
50 51 text.SetColour(colour)
51 52 text.SetSize(const.TEXT_SIZE_LARGE)
52 53 text.SetPosition(const.TEXT_POS_LEFT_DOWN_ZERO)
  54 + text.SetSymbolicSize(wx.FONTSIZE_LARGE)
53 55 #text.SetVerticalJustificationToBottom()
54 56 text.SetValue(self.number)
55 57 self.text = text
... ...
invesalius/data/styles.py
... ... @@ -272,12 +272,14 @@ class WWWLInteractorStyle(DefaultInteractorStyle):
272 272  
273 273 def SetUp(self):
274 274 self.viewer.on_wl = True
275   - self.viewer.wl_text.Show()
  275 + self.viewer.canvas.draw_list.append(self.viewer.wl_text)
  276 + self.viewer.UpdateCanvas()
276 277  
277 278 def CleanUp(self):
278 279 self.viewer.on_wl = False
279 280 if self.viewer.wl_text is not None:
280   - self.viewer.wl_text.Hide()
  281 + self.viewer.canvas.draw_list.remove(self.viewer.wl_text)
  282 + self.viewer.UpdateCanvas()
281 283  
282 284 def OnWindowLevelMove(self, obj, evt):
283 285 if (self.left_pressed):
... ...
invesalius/data/viewer_slice.py
... ... @@ -212,6 +212,10 @@ class CanvasRendererCTX:
212 212  
213 213 self.modified = True
214 214  
  215 + def remove_from_renderer(self):
  216 + self.canvas_renderer.RemoveActor(self.actor)
  217 + self.evt_renderer.RemoveObservers("StartEvent")
  218 +
215 219 def OnPaint(self, evt, obj):
216 220 size = self.canvas_renderer.GetSize()
217 221 w, h = size
... ... @@ -233,7 +237,8 @@ class CanvasRendererCTX:
233 237 self.image.SetAlphaBuffer(self.alpha)
234 238 self.image.Clear()
235 239 gc = wx.GraphicsContext.Create(self.image)
236   - gc.SetAntialiasMode(0)
  240 + if sys.platform != 'darwin':
  241 + gc.SetAntialiasMode(0)
237 242  
238 243 self.gc = gc
239 244  
... ... @@ -428,6 +433,8 @@ class CanvasRendererCTX:
428 433 gc.SetFont(font)
429 434  
430 435 px, py = pos
  436 + py = -py
  437 +
431 438 gc.DrawText(text, px, py)
432 439 self._drawn = True
433 440  
... ... @@ -455,14 +462,13 @@ class CanvasRendererCTX:
455 462 w, h = gc.GetTextExtent(text)
456 463  
457 464 px, py = pos
458   - py = -py
459 465  
460 466 # Drawing the box
461 467 cw, ch = w + border * 2, h + border * 2
462   - self.draw_rectangle((px, py), cw, ch, bg_colour, bg_colour)
  468 + self.draw_rectangle((px, -py), cw, ch, bg_colour, bg_colour)
463 469  
464 470 # Drawing the text
465   - tpx, tpy = px + border, py + border
  471 + tpx, tpy = px + border, py - border
466 472 self.draw_text(text, (tpx, tpy), font, txt_colour)
467 473 self._drawn = True
468 474  
... ... @@ -532,10 +538,12 @@ class Viewer(wx.Panel):
532 538 # All renderers and image actors in this viewer
533 539 self.slice_data_list = []
534 540 self.slice_data = None
535   -
  541 +
536 542 self.slice_actor = None
537 543 self.interpolation_slice_status = True
538 544  
  545 + self.canvas = None
  546 +
539 547 # The layout from slice_data, the first is number of cols, the second
540 548 # is the number of rows
541 549 self.layout = (1, 1)
... ... @@ -617,19 +625,23 @@ class Viewer(wx.Panel):
617 625 self.__configure_scroll()
618 626  
619 627 def HideTextActors(self, change_status=True):
620   - if self.wl_text:
621   - self.wl_text.Hide()
622   - [t.Hide() for t in self.orientation_texts]
623   - self.interactor.Render()
  628 + try:
  629 + self.canvas.draw_list.remove(self.wl_text)
  630 + except (ValueError, AttributeError):
  631 + pass
  632 +
  633 + [self.canvas.draw_list.remove(t) for t in self.orientation_texts]
  634 + self.UpdateCanvas()
624 635 if change_status:
625 636 self.on_text = False
626 637  
627 638 def ShowTextActors(self):
628 639 if self.on_wl and self.wl_text:
629   - self.wl_text.Show()
630   - [t.Show() for t in self.orientation_texts]
631   - self.Update()
632   - self.interactor.Render()
  640 + self.canvas.draw_list.append(self.wl_text)
  641 + print "Canvas", self.canvas.draw_list
  642 + print "text ori", self.orientation_texts
  643 + [self.canvas.draw_list.append(t) for t in self.orientation_texts]
  644 + self.UpdateCanvas()
633 645 self.on_text = True
634 646  
635 647 def __set_layout(self, pubsub_evt):
... ... @@ -689,6 +701,7 @@ class Viewer(wx.Panel):
689 701 value = STR_WL%(window_level, window_width)
690 702 if (self.wl_text):
691 703 self.wl_text.SetValue(value)
  704 + self.canvas.modified = True
692 705 #self.interactor.Render()
693 706  
694 707 def EnableText(self):
... ... @@ -697,8 +710,11 @@ class Viewer(wx.Panel):
697 710 colour = const.ORIENTATION_COLOUR[self.orientation]
698 711  
699 712 # Window & Level text
700   - self.wl_text = vtku.Text()
  713 + self.wl_text = vtku.TextZero()
  714 + self.wl_text.SetPosition(const.TEXT_POS_LEFT_UP)
  715 + self.wl_text.SetSymbolicSize(wx.FONTSIZE_LARGE)
701 716 self.SetWLText(proj.level, proj.window)
  717 +
702 718 # Orientation text
703 719 if self.orientation == 'AXIAL':
704 720 values = [_('R'), _('L'), _('A'), _('P')]
... ... @@ -713,6 +729,7 @@ class Viewer(wx.Panel):
713 729 left_text.SetPosition(const.TEXT_POS_VCENTRE_LEFT)
714 730 left_text.SetVerticalJustificationToCentered()
715 731 left_text.SetValue(values[0])
  732 + left_text.SetSymbolicSize(wx.FONTSIZE_LARGE)
716 733  
717 734 right_text = self.right_text = vtku.TextZero()
718 735 right_text.ShadowOff()
... ... @@ -721,6 +738,7 @@ class Viewer(wx.Panel):
721 738 right_text.SetVerticalJustificationToCentered()
722 739 right_text.SetJustificationToRight()
723 740 right_text.SetValue(values[1])
  741 + right_text.SetSymbolicSize(wx.FONTSIZE_LARGE)
724 742  
725 743 up_text = self.up_text = vtku.TextZero()
726 744 up_text.ShadowOff()
... ... @@ -728,6 +746,7 @@ class Viewer(wx.Panel):
728 746 up_text.SetPosition(const.TEXT_POS_HCENTRE_UP)
729 747 up_text.SetJustificationToCentered()
730 748 up_text.SetValue(values[2])
  749 + up_text.SetSymbolicSize(wx.FONTSIZE_LARGE)
731 750  
732 751 down_text = self.down_text = vtku.TextZero()
733 752 down_text.ShadowOff()
... ... @@ -736,17 +755,11 @@ class Viewer(wx.Panel):
736 755 down_text.SetJustificationToCentered()
737 756 down_text.SetVerticalJustificationToBottom()
738 757 down_text.SetValue(values[3])
  758 + down_text.SetSymbolicSize(wx.FONTSIZE_LARGE)
739 759  
740 760 self.orientation_texts = [left_text, right_text, up_text,
741 761 down_text]
742 762  
743   -
744   - self.slice_data.renderer.AddActor(self.wl_text.actor)
745   - self.slice_data.renderer.AddActor(left_text.actor)
746   - self.slice_data.renderer.AddActor(right_text.actor)
747   - self.slice_data.renderer.AddActor(up_text.actor)
748   - self.slice_data.renderer.AddActor(down_text.actor)
749   -
750 763 def RenderTextDirection(self, directions):
751 764 # Values are on ccw order, starting from the top:
752 765 self.up_text.SetValue(directions[0])
... ... @@ -1304,7 +1317,16 @@ class Viewer(wx.Panel):
1304 1317  
1305 1318 self.slice_data_list = []
1306 1319 self.layout = (1, 1)
  1320 +
  1321 + del self.slice_data
  1322 + self.slice_data = None
  1323 +
  1324 + self.canvas.draw_list = []
  1325 + self.canvas.remove_from_renderer()
  1326 + self.canvas = None
  1327 +
1307 1328 self.orientation_texts = []
  1329 +
1308 1330 self.slice_number = 0
1309 1331 self.cursor = None
1310 1332 self.wl_text = None
... ... @@ -1405,6 +1427,7 @@ class Viewer(wx.Panel):
1405 1427 self.__build_cross_lines()
1406 1428  
1407 1429 self.canvas = CanvasRendererCTX(self.slice_data.renderer, self.slice_data.canvas_renderer, self.orientation)
  1430 + self.canvas.draw_list.append(self.slice_data.text)
1408 1431  
1409 1432 # Set the slice number to the last slice to ensure the camera if far
1410 1433 # enough to show all slices.
... ... @@ -1502,7 +1525,7 @@ class Viewer(wx.Panel):
1502 1525 slice_data.actor = actor
1503 1526 slice_data.SetBorderStyle(sd.BORDER_ALL)
1504 1527 renderer.AddActor(actor)
1505   - renderer.AddActor(slice_data.text.actor)
  1528 + # renderer.AddActor(slice_data.text.actor)
1506 1529 renderer.AddViewProp(slice_data.box_actor)
1507 1530  
1508 1531 return slice_data
... ... @@ -1547,21 +1570,22 @@ class Viewer(wx.Panel):
1547 1570 self.interactor.Render()
1548 1571  
1549 1572 def UpdateCanvas(self, evt=None):
1550   - cp_draw_list = self.canvas.draw_list[:]
1551   - self.canvas.draw_list = []
  1573 + if self.canvas is not None:
  1574 + cp_draw_list = self.canvas.draw_list[:]
  1575 + self.canvas.draw_list = []
1552 1576  
1553   - # Removing all measures
1554   - for i in cp_draw_list:
1555   - if not isinstance(i, (measures.AngularMeasure, measures.LinearMeasure)):
1556   - self.canvas.draw_list.append(i)
  1577 + # Removing all measures
  1578 + for i in cp_draw_list:
  1579 + if not isinstance(i, (measures.AngularMeasure, measures.LinearMeasure)):
  1580 + self.canvas.draw_list.append(i)
1557 1581  
1558   - # Then add all needed measures
1559   - for (m, mr) in self.measures.get(self.orientation, self.slice_data.number):
1560   - if m.visible:
1561   - self.canvas.draw_list.append(mr)
  1582 + # Then add all needed measures
  1583 + for (m, mr) in self.measures.get(self.orientation, self.slice_data.number):
  1584 + if m.visible:
  1585 + self.canvas.draw_list.append(mr)
1562 1586  
1563   - self.canvas.modified = True
1564   - self.interactor.Render()
  1587 + self.canvas.modified = True
  1588 + self.interactor.Render()
1565 1589  
1566 1590 def __configure_scroll(self):
1567 1591 actor = self.slice_data_list[0].actor
... ...
invesalius/data/vtk_utils.py
... ... @@ -19,6 +19,7 @@
19 19 import sys
20 20  
21 21 import vtk
  22 +import wx
22 23 from wx.lib.pubsub import pub as Publisher
23 24 import invesalius.constants as const
24 25 from invesalius.gui.dialogs import ProgressDialog
... ... @@ -189,6 +190,10 @@ class TextZero(object):
189 190 actor.PickableOff()
190 191 self.actor = actor
191 192  
  193 + self.text = ''
  194 + self.position = (0, 0)
  195 + self.symbolic_syze = wx.FONTSIZE_MEDIUM
  196 +
192 197 def SetColour(self, colour):
193 198 self.property.SetColor(colour)
194 199  
... ... @@ -198,6 +203,9 @@ class TextZero(object):
198 203 def SetSize(self, size):
199 204 self.property.SetFontSize(size)
200 205  
  206 + def SetSymbolicSize(self, size):
  207 + self.symbolic_syze = size
  208 +
201 209 def SetValue(self, value):
202 210 if isinstance(value, int) or isinstance(value, float):
203 211 value = str(value)
... ... @@ -207,13 +215,15 @@ class TextZero(object):
207 215 # UnicodeEncodeError because they have non-ascii characters. To avoid
208 216 # that we encode in utf-8.
209 217 self.actor.SetInput(value.encode("cp1252"))
  218 + self.text = value
210 219  
211 220 def SetPosition(self, position):
  221 + self.position = position
212 222 self.actor.GetPositionCoordinate().SetValue(position[0],
213 223 position[1])
214 224  
215   - def GetPosition(self, position):
216   - self.actor.GetPositionCoordinate().GetValue()
  225 + def GetPosition(self):
  226 + return self.actor.GetPositionCoordinate().GetValue()
217 227  
218 228 def SetJustificationToRight(self):
219 229 self.property.SetJustificationToRight()
... ... @@ -237,3 +247,13 @@ class TextZero(object):
237 247 def Hide(self):
238 248 self.actor.VisibilityOff()
239 249  
  250 + def draw_to_canvas(self, gc, canvas):
  251 + coord = vtk.vtkCoordinate()
  252 + coord.SetCoordinateSystemToNormalizedDisplay()
  253 + coord.SetValue(*self.position)
  254 + x, y = coord.GetComputedDisplayValue(canvas.evt_renderer)
  255 +
  256 + font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  257 + # font.SetWeight(wx.FONTWEIGHT_BOLD)
  258 + font.SetSymbolicSize(self.symbolic_syze)
  259 + canvas.draw_text(self.text, (x, y), font=font)
... ...