Commit a3979279e26d5cb05a239c8f07c051bcde287c02
1 parent
2b11a51c
Exists in
master
and in
68 other branches
FIX: Fixed the circle cursor proportion
Showing
2 changed files
with
56 additions
and
12 deletions
Show diff stats
invesalius/data/cursor_actors.py
| @@ -2,6 +2,28 @@ from math import * | @@ -2,6 +2,28 @@ from math import * | ||
| 2 | 2 | ||
| 3 | import vtk | 3 | import vtk |
| 4 | 4 | ||
| 5 | +def frange(start, end=None, inc=None): | ||
| 6 | + "A range function, that does accept float increments..." | ||
| 7 | + | ||
| 8 | + if end == None: | ||
| 9 | + end = start + 0.0 | ||
| 10 | + start = 0.0 | ||
| 11 | + | ||
| 12 | + if inc == None: | ||
| 13 | + inc = 1.0 | ||
| 14 | + | ||
| 15 | + L = [] | ||
| 16 | + while 1: | ||
| 17 | + next = start + len(L) * inc | ||
| 18 | + if inc > 0 and next >= end: | ||
| 19 | + break | ||
| 20 | + elif inc < 0 and next <= end: | ||
| 21 | + break | ||
| 22 | + L.append(next) | ||
| 23 | + | ||
| 24 | + return L | ||
| 25 | + | ||
| 26 | + | ||
| 5 | class CursorCircle: | 27 | class CursorCircle: |
| 6 | # TODO: Think and try to change this class to an actor | 28 | # TODO: Think and try to change this class to an actor |
| 7 | # CursorCircleActor(vtk.vtkActor) | 29 | # CursorCircleActor(vtk.vtkActor) |
| @@ -14,6 +36,7 @@ class CursorCircle: | @@ -14,6 +36,7 @@ class CursorCircle: | ||
| 14 | self.position = (0 ,0, 1) | 36 | self.position = (0 ,0, 1) |
| 15 | self.points = [] | 37 | self.points = [] |
| 16 | self.orientation = "AXIAL" | 38 | self.orientation = "AXIAL" |
| 39 | + self.spacing = (1, 1, 1) | ||
| 17 | 40 | ||
| 18 | self.mapper = vtk.vtkPolyDataMapper() | 41 | self.mapper = vtk.vtkPolyDataMapper() |
| 19 | self.disk = vtk.vtkDiskSource() | 42 | self.disk = vtk.vtkDiskSource() |
| @@ -54,19 +77,24 @@ class CursorCircle: | @@ -54,19 +77,24 @@ class CursorCircle: | ||
| 54 | xc = 0 | 77 | xc = 0 |
| 55 | yc = 0 | 78 | yc = 0 |
| 56 | z = 0 | 79 | z = 0 |
| 80 | + xs, ys, zs = self.spacing | ||
| 81 | + orientation_based_spacing = {"AXIAL" : (xs, ys), | ||
| 82 | + "SAGITAL" : (ys, zs), | ||
| 83 | + "CORONAL" : (xs, zs) } | ||
| 84 | + xs, ys = orientation_based_spacing[self.orientation] | ||
| 57 | self.pixel_list = [] | 85 | self.pixel_list = [] |
| 58 | - radius = int(self.radius) | ||
| 59 | - for i in xrange(int(yc - radius), int(yc + radius)): | 86 | + radius = self.radius |
| 87 | + for i in frange(yc - radius, yc + radius, ys): | ||
| 60 | # distance from the line to the circle's center | 88 | # distance from the line to the circle's center |
| 61 | d = yc - i | 89 | d = yc - i |
| 62 | # line size | 90 | # line size |
| 63 | - line = sqrt(round(radius ** 2) - round(d ** 2)) * 2 | 91 | + line = sqrt(radius**2 - d**2) * 2 |
| 64 | # line initial x | 92 | # line initial x |
| 65 | - xi = int(xc - line/2) | 93 | + xi = xc - line/2 |
| 66 | # line final | 94 | # line final |
| 67 | - xf = int(line/2 + xc) | 95 | + xf = line/2 + xc |
| 68 | yi = i | 96 | yi = i |
| 69 | - for k in xrange(xi,xf): | 97 | + for k in frange(xi,xf,xs): |
| 70 | self.pixel_list.append((k, yi)) | 98 | self.pixel_list.append((k, yi)) |
| 71 | 99 | ||
| 72 | def SetSize(self, radius): | 100 | def SetSize(self, radius): |
| @@ -97,15 +125,22 @@ class CursorCircle: | @@ -97,15 +125,22 @@ class CursorCircle: | ||
| 97 | self.position = position | 125 | self.position = position |
| 98 | self.actor.SetPosition(position) | 126 | self.actor.SetPosition(position) |
| 99 | 127 | ||
| 128 | + def SetEditionPosition(self, position): | ||
| 129 | + self.edition_position = position | ||
| 130 | + | ||
| 131 | + def SetSpacing(self, spacing): | ||
| 132 | + self.spacing = spacing | ||
| 133 | + | ||
| 100 | def GetPixels(self): | 134 | def GetPixels(self): |
| 101 | - px, py, pz = self.position | 135 | + px, py, pz = self.edition_position |
| 102 | orient = self.orientation | 136 | orient = self.orientation |
| 137 | + xs, ys, zs = self.spacing | ||
| 103 | for pixel_0,pixel_1 in self.pixel_list: | 138 | for pixel_0,pixel_1 in self.pixel_list: |
| 104 | # The position of the pixels in this list is relative (based only on | 139 | # The position of the pixels in this list is relative (based only on |
| 105 | # the area, and not the cursor position). | 140 | # the area, and not the cursor position). |
| 106 | # Let's calculate the absolute position | 141 | # Let's calculate the absolute position |
| 107 | # TODO: Optimize this!!!! | 142 | # TODO: Optimize this!!!! |
| 108 | - absolute_pixel = {"AXIAL": (px + pixel_0, py + pixel_1, pz), | ||
| 109 | - "CORONAL": (px + pixel_0, py, pz + pixel_1), | ||
| 110 | - "SAGITAL": (px, py + pixel_0, pz + pixel_1)} | 143 | + absolute_pixel = {"AXIAL": (px + pixel_0 / xs , py + pixel_1 / ys, pz), |
| 144 | + "CORONAL": (px + pixel_0 / xs, py, pz + pixel_1 / zs), | ||
| 145 | + "SAGITAL": (px, py + pixel_0 / ys, pz + pixel_1 / zs) } | ||
| 111 | yield absolute_pixel[orient] | 146 | yield absolute_pixel[orient] |
invesalius/data/viewer_slice.py
| @@ -145,6 +145,7 @@ class Viewer(wx.Panel): | @@ -145,6 +145,7 @@ class Viewer(wx.Panel): | ||
| 145 | def OnBrushMove(self, obj, evt_vtk): | 145 | def OnBrushMove(self, obj, evt_vtk): |
| 146 | coord = self.GetCoordinateCursor() | 146 | coord = self.GetCoordinateCursor() |
| 147 | self.cursor.SetPosition(coord) | 147 | self.cursor.SetPosition(coord) |
| 148 | + self.cursor.SetEditionPosition(self.GetCoordinateCursorEdition()) | ||
| 148 | self.ren.Render() | 149 | self.ren.Render() |
| 149 | if self.mouse_pressed: | 150 | if self.mouse_pressed: |
| 150 | print "Edit pixel region based on origin:", coord | 151 | print "Edit pixel region based on origin:", coord |
| @@ -208,13 +209,20 @@ class Viewer(wx.Panel): | @@ -208,13 +209,20 @@ class Viewer(wx.Panel): | ||
| 208 | 209 | ||
| 209 | return coord | 210 | return coord |
| 210 | 211 | ||
| 211 | - | ||
| 212 | def GetCoordinateCursor(self): | 212 | def GetCoordinateCursor(self): |
| 213 | 213 | ||
| 214 | # Find position | 214 | # Find position |
| 215 | mouse_x, mouse_y = self.interactor.GetEventPosition() | 215 | mouse_x, mouse_y = self.interactor.GetEventPosition() |
| 216 | self.pick.Pick(mouse_x, mouse_y, 0, self.ren) | 216 | self.pick.Pick(mouse_x, mouse_y, 0, self.ren) |
| 217 | x, y, z = self.pick.GetPickPosition() | 217 | x, y, z = self.pick.GetPickPosition() |
| 218 | + return x, y, z | ||
| 219 | + | ||
| 220 | + def GetCoordinateCursorEdition(self): | ||
| 221 | + | ||
| 222 | + # Find position | ||
| 223 | + mouse_x, mouse_y = self.interactor.GetEventPosition() | ||
| 224 | + self.pick.Pick(mouse_x, mouse_y, 0, self.ren) | ||
| 225 | + x, y, z = self.pick.GetPickPosition() | ||
| 218 | 226 | ||
| 219 | # First we fix the position origin, based on vtkActor bounds | 227 | # First we fix the position origin, based on vtkActor bounds |
| 220 | bounds = self.actor.GetBounds() | 228 | bounds = self.actor.GetBounds() |
| @@ -241,7 +249,7 @@ class Viewer(wx.Panel): | @@ -241,7 +249,7 @@ class Viewer(wx.Panel): | ||
| 241 | z = (z * dimensions[2]) / dz | 249 | z = (z * dimensions[2]) / dz |
| 242 | except ZeroDivisionError: | 250 | except ZeroDivisionError: |
| 243 | z = self.slice_number | 251 | z = self.slice_number |
| 244 | - | 252 | + |
| 245 | return x,y,z | 253 | return x,y,z |
| 246 | 254 | ||
| 247 | def __bind_events(self): | 255 | def __bind_events(self): |
| @@ -296,6 +304,7 @@ class Viewer(wx.Panel): | @@ -296,6 +304,7 @@ class Viewer(wx.Panel): | ||
| 296 | self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, | 304 | self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, |
| 297 | max_slice_number) | 305 | max_slice_number) |
| 298 | self.SetScrollPosition(0) | 306 | self.SetScrollPosition(0) |
| 307 | + self.cursor.SetSpacing(imagedata.GetSpacing()) | ||
| 299 | 308 | ||
| 300 | def SetOrientation(self, orientation): | 309 | def SetOrientation(self, orientation): |
| 301 | self.orientation = orientation | 310 | self.orientation = orientation |