Commit dbecc12e2349879b6d0e7056a0dff36771a35e52
Exists in
master
and in
45 other branches
Merge pull request #27 from tfmoraes/editor_improvements
Editor improvements
Showing
4 changed files
with
86 additions
and
2 deletions
Show diff stats
invesalius/constants.py
| @@ -250,11 +250,15 @@ DEFAULT_BRUSH_FORMAT = BRUSH_CIRCLE | @@ -250,11 +250,15 @@ DEFAULT_BRUSH_FORMAT = BRUSH_CIRCLE | ||
| 250 | BRUSH_DRAW = 0 | 250 | BRUSH_DRAW = 0 |
| 251 | BRUSH_ERASE = 1 | 251 | BRUSH_ERASE = 1 |
| 252 | BRUSH_THRESH = 2 | 252 | BRUSH_THRESH = 2 |
| 253 | +BRUSH_THRESH_ERASE = 3 | ||
| 254 | +BRUSH_THRESH_ADD_ONLY = 4 | ||
| 255 | +BRUSH_THRESH_ERASE_ONLY = 5 | ||
| 253 | DEFAULT_BRUSH_OP = BRUSH_THRESH | 256 | DEFAULT_BRUSH_OP = BRUSH_THRESH |
| 254 | BRUSH_OP_NAME = [_("Draw"), _("Erase"), _("Threshold")] | 257 | BRUSH_OP_NAME = [_("Draw"), _("Erase"), _("Threshold")] |
| 255 | 258 | ||
| 256 | BRUSH_COLOUR = (0,0,1.0) | 259 | BRUSH_COLOUR = (0,0,1.0) |
| 257 | BRUSH_SIZE = 30 | 260 | BRUSH_SIZE = 30 |
| 261 | +BRUSH_MAX_SIZE = 100 | ||
| 258 | 262 | ||
| 259 | # Surface creation values. Each element's list contains: | 263 | # Surface creation values. Each element's list contains: |
| 260 | # 0: imagedata reformat ratio | 264 | # 0: imagedata reformat ratio |
invesalius/data/cursor_actors.py
| @@ -78,6 +78,7 @@ class CursorBase(object): | @@ -78,6 +78,7 @@ class CursorBase(object): | ||
| 78 | self.size = 15.0 | 78 | self.size = 15.0 |
| 79 | self.orientation = "AXIAL" | 79 | self.orientation = "AXIAL" |
| 80 | self.spacing = (1, 1, 1) | 80 | self.spacing = (1, 1, 1) |
| 81 | + self.position = (0, 0, 0) | ||
| 81 | if vtk.vtkVersion().GetVTKVersion() > '5.8.0': | 82 | if vtk.vtkVersion().GetVTKVersion() > '5.8.0': |
| 82 | self.mapper = vtk.vtkImageSliceMapper() | 83 | self.mapper = vtk.vtkImageSliceMapper() |
| 83 | cursor_property = vtk.vtkImageProperty() | 84 | cursor_property = vtk.vtkImageProperty() |
| @@ -108,6 +109,7 @@ class CursorBase(object): | @@ -108,6 +109,7 @@ class CursorBase(object): | ||
| 108 | def SetPosition(self, position): | 109 | def SetPosition(self, position): |
| 109 | # Overriding SetPosition method because in rectangles with odd | 110 | # Overriding SetPosition method because in rectangles with odd |
| 110 | # dimensions there is no half position. | 111 | # dimensions there is no half position. |
| 112 | + self.position = position | ||
| 111 | px, py, pz = position | 113 | px, py, pz = position |
| 112 | sx, sy, sz = self.spacing | 114 | sx, sy, sz = self.spacing |
| 113 | tx = self.actor.GetXRange()[1] - self.actor.GetXRange()[0] | 115 | tx = self.actor.GetXRange()[1] - self.actor.GetXRange()[0] |
invesalius/data/slice_.py
| @@ -460,6 +460,13 @@ class Slice(object): | @@ -460,6 +460,13 @@ class Slice(object): | ||
| 460 | # (1 * 253 + 1) and out ones gets value 1 (0 * 253 + 1). | 460 | # (1 * 253 + 1) and out ones gets value 1 (0 * 253 + 1). |
| 461 | roi_m[index] = (((roi_i[index] >= thresh_min) | 461 | roi_m[index] = (((roi_i[index] >= thresh_min) |
| 462 | & (roi_i[index] <= thresh_max)) * 253) + 1 | 462 | & (roi_i[index] <= thresh_max)) * 253) + 1 |
| 463 | + elif operation == const.BRUSH_THRESH_ERASE: | ||
| 464 | + roi_m[index] = (((roi_i[index] < thresh_min) | ||
| 465 | + | (roi_i[index] > thresh_max)) * 253) + 1 | ||
| 466 | + elif operation == const.BRUSH_THRESH_ADD_ONLY: | ||
| 467 | + roi_m[((index) & (roi_i >= thresh_min) & (roi_i <= thresh_max))] = 254 | ||
| 468 | + elif operation == const.BRUSH_THRESH_ERASE_ONLY: | ||
| 469 | + roi_m[((index) & ((roi_i < thresh_min) | (roi_i > thresh_max)))] = 1 | ||
| 463 | elif operation == const.BRUSH_DRAW: | 470 | elif operation == const.BRUSH_DRAW: |
| 464 | roi_m[index] = 254 | 471 | roi_m[index] = 254 |
| 465 | elif operation == const.BRUSH_ERASE: | 472 | elif operation == const.BRUSH_ERASE: |
invesalius/data/styles.py
| @@ -540,6 +540,11 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -540,6 +540,11 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 540 | self.AddObserver("LeftButtonReleaseEvent", self.OnBrushRelease) | 540 | self.AddObserver("LeftButtonReleaseEvent", self.OnBrushRelease) |
| 541 | self.AddObserver("MouseMoveEvent", self.OnBrushMove) | 541 | self.AddObserver("MouseMoveEvent", self.OnBrushMove) |
| 542 | 542 | ||
| 543 | + self.RemoveObservers("MouseWheelForwardEvent") | ||
| 544 | + self.RemoveObservers("MouseWheelBackwardEvent") | ||
| 545 | + self.AddObserver("MouseWheelForwardEvent",self.EOnScrollForward) | ||
| 546 | + self.AddObserver("MouseWheelBackwardEvent", self.EOnScrollBackward) | ||
| 547 | + | ||
| 543 | def OnEnterInteractor(self, obj, evt): | 548 | def OnEnterInteractor(self, obj, evt): |
| 544 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 549 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
| 545 | return | 550 | return |
| @@ -556,9 +561,26 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -556,9 +561,26 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 556 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): | 561 | if (self.viewer.slice_.buffer_slices[self.orientation].mask is None): |
| 557 | return | 562 | return |
| 558 | 563 | ||
| 564 | + | ||
| 559 | viewer = self.viewer | 565 | viewer = self.viewer |
| 560 | iren = viewer.interactor | 566 | iren = viewer.interactor |
| 561 | 567 | ||
| 568 | + operation = viewer._brush_cursor_op | ||
| 569 | + if operation == const.BRUSH_THRESH: | ||
| 570 | + if iren.GetControlKey(): | ||
| 571 | + if iren.GetShiftKey(): | ||
| 572 | + operation = const.BRUSH_THRESH_ERASE_ONLY | ||
| 573 | + else: | ||
| 574 | + operation = const.BRUSH_THRESH_ERASE | ||
| 575 | + elif iren.GetShiftKey(): | ||
| 576 | + operation = const.BRUSH_THRESH_ADD_ONLY | ||
| 577 | + | ||
| 578 | + elif operation == const.BRUSH_ERASE and iren.GetControlKey(): | ||
| 579 | + operation = const.BRUSH_DRAW | ||
| 580 | + | ||
| 581 | + elif operation == const.BRUSH_DRAW and iren.GetControlKey(): | ||
| 582 | + operation = const.BRUSH_ERASE | ||
| 583 | + | ||
| 562 | viewer._set_editor_cursor_visibility(1) | 584 | viewer._set_editor_cursor_visibility(1) |
| 563 | 585 | ||
| 564 | mouse_x, mouse_y = iren.GetEventPosition() | 586 | mouse_x, mouse_y = iren.GetEventPosition() |
| @@ -585,7 +607,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -585,7 +607,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 585 | if position < 0: | 607 | if position < 0: |
| 586 | position = viewer.calculate_matrix_position(coord) | 608 | position = viewer.calculate_matrix_position(coord) |
| 587 | 609 | ||
| 588 | - viewer.slice_.edit_mask_pixel(viewer._brush_cursor_op, cursor.GetPixels(), | 610 | + viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), |
| 589 | position, radius, viewer.orientation) | 611 | position, radius, viewer.orientation) |
| 590 | viewer._flush_buffer = True | 612 | viewer._flush_buffer = True |
| 591 | 613 | ||
| @@ -605,6 +627,22 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -605,6 +627,22 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 605 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 627 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
| 606 | slice_data = viewer.get_slice_data(render) | 628 | slice_data = viewer.get_slice_data(render) |
| 607 | 629 | ||
| 630 | + operation = viewer._brush_cursor_op | ||
| 631 | + if operation == const.BRUSH_THRESH: | ||
| 632 | + if iren.GetControlKey(): | ||
| 633 | + if iren.GetShiftKey(): | ||
| 634 | + operation = const.BRUSH_THRESH_ERASE_ONLY | ||
| 635 | + else: | ||
| 636 | + operation = const.BRUSH_THRESH_ERASE | ||
| 637 | + elif iren.GetShiftKey(): | ||
| 638 | + operation = const.BRUSH_THRESH_ADD_ONLY | ||
| 639 | + | ||
| 640 | + elif operation == const.BRUSH_ERASE and iren.GetControlKey(): | ||
| 641 | + operation = const.BRUSH_DRAW | ||
| 642 | + | ||
| 643 | + elif operation == const.BRUSH_DRAW and iren.GetControlKey(): | ||
| 644 | + operation = const.BRUSH_ERASE | ||
| 645 | + | ||
| 608 | # TODO: Improve! | 646 | # TODO: Improve! |
| 609 | #for i in self.slice_data_list: | 647 | #for i in self.slice_data_list: |
| 610 | #i.cursor.Show(0) | 648 | #i.cursor.Show(0) |
| @@ -635,7 +673,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -635,7 +673,7 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 635 | if position < 0: | 673 | if position < 0: |
| 636 | position = viewer.calculate_matrix_position(coord) | 674 | position = viewer.calculate_matrix_position(coord) |
| 637 | 675 | ||
| 638 | - viewer.slice_.edit_mask_pixel(viewer._brush_cursor_op, cursor.GetPixels(), | 676 | + viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), |
| 639 | position, radius, self.orientation) | 677 | position, radius, self.orientation) |
| 640 | # TODO: To create a new function to reload images to viewer. | 678 | # TODO: To create a new function to reload images to viewer. |
| 641 | viewer.OnScrollBar(update3D=False) | 679 | viewer.OnScrollBar(update3D=False) |
| @@ -650,6 +688,39 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -650,6 +688,39 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
| 650 | self.viewer.slice_.apply_slice_buffer_to_mask(self.orientation) | 688 | self.viewer.slice_.apply_slice_buffer_to_mask(self.orientation) |
| 651 | self.viewer._flush_buffer = False | 689 | self.viewer._flush_buffer = False |
| 652 | 690 | ||
| 691 | + def EOnScrollForward(self, evt, obj): | ||
| 692 | + iren = self.viewer.interactor | ||
| 693 | + if iren.GetControlKey(): | ||
| 694 | + mouse_x, mouse_y = iren.GetEventPosition() | ||
| 695 | + render = iren.FindPokedRenderer(mouse_x, mouse_y) | ||
| 696 | + slice_data = self.viewer.get_slice_data(render) | ||
| 697 | + cursor = slice_data.cursor | ||
| 698 | + size = cursor.radius * 2 | ||
| 699 | + | ||
| 700 | + if size < 100: | ||
| 701 | + Publisher.sendMessage('Set edition brush size', size + 1) | ||
| 702 | + cursor.SetPosition(cursor.position) | ||
| 703 | + self.viewer.interactor.Render() | ||
| 704 | + | ||
| 705 | + else: | ||
| 706 | + self.OnScrollForward(obj, evt) | ||
| 707 | + | ||
| 708 | + def EOnScrollBackward(self, evt, obj): | ||
| 709 | + iren = self.viewer.interactor | ||
| 710 | + if iren.GetControlKey(): | ||
| 711 | + mouse_x, mouse_y = iren.GetEventPosition() | ||
| 712 | + render = iren.FindPokedRenderer(mouse_x, mouse_y) | ||
| 713 | + slice_data = self.viewer.get_slice_data(render) | ||
| 714 | + cursor = slice_data.cursor | ||
| 715 | + size = cursor.radius * 2 | ||
| 716 | + | ||
| 717 | + if size > 0: | ||
| 718 | + Publisher.sendMessage('Set edition brush size', size - 1) | ||
| 719 | + cursor.SetPosition(cursor.position) | ||
| 720 | + self.viewer.interactor.Render() | ||
| 721 | + else: | ||
| 722 | + self.OnScrollBackward(obj, evt) | ||
| 723 | + | ||
| 653 | def get_coordinate_cursor(self): | 724 | def get_coordinate_cursor(self): |
| 654 | # Find position | 725 | # Find position |
| 655 | x, y, z = self.picker.GetPickPosition() | 726 | x, y, z = self.picker.GetPickPosition() |