Commit 41d183fe015e1b8add1ae88100f01bf92d510847

Authored by Thiago Franco de Moraes
2 parents 8d9b272f 855d18d9

Merge pull request #17 from tfmoraes/measure_spacing

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