Commit 855d18d945af1d79bb186147ab6efd985833ad80

Authored by Thiago Franco de Moraes
1 parent 8d9b272f

Makes the measure mark proportional to image spacing

* Added the parameter radius "Add measurement point" pubsub message. This
  parameter is proportional the image spacing.
* Added PROP_MEASURE to constants.py. This constant is used to set the
  proportion the image spacing.

The measure mark is proportional to the image spacing

Loading measures with circlerepresentation proportional to the image spacing

Adding measures in polydata with circlerepresentation proportional to the image spacing

Added PROP_MEASURE to constants.py
invesalius/constants.py
... ... @@ -38,6 +38,8 @@ DEFAULT_MEASURE_BG_COLOUR = (250/255.0, 247/255.0, 218/255.0)
38 38 DEFAULT_MEASURE_RADIUS = 1
39 39 DEFAULT_MEASURE_TYPE = MEASURE_LINEAR
40 40  
  41 +PROP_MEASURE = 0.8
  42 +
41 43  
42 44 STEREO_OFF = _(" Off")
43 45 STEREO_RED_BLUE = _("Red-blue")
... ...
invesalius/control.py
... ... @@ -405,7 +405,7 @@ class Controller():
405 405 (mask_name, thresh, colour))
406 406  
407 407 Publisher.sendMessage('Load measurement dict',
408   - proj.measurement_dict)
  408 + (proj.measurement_dict, self.Slice.spacing))
409 409  
410 410 Publisher.sendMessage(('Set scroll position', 'AXIAL'),proj.matrix_shape[0]/2)
411 411 Publisher.sendMessage(('Set scroll position', 'SAGITAL'),proj.matrix_shape[1]/2)
... ...
invesalius/data/measures.py
... ... @@ -21,6 +21,7 @@ LOCATION = {const.SURFACE: _(u"3D"),
21 21 const.SAGITAL: _(u"Sagittal")
22 22 }
23 23  
  24 +
24 25 class MeasurementManager(object):
25 26 """
26 27 A class to manage the use (Addition, remotion and visibility) from
... ... @@ -39,13 +40,31 @@ class MeasurementManager(object):
39 40 Publisher.subscribe(self._load_measurements, "Load measurement dict")
40 41  
41 42 def _load_measurements(self, pubsub_evt):
42   - dict = pubsub_evt.data
  43 + try:
  44 + dict, spacing = pubsub_evt.data
  45 + except ValueError:
  46 + dict = pubsub_evt.data
  47 + spacing = 1.0, 1.0, 1.0
43 48 for i in dict:
44 49 m = dict[i]
  50 +
  51 + if m.location == const.AXIAL:
  52 + radius = min(spacing[1], spacing[2]) * const.PROP_MEASURE
  53 +
  54 + elif m.location == const.CORONAL:
  55 + radius = min(spacing[0], spacing[1]) * const.PROP_MEASURE
  56 +
  57 + elif m.location == const.SAGITAL:
  58 + radius = min(spacing[1], spacing[2]) * const.PROP_MEASURE
  59 +
  60 + else:
  61 + radius = min(spacing) * const.PROP_MEASURE
  62 +
  63 + representation = CirclePointRepresentation(m.colour, radius)
45 64 if m.type == const.LINEAR:
46   - mr = LinearMeasure(m.colour)
  65 + mr = LinearMeasure(m.colour, representation)
47 66 else:
48   - mr = AngularMeasure(m.colour)
  67 + mr = AngularMeasure(m.colour, representation)
49 68 self.current = (m, mr)
50 69 self.measures.append(self.current)
51 70 for point in m.points:
... ... @@ -66,10 +85,23 @@ class MeasurementManager(object):
66 85 position = pubsub_evt.data[0]
67 86 type = pubsub_evt.data[1] # Linear or Angular
68 87 location = pubsub_evt.data[2] # 3D, AXIAL, SAGITAL, CORONAL
69   - try:
70   - slice_number = pubsub_evt.data[3]
71   - except IndexError:
  88 +
  89 + if location == const.SURFACE:
72 90 slice_number = 0
  91 + try:
  92 + radius = pubsub_evt.data[3]
  93 + except IndexError:
  94 + radius = const.PROP_MEASURE
  95 + else:
  96 + try:
  97 + slice_number = pubsub_evt.data[3]
  98 + except IndexError:
  99 + slice_number = 0
  100 +
  101 + try:
  102 + radius = pubsub_evt.data[4]
  103 + except IndexError:
  104 + radius = const.PROP_MEASURE
73 105  
74 106 to_remove = False
75 107 if self.current is None:
... ... @@ -95,10 +127,11 @@ class MeasurementManager(object):
95 127 m.location = location
96 128 m.slice_number = slice_number
97 129 m.type = type
  130 + representation = CirclePointRepresentation(m.colour, radius)
98 131 if type == const.LINEAR:
99   - mr = LinearMeasure(m.colour)
  132 + mr = LinearMeasure(m.colour, representation)
100 133 else:
101   - mr = AngularMeasure(m.colour)
  134 + mr = AngularMeasure(m.colour, representation)
102 135 if to_remove:
103 136 print "---To REMOVE"
104 137 actors = self.current[1].GetActors()
... ...
invesalius/data/styles.py
... ... @@ -271,6 +271,17 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
271 271 self.orientation = viewer.orientation
272 272 self.slice_data = viewer.slice_data
273 273  
  274 + spacing = self.slice_data.actor.GetInput().GetSpacing()
  275 +
  276 + if self.orientation == "AXIAL":
  277 + self.radius = min(spacing[1], spacing[2]) * 0.8
  278 +
  279 + elif self.orientation == 'CORONAL':
  280 + self.radius = min(spacing[0], spacing[1]) * 0.8
  281 +
  282 + elif self.orientation == 'SAGITAL':
  283 + self.radius = min(spacing[1], spacing[2]) * 0.8
  284 +
274 285 self.picker = vtk.vtkCellPicker()
275 286  
276 287 self.AddObserver("LeftButtonPressEvent", self.OnInsertLinearMeasurePoint)
... ... @@ -286,7 +297,7 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
286 297 Publisher.sendMessage("Add measurement point",
287 298 ((x, y,z), const.LINEAR,
288 299 ORIENTATIONS[self.orientation],
289   - slice_number))
  300 + slice_number, self.radius))
290 301 self.viewer.interactor.Render()
291 302  
292 303  
... ... @@ -301,6 +312,17 @@ class AngularMeasureInteractorStyle(DefaultInteractorStyle):
301 312 self.orientation = viewer.orientation
302 313 self.slice_data = viewer.slice_data
303 314  
  315 + spacing = self.slice_data.actor.GetInput().GetSpacing()
  316 +
  317 + if self.orientation == "AXIAL":
  318 + self.radius = min(spacing[1], spacing[2]) * 0.8
  319 +
  320 + elif self.orientation == 'CORONAL':
  321 + self.radius = min(spacing[0], spacing[1]) * 0.8
  322 +
  323 + elif self.orientation == 'SAGITAL':
  324 + self.radius = min(spacing[1], spacing[2]) * 0.8
  325 +
304 326 self.picker = vtk.vtkCellPicker()
305 327  
306 328 self.AddObserver("LeftButtonPressEvent", self.OnInsertAngularMeasurePoint)
... ... @@ -316,7 +338,7 @@ class AngularMeasureInteractorStyle(DefaultInteractorStyle):
316 338 Publisher.sendMessage("Add measurement point",
317 339 ((x, y,z), const.ANGULAR,
318 340 ORIENTATIONS[self.orientation],
319   - slice_number))
  341 + slice_number, self.radius))
320 342 self.viewer.interactor.Render()
321 343  
322 344  
... ...
invesalius/data/viewer_volume.py
... ... @@ -37,6 +37,8 @@ import utils
37 37  
38 38 from data import measures
39 39  
  40 +PROP_MEASURE = 0.8
  41 +
40 42 class Viewer(wx.Panel):
41 43 def __init__(self, parent):
42 44 wx.Panel.__init__(self, parent, size=wx.Size(320, 320))
... ... @@ -815,6 +817,9 @@ class Viewer(wx.Panel):
815 817 x,y = self.interactor.GetEventPosition()
816 818 self.measure_picker.Pick(x, y, 0, self.ren)
817 819 x, y, z = self.measure_picker.GetPickPosition()
  820 +
  821 + proj = prj.Project()
  822 + radius = min(proj.spacing) * PROP_MEASURE
818 823 if self.measure_picker.GetActor():
819 824 # if not self.measures or self.measures[-1].IsComplete():
820 825 # m = measures.LinearMeasure(self.ren)
... ... @@ -827,7 +832,7 @@ class Viewer(wx.Panel):
827 832 # Publisher.sendMessage("Add measure to list",
828 833 # (u"3D", _(u"%.3f mm" % m.GetValue())))
829 834 Publisher.sendMessage("Add measurement point",
830   - ((x, y,z), const.LINEAR, const.SURFACE))
  835 + ((x, y,z), const.LINEAR, const.SURFACE, radius))
831 836 self.interactor.Render()
832 837  
833 838 def OnInsertAngularMeasurePoint(self, obj, evt):
... ... @@ -835,6 +840,9 @@ class Viewer(wx.Panel):
835 840 x,y = self.interactor.GetEventPosition()
836 841 self.measure_picker.Pick(x, y, 0, self.ren)
837 842 x, y, z = self.measure_picker.GetPickPosition()
  843 +
  844 + proj = prj.Project()
  845 + radius = min(proj.spacing) * PROP_MEASURE
838 846 if self.measure_picker.GetActor():
839 847 # if not self.measures or self.measures[-1].IsComplete():
840 848 # m = measures.AngularMeasure(self.ren)
... ... @@ -856,7 +864,7 @@ class Viewer(wx.Panel):
856 864 # type_, location,
857 865 # value))
858 866 Publisher.sendMessage("Add measurement point",
859   - ((x, y,z), const.ANGULAR, const.SURFACE))
  867 + ((x, y,z), const.ANGULAR, const.SURFACE, radius))
860 868 self.interactor.Render()
861 869  
862 870 def Reposition3DPlane(self, evt_pubsub):
... ...
invesalius/gui/data_notebook.py
... ... @@ -1064,7 +1064,10 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
1064 1064 (index, visibility))
1065 1065  
1066 1066 def OnLoadData(self, pubsub_evt):
1067   - items_dict = pubsub_evt.data
  1067 + try:
  1068 + items_dict, spacing = pubsub_evt.data
  1069 + except ValueError:
  1070 + items_dict = pubsub_evt.data
1068 1071 for i in items_dict:
1069 1072 m = items_dict[i]
1070 1073 image = self.CreateColourBitmap(m.colour)
... ...