Commit 08e6f1bdae672082c685fe7a010b4a1244238ad5

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent 794ea503
Exists in master

Drag and drop support to measures in slices

* Created an class to keep measurements data

* Picking only the slice actor when adding measure

* Moving measure points

* melhorias

* Improvements

* Improvements

* Improvements

* Improvements
invesalius/data/measures.py
... ... @@ -10,6 +10,7 @@ import vtk
10 10 import constants as const
11 11 import project as prj
12 12 import session as ses
  13 +import utils
13 14  
14 15 TYPE = {const.LINEAR: _(u"Linear"),
15 16 const.ANGULAR: _(u"Angular"),
... ... @@ -21,6 +22,63 @@ LOCATION = {const.SURFACE: _(u"3D"),
21 22 const.SAGITAL: _(u"Sagittal")
22 23 }
23 24  
  25 +map_locations_id = {
  26 + "3D": const.SURFACE,
  27 + "AXIAL": const.AXIAL,
  28 + "CORONAL": const.CORONAL,
  29 + "SAGITAL": const.SAGITAL,
  30 +}
  31 +
  32 +map_id_locations = {const.SURFACE: "3D",
  33 + const.AXIAL: "AXIAL",
  34 + const.CORONAL: "CORONAL",
  35 + const.SAGITAL: "SAGITAL",
  36 + }
  37 +
  38 +class MeasureData:
  39 + """
  40 + Responsible to keep measures data.
  41 + """
  42 + __metaclass__= utils.Singleton
  43 + def __init__(self):
  44 + self.measures = {const.SURFACE: {},
  45 + const.AXIAL: {},
  46 + const.CORONAL: {},
  47 + const.SAGITAL: {}}
  48 + self._list_measures = []
  49 +
  50 + def append(self, m):
  51 + try:
  52 + self.measures[m[0].location][m[0].slice_number].append(m)
  53 + except KeyError:
  54 + self.measures[m[0].location][m[0].slice_number] = [m, ]
  55 +
  56 + self._list_measures.append(m)
  57 +
  58 + def get(self, location, slice_number):
  59 + return self.measures[map_locations_id[location]].get(slice_number, [])
  60 +
  61 + def pop(self, idx=None):
  62 + if idx is None:
  63 + m = self._list_measures.pop()
  64 + else:
  65 + m = self._list_measures.pop(idx)
  66 + self.measures[m[0].location][m[0].slice_number].remove(m)
  67 + return m
  68 +
  69 + def remove(self, m):
  70 + self._list_measures.remove(m)
  71 + self.measures[m[0].location][m[0].slice_number].remove(m)
  72 +
  73 + def __contains__(self, m):
  74 + return m in self._list_measures
  75 +
  76 + def __getitem__(self, idx):
  77 + return self._list_measures[idx]
  78 +
  79 + def __len__(self):
  80 + return len(self._list_measures)
  81 +
24 82  
25 83 class MeasurementManager(object):
26 84 """
... ... @@ -29,7 +87,7 @@ class MeasurementManager(object):
29 87 """
30 88 def __init__(self):
31 89 self.current = None
32   - self.measures = []
  90 + self.measures = MeasureData()
33 91 self._bind_events()
34 92  
35 93 def _bind_events(self):
... ... @@ -40,6 +98,7 @@ class MeasurementManager(object):
40 98 Publisher.subscribe(self._load_measurements, "Load measurement dict")
41 99 Publisher.subscribe(self._rm_incomplete_measurements,
42 100 "Remove incomplete measurements")
  101 + Publisher.subscribe(self._change_measure_point_pos, 'Change measurement point position')
43 102  
44 103 def _load_measurements(self, pubsub_evt):
45 104 try:
... ... @@ -49,7 +108,7 @@ class MeasurementManager(object):
49 108 spacing = 1.0, 1.0, 1.0
50 109 for i in dict:
51 110 m = dict[i]
52   -
  111 +
53 112 if m.location == const.AXIAL:
54 113 radius = min(spacing[1], spacing[2]) * const.PROP_MEASURE
55 114  
... ... @@ -72,8 +131,10 @@ class MeasurementManager(object):
72 131 for point in m.points:
73 132 x, y, z = point
74 133 actors = mr.AddPoint(x, y, z)
75   - Publisher.sendMessage(("Add actors " + str(m.location)),
76   - (actors, m.slice_number))
  134 +
  135 + if m.location == const.SURFACE:
  136 + Publisher.sendMessage(("Add actors " + str(m.location)),
  137 + (actors, m.slice_number))
77 138 self.current = None
78 139  
79 140 if not m.is_shown:
... ... @@ -136,14 +197,15 @@ class MeasurementManager(object):
136 197 mr = AngularMeasure(m.colour, representation)
137 198 if to_remove:
138 199 print "---To REMOVE"
139   - actors = self.current[1].GetActors()
140   - slice_number = self.current[0].slice_number
141   - Publisher.sendMessage(('Remove actors ' + str(self.current[0].location)),
142   - (actors, slice_number))
  200 + # actors = self.current[1].GetActors()
  201 + # slice_number = self.current[0].slice_number
  202 + # Publisher.sendMessage(('Remove actors ' + str(self.current[0].location)),
  203 + # (actors, slice_number))
  204 + self.measures.pop()[1].Remove()
143 205 if self.current[0].location == const.SURFACE:
144 206 Publisher.sendMessage('Render volume viewer')
145 207 else:
146   - Publisher.sendMessage('Update slice viewer')
  208 + Publisher.sendMessage('Reload actual slice')
147 209  
148 210 session = ses.Session()
149 211 session.ChangeProject()
... ... @@ -156,13 +218,17 @@ class MeasurementManager(object):
156 218 x, y, z = position
157 219 actors = mr.AddPoint(x, y, z)
158 220 m.points.append(position)
159   - Publisher.sendMessage("Add actors " + str(location),
160   - (actors, m.slice_number))
  221 +
  222 + if m.location == const.SURFACE:
  223 + Publisher.sendMessage("Add actors " + str(location),
  224 + (actors, m.slice_number))
  225 +
  226 + if self.current not in self.measures:
  227 + self.measures.append(self.current)
161 228  
162 229 if mr.IsComplete():
163 230 index = prj.Project().AddMeasurement(m)
164 231 #m.index = index # already done in proj
165   - self.measures.append(self.current)
166 232 name = m.name
167 233 colour = m.colour
168 234 m.value = mr.GetValue()
... ... @@ -181,19 +247,57 @@ class MeasurementManager(object):
181 247 value))
182 248 self.current = None
183 249  
  250 + def _change_measure_point_pos(self, pubsub_evt):
  251 + index, npoint, pos = pubsub_evt.data
  252 + print index, npoint, pos
  253 + m, mr = self.measures[index]
  254 + x, y, z = pos
  255 + if npoint == 0:
  256 + mr.SetPoint1(x, y, z)
  257 + m.points[0] = x, y, z
  258 + elif npoint == 1:
  259 + mr.SetPoint2(x, y, z)
  260 + m.points[1] = x, y, z
  261 + elif npoint == 2:
  262 + mr.SetPoint3(x, y, z)
  263 + m.points[2] = x, y, z
  264 +
  265 + m.value = mr.GetValue()
  266 +
  267 + name = m.name
  268 + colour = m.colour
  269 + m.value = mr.GetValue()
  270 + type_ = TYPE[m.type]
  271 + location = LOCATION[m.location]
  272 +
  273 + if m.type == const.LINEAR:
  274 + value = u"%.2f mm"% m.value
  275 + else:
  276 + value = u"%.2f°"% m.value
  277 +
  278 + Publisher.sendMessage('Update measurement info in GUI',
  279 + (index, name, colour,
  280 + location,
  281 + type_,
  282 + value))
  283 +
184 284 def _change_name(self, pubsub_evt):
185 285 index, new_name = pubsub_evt.data
186   - self.measures[index][0].name = new_name
  286 + self.measures[index].name = new_name
187 287  
188 288 def _remove_measurements(self, pubsub_evt):
189 289 indexes = pubsub_evt.data
190   - print indexes
191 290 for index in indexes:
192 291 m, mr = self.measures.pop(index)
193   - actors = mr.GetActors()
  292 + try:
  293 + mr.Remove()
  294 + except AttributeError:
  295 + # The is not being displayed
  296 + pass
194 297 prj.Project().RemoveMeasurement(index)
195   - Publisher.sendMessage(('Remove actors ' + str(m.location)),
196   - (actors, m.slice_number))
  298 + if m.location == const.SURFACE:
  299 + Publisher.sendMessage(('Remove actors ' + str(m.location)),
  300 + (mr.GetActors(), m.slice_number))
197 301 Publisher.sendMessage('Update slice viewer')
198 302 Publisher.sendMessage('Render volume viewer')
199 303  
... ... @@ -212,12 +316,13 @@ class MeasurementManager(object):
212 316  
213 317 def _rm_incomplete_measurements(self, pubsub_evt):
214 318 if self.current is None:
215   - return
  319 + return
216 320  
217 321 mr = self.current[1]
218 322 print "RM INC M", self.current, mr.IsComplete()
219 323 if not mr.IsComplete():
220 324 print "---To REMOVE"
  325 + self.measures.pop()
221 326 actors = mr.GetActors()
222 327 slice_number = self.current[0].slice_number
223 328 Publisher.sendMessage(('Remove actors ' + str(self.current[0].location)),
... ... @@ -364,6 +469,7 @@ class LinearMeasure(object):
364 469 self.point_actor2 = None
365 470 self.line_actor = None
366 471 self.text_actor = None
  472 + self.renderer = None
367 473 if not representation:
368 474 representation = CirclePointRepresentation(colour)
369 475 self.representation = representation
... ... @@ -384,13 +490,31 @@ class LinearMeasure(object):
384 490 return (self.point_actor2, self.line_actor, self.text_actor)
385 491  
386 492 def SetPoint1(self, x, y, z):
387   - self.points.append((x, y, z))
388   - self.point_actor1 = self.representation.GetRepresentation(x, y, z)
  493 + if len(self.points) == 0:
  494 + self.points.append((x, y, z))
  495 + self.point_actor1 = self.representation.GetRepresentation(x, y, z)
  496 + else:
  497 + self.points[0] = (x, y, z)
  498 + if len(self.points) == 2:
  499 + self.Remove()
  500 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  501 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
  502 + self.CreateMeasure()
  503 + else:
  504 + self.Remove()
  505 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
389 506  
390 507 def SetPoint2(self, x, y, z):
391   - self.points.append((x, y, z))
392   - self.point_actor2 = self.representation.GetRepresentation(x, y, z)
393   - self.CreateMeasure()
  508 + if len(self.points) == 1:
  509 + self.points.append((x, y, z))
  510 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
  511 + self.CreateMeasure()
  512 + else:
  513 + self.points[1] = (x, y, z)
  514 + self.Remove()
  515 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  516 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
  517 + self.CreateMeasure()
394 518  
395 519 def CreateMeasure(self):
396 520 self._draw_line()
... ... @@ -432,6 +556,7 @@ class LinearMeasure(object):
432 556 a.GetPositionCoordinate().SetCoordinateSystemToWorld()
433 557 a.GetPositionCoordinate().SetValue(x,y,z)
434 558 a.GetProperty().SetColor((0, 1, 0))
  559 + a.GetProperty().SetOpacity(0.75)
435 560 self.text_actor = a
436 561  
437 562 def GetNumberOfPoints(self):
... ... @@ -443,22 +568,22 @@ class LinearMeasure(object):
443 568  
444 569 def SetRenderer(self, renderer):
445 570 if self.point_actor1:
446   - self.render.RemoveActor(self.point_actor1)
  571 + self.renderer.RemoveActor(self.point_actor1)
447 572 renderer.AddActor(self.point_actor1)
448 573  
449 574 if self.point_actor2:
450   - self.render.RemoveActor(self.point_actor2)
  575 + self.renderer.RemoveActor(self.point_actor2)
451 576 renderer.AddActor(self.point_actor2)
452 577  
453 578 if self.line_actor:
454   - self.render.RemoveActor(self.line_actor)
  579 + self.renderer.RemoveActor(self.line_actor)
455 580 renderer.AddActor(self.line_actor)
456 581  
457 582 if self.text_actor:
458   - self.render.RemoveActor(self.text_actor)
  583 + self.renderer.RemoveActor(self.text_actor)
459 584 renderer.AddActor(self.text_actor)
460 585  
461   - self.render = renderer
  586 + self.renderer = renderer
462 587  
463 588 def SetVisibility(self, v):
464 589 self.point_actor1.SetVisibility(v)
... ... @@ -483,19 +608,19 @@ class LinearMeasure(object):
483 608  
484 609 def Remove(self):
485 610 if self.point_actor1:
486   - self.render.RemoveActor(self.point_actor1)
  611 + self.renderer.RemoveActor(self.point_actor1)
487 612 del self.point_actor1
488 613  
489 614 if self.point_actor2:
490   - self.render.RemoveActor(self.point_actor2)
  615 + self.renderer.RemoveActor(self.point_actor2)
491 616 del self.point_actor2
492 617  
493 618 if self.line_actor:
494   - self.render.RemoveActor(self.line_actor)
  619 + self.renderer.RemoveActor(self.line_actor)
495 620 del self.line_actor
496 621  
497 622 if self.text_actor:
498   - self.render.RemoveActor(self.text_actor)
  623 + self.renderer.RemoveActor(self.text_actor)
499 624 del self.text_actor
500 625  
501 626 # def __del__(self):
... ... @@ -532,20 +657,59 @@ class AngularMeasure(object):
532 657 return (self.point_actor3, self.line_actor, self.text_actor)
533 658  
534 659 def SetPoint1(self, x, y, z):
535   - self.points[0] = (x, y, z)
536   - self.number_of_points = 1
537   - self.point_actor1 = self.representation.GetRepresentation(x, y, z)
  660 + if self.number_of_points == 0:
  661 + self.points[0] = (x, y, z)
  662 + self.number_of_points = 1
  663 + self.point_actor1 = self.representation.GetRepresentation(x, y, z)
  664 + else:
  665 + self.points[0] = (x, y, z)
  666 + if len(self.points) == 3:
  667 + self.Remove()
  668 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  669 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
  670 + self.point_actor3 = self.representation.GetRepresentation(*self.points[2])
  671 + self.CreateMeasure()
  672 + else:
  673 + self.Remove()
  674 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  675 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
538 676  
539 677 def SetPoint2(self, x, y, z):
540   - self.number_of_points = 2
541   - self.points[1] = (x, y, z)
542   - self.point_actor2 = self.representation.GetRepresentation(x, y, z)
  678 + if self.number_of_points == 1:
  679 + self.number_of_points = 2
  680 + self.points[1] = (x, y, z)
  681 + self.point_actor2 = self.representation.GetRepresentation(x, y, z)
  682 + else:
  683 + self.points[1] = (x, y, z)
  684 + if len(self.points) == 3:
  685 + self.Remove()
  686 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  687 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
  688 + self.point_actor3 = self.representation.GetRepresentation(*self.points[2])
  689 + self.CreateMeasure()
  690 + else:
  691 + self.Remove()
  692 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  693 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
543 694  
544 695 def SetPoint3(self, x, y, z):
545   - self.number_of_points = 3
546   - self.points[2] = (x, y, z)
547   - self.point_actor3 = self.representation.GetRepresentation(x, y, z)
548   - self.CreateMeasure()
  696 + if self.number_of_points == 2:
  697 + self.number_of_points = 3
  698 + self.points[2] = (x, y, z)
  699 + self.point_actor3 = self.representation.GetRepresentation(x, y, z)
  700 + self.CreateMeasure()
  701 + else:
  702 + self.points[2] = (x, y, z)
  703 + if len(self.points) == 3:
  704 + self.Remove()
  705 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  706 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
  707 + self.point_actor3 = self.representation.GetRepresentation(*self.points[2])
  708 + self.CreateMeasure()
  709 + else:
  710 + self.Remove()
  711 + self.point_actor1 = self.representation.GetRepresentation(*self.points[0])
  712 + self.point_actor2 = self.representation.GetRepresentation(*self.points[1])
549 713  
550 714 def CreateMeasure(self):
551 715 self._draw_line()
... ... @@ -677,47 +841,47 @@ class AngularMeasure(object):
677 841  
678 842 def Remove(self):
679 843 if self.point_actor1:
680   - self.render.RemoveActor(self.point_actor1)
  844 + self.renderer.RemoveActor(self.point_actor1)
681 845 del self.point_actor1
682 846  
683 847 if self.point_actor2:
684   - self.render.RemoveActor(self.point_actor2)
  848 + self.renderer.RemoveActor(self.point_actor2)
685 849 del self.point_actor2
686 850  
687 851 if self.point_actor3:
688   - self.render.RemoveActor(self.point_actor3)
  852 + self.renderer.RemoveActor(self.point_actor3)
689 853 del self.point_actor3
690 854  
691 855 if self.line_actor:
692   - self.render.RemoveActor(self.line_actor)
  856 + self.renderer.RemoveActor(self.line_actor)
693 857 del self.line_actor
694 858  
695 859 if self.text_actor:
696   - self.render.RemoveActor(self.text_actor)
  860 + self.renderer.RemoveActor(self.text_actor)
697 861 del self.text_actor
698 862  
699 863 def SetRenderer(self, renderer):
700 864 if self.point_actor1:
701   - self.render.RemoveActor(self.point_actor1)
  865 + self.renderer.RemoveActor(self.point_actor1)
702 866 renderer.AddActor(self.point_actor1)
703 867  
704 868 if self.point_actor2:
705   - self.render.RemoveActor(self.point_actor2)
  869 + self.renderer.RemoveActor(self.point_actor2)
706 870 renderer.AddActor(self.point_actor2)
707 871  
708 872 if self.point_actor3:
709   - self.render.RemoveActor(self.point_actor3)
  873 + self.renderer.RemoveActor(self.point_actor3)
710 874 renderer.AddActor(self.point_actor3)
711 875  
712 876 if self.line_actor:
713   - self.render.RemoveActor(self.line_actor)
  877 + self.renderer.RemoveActor(self.line_actor)
714 878 renderer.AddActor(self.line_actor)
715 879  
716 880 if self.text_actor:
717   - self.render.RemoveActor(self.text_actor)
  881 + self.renderer.RemoveActor(self.text_actor)
718 882 renderer.AddActor(self.text_actor)
719 883  
720   - self.render = renderer
  884 + self.renderer = renderer
721 885  
722 886 # def __del__(self):
723 887 # self.Remove()
... ...
invesalius/data/styles.py
... ... @@ -40,6 +40,8 @@ from scipy.ndimage import watershed_ift, generate_binary_structure
40 40 from skimage.morphology import watershed
41 41 from skimage import filter
42 42  
  43 +from .measures import MeasureData
  44 +
43 45 import watershed_process
44 46  
45 47 import utils
... ... @@ -350,78 +352,107 @@ class LinearMeasureInteractorStyle(DefaultInteractorStyle):
350 352 self.orientation = viewer.orientation
351 353 self.slice_data = viewer.slice_data
352 354  
  355 + self.measures = MeasureData()
  356 + self.selected = None
  357 +
  358 + self._type = const.LINEAR
  359 +
353 360 spacing = self.slice_data.actor.GetInput().GetSpacing()
354 361  
355 362 if self.orientation == "AXIAL":
356 363 self.radius = min(spacing[1], spacing[2]) * 0.8
  364 + self._ori = const.AXIAL
357 365  
358 366 elif self.orientation == 'CORONAL':
359 367 self.radius = min(spacing[0], spacing[1]) * 0.8
  368 + self._ori = const.CORONAL
360 369  
361 370 elif self.orientation == 'SAGITAL':
362 371 self.radius = min(spacing[1], spacing[2]) * 0.8
  372 + self._ori = const.SAGITAL
363 373  
364 374 self.picker = vtk.vtkCellPicker()
  375 + self.picker.PickFromListOn()
365 376  
  377 + self._bind_events()
  378 +
  379 + def _bind_events(self):
366 380 self.AddObserver("LeftButtonPressEvent", self.OnInsertLinearMeasurePoint)
  381 + self.AddObserver("LeftButtonReleaseEvent", self.OnReleaseMeasurePoint)
  382 + self.AddObserver("MouseMoveEvent", self.OnMoveMeasurePoint)
367 383  
368 384 def OnInsertLinearMeasurePoint(self, obj, evt):
369   - iren = obj.GetInteractor()
370   - x,y = iren.GetEventPosition()
371   - render = iren.FindPokedRenderer(x, y)
372 385 slice_number = self.slice_data.number
373   - self.picker.Pick(x, y, 0, render)
374   - x, y, z = self.picker.GetPickPosition()
375   - if self.picker.GetViewProp():
376   - Publisher.sendMessage("Add measurement point",
377   - ((x, y,z), const.LINEAR,
378   - ORIENTATIONS[self.orientation],
379   - slice_number, self.radius))
380   - self.viewer.interactor.Render()
  386 + x, y, z = self._get_pos_clicked()
  387 +
  388 + selected = self._verify_clicked(x, y, z)
  389 + if selected:
  390 + self.selected = selected
  391 + else:
  392 + if self.picker.GetViewProp():
  393 + renderer = self.viewer.slice_data.renderer
  394 + Publisher.sendMessage("Add measurement point",
  395 + ((x, y,z), self._type,
  396 + ORIENTATIONS[self.orientation],
  397 + slice_number, self.radius))
  398 + Publisher.sendMessage('Reload actual slice %s' % self.orientation)
  399 +
  400 + def OnReleaseMeasurePoint(self, obj, evt):
  401 + if self.selected:
  402 + n, m, mr = self.selected
  403 + x, y, z = self._get_pos_clicked()
  404 + idx = self.measures._list_measures.index((m, mr))
  405 + Publisher.sendMessage('Change measurement point position', (idx, n, (x, y, z)))
  406 + Publisher.sendMessage('Reload actual slice %s' % self.orientation)
  407 + self.selected = None
  408 +
  409 + def OnMoveMeasurePoint(self, obj, evt):
  410 + if self.selected:
  411 + n, m, mr = self.selected
  412 + x, y, z = self._get_pos_clicked()
  413 + idx = self.measures._list_measures.index((m, mr))
  414 + Publisher.sendMessage('Change measurement point position', (idx, n, (x, y, z)))
  415 +
  416 + Publisher.sendMessage('Reload actual slice %s' % self.orientation)
381 417  
382 418 def CleanUp(self):
  419 + self.picker.PickFromListOff()
383 420 Publisher.sendMessage("Remove incomplete measurements")
384 421  
  422 + def _get_pos_clicked(self):
  423 + iren = self.viewer.interactor
  424 + mx,my = iren.GetEventPosition()
  425 + render = iren.FindPokedRenderer(mx, my)
  426 + self.picker.AddPickList(self.slice_data.actor)
  427 + self.picker.Pick(mx, my, 0, render)
  428 + x, y, z = self.picker.GetPickPosition()
  429 + self.picker.DeletePickList(self.slice_data.actor)
  430 + return (x, y, z)
385 431  
386   -class AngularMeasureInteractorStyle(DefaultInteractorStyle):
387   - """
388   - Interactor style responsible for insert angular measurements.
389   - """
390   - def __init__(self, viewer):
391   - DefaultInteractorStyle.__init__(self, viewer)
392   -
393   - self.viewer = viewer
394   - self.orientation = viewer.orientation
395   - self.slice_data = viewer.slice_data
396   -
397   - spacing = self.slice_data.actor.GetInput().GetSpacing()
398   -
399   - if self.orientation == "AXIAL":
400   - self.radius = min(spacing[1], spacing[2]) * 0.8
401   -
402   - elif self.orientation == 'CORONAL':
403   - self.radius = min(spacing[0], spacing[1]) * 0.8
404   -
405   - elif self.orientation == 'SAGITAL':
406   - self.radius = min(spacing[1], spacing[2]) * 0.8
407   -
408   - self.picker = vtk.vtkCellPicker()
409   -
410   - self.AddObserver("LeftButtonPressEvent", self.OnInsertAngularMeasurePoint)
411   -
412   - def OnInsertAngularMeasurePoint(self, obj, evt):
413   - iren = obj.GetInteractor()
414   - x,y = iren.GetEventPosition()
415   - render = iren.FindPokedRenderer(x, y)
  432 + def _verify_clicked(self, x, y, z):
416 433 slice_number = self.slice_data.number
417   - self.picker.Pick(x, y, 0, render)
418   - x, y, z = self.picker.GetPickPosition()
419   - if self.picker.GetViewProp():
420   - Publisher.sendMessage("Add measurement point",
421   - ((x, y,z), const.ANGULAR,
422   - ORIENTATIONS[self.orientation],
423   - slice_number, self.radius))
424   - self.viewer.interactor.Render()
  434 + sx, sy, sz = self.viewer.slice_.spacing
  435 + if self.orientation == "AXIAL":
  436 + max_dist = 2 * max(sx, sy)
  437 + elif self.orientation == "CORONAL":
  438 + max_dist = 2 * max(sx, sz)
  439 + elif self.orientation == "SAGITAL":
  440 + max_dist = 2 * max(sy, sz)
  441 +
  442 + if slice_number in self.measures.measures[self._ori]:
  443 + for m, mr in self.measures.measures[self._ori][slice_number]:
  444 + if mr.IsComplete():
  445 + for n, p in enumerate(m.points):
  446 + px, py, pz = p
  447 + dist = ((px-x)**2 + (py-y)**2 + (pz-z)**2)**0.5
  448 + if dist < max_dist:
  449 + return (n, m, mr)
  450 + return None
  451 +
  452 +class AngularMeasureInteractorStyle(LinearMeasureInteractorStyle):
  453 + def __init__(self, viewer):
  454 + LinearMeasureInteractorStyle.__init__(self, viewer)
  455 + self._type = const.ANGULAR
425 456  
426 457  
427 458 class PanMoveInteractorStyle(DefaultInteractorStyle):
... ...
invesalius/data/viewer_slice.py
... ... @@ -19,6 +19,7 @@
19 19 # detalhes.
20 20 #--------------------------------------------------------------------------
21 21  
  22 +import collections
22 23 import itertools
23 24 import tempfile
24 25  
... ... @@ -171,8 +172,8 @@ class Viewer(wx.Panel):
171 172 self.layout = (1, 1)
172 173 self.orientation_texts = []
173 174  
174   - self.measures = []
175   - self.actors_by_slice_number = {}
  175 + self.measures = measures.MeasureData()
  176 + self.actors_by_slice_number = collections.defaultdict(list)
176 177 self.renderers_by_slice_number = {}
177 178  
178 179 self.orientation = orientation
... ... @@ -1178,11 +1179,20 @@ class Viewer(wx.Panel):
1178 1179 image = self.slice_.GetSlices(self.orientation, index,
1179 1180 self.number_slices, inverted, border_size)
1180 1181 self.slice_data.actor.SetInputData(image)
1181   - for actor in self.actors_by_slice_number.get(self.slice_data.number, []):
  1182 + for actor in self.actors_by_slice_number[self.slice_data.number]:
1182 1183 self.slice_data.renderer.RemoveActor(actor)
1183   - for actor in self.actors_by_slice_number.get(index, []):
  1184 + for actor in self.actors_by_slice_number[index]:
1184 1185 self.slice_data.renderer.AddActor(actor)
1185 1186  
  1187 + for (m, mr) in self.measures.get(self.orientation, self.slice_data.number):
  1188 + for actor in mr.GetActors():
  1189 + self.slice_data.renderer.RemoveActor(actor)
  1190 +
  1191 + for (m, mr) in self.measures.get(self.orientation, index):
  1192 + mr.renderer = self.slice_data.renderer
  1193 + for actor in mr.GetActors():
  1194 + self.slice_data.renderer.AddActor(actor)
  1195 +
1186 1196 if self.slice_._type_projection == const.PROJECTION_NORMAL:
1187 1197 self.slice_data.SetNumber(index)
1188 1198 else:
... ... @@ -1239,10 +1249,7 @@ class Viewer(wx.Panel):
1239 1249 for actor in actors:
1240 1250 self.slice_data.renderer.AddActor(actor)
1241 1251  
1242   - try:
1243   - self.actors_by_slice_number[n].extend(actors)
1244   - except KeyError:
1245   - self.actors_by_slice_number[n] = list(actors)
  1252 + self.actors_by_slice_number[n].extend(actors)
1246 1253  
1247 1254 def RemoveActors(self, pubsub_evt):
1248 1255 "Remove a list of actors"
... ...
invesalius/gui/data_notebook.py
... ... @@ -1127,6 +1127,8 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
1127 1127 self.UpdateItemInfo(index, name, colour, location, type_, value)
1128 1128 else:
1129 1129 self.InsertNewItem(index, name, colour, location, type_, value)
  1130 + else:
  1131 + self.UpdateItemInfo(index, name, colour, location, type_, value)
1130 1132  
1131 1133  
1132 1134  
... ...
invesalius/utils.py
... ... @@ -23,6 +23,8 @@ import re
23 23 import locale
24 24 import math
25 25  
  26 +import numpy as np
  27 +
26 28 def format_time(value):
27 29 sp1 = value.split(".")
28 30 sp2 = value.split(":")
... ... @@ -418,3 +420,11 @@ def UpdateCheck():
418 420 if (last!=const.INVESALIUS_VERSION):
419 421 print " ...New update found!!! -> version:", last #, ", url=",url
420 422 wx.CallAfter(wx.CallLater, 1000, _show_update_info)
  423 +
  424 +
  425 +def vtkarray_to_numpy(m):
  426 + nm = np.zeros((4, 4))
  427 + for i in xrange(4):
  428 + for j in xrange(4):
  429 + nm[i, j] = m.GetElement(i, j)
  430 + return nm
... ...