Commit 6a01b805c62a713f7ca83cfd3a028680b9c0ca6b

Authored by Thiago Franco de Moraes
1 parent 64eec96a
Exists in rotvol

Rotating using quaternion

invesalius/data/slice_.py
... ... @@ -97,6 +97,8 @@ class Slice(object):
97 97 self.rotations = [0, 0, 0]
98 98 self.center = [0, 0, 0]
99 99  
  100 + self.q_orientation = np.array((1, 0, 0, 0))
  101 +
100 102 self.number_of_colours = 256
101 103 self.saturation_range = (0, 0)
102 104 self.hue_range = (0, 0)
... ... @@ -583,11 +585,12 @@ class Slice(object):
583 585 rx, ry, rz = self.rotations
584 586 sx, sy, sz = self.spacing
585 587 T0 = transformations.translation_matrix((-cz, -cy, -cx))
586   - Rx = transformations.rotation_matrix(rx, (0, 0, 1))
587   - Ry = transformations.rotation_matrix(ry, (0, 1, 0))
588   - Rz = transformations.rotation_matrix(rz, (1, 0, 0))
589   - # R = transformations.euler_matrix(rz, ry, rx, 'rzyx')
590   - R = transformations.concatenate_matrices(Rx, Ry, Rz)
  588 + # Rx = transformations.rotation_matrix(rx, (0, 0, 1))
  589 + # Ry = transformations.rotation_matrix(ry, (0, 1, 0))
  590 + # Rz = transformations.rotation_matrix(rz, (1, 0, 0))
  591 + # # R = transformations.euler_matrix(rz, ry, rx, 'rzyx')
  592 + # R = transformations.concatenate_matrices(Rx, Ry, Rz)
  593 + R = transformations.quaternion_matrix(self.q_orientation)
591 594 T1 = transformations.translation_matrix((cz, cy, cx))
592 595 M = transformations.concatenate_matrices(T1, R.T, T0)
593 596  
... ...
invesalius/data/styles.py
... ... @@ -43,6 +43,7 @@ from skimage import filter
43 43 import watershed_process
44 44  
45 45 import utils
  46 +import transformations
46 47  
47 48 ORIENTATIONS = {
48 49 "AXIAL": const.AXIAL,
... ... @@ -1479,13 +1480,13 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
1479 1480 self.picker.Pick(x, y, 0, self.viewer.slice_data.renderer)
1480 1481 x, y, z = self.picker.GetPickPosition()
1481 1482  
1482   - if self.viewer.orientation == 'AXIAL':
1483   - self.p0 = np.array((y-cy, x-cx))
1484   - elif self.viewer.orientation == 'CORONAL':
1485   - self.p0 = np.array((z-cz, x-cx))
1486   - elif self.viewer.orientation == 'SAGITAL':
1487   - self.p0 = np.array((z-cz, y-cy))
1488   -
  1483 + # if self.viewer.orientation == 'AXIAL':
  1484 + # self.p0 = np.array((y-cy, x-cx))
  1485 + # elif self.viewer.orientation == 'CORONAL':
  1486 + # self.p0 = np.array((z-cz, x-cx))
  1487 + # elif self.viewer.orientation == 'SAGITAL':
  1488 + # self.p0 = np.array((z-cz, y-cy))
  1489 + self.p0 = self.get_image_point_coord(x, y, z)
1489 1490 self.to_rot = True
1490 1491  
1491 1492  
... ... @@ -1541,6 +1542,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
1541 1542  
1542 1543 def OnDblClick(self, evt):
1543 1544 self.viewer.slice_.rotations = [0, 0, 0]
  1545 + self.viewer.slice_.q_orientation = np.array((1, 0, 0, 0))
1544 1546 self._discard_buffers()
1545 1547 self.viewer.slice_.current_mask.clear_history()
1546 1548 Publisher.sendMessage('Reload actual slice')
... ... @@ -1582,20 +1584,49 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
1582 1584 elif self.viewer.orientation == 'SAGITAL':
1583 1585 p1 = np.array((z-cz, y-cy))
1584 1586 p0 = self.p0
  1587 + p1 = self.get_image_point_coord(x, y, z)
  1588 +
  1589 + axis = np.cross(p0, p1)
  1590 + axis = axis / np.linalg.norm(axis)
  1591 + angle = np.arccos(np.dot(p0, p1)/(np.linalg.norm(p0)*np.linalg.norm(p1)))
  1592 +
  1593 + self.viewer.slice_.q_orientation = transformations.quaternion_multiply(self.viewer.slice_.q_orientation, transformations.quaternion_about_axis(angle, axis))
  1594 +
  1595 + # print axis, angle, self.viewer.slice_.q_orientation
  1596 + print axis, angle
1585 1597  
1586 1598 if self.viewer.orientation == 'AXIAL':
1587   - angle = np.arctan2(p0[0] , p0[1]) - np.arctan2(p1[0], p1[1])
  1599 + # angle = np.arctan2(p0[0] , p0[1]) - np.arctan2(p1[0], p1[1])
1588 1600 self.viewer.slice_.rotations[2] = angle
1589 1601 elif self.viewer.orientation == 'CORONAL':
1590   - angle = np.arctan2(p0[0] , p0[1]) - np.arctan2(p1[0], p1[1])
  1602 + # angle = np.arctan2(p0[0] , p0[1]) - np.arctan2(p1[0], p1[1])
1591 1603 self.viewer.slice_.rotations[1] = angle
1592 1604 elif self.viewer.orientation == 'SAGITAL':
1593   - angle = np.arctan2(p0[0] , p0[1]) - np.arctan2(p1[0], p1[1])
  1605 + # angle = np.arctan2(p0[0] , p0[1]) - np.arctan2(p1[0], p1[1])
1594 1606 self.viewer.slice_.rotations[0] = angle
1595 1607  
1596 1608 self._discard_buffers()
1597 1609 self.viewer.slice_.current_mask.clear_history()
1598 1610 Publisher.sendMessage('Reload actual slice')
  1611 + self.p0 = self.get_image_point_coord(x, y, z)
  1612 +
  1613 + def get_image_point_coord(self, x, y, z):
  1614 + cx, cy, cz = self.viewer.slice_.center
  1615 + if self.viewer.orientation == 'AXIAL':
  1616 + z = cz
  1617 + elif self.viewer.orientation == 'CORONAL':
  1618 + y = cy
  1619 + elif self.viewer.orientation == 'SAGITAL':
  1620 + x = cx
  1621 +
  1622 + x, y, z = x-cx, y-cy, z-cz
  1623 +
  1624 + M = transformations.quaternion_matrix(self.viewer.slice_.q_orientation)
  1625 + tcoord = np.array((z, y, x, 1)).dot(M)
  1626 + tcoord = tcoord[:3]/tcoord[3]
  1627 +
  1628 + # print (z, y, x), tcoord
  1629 + return tcoord
1599 1630  
1600 1631 def _create_line(self, x0, y0, x1, y1, color):
1601 1632 line = vtk.vtkLineSource()
... ...