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 | 93 | self._type_projection = const.PROJECTION_NORMAL |
| 94 | 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 | 97 | self.rotations = (0, 0, 0) |
| 98 | + self.center = [0, 0, 0] | |
| 98 | 99 | |
| 99 | 100 | self.number_of_colours = 256 |
| 100 | 101 | self.saturation_range = (0, 0) |
| ... | ... | @@ -125,6 +126,16 @@ class Slice(object): |
| 125 | 126 | i, e = value.min(), value.max() |
| 126 | 127 | r = int(e) - int(i) |
| 127 | 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 | 140 | def __bind_events(self): |
| 130 | 141 | # General slice control |
| ... | ... | @@ -568,16 +579,16 @@ class Slice(object): |
| 568 | 579 | number_slices = 1 |
| 569 | 580 | |
| 570 | 581 | if np.any(self.rotations): |
| 571 | - dz, dy, dx = self.matrix.shape | |
| 582 | + cx, cy, cz = self.center | |
| 572 | 583 | rx, ry, rz = self.rotations |
| 573 | 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 | 586 | Rx = transformations.rotation_matrix(rx, (0, 0, 1)) |
| 576 | 587 | Ry = transformations.rotation_matrix(ry, (0, 1, 0)) |
| 577 | 588 | Rz = transformations.rotation_matrix(rz, (1, 0, 0)) |
| 578 | 589 | # R = transformations.euler_matrix(rz, ry, rx, 'rzyx') |
| 579 | 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 | 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 | 1417 | self.line1 = None |
| 1418 | 1418 | self.line2 = None |
| 1419 | 1419 | |
| 1420 | + self.actors = [] | |
| 1421 | + | |
| 1422 | + self.picker = vtk.vtkWorldPointPicker() | |
| 1423 | + | |
| 1420 | 1424 | self.AddObserver("KeyPressEvent", self.OnKeyPress) |
| 1425 | + self.AddObserver("MouseMoveEvent", self.OnMouseMove) | |
| 1421 | 1426 | self.viewer.slice_data.renderer.AddObserver("StartEvent", self.OnUpdate) |
| 1422 | 1427 | |
| 1423 | 1428 | def SetUp(self): |
| ... | ... | @@ -1425,6 +1430,10 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): |
| 1425 | 1430 | self.draw_lines() |
| 1426 | 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 | 1437 | def OnKeyPress(self, evt, obj): |
| 1429 | 1438 | key = self.viewer.interactor.GetKeyCode() |
| 1430 | 1439 | if key == '+': |
| ... | ... | @@ -1452,10 +1461,46 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): |
| 1452 | 1461 | self.viewer.slice_.current_mask.clear_history() |
| 1453 | 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 | 1500 | def OnUpdate(self, obj, evt): |
| 1456 | 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 | 1504 | coord = vtk.vtkCoordinate() |
| 1460 | 1505 | coord.SetValue(center) |
| 1461 | 1506 | x, y = coord.GetComputedDisplayValue(self.viewer.slice_data.renderer) |
| ... | ... | @@ -1488,6 +1533,8 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): |
| 1488 | 1533 | |
| 1489 | 1534 | self.viewer.slice_data.renderer.AddActor(actor) |
| 1490 | 1535 | |
| 1536 | + self.actors.append(actor) | |
| 1537 | + | |
| 1491 | 1538 | return line |
| 1492 | 1539 | |
| 1493 | 1540 | def draw_lines(self): | ... | ... |