Commit 855d18d945af1d79bb186147ab6efd985833ad80
1 parent
8d9b272f
Exists in
master
and in
58 other branches
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
Showing
6 changed files
with
82 additions
and
14 deletions
Show diff stats
invesalius/constants.py
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) | ... | ... |