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,6 +97,8 @@ class Slice(object):
97 self.rotations = [0, 0, 0] 97 self.rotations = [0, 0, 0]
98 self.center = [0, 0, 0] 98 self.center = [0, 0, 0]
99 99
  100 + self.q_orientation = np.array((1, 0, 0, 0))
  101 +
100 self.number_of_colours = 256 102 self.number_of_colours = 256
101 self.saturation_range = (0, 0) 103 self.saturation_range = (0, 0)
102 self.hue_range = (0, 0) 104 self.hue_range = (0, 0)
@@ -583,11 +585,12 @@ class Slice(object): @@ -583,11 +585,12 @@ class Slice(object):
583 rx, ry, rz = self.rotations 585 rx, ry, rz = self.rotations
584 sx, sy, sz = self.spacing 586 sx, sy, sz = self.spacing
585 T0 = transformations.translation_matrix((-cz, -cy, -cx)) 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 T1 = transformations.translation_matrix((cz, cy, cx)) 594 T1 = transformations.translation_matrix((cz, cy, cx))
592 M = transformations.concatenate_matrices(T1, R.T, T0) 595 M = transformations.concatenate_matrices(T1, R.T, T0)
593 596
invesalius/data/styles.py
@@ -43,6 +43,7 @@ from skimage import filter @@ -43,6 +43,7 @@ from skimage import filter
43 import watershed_process 43 import watershed_process
44 44
45 import utils 45 import utils
  46 +import transformations
46 47
47 ORIENTATIONS = { 48 ORIENTATIONS = {
48 "AXIAL": const.AXIAL, 49 "AXIAL": const.AXIAL,
@@ -1479,13 +1480,13 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): @@ -1479,13 +1480,13 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
1479 self.picker.Pick(x, y, 0, self.viewer.slice_data.renderer) 1480 self.picker.Pick(x, y, 0, self.viewer.slice_data.renderer)
1480 x, y, z = self.picker.GetPickPosition() 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 self.to_rot = True 1490 self.to_rot = True
1490 1491
1491 1492
@@ -1541,6 +1542,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): @@ -1541,6 +1542,7 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
1541 1542
1542 def OnDblClick(self, evt): 1543 def OnDblClick(self, evt):
1543 self.viewer.slice_.rotations = [0, 0, 0] 1544 self.viewer.slice_.rotations = [0, 0, 0]
  1545 + self.viewer.slice_.q_orientation = np.array((1, 0, 0, 0))
1544 self._discard_buffers() 1546 self._discard_buffers()
1545 self.viewer.slice_.current_mask.clear_history() 1547 self.viewer.slice_.current_mask.clear_history()
1546 Publisher.sendMessage('Reload actual slice') 1548 Publisher.sendMessage('Reload actual slice')
@@ -1582,20 +1584,49 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle): @@ -1582,20 +1584,49 @@ class ReorientImageInteractorStyle(DefaultInteractorStyle):
1582 elif self.viewer.orientation == 'SAGITAL': 1584 elif self.viewer.orientation == 'SAGITAL':
1583 p1 = np.array((z-cz, y-cy)) 1585 p1 = np.array((z-cz, y-cy))
1584 p0 = self.p0 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 if self.viewer.orientation == 'AXIAL': 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 self.viewer.slice_.rotations[2] = angle 1600 self.viewer.slice_.rotations[2] = angle
1589 elif self.viewer.orientation == 'CORONAL': 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 self.viewer.slice_.rotations[1] = angle 1603 self.viewer.slice_.rotations[1] = angle
1592 elif self.viewer.orientation == 'SAGITAL': 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 self.viewer.slice_.rotations[0] = angle 1606 self.viewer.slice_.rotations[0] = angle
1595 1607
1596 self._discard_buffers() 1608 self._discard_buffers()
1597 self.viewer.slice_.current_mask.clear_history() 1609 self.viewer.slice_.current_mask.clear_history()
1598 Publisher.sendMessage('Reload actual slice') 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 def _create_line(self, x0, y0, x1, y1, color): 1631 def _create_line(self, x0, y0, x1, y1, color):
1601 line = vtk.vtkLineSource() 1632 line = vtk.vtkLineSource()