Commit 41d183fe015e1b8add1ae88100f01bf92d510847
Exists in
master
and in
57 other branches
Merge pull request #17 from tfmoraes/measure_spacing
Measure spacing
Showing
6 changed files
with
82 additions
and
14 deletions
Show diff stats
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) |