Commit 6da76721b2f2ffe54fee27b149f838a8aa9bd185
Committed by
GitHub
1 parent
c79f0659
Exists in
master
and in
19 other branches
Created methods to get pixel and voxel position given the x,y screen position (#51)
Showing
3 changed files
with
126 additions
and
229 deletions
Show diff stats
invesalius/data/slice_.py
@@ -434,7 +434,7 @@ class Slice(object): | @@ -434,7 +434,7 @@ class Slice(object): | ||
434 | thresh_min, thresh_max = self.current_mask.edition_threshold_range | 434 | thresh_min, thresh_max = self.current_mask.edition_threshold_range |
435 | 435 | ||
436 | if hasattr(position, '__iter__'): | 436 | if hasattr(position, '__iter__'): |
437 | - py, px = position | 437 | + px, py = position |
438 | if orientation == 'AXIAL': | 438 | if orientation == 'AXIAL': |
439 | sx = self.spacing[0] | 439 | sx = self.spacing[0] |
440 | sy = self.spacing[1] | 440 | sy = self.spacing[1] |
invesalius/data/styles.py
@@ -76,6 +76,7 @@ def get_LUT_value(data, window, level): | @@ -76,6 +76,7 @@ def get_LUT_value(data, window, level): | ||
76 | data.shape = shape | 76 | data.shape = shape |
77 | return data | 77 | return data |
78 | 78 | ||
79 | + | ||
79 | class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage): | 80 | class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage): |
80 | def __init__(self, viewer): | 81 | def __init__(self, viewer): |
81 | self.right_pressed = False | 82 | self.right_pressed = False |
@@ -213,52 +214,18 @@ class CrossInteractorStyle(DefaultInteractorStyle): | @@ -213,52 +214,18 @@ class CrossInteractorStyle(DefaultInteractorStyle): | ||
213 | 214 | ||
214 | def ChangeCrossPosition(self, iren): | 215 | def ChangeCrossPosition(self, iren): |
215 | mouse_x, mouse_y = iren.GetEventPosition() | 216 | mouse_x, mouse_y = iren.GetEventPosition() |
216 | - ren = iren.GetRenderWindow().GetRenderers().GetFirstRenderer() | ||
217 | - self.picker.Pick(mouse_x, mouse_y, 0, ren) | ||
218 | - | ||
219 | - # Get in what slice data the click occurred | ||
220 | - # pick to get click position in the 3d world | ||
221 | - coord_cross = self.get_coordinate_cursor() | ||
222 | - position = self.slice_actor.GetInput().FindPoint(coord_cross) | ||
223 | - # Forcing focal point to be setted in the center of the pixel. | ||
224 | - coord_cross = self.slice_actor.GetInput().GetPoint(position) | ||
225 | - | ||
226 | - coord = self.calcultate_scroll_position(position) | ||
227 | - Publisher.sendMessage('Update cross position', coord_cross) | 217 | + wx, wy, wz = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) |
218 | + px, py = self.viewer.get_slice_pixel_coord_by_world_pos(wx, wy, wz) | ||
219 | + coord = self.viewer.calcultate_scroll_position(px, py) | ||
220 | + Publisher.sendMessage('Update cross position', (wx, wy, wz)) | ||
228 | self.ScrollSlice(coord) | 221 | self.ScrollSlice(coord) |
229 | Publisher.sendMessage('Set ball reference position based on bound', | 222 | Publisher.sendMessage('Set ball reference position based on bound', |
230 | - coord_cross) | ||
231 | - Publisher.sendMessage('Set camera in volume', coord_cross) | 223 | + (wx, wy, wz)) |
224 | + Publisher.sendMessage('Set camera in volume', (wx, wy, wz)) | ||
232 | Publisher.sendMessage('Render volume viewer') | 225 | Publisher.sendMessage('Render volume viewer') |
233 | 226 | ||
234 | iren.Render() | 227 | iren.Render() |
235 | 228 | ||
236 | - | ||
237 | - def calcultate_scroll_position(self, position): | ||
238 | - # Based in the given coord (x, y, z), returns a list with the scroll positions for each | ||
239 | - # orientation, being the first position the sagital, second the coronal | ||
240 | - # and the last, axial. | ||
241 | - | ||
242 | - if self.orientation == 'AXIAL': | ||
243 | - image_width = self.slice_actor.GetInput().GetDimensions()[0] | ||
244 | - axial = self.slice_data.number | ||
245 | - coronal = position / image_width | ||
246 | - sagital = position % image_width | ||
247 | - | ||
248 | - elif self.orientation == 'CORONAL': | ||
249 | - image_width = self.slice_actor.GetInput().GetDimensions()[0] | ||
250 | - axial = position / image_width | ||
251 | - coronal = self.slice_data.number | ||
252 | - sagital = position % image_width | ||
253 | - | ||
254 | - elif self.orientation == 'SAGITAL': | ||
255 | - image_width = self.slice_actor.GetInput().GetDimensions()[1] | ||
256 | - axial = position / image_width | ||
257 | - coronal = position % image_width | ||
258 | - sagital = self.slice_data.number | ||
259 | - | ||
260 | - return sagital, coronal, axial | ||
261 | - | ||
262 | def ScrollSlice(self, coord): | 229 | def ScrollSlice(self, coord): |
263 | if self.orientation == "AXIAL": | 230 | if self.orientation == "AXIAL": |
264 | Publisher.sendMessage(('Set scroll position', 'SAGITAL'), | 231 | Publisher.sendMessage(('Set scroll position', 'SAGITAL'), |
@@ -276,18 +243,6 @@ class CrossInteractorStyle(DefaultInteractorStyle): | @@ -276,18 +243,6 @@ class CrossInteractorStyle(DefaultInteractorStyle): | ||
276 | Publisher.sendMessage(('Set scroll position', 'SAGITAL'), | 243 | Publisher.sendMessage(('Set scroll position', 'SAGITAL'), |
277 | coord[0]) | 244 | coord[0]) |
278 | 245 | ||
279 | - def get_coordinate_cursor(self): | ||
280 | - # Find position | ||
281 | - x, y, z = self.picker.GetPickPosition() | ||
282 | - bounds = self.viewer.slice_data.actor.GetBounds() | ||
283 | - if bounds[0] == bounds[1]: | ||
284 | - x = bounds[0] | ||
285 | - elif bounds[2] == bounds[3]: | ||
286 | - y = bounds[2] | ||
287 | - elif bounds[4] == bounds[5]: | ||
288 | - z = bounds[4] | ||
289 | - return x, y, z | ||
290 | - | ||
291 | 246 | ||
292 | class WWWLInteractorStyle(DefaultInteractorStyle): | 247 | class WWWLInteractorStyle(DefaultInteractorStyle): |
293 | """ | 248 | """ |
@@ -791,21 +746,13 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -791,21 +746,13 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
791 | #i.cursor.Show(0) | 746 | #i.cursor.Show(0) |
792 | slice_data.cursor.Show() | 747 | slice_data.cursor.Show() |
793 | 748 | ||
794 | - self.picker.Pick(mouse_x, mouse_y, 0, render) | ||
795 | - | ||
796 | - coord = self.get_coordinate_cursor() | ||
797 | - position = slice_data.actor.GetInput().FindPoint(coord) | 749 | + wx, wy, wz = viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) |
750 | + position = viewer.get_slice_pixel_coord_by_world_pos(wx, wy, wz) | ||
798 | 751 | ||
799 | - if position != -1: | ||
800 | - coord = slice_data.actor.GetInput().GetPoint(position) | ||
801 | - | ||
802 | - slice_data.cursor.SetPosition(coord) | ||
803 | cursor = slice_data.cursor | 752 | cursor = slice_data.cursor |
804 | radius = cursor.radius | 753 | radius = cursor.radius |
805 | 754 | ||
806 | - if position < 0: | ||
807 | - position = viewer.calculate_matrix_position(coord) | ||
808 | - | 755 | + slice_data.cursor.SetPosition((wx, wy, wz)) |
809 | viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), | 756 | viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), |
810 | position, radius, viewer.orientation) | 757 | position, radius, viewer.orientation) |
811 | #viewer._flush_buffer = True | 758 | #viewer._flush_buffer = True |
@@ -842,39 +789,19 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -842,39 +789,19 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
842 | elif operation == const.BRUSH_DRAW and iren.GetControlKey(): | 789 | elif operation == const.BRUSH_DRAW and iren.GetControlKey(): |
843 | operation = const.BRUSH_ERASE | 790 | operation = const.BRUSH_ERASE |
844 | 791 | ||
845 | - # TODO: Improve! | ||
846 | - #for i in self.slice_data_list: | ||
847 | - #i.cursor.Show(0) | ||
848 | - | ||
849 | - self.picker.Pick(mouse_x, mouse_y, 0, render) | ||
850 | - | ||
851 | - #if (self.pick.GetViewProp()): | ||
852 | - #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) | ||
853 | - #else: | ||
854 | - #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||
855 | - | ||
856 | - coord = self.get_coordinate_cursor() | ||
857 | - position = viewer.slice_data.actor.GetInput().FindPoint(coord) | ||
858 | - | ||
859 | - # when position == -1 the cursos is not over the image, so is not | ||
860 | - # necessary to set the cursor position to world coordinate center of | ||
861 | - # pixel from slice image. | ||
862 | - if position != -1: | ||
863 | - coord = slice_data.actor.GetInput().GetPoint(position) | ||
864 | - slice_data.cursor.SetPosition(coord) | ||
865 | - #self.__update_cursor_position(slice_data, coord) | 792 | + wx, wy, wz = viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) |
793 | + slice_data.cursor.SetPosition((wx, wy, wz)) | ||
866 | 794 | ||
867 | if (self.left_pressed): | 795 | if (self.left_pressed): |
868 | cursor = slice_data.cursor | 796 | cursor = slice_data.cursor |
869 | - position = slice_data.actor.GetInput().FindPoint(coord) | ||
870 | radius = cursor.radius | 797 | radius = cursor.radius |
871 | 798 | ||
872 | - if position < 0: | ||
873 | - position = viewer.calculate_matrix_position(coord) | 799 | + position = viewer.get_slice_pixel_coord_by_world_pos(wx, wy, wz) |
874 | 800 | ||
801 | + slice_data.cursor.SetPosition((wx, wy, wz)) | ||
875 | viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), | 802 | viewer.slice_.edit_mask_pixel(operation, cursor.GetPixels(), |
876 | - position, radius, self.orientation) | ||
877 | - # TODO: To create a new function to reload images to viewer. | 803 | + position, radius, viewer.orientation) |
804 | + | ||
878 | viewer.OnScrollBar(update3D=False) | 805 | viewer.OnScrollBar(update3D=False) |
879 | 806 | ||
880 | else: | 807 | else: |
@@ -924,18 +851,6 @@ class EditorInteractorStyle(DefaultInteractorStyle): | @@ -924,18 +851,6 @@ class EditorInteractorStyle(DefaultInteractorStyle): | ||
924 | else: | 851 | else: |
925 | self.OnScrollBackward(obj, evt) | 852 | self.OnScrollBackward(obj, evt) |
926 | 853 | ||
927 | - def get_coordinate_cursor(self): | ||
928 | - # Find position | ||
929 | - x, y, z = self.picker.GetPickPosition() | ||
930 | - bounds = self.viewer.slice_data.actor.GetBounds() | ||
931 | - if bounds[0] == bounds[1]: | ||
932 | - x = bounds[0] | ||
933 | - elif bounds[2] == bounds[3]: | ||
934 | - y = bounds[2] | ||
935 | - elif bounds[4] == bounds[5]: | ||
936 | - z = bounds[4] | ||
937 | - return x, y, z | ||
938 | - | ||
939 | 854 | ||
940 | class WatershedProgressWindow(object): | 855 | class WatershedProgressWindow(object): |
941 | def __init__(self, process): | 856 | def __init__(self, process): |
@@ -1153,28 +1068,15 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1153,28 +1068,15 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
1153 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 1068 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
1154 | slice_data = viewer.get_slice_data(render) | 1069 | slice_data = viewer.get_slice_data(render) |
1155 | 1070 | ||
1156 | - # TODO: Improve! | ||
1157 | - #for i in self.slice_data_list: | ||
1158 | - #i.cursor.Show(0) | ||
1159 | - slice_data.cursor.Show() | ||
1160 | - | ||
1161 | - self.picker.Pick(mouse_x, mouse_y, 0, render) | ||
1162 | - | ||
1163 | - coord = self.get_coordinate_cursor() | ||
1164 | - position = slice_data.actor.GetInput().FindPoint(coord) | ||
1165 | - | ||
1166 | - if position != -1: | ||
1167 | - coord = slice_data.actor.GetInput().GetPoint(position) | 1071 | + coord = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, picker=None) |
1072 | + position = self.viewer.get_slice_pixel_coord_by_screen_pos(mouse_x, mouse_y, self.picker) | ||
1168 | 1073 | ||
1074 | + slice_data.cursor.Show() | ||
1169 | slice_data.cursor.SetPosition(coord) | 1075 | slice_data.cursor.SetPosition(coord) |
1170 | 1076 | ||
1171 | cursor = slice_data.cursor | 1077 | cursor = slice_data.cursor |
1172 | - position = slice_data.actor.GetInput().FindPoint(coord) | ||
1173 | radius = cursor.radius | 1078 | radius = cursor.radius |
1174 | 1079 | ||
1175 | - if position < 0: | ||
1176 | - position = viewer.calculate_matrix_position(coord) | ||
1177 | - | ||
1178 | operation = self.config.operation | 1080 | operation = self.config.operation |
1179 | 1081 | ||
1180 | if operation == BRUSH_FOREGROUND: | 1082 | if operation == BRUSH_FOREGROUND: |
@@ -1213,31 +1115,13 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1213,31 +1115,13 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
1213 | render = iren.FindPokedRenderer(mouse_x, mouse_y) | 1115 | render = iren.FindPokedRenderer(mouse_x, mouse_y) |
1214 | slice_data = viewer.get_slice_data(render) | 1116 | slice_data = viewer.get_slice_data(render) |
1215 | 1117 | ||
1216 | - # TODO: Improve! | ||
1217 | - #for i in self.slice_data_list: | ||
1218 | - #i.cursor.Show(0) | ||
1219 | - | ||
1220 | - self.picker.Pick(mouse_x, mouse_y, 0, render) | ||
1221 | - | ||
1222 | - #if (self.pick.GetViewProp()): | ||
1223 | - #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_BLANK)) | ||
1224 | - #else: | ||
1225 | - #self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||
1226 | - | ||
1227 | - coord = self.get_coordinate_cursor() | ||
1228 | - position = viewer.slice_data.actor.GetInput().FindPoint(coord) | ||
1229 | - | ||
1230 | - # when position == -1 the cursos is not over the image, so is not | ||
1231 | - # necessary to set the cursor position to world coordinate center of | ||
1232 | - # pixel from slice image. | ||
1233 | - if position != -1: | ||
1234 | - coord = slice_data.actor.GetInput().GetPoint(position) | 1118 | + coord = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) |
1235 | slice_data.cursor.SetPosition(coord) | 1119 | slice_data.cursor.SetPosition(coord) |
1236 | - #self.__update_cursor_position(slice_data, coord) | ||
1237 | 1120 | ||
1238 | if (self.left_pressed): | 1121 | if (self.left_pressed): |
1239 | cursor = slice_data.cursor | 1122 | cursor = slice_data.cursor |
1240 | - position = slice_data.actor.GetInput().FindPoint(coord) | 1123 | + position = self.viewer.get_slice_pixel_coord_by_world_pos(*coord) |
1124 | + print ">>>", position | ||
1241 | radius = cursor.radius | 1125 | radius = cursor.radius |
1242 | 1126 | ||
1243 | if position < 0: | 1127 | if position < 0: |
@@ -1344,18 +1228,6 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1344,18 +1228,6 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
1344 | 1228 | ||
1345 | Publisher.sendMessage('Reload actual slice') | 1229 | Publisher.sendMessage('Reload actual slice') |
1346 | 1230 | ||
1347 | - def get_coordinate_cursor(self): | ||
1348 | - # Find position | ||
1349 | - x, y, z = self.picker.GetPickPosition() | ||
1350 | - bounds = self.viewer.slice_data.actor.GetBounds() | ||
1351 | - if bounds[0] == bounds[1]: | ||
1352 | - x = bounds[0] | ||
1353 | - elif bounds[2] == bounds[3]: | ||
1354 | - y = bounds[2] | ||
1355 | - elif bounds[4] == bounds[5]: | ||
1356 | - z = bounds[4] | ||
1357 | - return x, y, z | ||
1358 | - | ||
1359 | def edit_mask_pixel(self, operation, n, index, position, radius, orientation): | 1231 | def edit_mask_pixel(self, operation, n, index, position, radius, orientation): |
1360 | if orientation == 'AXIAL': | 1232 | if orientation == 'AXIAL': |
1361 | mask = self.matrix[n, :, :] | 1233 | mask = self.matrix[n, :, :] |
@@ -1366,7 +1238,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | @@ -1366,7 +1238,7 @@ class WaterShedInteractorStyle(DefaultInteractorStyle): | ||
1366 | 1238 | ||
1367 | spacing = self.viewer.slice_.spacing | 1239 | spacing = self.viewer.slice_.spacing |
1368 | if hasattr(position, '__iter__'): | 1240 | if hasattr(position, '__iter__'): |
1369 | - py, px = position | 1241 | + px, py = position |
1370 | if orientation == 'AXIAL': | 1242 | if orientation == 'AXIAL': |
1371 | sx = spacing[0] | 1243 | sx = spacing[0] |
1372 | sy = spacing[1] | 1244 | sy = spacing[1] |
@@ -1804,24 +1676,10 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): | @@ -1804,24 +1676,10 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): | ||
1804 | 1676 | ||
1805 | viewer = self.viewer | 1677 | viewer = self.viewer |
1806 | iren = viewer.interactor | 1678 | iren = viewer.interactor |
1807 | - | ||
1808 | mouse_x, mouse_y = iren.GetEventPosition() | 1679 | mouse_x, mouse_y = iren.GetEventPosition() |
1809 | - render = iren.FindPokedRenderer(mouse_x, mouse_y) | ||
1810 | - slice_data = viewer.get_slice_data(render) | ||
1811 | - | ||
1812 | - self.picker.Pick(mouse_x, mouse_y, 0, render) | ||
1813 | - | ||
1814 | - coord = self.get_coordinate_cursor() | ||
1815 | - position = slice_data.actor.GetInput().FindPoint(coord) | ||
1816 | - | ||
1817 | - if position != -1: | ||
1818 | - coord = slice_data.actor.GetInput().GetPoint(position) | ||
1819 | - | ||
1820 | - if position < 0: | ||
1821 | - position = viewer.calculate_matrix_position(coord) | 1680 | + x, y, z = self.viewer.get_voxel_coord_by_screen_pos(mouse_x, mouse_y, self.picker) |
1822 | 1681 | ||
1823 | mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:] | 1682 | mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:] |
1824 | - x, y, z = self.calcultate_scroll_position(position) | ||
1825 | if mask[z, y, x] < self.t0 or mask[z, y, x] > self.t1: | 1683 | if mask[z, y, x] < self.t0 or mask[z, y, x] > self.t1: |
1826 | return | 1684 | return |
1827 | 1685 | ||
@@ -1878,43 +1736,6 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): | @@ -1878,43 +1736,6 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): | ||
1878 | self.viewer.slice_.current_mask.was_edited = True | 1736 | self.viewer.slice_.current_mask.was_edited = True |
1879 | Publisher.sendMessage('Reload actual slice') | 1737 | Publisher.sendMessage('Reload actual slice') |
1880 | 1738 | ||
1881 | - def get_coordinate_cursor(self): | ||
1882 | - # Find position | ||
1883 | - x, y, z = self.picker.GetPickPosition() | ||
1884 | - bounds = self.viewer.slice_data.actor.GetBounds() | ||
1885 | - if bounds[0] == bounds[1]: | ||
1886 | - x = bounds[0] | ||
1887 | - elif bounds[2] == bounds[3]: | ||
1888 | - y = bounds[2] | ||
1889 | - elif bounds[4] == bounds[5]: | ||
1890 | - z = bounds[4] | ||
1891 | - return x, y, z | ||
1892 | - | ||
1893 | - def calcultate_scroll_position(self, position): | ||
1894 | - # Based in the given coord (x, y, z), returns a list with the scroll positions for each | ||
1895 | - # orientation, being the first position the sagital, second the coronal | ||
1896 | - # and the last, axial. | ||
1897 | - | ||
1898 | - if self.orientation == 'AXIAL': | ||
1899 | - image_width = self.slice_actor.GetInput().GetDimensions()[0] | ||
1900 | - axial = self.slice_data.number | ||
1901 | - coronal = position / image_width | ||
1902 | - sagital = position % image_width | ||
1903 | - | ||
1904 | - elif self.orientation == 'CORONAL': | ||
1905 | - image_width = self.slice_actor.GetInput().GetDimensions()[0] | ||
1906 | - axial = position / image_width | ||
1907 | - coronal = self.slice_data.number | ||
1908 | - sagital = position % image_width | ||
1909 | - | ||
1910 | - elif self.orientation == 'SAGITAL': | ||
1911 | - image_width = self.slice_actor.GetInput().GetDimensions()[1] | ||
1912 | - axial = position / image_width | ||
1913 | - coronal = position % image_width | ||
1914 | - sagital = self.slice_data.number | ||
1915 | - | ||
1916 | - return sagital, coronal, axial | ||
1917 | - | ||
1918 | 1739 | ||
1919 | class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle): | 1740 | class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle): |
1920 | def __init__(self, viewer): | 1741 | def __init__(self, viewer): |
@@ -1989,7 +1810,7 @@ class SelectMaskPartsInteractorStyle(DefaultInteractorStyle): | @@ -1989,7 +1810,7 @@ class SelectMaskPartsInteractorStyle(DefaultInteractorStyle): | ||
1989 | 1810 | ||
1990 | iren = self.viewer.interactor | 1811 | iren = self.viewer.interactor |
1991 | mouse_x, mouse_y = iren.GetEventPosition() | 1812 | mouse_x, mouse_y = iren.GetEventPosition() |
1992 | - x, y, z = self.viewer.get_voxel_clicked(mouse_x, mouse_y, self.picker) | 1813 | + x, y, z = self.viewer.get_voxel_coord_by_screen_pos(mouse_x, mouse_y, self.picker) |
1993 | 1814 | ||
1994 | mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:] | 1815 | mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:] |
1995 | 1816 |
invesalius/data/viewer_slice.py
@@ -940,25 +940,23 @@ class Viewer(wx.Panel): | @@ -940,25 +940,23 @@ class Viewer(wx.Panel): | ||
940 | # WARN: Return the only slice_data used in this slice_viewer. | 940 | # WARN: Return the only slice_data used in this slice_viewer. |
941 | return self.slice_data | 941 | return self.slice_data |
942 | 942 | ||
943 | - def calcultate_scroll_position(self, position): | ||
944 | - # Based in the given coord (x, y, z), returns a list with the scroll positions for each | 943 | + def calcultate_scroll_position(self, x, y): |
944 | + # Based in the given coord (x, y), returns a list with the scroll positions for each | ||
945 | # orientation, being the first position the sagital, second the coronal | 945 | # orientation, being the first position the sagital, second the coronal |
946 | # and the last, axial. | 946 | # and the last, axial. |
947 | - image_width = self.slice_.buffer_slices[self.orientation].image.shape[1] | ||
948 | - | ||
949 | if self.orientation == 'AXIAL': | 947 | if self.orientation == 'AXIAL': |
950 | axial = self.slice_data.number | 948 | axial = self.slice_data.number |
951 | - coronal = position / image_width | ||
952 | - sagital = position % image_width | 949 | + coronal = y |
950 | + sagital = x | ||
953 | 951 | ||
954 | elif self.orientation == 'CORONAL': | 952 | elif self.orientation == 'CORONAL': |
955 | - axial = position / image_width | 953 | + axial = y |
956 | coronal = self.slice_data.number | 954 | coronal = self.slice_data.number |
957 | - sagital = position % image_width | 955 | + sagital = x |
958 | 956 | ||
959 | elif self.orientation == 'SAGITAL': | 957 | elif self.orientation == 'SAGITAL': |
960 | - axial = position / image_width | ||
961 | - coronal = position % image_width | 958 | + axial = y |
959 | + coronal = x | ||
962 | sagital = self.slice_data.number | 960 | sagital = self.slice_data.number |
963 | 961 | ||
964 | return sagital, coronal, axial | 962 | return sagital, coronal, axial |
@@ -975,13 +973,28 @@ class Viewer(wx.Panel): | @@ -975,13 +973,28 @@ class Viewer(wx.Panel): | ||
975 | elif self.orientation == 'SAGITAL': | 973 | elif self.orientation == 'SAGITAL': |
976 | mx = round((y - yi)/self.slice_.spacing[1], 0) | 974 | mx = round((y - yi)/self.slice_.spacing[1], 0) |
977 | my = round((z - zi)/self.slice_.spacing[2], 0) | 975 | my = round((z - zi)/self.slice_.spacing[2], 0) |
978 | - return my, mx | 976 | + return mx, my |
979 | 977 | ||
980 | - def get_coordinate_cursor(self, picker=None): | ||
981 | - # Find position | 978 | + def get_coordinate_cursor(self, mx, my, picker=None): |
979 | + """ | ||
980 | + Given the mx, my screen position returns the x, y, z position in world | ||
981 | + coordinates. | ||
982 | + | ||
983 | + Parameters | ||
984 | + mx (int): x position. | ||
985 | + my (int): y position | ||
986 | + picker: the picker used to get calculate the voxel coordinate. | ||
987 | + | ||
988 | + Returns: | ||
989 | + world coordinate (x, y, z) | ||
990 | + """ | ||
982 | if picker is None: | 991 | if picker is None: |
983 | picker = self.pick | 992 | picker = self.pick |
984 | 993 | ||
994 | + slice_data = self.slice_data | ||
995 | + renderer = slice_data.renderer | ||
996 | + | ||
997 | + picker.Pick(mx, my, 0, renderer) | ||
985 | x, y, z = picker.GetPickPosition() | 998 | x, y, z = picker.GetPickPosition() |
986 | bounds = self.slice_data.actor.GetBounds() | 999 | bounds = self.slice_data.actor.GetBounds() |
987 | if bounds[0] == bounds[1]: | 1000 | if bounds[0] == bounds[1]: |
@@ -1029,10 +1042,10 @@ class Viewer(wx.Panel): | @@ -1029,10 +1042,10 @@ class Viewer(wx.Panel): | ||
1029 | 1042 | ||
1030 | return x, y, z | 1043 | return x, y, z |
1031 | 1044 | ||
1032 | - def get_voxel_clicked(self, mx, my, picker=None): | 1045 | + def get_voxel_coord_by_screen_pos(self, mx, my, picker=None): |
1033 | """ | 1046 | """ |
1034 | - Given the (mx, my) mouse clicked position returns the voxel coordinate | ||
1035 | - of the voxel at (that mx, my) position. | 1047 | + Given the (mx, my) screen position returns the voxel coordinate |
1048 | + of the volume at (that mx, my) position. | ||
1036 | 1049 | ||
1037 | Parameters: | 1050 | Parameters: |
1038 | mx (int): x position. | 1051 | mx (int): x position. |
@@ -1046,23 +1059,86 @@ class Viewer(wx.Panel): | @@ -1046,23 +1059,86 @@ class Viewer(wx.Panel): | ||
1046 | if picker is None: | 1059 | if picker is None: |
1047 | picker = self.pick | 1060 | picker = self.pick |
1048 | 1061 | ||
1062 | + wx, wy, wz = self.get_coordinate_cursor(mx, my, picker) | ||
1063 | + x, y, z = self.get_voxel_coord_by_world_pos(wx, wy, wz) | ||
1064 | + | ||
1065 | + return (x, y, z) | ||
1066 | + | ||
1067 | + def get_voxel_coord_by_world_pos(self, wx, wy, wz): | ||
1068 | + """ | ||
1069 | + Given the (x, my) screen position returns the voxel coordinate | ||
1070 | + of the volume at (that mx, my) position. | ||
1071 | + | ||
1072 | + Parameters: | ||
1073 | + wx (float): x position. | ||
1074 | + wy (float): y position | ||
1075 | + wz (float): z position | ||
1076 | + | ||
1077 | + Returns: | ||
1078 | + voxel_coordinate (x, y, z): voxel coordinate inside the matrix. Can | ||
1079 | + be used to access the voxel value inside the matrix. | ||
1080 | + """ | ||
1081 | + px, py = self.get_slice_pixel_coord_by_world_pos(wx, wy, wz) | ||
1082 | + x, y, z = self.calcultate_scroll_position(px, py) | ||
1083 | + | ||
1084 | + return (x, y, z) | ||
1085 | + | ||
1086 | + | ||
1087 | + def get_slice_pixel_coord_by_screen_pos(self, mx, my, picker=None): | ||
1088 | + """ | ||
1089 | + Given the (mx, my) screen position returns the pixel coordinate | ||
1090 | + of the slice at (that mx, my) position. | ||
1091 | + | ||
1092 | + Parameters: | ||
1093 | + mx (int): x position. | ||
1094 | + my (int): y position | ||
1095 | + picker: the picker used to get calculate the pixel coordinate. | ||
1096 | + | ||
1097 | + Returns: | ||
1098 | + voxel_coordinate (x, y): voxel coordinate inside the matrix. Can | ||
1099 | + be used to access the voxel value inside the matrix. | ||
1100 | + """ | ||
1101 | + if picker is None: | ||
1102 | + picker = self.pick | ||
1103 | + | ||
1104 | + wx, wy, wz = self.get_coordinate_cursor(mx, my, picker) | ||
1105 | + return self.get_slice_pixel_coord_by_world_pos(wx, wy, wz) | ||
1106 | + | ||
1107 | + return px, py | ||
1108 | + | ||
1109 | + def get_slice_pixel_coord_by_world_pos(self, wx, wy, wz): | ||
1110 | + """ | ||
1111 | + Given the (wx, wy, wz) world position returns the pixel coordinate | ||
1112 | + of the slice at (that mx, my) position. | ||
1113 | + | ||
1114 | + Parameters: | ||
1115 | + mx (int): x position. | ||
1116 | + my (int): y position | ||
1117 | + picker: the picker used to get calculate the pixel coordinate. | ||
1118 | + | ||
1119 | + Returns: | ||
1120 | + voxel_coordinate (x, y): voxel coordinate inside the matrix. Can | ||
1121 | + be used to access the voxel value inside the matrix. | ||
1122 | + """ | ||
1123 | + coord = wx, wy, wz | ||
1124 | + px, py = self.calculate_matrix_position(coord) | ||
1125 | + | ||
1126 | + return px, py | ||
1127 | + | ||
1128 | + def get_coord_inside_volume(self, mx, my, picker=None): | ||
1129 | + if picker is None: | ||
1130 | + picker = self.pick | ||
1131 | + | ||
1049 | slice_data = self.slice_data | 1132 | slice_data = self.slice_data |
1050 | renderer = slice_data.renderer | 1133 | renderer = slice_data.renderer |
1051 | 1134 | ||
1052 | - picker.Pick(mx, my, 0, renderer) | ||
1053 | - | ||
1054 | coord = self.get_coordinate_cursor(picker) | 1135 | coord = self.get_coordinate_cursor(picker) |
1055 | position = slice_data.actor.GetInput().FindPoint(coord) | 1136 | position = slice_data.actor.GetInput().FindPoint(coord) |
1056 | 1137 | ||
1057 | if position != -1: | 1138 | if position != -1: |
1058 | coord = slice_data.actor.GetInput().GetPoint(position) | 1139 | coord = slice_data.actor.GetInput().GetPoint(position) |
1059 | 1140 | ||
1060 | - if position < 0: | ||
1061 | - position = viewer.calculate_matrix_position(coord) | ||
1062 | - | ||
1063 | - x, y, z = self.calcultate_scroll_position(position) | ||
1064 | - | ||
1065 | - return (x, y, z) | 1141 | + return coord |
1066 | 1142 | ||
1067 | def __bind_events(self): | 1143 | def __bind_events(self): |
1068 | Publisher.subscribe(self.LoadImagedata, | 1144 | Publisher.subscribe(self.LoadImagedata, |