Commit b2b98a16e815eb15416382c43600d68f94a75676
1 parent
a39e606a
Exists in
rotvol
Dragging the center of rotation
Showing
2 changed files
with
63 additions
and
5 deletions
Show diff stats
invesalius/data/slice_.py
@@ -93,8 +93,9 @@ class Slice(object): | @@ -93,8 +93,9 @@ class Slice(object): | ||
93 | self._type_projection = const.PROJECTION_NORMAL | 93 | self._type_projection = const.PROJECTION_NORMAL |
94 | self.n_border = const.PROJECTION_BORDER_SIZE | 94 | self.n_border = const.PROJECTION_BORDER_SIZE |
95 | 95 | ||
96 | - self.spacing = (1.0, 1.0, 1.0) | 96 | + self._spacing = (1.0, 1.0, 1.0) |
97 | self.rotations = (0, 0, 0) | 97 | self.rotations = (0, 0, 0) |
98 | + self.center = [0, 0, 0] | ||
98 | 99 | ||
99 | self.number_of_colours = 256 | 100 | self.number_of_colours = 256 |
100 | self.saturation_range = (0, 0) | 101 | self.saturation_range = (0, 0) |
@@ -125,6 +126,16 @@ class Slice(object): | @@ -125,6 +126,16 @@ class Slice(object): | ||
125 | i, e = value.min(), value.max() | 126 | i, e = value.min(), value.max() |
126 | r = int(e) - int(i) | 127 | r = int(e) - int(i) |
127 | self.histogram = np.histogram(self._matrix, r, (i, e))[0] | 128 | self.histogram = np.histogram(self._matrix, r, (i, e))[0] |
129 | + self.center = [(s * d/2.0) for (d, s) in zip(self.matrix.shape[::-1], self.spacing)] | ||
130 | + | ||
131 | + @property | ||
132 | + def spacing(self): | ||
133 | + return self._spacing | ||
134 | + | ||
135 | + @spacing.setter | ||
136 | + def spacing(self, value): | ||
137 | + self._spacing = value | ||
138 | + self.center = [(s * d/2.0) for (d, s) in zip(self.matrix.shape[::-1], self.spacing)] | ||
128 | 139 | ||
129 | def __bind_events(self): | 140 | def __bind_events(self): |
130 | # General slice control | 141 | # General slice control |
@@ -568,16 +579,16 @@ class Slice(object): | @@ -568,16 +579,16 @@ class Slice(object): | ||
568 | number_slices = 1 | 579 | number_slices = 1 |
569 | 580 | ||
570 | if np.any(self.rotations): | 581 | if np.any(self.rotations): |
571 | - dz, dy, dx = self.matrix.shape | 582 | + cx, cy, cz = self.center |
572 | rx, ry, rz = self.rotations | 583 | rx, ry, rz = self.rotations |
573 | sx, sy, sz = self.spacing | 584 | sx, sy, sz = self.spacing |
574 | - T0 = transformations.translation_matrix((-dz/2.0 * sz, -dy/2.0 * sy, -dx/2.0 * sx)) | 585 | + T0 = transformations.translation_matrix((-cz, -cy, -cx)) |
575 | Rx = transformations.rotation_matrix(rx, (0, 0, 1)) | 586 | Rx = transformations.rotation_matrix(rx, (0, 0, 1)) |
576 | Ry = transformations.rotation_matrix(ry, (0, 1, 0)) | 587 | Ry = transformations.rotation_matrix(ry, (0, 1, 0)) |
577 | Rz = transformations.rotation_matrix(rz, (1, 0, 0)) | 588 | Rz = transformations.rotation_matrix(rz, (1, 0, 0)) |
578 | # R = transformations.euler_matrix(rz, ry, rx, 'rzyx') | 589 | # R = transformations.euler_matrix(rz, ry, rx, 'rzyx') |
579 | R = transformations.concatenate_matrices(Rx, Ry, Rz) | 590 | R = transformations.concatenate_matrices(Rx, Ry, Rz) |
580 | - T1 = transformations.translation_matrix((dz/2.0 * sz, dy/2.0 * sy, dx/2.0 * sx)) | 591 | + T1 = transformations.translation_matrix((cz, cy, cx)) |
581 | M = transformations.concatenate_matrices(T1, R.T, T0) | 592 | M = transformations.concatenate_matrices(T1, R.T, T0) |
582 | 593 | ||
583 | 594 |
invesalius/data/styles.py
@@ -1417,7 +1417,12 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | @@ -1417,7 +1417,12 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | ||
1417 | self.line1 = None | 1417 | self.line1 = None |
1418 | self.line2 = None | 1418 | self.line2 = None |
1419 | 1419 | ||
1420 | + self.actors = [] | ||
1421 | + | ||
1422 | + self.picker = vtk.vtkWorldPointPicker() | ||
1423 | + | ||
1420 | self.AddObserver("KeyPressEvent", self.OnKeyPress) | 1424 | self.AddObserver("KeyPressEvent", self.OnKeyPress) |
1425 | + self.AddObserver("MouseMoveEvent", self.OnMouseMove) | ||
1421 | self.viewer.slice_data.renderer.AddObserver("StartEvent", self.OnUpdate) | 1426 | self.viewer.slice_data.renderer.AddObserver("StartEvent", self.OnUpdate) |
1422 | 1427 | ||
1423 | def SetUp(self): | 1428 | def SetUp(self): |
@@ -1425,6 +1430,10 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | @@ -1425,6 +1430,10 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | ||
1425 | self.draw_lines() | 1430 | self.draw_lines() |
1426 | Publisher.sendMessage('Reload actual slice') | 1431 | Publisher.sendMessage('Reload actual slice') |
1427 | 1432 | ||
1433 | + def CleanUp(self): | ||
1434 | + for actor in self.actors: | ||
1435 | + self.viewer.slice_data.renderer.RemoveActor(actor) | ||
1436 | + | ||
1428 | def OnKeyPress(self, evt, obj): | 1437 | def OnKeyPress(self, evt, obj): |
1429 | key = self.viewer.interactor.GetKeyCode() | 1438 | key = self.viewer.interactor.GetKeyCode() |
1430 | if key == '+': | 1439 | if key == '+': |
@@ -1452,10 +1461,46 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | @@ -1452,10 +1461,46 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | ||
1452 | self.viewer.slice_.current_mask.clear_history() | 1461 | self.viewer.slice_.current_mask.clear_history() |
1453 | Publisher.sendMessage('Reload actual slice') | 1462 | Publisher.sendMessage('Reload actual slice') |
1454 | 1463 | ||
1464 | + def OnMouseMove(self, obj, evt): | ||
1465 | + """ | ||
1466 | + This event is responsible to reorient image, set mouse cursors | ||
1467 | + """ | ||
1468 | + # Getting mouse position | ||
1469 | + iren = self.viewer.interactor | ||
1470 | + mx, my = iren.GetEventPosition() | ||
1471 | + | ||
1472 | + # Getting center value | ||
1473 | + center = self.viewer.slice_.center | ||
1474 | + coord = vtk.vtkCoordinate() | ||
1475 | + coord.SetValue(center) | ||
1476 | + cx, cy = coord.GetComputedDisplayValue(self.viewer.slice_data.renderer) | ||
1477 | + | ||
1478 | + dist_center = ((mx - cx)**2 + (my - cy)**2)**0.5 | ||
1479 | + | ||
1480 | + if dist_center <= 15: | ||
1481 | + cursor = wx.StockCursor(wx.CURSOR_SIZENESW) | ||
1482 | + | ||
1483 | + if self.left_pressed: | ||
1484 | + self.picker.Pick(mx, my, 0, self.viewer.slice_data.renderer) | ||
1485 | + x, y, z = self.picker.GetPickPosition() | ||
1486 | + icx, icy, icz = self.viewer.slice_.center | ||
1487 | + | ||
1488 | + if self.viewer.orientation == 'AXIAL': | ||
1489 | + self.viewer.slice_.center = (x, y, icz) | ||
1490 | + elif self.viewer.orientation == 'CORONAL': | ||
1491 | + self.viewer.slice_.center = (x, icy, z) | ||
1492 | + elif self.viewer.orientation == 'SAGITAL': | ||
1493 | + self.viewer.slice_.center = (icx, y, z) | ||
1494 | + Publisher.sendMessage('Update slice viewer') | ||
1495 | + else: | ||
1496 | + cursor = wx.StockCursor(wx.CURSOR_DEFAULT) | ||
1497 | + | ||
1498 | + self.viewer.interactor.SetCursor(cursor) | ||
1499 | + | ||
1455 | def OnUpdate(self, obj, evt): | 1500 | def OnUpdate(self, obj, evt): |
1456 | w, h = self.viewer.slice_data.renderer.GetSize() | 1501 | w, h = self.viewer.slice_data.renderer.GetSize() |
1457 | 1502 | ||
1458 | - center = self.viewer.slice_data.actor.GetCenter() | 1503 | + center = self.viewer.slice_.center |
1459 | coord = vtk.vtkCoordinate() | 1504 | coord = vtk.vtkCoordinate() |
1460 | coord.SetValue(center) | 1505 | coord.SetValue(center) |
1461 | x, y = coord.GetComputedDisplayValue(self.viewer.slice_data.renderer) | 1506 | x, y = coord.GetComputedDisplayValue(self.viewer.slice_data.renderer) |
@@ -1488,6 +1533,8 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | @@ -1488,6 +1533,8 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): | ||
1488 | 1533 | ||
1489 | self.viewer.slice_data.renderer.AddActor(actor) | 1534 | self.viewer.slice_data.renderer.AddActor(actor) |
1490 | 1535 | ||
1536 | + self.actors.append(actor) | ||
1537 | + | ||
1491 | return line | 1538 | return line |
1492 | 1539 | ||
1493 | def draw_lines(self): | 1540 | def draw_lines(self): |