Commit a2350755deb300f540a1088388803108d1b714f1

Authored by tfmoraes
1 parent dd2cd7d0

Improved cursor_actors, better handlings and more accurate

invesalius/data/cursor_actors.py
... ... @@ -17,127 +17,174 @@
17 17 # detalhes.
18 18 #--------------------------------------------------------------------------
19 19  
20   -from math import *
  20 +import math
21 21  
22 22 import numpy
23 23 import vtk
24   -import wx.lib.pubsub as ps
  24 +import imagedata_utils
25 25 from project import Project
26 26 import constants as const
27   -import utils
28 27  
29   -class CursorCircle:
30   - # TODO: Think and try to change this class to an actor
31   - # CursorCircleActor(vtk.vtkActor)
  28 +from vtk.util import numpy_support
  29 +
  30 +ORIENTATION = {'AXIAL': 2,
  31 + 'CORONAL': 1,
  32 + 'SAGITAL': 0}
  33 +
  34 +def to_vtk(n_array, spacing, slice_number, orientation):
  35 + """
  36 + It transforms a numpy array into a vtkImageData.
  37 + """
  38 + # TODO Merge this function with imagedata_utils.to_vtk to eliminate
  39 + # duplicated code
  40 + try:
  41 + dz, dy, dx = n_array.shape
  42 + except ValueError:
  43 + dy, dx = n_array.shape
  44 + dz = 1
  45 +
  46 + v_image = numpy_support.numpy_to_vtk(n_array.flat)
  47 +
  48 + if orientation == 'AXIAL':
  49 + extent = (0, dx -1, 0, dy -1, slice_number, slice_number + dz - 1)
  50 + elif orientation == 'SAGITAL':
  51 + extent = (slice_number, slice_number + dx - 1, 0, dy - 1, 0, dz - 1)
  52 + elif orientation == 'CORONAL':
  53 + extent = (0, dx - 1, slice_number, slice_number + dy - 1, 0, dz - 1)
  54 +
  55 + image = vtk.vtkImageData()
  56 + image.SetOrigin(0, 0, 0)
  57 + image.SetSpacing(spacing)
  58 + image.SetNumberOfScalarComponents(1)
  59 + image.SetDimensions(dx, dy, dz)
  60 + image.SetExtent(extent)
  61 + image.SetScalarType(numpy_support.get_vtk_array_type(n_array.dtype))
  62 + image.AllocateScalars()
  63 + image.Update()
  64 + image.GetCellData().SetScalars(v_image)
  65 + image.GetPointData().SetScalars(v_image)
  66 + image.Update()
  67 +
  68 + image_copy = vtk.vtkImageData()
  69 + image_copy.DeepCopy(image)
  70 + image_copy.Update()
  71 +
  72 + return image_copy
  73 +
  74 +class CursorBase(object):
32 75 def __init__(self):
33 76 self.colour = (0.0, 0.0, 1.0)
34 77 self.opacity = 1
35   - self.radius = 15.0
36   - #self.position = (0.5,0.5, 1)
37   - self.points = []
  78 + self.size = 15.0
38 79 self.orientation = "AXIAL"
39 80 self.spacing = (1, 1, 1)
40   -
41   - self.mapper = vtk.vtkPolyDataMapper()
42   - self.actor = vtk.vtkActor()
43   - self.property = vtk.vtkProperty()
44   -
45   - self.__build_actor()
46   - self.__calculate_area_pixels()
47   -
48   - def __build_actor(self):
49   - """
50   - Function to plot the circle
51   - """
52   - print "Building circle cursor", self.orientation
53   - r = self.radius
54   - t = 0
55   -
56   - self.posc_a = 0
57   - self.posc_b = 0
58   -
59   - self.segment = vtk.vtkAppendPolyData()
60   -
61   - self.xa = self.posc_a + r * cos(t)
62   - self.ya = self.posc_a + r * sin(t)
63   -
64   - while(t <= 2 * pi):
65   - self.GenerateCicleSegment(t)
66   - t = t + 0.05
67   -
68   - self.GenerateCicleSegment(0)
69   -
70   - self.mapper.SetInputConnection(self.segment.GetOutputPort())
71   - self.actor.SetMapper(self.mapper)
72   - self.actor.GetProperty().SetOpacity(self.opacity)
73   - self.actor.GetProperty().SetColor(self.colour)
74   - self.actor.PickableOff()
75   -
76   - def GenerateCicleSegment(self, t):
77   - """
78   - Generate cicle segment
79   - """
80   - x = self.posc_a + self.radius * cos(t)
81   - y = self.posc_b + self.radius * sin(t)
82   -
83   - ls = vtk.vtkLineSource()
84   - ls.SetPoint1(self.xa, self.ya, 0)
85   - ls.SetPoint2(x, y, 0)
86   -
87   - self.segment.AddInput(ls.GetOutput())
88   - self.xa, self.ya = x, y
89   -
90   - def __calculate_area_pixels(self):
91   - """
92   - Return the cursor's pixels.
93   - """
94   - radius = self.radius
95   - if self.orientation == 'AXIAL':
96   - sx = self.spacing[0]
97   - sy = self.spacing[1]
98   - elif self.orientation == 'CORONAL':
99   - sx = self.spacing[0]
100   - sy = self.spacing[2]
101   - elif self.orientation == 'SAGITAL':
102   - sx = self.spacing[1]
103   - sy = self.spacing[2]
104   -
105   - y,x = numpy.ogrid[-radius/sy:+radius/sy,
106   - -radius/sx:+radius/sx]
107   -
108   - index = (y*sy)**2 + (x*sx)**2 <= radius**2
109   - self.points = index
  81 + if vtk.vtkVersion().GetVTKVersion() > '5.8.0':
  82 + self.mapper = vtk.vtkImageSliceMapper()
  83 + cursor_property = vtk.vtkImageProperty()
  84 + cursor_property.SetInterpolationTypeToNearest()
  85 + self.actor = vtk.vtkImageSlice()
  86 + self.actor.SetMapper(self.mapper)
  87 + self.actor.SetProperty(cursor_property)
  88 + else:
  89 + self.actor = vtk.vtkImageActor()
  90 + self.mapper = None
  91 + self._build_actor()
  92 + self._calculate_area_pixels()
110 93  
111 94 def SetSize(self, diameter):
112   - radius = self.radius = diameter/2.0
113   - #self.disk.SetInnerRadius(radius-1) # filled = self.radius
114   - #self.disk.SetOuterRadius(radius) # filled = 0
115   - self.__build_actor()
116   - self.__calculate_area_pixels()
  95 + self.radius = diameter/2.0
  96 + self._build_actor()
  97 + self._calculate_area_pixels()
117 98  
118 99 def SetColour(self, colour):
119 100 self.colour = colour
120   - self.actor.GetProperty().SetColor(colour)
  101 + self._build_actor()
121 102  
122 103 def SetOrientation(self, orientation):
123 104 self.orientation = orientation
124   - proj = Project()
125   - orig_orien = proj.original_orientation
126   - if orientation == "CORONAL":
127   - self.actor.RotateX(90)
128   - if orientation == "SAGITAL":
129   - self.actor.RotateY(90)
  105 + self._build_actor()
  106 + self._calculate_area_pixels()
130 107  
131 108 def SetPosition(self, position):
132   - self.position = position
133   - self.actor.SetPosition(position)
  109 + # Overriding SetPosition method because in rectangles with odd
  110 + # dimensions there is no half position.
  111 + px, py, pz = position
  112 + sx, sy, sz = self.spacing
  113 + tx = self.actor.GetXRange()[1] - self.actor.GetXRange()[0]
  114 + ty = self.actor.GetYRange()[1] - self.actor.GetYRange()[0]
  115 + tz = self.actor.GetZRange()[1] - self.actor.GetZRange()[0]
  116 +
  117 + if self.orientation == 'AXIAL':
  118 + if self.points.shape[0] % 2:
  119 + y = py - ty / 2.0
  120 + else:
  121 + y = py - ty / 2.0 + self.spacing[1] / 2.0
  122 +
  123 + if self.points.shape[1] % 2:
  124 + x = px - tx / 2.0
  125 + else:
  126 + x = px - tx / 2.0 + self.spacing[0] / 2.0
  127 + z = pz
  128 +
  129 + if self.mapper:
  130 + x += sx / 2.0
  131 + y += sy / 2.0
  132 +
  133 + elif self.orientation == 'CORONAL':
  134 + if self.points.shape[0] % 2:
  135 + z = pz - tz / 2.0
  136 + else:
  137 + z = pz - tz / 2.0 + self.spacing[2] / 2.0
  138 +
  139 + if self.points.shape[1] % 2:
  140 + x = px - tx / 2.0
  141 + else:
  142 + x = px - tx / 2.0 + self.spacing[0] / 2.0
  143 + y = py
  144 +
  145 + if self.mapper:
  146 + x += sx / 2.0
  147 + z += sz / 2.0
134 148  
135   - def SetEditionPosition(self, position):
136   - self.edition_position = position
  149 + elif self.orientation == 'SAGITAL':
  150 + # height shape is odd
  151 + if self.points.shape[1] % 2:
  152 + y = py - ty / 2.0
  153 + else:
  154 + y = py - ty / 2.0 + self.spacing[1] / 2.0
  155 +
  156 + if self.points.shape[0] % 2:
  157 + z = pz - tz / 2.0
  158 + else:
  159 + z = pz - tz / 2.0 + self.spacing[2] / 2.0
  160 + x = px
  161 +
  162 + if self.mapper:
  163 + y += sy / 2.0
  164 + z += sz / 2.0
  165 +
  166 + else:
  167 + if self.points.shape[0] % 2:
  168 + y = py - ty / 2.0
  169 + else:
  170 + y = py - ty / 2.0 + self.spacing[1] / 2.0
  171 +
  172 + if self.points.shape[1] % 2:
  173 + x = px - tx / 2.0
  174 + else:
  175 + x = px - tx / 2.0 + self.spacing[0] / 2.0
  176 + z = pz
  177 +
  178 + if self.mapper:
  179 + x += sx / 2.0
  180 + y += sy / 2.0
  181 +
  182 + self.actor.SetPosition(x, y, z)
137 183  
138 184 def SetSpacing(self, spacing):
139 185 self.spacing = spacing
140   - self.__calculate_area_pixels()
  186 + self._build_actor()
  187 + self._calculate_area_pixels()
141 188  
142 189 def Show(self, value=1):
143 190 if value:
... ... @@ -148,90 +195,104 @@ class CursorCircle:
148 195 def GetPixels(self):
149 196 return self.points
150 197  
  198 + def _build_actor(self):
  199 + pass
  200 +
  201 + def _calculate_area_pixels(self):
  202 + pass
151 203  
152   -class CursorRectangle:
  204 + def _set_colour(self, imagedata, colour):
  205 + scalar_range = int(imagedata.GetScalarRange()[1])
  206 + r, g, b = colour
  207 +
  208 + # map scalar values into colors
  209 + lut_mask = vtk.vtkLookupTable()
  210 + lut_mask.SetNumberOfColors(256)
  211 + lut_mask.SetHueRange(const.THRESHOLD_HUE_RANGE)
  212 + lut_mask.SetSaturationRange(1, 1)
  213 + lut_mask.SetValueRange(0, 255)
  214 + lut_mask.SetRange(0, 255)
  215 + lut_mask.SetNumberOfTableValues(256)
  216 + lut_mask.SetTableValue(0, 0, 0, 0, 0.0)
  217 + lut_mask.SetTableValue(1.0, 1-r, 1-g, 1-b, 0.50)
  218 + lut_mask.SetRampToLinear()
  219 + lut_mask.Build()
  220 +
  221 + # map the input image through a lookup table
  222 + img_colours_mask = vtk.vtkImageMapToColors()
  223 + img_colours_mask.SetLookupTable(lut_mask)
  224 + img_colours_mask.SetOutputFormatToRGBA()
  225 + img_colours_mask.SetInput(imagedata)
  226 + img_colours_mask.Update()
  227 +
  228 + return img_colours_mask.GetOutput()
  229 +
  230 +
  231 +class CursorCircle(CursorBase):
  232 + # TODO: Think and try to change this class to an actor
  233 + # CursorCircleActor(vtk.vtkActor)
153 234 def __init__(self):
154   -
155   - self.colour = (0.0, 0.0, 1.0)
156   - self.opacity = 1
157   -
158   - self.x_length = 30
159   - self.y_length = 30
160   - self.radius = 15
161   -
162   - self.dimension = (self.x_length, self.y_length)
163   - self.position = (0 ,0)
164   - self.orientation = "AXIAL"
165   - self.spacing = (1, 1, 1)
166   -
167   - self.__build_actor()
168   - self.__calculate_area_pixels()
169   -
170   - def SetSize(self, size):
171   - self.x_length = size
172   - self.y_length = size
173   - self.radius = size / 2
174   - retangle = self.retangle
175   - retangle.SetXLength(size)
176   - retangle.SetYLength(size)
177   - self.__calculate_area_pixels()
178   -
179   - def SetOrientation(self, orientation):
180   - self.orientation = orientation
181   -
182   - def SetColour(self, colour):
183   - self.colour = colour
184   - self.actor.GetProperty().SetColor(colour)
  235 + self.radius = 15.0
  236 + super(CursorCircle, self).__init__()
185 237  
186   - def SetOrientation(self, orientation):
187   - self.orientation = orientation
188   - proj = Project()
189   - orig_orien = proj.original_orientation
190   - if orientation == "CORONAL":
191   - self.actor.RotateX(90)
192   - if orientation == "SAGITAL":
193   - self.actor.RotateY(90)
  238 + def _build_actor(self):
  239 + """
  240 + Function to plot the circle
  241 + """
  242 + print "Building circle cursor", self.orientation
  243 + r = self.radius
  244 + sx, sy, sz = self.spacing
  245 + if self.orientation == 'AXIAL':
  246 + xi = math.floor(-r/sx)
  247 + xf = math.ceil(r/sx) + 1
  248 + yi = math.floor(-r/sy)
  249 + yf = math.ceil(r/sy) + 1
  250 + zi = 0
  251 + zf = 1
  252 + elif self.orientation == 'CORONAL':
  253 + xi = math.floor(-r/sx)
  254 + xf = math.ceil(r/sx) + 1
  255 + yi = 0
  256 + yf = 1
  257 + zi = math.floor(-r/sz)
  258 + zf = math.ceil(r/sz) + 1
  259 + elif self.orientation == 'SAGITAL':
  260 + xi = 0
  261 + xf = 1
  262 + yi = math.floor(-r/sy)
  263 + yf = math.ceil(r/sy) + 1
  264 + zi = math.floor(-r/sz)
  265 + zf = math.ceil(r/sz) + 1
194 266  
195   - def SetPosition(self, position):
196   - x,y,z = position
197   - self.position = position
198   - self.actor.SetPosition(x,y,z)
199   -
200   - def SetEditionPosition(self, position):
201   - self.edition_position = position
  267 + z,y,x = numpy.ogrid[zi:zf,yi:yf, xi:xf]
202 268  
203   - def SetSpacing(self, spacing):
204   - self.spacing = spacing
  269 + circle_m = (z*sz)**2 + (y*sy)**2 + (x*sx)**2 <= r**2
  270 + circle_i = to_vtk(circle_m.astype('uint8'),
  271 + self.spacing, 0, self.orientation)
  272 + circle_ci = self._set_colour(circle_i, self.colour)
205 273  
206   - def Show(self, value=1):
207   - if value:
208   - self.actor.VisibilityOn()
  274 + if self.mapper is None:
  275 + self.actor.SetInput(circle_ci)
  276 + self.actor.InterpolateOff()
  277 + self.actor.PickableOff()
  278 + self.actor.SetDisplayExtent(circle_ci.GetExtent())
209 279 else:
210   - self.actor.VisibilityOff()
  280 + self.mapper.SetInput(circle_ci)
  281 + self.mapper.BorderOn()
  282 +
  283 + self.mapper.SetOrientation(ORIENTATION[self.orientation])
211 284  
212   - def __build_actor(self):
  285 + print '===================================='
  286 + print self.orientation
  287 + print circle_ci.GetSpacing()
  288 + print xi, xf, yi, yf, zi, zf
  289 + print '===================================='
  290 +
  291 + def _calculate_area_pixels(self):
213 292 """
214   - Function to plot the Retangle
  293 + Return the cursor's pixels.
215 294 """
216   - print "Building rectangle cursor", self.orientation
217   - mapper = vtk.vtkPolyDataMapper()
218   - self.retangle = vtk.vtkCubeSource()
219   - self.actor = actor = vtk.vtkActor()
220   -
221   - prop = vtk.vtkProperty()
222   - prop.SetRepresentationToWireframe()
223   - self.actor.SetProperty(prop)
224   -
225   - mapper.SetInput(self.retangle.GetOutput())
226   - actor.SetPosition(self.position[0] - self.x_length,\
227   - self.position[1] - self.y_length, 1)
228   -
229   - actor.SetMapper(mapper)
230   - actor.GetProperty().SetOpacity(self.opacity)
231   - actor.GetProperty().SetColor(self.colour)
232   - actor.SetVisibility(0)
233   -
234   - def __calculate_area_pixels(self):
  295 + r = self.radius
235 296 if self.orientation == 'AXIAL':
236 297 sx = self.spacing[0]
237 298 sy = self.spacing[1]
... ... @@ -241,12 +302,71 @@ class CursorRectangle:
241 302 elif self.orientation == 'SAGITAL':
242 303 sx = self.spacing[1]
243 304 sy = self.spacing[2]
244   - shape = (self.y_length/sy, self.x_length/sx)
245   - self.points = numpy.empty(shape, dtype='bool')
246   - self.points.fill(True)
247 305  
248   - def GetPixels(self):
  306 + xi = math.floor(-r/sx)
  307 + xf = math.ceil(r/sx) + 1
  308 + yi = math.floor(-r/sy)
  309 + yf = math.ceil(r/sy) + 1
  310 +
  311 + y,x = numpy.ogrid[yi:yf, xi:xf]
  312 +
  313 + print "AREA", x
  314 +
  315 + index = (y*sy)**2 + (x*sx)**2 <= r**2
  316 + self.points = index
  317 +
  318 +
  319 +class CursorRectangle(CursorBase):
  320 + def __init__(self):
  321 + self.radius = 15.0
  322 + super(CursorRectangle, self).__init__()
  323 +
  324 +
  325 + def _build_actor(self):
249 326 """
250   - Return the points of the rectangle
  327 + Function to plot the Retangle
251 328 """
252   - return self.points
  329 + print "Building rectangle cursor", self.orientation
  330 + r = self.radius
  331 + sx, sy, sz = self.spacing
  332 + if self.orientation == 'AXIAL':
  333 + x = math.floor(2*r/sx)
  334 + y = math.floor(2*r/sy)
  335 + z = 1
  336 + elif self.orientation == 'CORONAL':
  337 + x = math.floor(r/sx)
  338 + y = 1
  339 + z = math.floor(r/sz)
  340 + elif self.orientation == 'SAGITAL':
  341 + x = 1
  342 + y = math.floor(r/sy)
  343 + z = math.floor(r/sz)
  344 +
  345 + rectangle_m = numpy.ones((z, y, x), dtype='uint8')
  346 + rectangle_i = to_vtk(rectangle_m, self.spacing, 0, self.orientation)
  347 + rectangle_ci = self._set_colour(rectangle_i, self.colour)
  348 +
  349 + if self.mapper is None:
  350 + self.actor.SetInput(rectangle_ci)
  351 + self.actor.InterpolateOff()
  352 + self.actor.PickableOff()
  353 + self.actor.SetDisplayExtent(rectangle_ci.GetExtent())
  354 + else:
  355 + self.mapper.SetInput(rectangle_ci)
  356 + self.mapper.BorderOn()
  357 + self.mapper.SetOrientation(ORIENTATION[self.orientation])
  358 +
  359 + def _calculate_area_pixels(self):
  360 + r = self.radius
  361 + sx, sy, sz = self.spacing
  362 + if self.orientation == 'AXIAL':
  363 + x = math.floor(2*r/sx)
  364 + y = math.floor(2*r/sy)
  365 + elif self.orientation == 'CORONAL':
  366 + x = math.floor(r/sx)
  367 + y = math.floor(r/sz)
  368 + elif self.orientation == 'SAGITAL':
  369 + x = math.floor(r/sy)
  370 + y = math.floor(r/sz)
  371 +
  372 + self.points = numpy.ones((y, x), dtype='bool')
... ...
invesalius/data/imagedata_utils.py
... ... @@ -545,5 +545,3 @@ def analyze2mmap(analyze):
545 545  
546 546 matrix.flush()
547 547 return matrix, temp_file
548   -
549   -
... ...
invesalius/data/slice_.py
... ... @@ -294,8 +294,8 @@ class Slice(object):
294 294 sx = self.spacing[0]
295 295 sy = self.spacing[2]
296 296 elif orientation == 'SAGITAL':
297   - sx = self.spacing[1]
298   - sy = self.spacing[2]
  297 + sx = self.spacing[2]
  298 + sy = self.spacing[1]
299 299  
300 300 else:
301 301 if orientation == 'AXIAL':
... ... @@ -309,15 +309,17 @@ class Slice(object):
309 309 py = position / mask.shape[1]
310 310 px = position % mask.shape[1]
311 311 elif orientation == 'SAGITAL':
312   - sx = self.spacing[1]
313   - sy = self.spacing[2]
  312 + sx = self.spacing[2]
  313 + sy = self.spacing[1]
314 314 py = position / mask.shape[1]
315 315 px = position % mask.shape[1]
316 316  
317   - xi = px - math.ceil(radius/sx)
318   - xf = px + math.ceil(radius/sx)
319   - yi = py - math.ceil(radius/sy)
320   - yf = py + math.ceil(radius/sy)
  317 + cx = index.shape[1] / 2 + 1
  318 + cy = index.shape[0] / 2 + 1
  319 + xi = px - index.shape[1] + cx
  320 + xf = xi + index.shape[1]
  321 + yi = py - index.shape[0] + cy
  322 + yf = yi + index.shape[0]
321 323  
322 324 if yi < 0:
323 325 index = index[abs(yi):,:]
... ... @@ -341,6 +343,12 @@ class Slice(object):
341 343 roi_m = mask[yi:yf,xi:xf]
342 344 roi_i = image[yi:yf, xi:xf]
343 345  
  346 + print
  347 + print"IMAGE", roi_m.shape
  348 + print "BRUSH", index.shape
  349 + print "IMAGE[BRUSH]", roi_m[index].shape
  350 + print
  351 +
344 352 if operation == const.BRUSH_THRESH:
345 353 # It's a trick to make points between threshold gets value 254
346 354 # (1 * 253 + 1) and out ones gets value 1 (0 * 253 + 1).
... ...
invesalius/data/slice_data.py
... ... @@ -38,6 +38,7 @@ class SliceData(object):
38 38 self.number = 0
39 39 self.orientation = 'AXIAL'
40 40 self.renderer = None
  41 + self.overlay_renderer = None
41 42 self.__create_text()
42 43 self.__create_box()
43 44  
... ... @@ -131,8 +132,8 @@ class SliceData(object):
131 132  
132 133 def SetCursor(self, cursor):
133 134 if self.cursor:
134   - self.renderer.RemoveActor(self.cursor.actor)
135   - self.renderer.AddActor(cursor.actor)
  135 + self.overlay_renderer.RemoveActor(self.cursor.actor)
  136 + self.overlay_renderer.AddActor(cursor.actor)
136 137 self.cursor = cursor
137 138  
138 139 def SetNumber(self, number):
... ... @@ -166,7 +167,7 @@ class SliceData(object):
166 167 self.line_r.SetPoint2((xf, yf, 0))
167 168  
168 169 def Hide(self):
169   - self.renderer.RemoveActor(self.actor)
  170 + self.overlay_renderer.RemoveActor(self.actor)
170 171 self.renderer.RemoveActor(self.text.actor)
171 172  
172 173 def Show(self):
... ...
invesalius/data/viewer_slice.py
... ... @@ -725,13 +725,13 @@ class Viewer(wx.Panel):
725 725 self.pick.Pick(mouse_x, mouse_y, 0, render)
726 726  
727 727 coord = self.get_coordinate_cursor()
728   - slice_data.cursor.SetPosition(coord)
729   - slice_data.cursor.SetEditionPosition(
730   - self.get_coordinate_cursor_edition(slice_data))
731   - self.__update_cursor_position(slice_data, coord)
  728 + position = self.slice_data.actor.GetInput().FindPoint(coord)
  729 +
  730 + if position != -1:
  731 + coord = self.slice_data.actor.GetInput().GetPoint(position)
732 732  
  733 + slice_data.cursor.SetPosition(coord)
733 734 cursor = self.slice_data.cursor
734   - position = self.slice_data.actor.GetInput().FindPoint(coord)
735 735 radius = cursor.radius
736 736  
737 737 if position < 0:
... ... @@ -771,9 +771,7 @@ class Viewer(wx.Panel):
771 771 if position != -1:
772 772 coord = self.slice_data.actor.GetInput().GetPoint(position)
773 773 slice_data.cursor.SetPosition(coord)
774   - slice_data.cursor.SetEditionPosition(
775   - self.get_coordinate_cursor_edition(slice_data))
776   - self.__update_cursor_position(slice_data, coord)
  774 + #self.__update_cursor_position(slice_data, coord)
777 775  
778 776 if (self.left_pressed):
779 777 cursor = self.slice_data.cursor
... ... @@ -1280,12 +1278,25 @@ class Viewer(wx.Panel):
1280 1278  
1281 1279 def create_slice_window(self):
1282 1280 renderer = vtk.vtkRenderer()
  1281 + renderer.SetLayer(0)
  1282 + cam = renderer.GetActiveCamera()
  1283 +
  1284 + overlay_renderer = vtk.vtkRenderer()
  1285 + overlay_renderer.SetLayer(1)
  1286 + overlay_renderer.SetActiveCamera(cam)
  1287 + overlay_renderer.SetInteractive(0)
  1288 +
  1289 +
  1290 + self.interactor.GetRenderWindow().SetNumberOfLayers(2)
  1291 + self.interactor.GetRenderWindow().AddRenderer(overlay_renderer)
1283 1292 self.interactor.GetRenderWindow().AddRenderer(renderer)
  1293 +
1284 1294 actor = vtk.vtkImageActor()
1285 1295 actor.InterpolateOff()
1286 1296 slice_data = sd.SliceData()
1287 1297 slice_data.SetOrientation(self.orientation)
1288 1298 slice_data.renderer = renderer
  1299 + slice_data.overlay_renderer = overlay_renderer
1289 1300 slice_data.actor = actor
1290 1301 slice_data.SetBorderStyle(sd.BORDER_ALL)
1291 1302 renderer.AddActor(actor)
... ... @@ -1301,7 +1312,7 @@ class Viewer(wx.Panel):
1301 1312 self.cam.SetFocalPoint(0, 0, 0)
1302 1313 self.cam.SetViewUp(const.SLICE_POSITION[orig_orien][0][self.orientation])
1303 1314 self.cam.SetPosition(const.SLICE_POSITION[orig_orien][1][self.orientation])
1304   - self.cam.ComputeViewPlaneNormal()
  1315 + #self.cam.ComputeViewPlaneNormal()
1305 1316 #self.cam.OrthogonalizeViewUp()
1306 1317 self.cam.ParallelProjectionOn()
1307 1318  
... ...