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): | ... | ... |