Commit 8f68c9cd843276e3385345e6650394d32163ce38
1 parent
30c6a6ab
Exists in
master
and in
26 other branches
Only testing
Showing
3 changed files
with
84 additions
and
4 deletions
Show diff stats
invesalius/data/converters.py
@@ -56,3 +56,25 @@ def to_vtk(n_array, spacing, slice_number, orientation): | @@ -56,3 +56,25 @@ def to_vtk(n_array, spacing, slice_number, orientation): | ||
56 | image_copy.DeepCopy(image) | 56 | image_copy.DeepCopy(image) |
57 | 57 | ||
58 | return image_copy | 58 | return image_copy |
59 | + | ||
60 | + | ||
61 | +def np_rgba_to_vtk(n_array, spacing=(1.0, 1.0, 1.0)): | ||
62 | + dy, dx, dc = n_array.shape | ||
63 | + v_image = numpy_support.numpy_to_vtk(n_array.reshape(dy*dx, dc)) | ||
64 | + | ||
65 | + extent = (0, dx -1, 0, dy -1, 0, 0) | ||
66 | + | ||
67 | + # Generating the vtkImageData | ||
68 | + image = vtk.vtkImageData() | ||
69 | + image.SetOrigin(0, 0, 0) | ||
70 | + image.SetSpacing(spacing) | ||
71 | + image.SetDimensions(dx, dy, 1) | ||
72 | + # SetNumberOfScalarComponents and SetScalrType were replaced by | ||
73 | + # AllocateScalars | ||
74 | + # image.SetNumberOfScalarComponents(1) | ||
75 | + # image.SetScalarType(numpy_support.get_vtk_array_type(n_array.dtype)) | ||
76 | + image.AllocateScalars(numpy_support.get_vtk_array_type(n_array.dtype), dc) | ||
77 | + image.SetExtent(extent) | ||
78 | + image.GetPointData().SetScalars(v_image) | ||
79 | + | ||
80 | + return image |
invesalius/data/slice_data.py
@@ -38,6 +38,7 @@ class SliceData(object): | @@ -38,6 +38,7 @@ class SliceData(object): | ||
38 | self.number = 0 | 38 | self.number = 0 |
39 | self.orientation = 'AXIAL' | 39 | self.orientation = 'AXIAL' |
40 | self.renderer = None | 40 | self.renderer = None |
41 | + self.canvas_renderer = None | ||
41 | self.overlay_renderer = None | 42 | self.overlay_renderer = None |
42 | self.__create_text() | 43 | self.__create_text() |
43 | self.__create_box() | 44 | self.__create_box() |
invesalius/data/viewer_slice.py
@@ -23,7 +23,7 @@ import collections | @@ -23,7 +23,7 @@ import collections | ||
23 | import itertools | 23 | import itertools |
24 | import tempfile | 24 | import tempfile |
25 | 25 | ||
26 | -import numpy | 26 | +import numpy as np |
27 | 27 | ||
28 | import vtk | 28 | import vtk |
29 | from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor | 29 | from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor |
@@ -46,6 +46,8 @@ import project | @@ -46,6 +46,8 @@ import project | ||
46 | import slice_data as sd | 46 | import slice_data as sd |
47 | import utils | 47 | import utils |
48 | 48 | ||
49 | +from data import converters | ||
50 | + | ||
49 | from data import measures | 51 | from data import measures |
50 | 52 | ||
51 | ID_TO_TOOL_ITEM = {} | 53 | ID_TO_TOOL_ITEM = {} |
@@ -144,6 +146,50 @@ class ContourMIPConfig(wx.Panel): | @@ -144,6 +146,50 @@ class ContourMIPConfig(wx.Panel): | ||
144 | self.txt_mip_border.Disable() | 146 | self.txt_mip_border.Disable() |
145 | 147 | ||
146 | 148 | ||
149 | +class CanvasRendererCTX: | ||
150 | + def __init__(self, viewer): | ||
151 | + self.viewer = viewer | ||
152 | + self.canvas_renderer = viewer.slice_data.canvas_renderer | ||
153 | + self._size = self.canvas_renderer.GetSize() | ||
154 | + self._init_canvas() | ||
155 | + viewer.slice_data.renderer.AddObserver("EndEvent", self.OnPaint) | ||
156 | + | ||
157 | + def _init_canvas(self): | ||
158 | + w, h = self._size | ||
159 | + self._array = np.empty((h, w, 4), dtype=np.uint8) | ||
160 | + | ||
161 | + self._cv_image = converters.np_rgba_to_vtk(self._array) | ||
162 | + | ||
163 | + self.mapper = vtk.vtkImageMapper() | ||
164 | + self.mapper.SetInputData(self._cv_image) | ||
165 | + self.mapper.SetColorWindow(255) | ||
166 | + self.mapper.SetColorLevel(128) | ||
167 | + | ||
168 | + self.actor = vtk.vtkActor2D() | ||
169 | + self.actor.SetPosition(0, 0) | ||
170 | + self.actor.SetMapper(self.mapper) | ||
171 | + self.actor.GetProperty().SetOpacity(0.99) | ||
172 | + | ||
173 | + self.canvas_renderer.AddActor2D(self.actor) | ||
174 | + | ||
175 | + def _resize_canvas(self, w, h): | ||
176 | + self._array = np.empty((h, w, 4), dtype=np.uint8) | ||
177 | + self._cv_image = converters.np_rgba_to_vtk(self._array) | ||
178 | + self.mapper.SetInputData(self._cv_image) | ||
179 | + self.mapper.Update() | ||
180 | + | ||
181 | + def OnPaint(self, evt, obj): | ||
182 | + size = self.canvas_renderer.GetSize() | ||
183 | + w, h = size | ||
184 | + if self._size != size: | ||
185 | + self._size = size | ||
186 | + self._resize_canvas(w, h) | ||
187 | + | ||
188 | + self._array[:] = 0 | ||
189 | + self._array[150:500, 150:500, 0] = 255 | ||
190 | + self._array[150:500, 150:500, 3] = 127 | ||
191 | + self._cv_image.Modified() | ||
192 | + | ||
147 | 193 | ||
148 | class Viewer(wx.Panel): | 194 | class Viewer(wx.Panel): |
149 | 195 | ||
@@ -896,6 +942,8 @@ class Viewer(wx.Panel): | @@ -896,6 +942,8 @@ class Viewer(wx.Panel): | ||
896 | self.cam = self.slice_data.renderer.GetActiveCamera() | 942 | self.cam = self.slice_data.renderer.GetActiveCamera() |
897 | self.__build_cross_lines() | 943 | self.__build_cross_lines() |
898 | 944 | ||
945 | + canvas = CanvasRendererCTX(self) | ||
946 | + | ||
899 | # Set the slice number to the last slice to ensure the camera if far | 947 | # Set the slice number to the last slice to ensure the camera if far |
900 | # enough to show all slices. | 948 | # enough to show all slices. |
901 | self.set_slice_number(max_slice_number - 1) | 949 | self.set_slice_number(max_slice_number - 1) |
@@ -958,13 +1006,20 @@ class Viewer(wx.Panel): | @@ -958,13 +1006,20 @@ class Viewer(wx.Panel): | ||
958 | renderer.SetLayer(0) | 1006 | renderer.SetLayer(0) |
959 | cam = renderer.GetActiveCamera() | 1007 | cam = renderer.GetActiveCamera() |
960 | 1008 | ||
1009 | + canvas_renderer = vtk.vtkRenderer() | ||
1010 | + canvas_renderer.SetLayer(1) | ||
1011 | + canvas_renderer.SetActiveCamera(cam) | ||
1012 | + canvas_renderer.SetInteractive(0) | ||
1013 | + canvas_renderer.PreserveDepthBufferOn() | ||
1014 | + | ||
961 | overlay_renderer = vtk.vtkRenderer() | 1015 | overlay_renderer = vtk.vtkRenderer() |
962 | - overlay_renderer.SetLayer(1) | 1016 | + overlay_renderer.SetLayer(2) |
963 | overlay_renderer.SetActiveCamera(cam) | 1017 | overlay_renderer.SetActiveCamera(cam) |
964 | overlay_renderer.SetInteractive(0) | 1018 | overlay_renderer.SetInteractive(0) |
965 | - | ||
966 | - self.interactor.GetRenderWindow().SetNumberOfLayers(2) | 1019 | + |
1020 | + self.interactor.GetRenderWindow().SetNumberOfLayers(3) | ||
967 | self.interactor.GetRenderWindow().AddRenderer(overlay_renderer) | 1021 | self.interactor.GetRenderWindow().AddRenderer(overlay_renderer) |
1022 | + self.interactor.GetRenderWindow().AddRenderer(canvas_renderer) | ||
968 | self.interactor.GetRenderWindow().AddRenderer(renderer) | 1023 | self.interactor.GetRenderWindow().AddRenderer(renderer) |
969 | 1024 | ||
970 | actor = vtk.vtkImageActor() | 1025 | actor = vtk.vtkImageActor() |
@@ -974,12 +1029,14 @@ class Viewer(wx.Panel): | @@ -974,12 +1029,14 @@ class Viewer(wx.Panel): | ||
974 | slice_data = sd.SliceData() | 1029 | slice_data = sd.SliceData() |
975 | slice_data.SetOrientation(self.orientation) | 1030 | slice_data.SetOrientation(self.orientation) |
976 | slice_data.renderer = renderer | 1031 | slice_data.renderer = renderer |
1032 | + slice_data.canvas_renderer = canvas_renderer | ||
977 | slice_data.overlay_renderer = overlay_renderer | 1033 | slice_data.overlay_renderer = overlay_renderer |
978 | slice_data.actor = actor | 1034 | slice_data.actor = actor |
979 | slice_data.SetBorderStyle(sd.BORDER_ALL) | 1035 | slice_data.SetBorderStyle(sd.BORDER_ALL) |
980 | renderer.AddActor(actor) | 1036 | renderer.AddActor(actor) |
981 | renderer.AddActor(slice_data.text.actor) | 1037 | renderer.AddActor(slice_data.text.actor) |
982 | renderer.AddViewProp(slice_data.box_actor) | 1038 | renderer.AddViewProp(slice_data.box_actor) |
1039 | + | ||
983 | return slice_data | 1040 | return slice_data |
984 | 1041 | ||
985 | def __update_camera(self): | 1042 | def __update_camera(self): |