Commit 0f30fe61b8c6b18f491c123b13f7fae165c26f7e
1 parent
259d97fe
Exists in
master
and in
68 other branches
ADD: Initial works in measures
Showing
7 changed files
with
394 additions
and
16 deletions
Show diff stats
.gitattributes
| ... | ... | @@ -141,6 +141,7 @@ invesalius/data/cursor_actors.py -text |
| 141 | 141 | invesalius/data/editor.py -text |
| 142 | 142 | invesalius/data/imagedata_utils.py -text |
| 143 | 143 | invesalius/data/mask.py -text |
| 144 | +invesalius/data/measures.py -text | |
| 144 | 145 | invesalius/data/orientation.py -text |
| 145 | 146 | invesalius/data/polydata_utils.py -text |
| 146 | 147 | invesalius/data/slice_.py -text | ... | ... |
invesalius/constants.py
| ... | ... | @@ -350,6 +350,7 @@ MODE_ZOOM_SELECTION = 1 #:"Set Zoom Select Mode", |
| 350 | 350 | MODE_ROTATE = 2#:"Set Spin Mode", |
| 351 | 351 | MODE_MOVE = 3#:"Set Pan Mode", |
| 352 | 352 | MODE_WW_WL = 4#:"Bright and contrast adjustment"} |
| 353 | +MODE_LINEAR_MEASURE = 5 | |
| 353 | 354 | |
| 354 | 355 | |
| 355 | 356 | # self.states = {0:"Set Zoom Mode", 1:"Set Zoom Select Mode", |
| ... | ... | @@ -431,6 +432,7 @@ SLICE_STATE_CROSS = 1006 |
| 431 | 432 | SLICE_STATE_SCROLL = 1007 |
| 432 | 433 | SLICE_STATE_EDITOR = 1008 |
| 433 | 434 | VOLUME_STATE_SEED = 2001 |
| 435 | +STATE_LINEAR_MEASURE = 3001 | |
| 434 | 436 | |
| 435 | 437 | |
| 436 | 438 | TOOL_STATES = [ STATE_WL, STATE_SPIN, STATE_ZOOM, |
| ... | ... | @@ -443,7 +445,7 @@ SLICE_STYLES = TOOL_STATES + TOOL_SLICE_STATES |
| 443 | 445 | SLICE_STYLES.append(STATE_DEFAULT) |
| 444 | 446 | SLICE_STYLES.append(SLICE_STATE_EDITOR) |
| 445 | 447 | |
| 446 | -VOLUME_STYLES = TOOL_STATES + [VOLUME_STATE_SEED] | |
| 448 | +VOLUME_STYLES = TOOL_STATES + [VOLUME_STATE_SEED, STATE_LINEAR_MEASURE] | |
| 447 | 449 | VOLUME_STYLES.append(STATE_DEFAULT) |
| 448 | 450 | |
| 449 | 451 | |
| ... | ... | @@ -456,4 +458,5 @@ STYLE_LEVEL = {SLICE_STATE_EDITOR: 1, |
| 456 | 458 | STATE_ZOOM: 2, |
| 457 | 459 | STATE_ZOOM_SL: 2, |
| 458 | 460 | STATE_PAN:2, |
| 459 | - VOLUME_STATE_SEED:1} | |
| 461 | + VOLUME_STATE_SEED:1, | |
| 462 | + STATE_LINEAR_MEASURE: 2} | ... | ... |
| ... | ... | @@ -0,0 +1,341 @@ |
| 1 | +#!/usr/bin/env python | |
| 2 | +# -*- coding: UTF-8 -*- | |
| 3 | + | |
| 4 | +# This example demonstrates the use of vtkSTLReader to load data into | |
| 5 | +# VTK from a file. This example also uses vtkLODActor which changes | |
| 6 | +# its graphical representation of the data to maintain interactive | |
| 7 | +# performance. | |
| 8 | + | |
| 9 | +import wx | |
| 10 | +import sys | |
| 11 | +import os | |
| 12 | +import time | |
| 13 | +import math | |
| 14 | + | |
| 15 | +from itertools import cycle | |
| 16 | +from wx.grid import Grid, GridCellBoolRenderer, GridCellBoolEditor, EVT_GRID_CELL_CHANGE | |
| 17 | + | |
| 18 | +import vtk | |
| 19 | +from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor | |
| 20 | + | |
| 21 | +class CirclePointRepresentation(object): | |
| 22 | + """ | |
| 23 | + This class represents a circle that indicate a point in the surface | |
| 24 | + """ | |
| 25 | + def __init__(self, color=(1, 0, 0), radius=1.0): | |
| 26 | + """ | |
| 27 | + color: the color of the representation | |
| 28 | + radius: the radius of circle representation | |
| 29 | + """ | |
| 30 | + self.color = color | |
| 31 | + self.radius = radius | |
| 32 | + | |
| 33 | + def GetRepresentation(self, x, y, z): | |
| 34 | + """ | |
| 35 | + Return a actor that represents the point in the given x, y, z point | |
| 36 | + """ | |
| 37 | + sphere = vtk.vtkSphereSource() | |
| 38 | + sphere.SetCenter(x, y, z) | |
| 39 | + sphere.SetRadius(self.radius) | |
| 40 | + | |
| 41 | + c = vtk.vtkCoordinate() | |
| 42 | + c.SetCoordinateSystemToWorld() | |
| 43 | + | |
| 44 | + m = vtk.vtkPolyDataMapper2D() | |
| 45 | + m.SetInputConnection(sphere.GetOutputPort()) | |
| 46 | + m.SetTransformCoordinate(c) | |
| 47 | + | |
| 48 | + a = vtk.vtkActor2D() | |
| 49 | + a.SetMapper(m) | |
| 50 | + a.GetProperty().SetColor(self.color) | |
| 51 | + | |
| 52 | + return a | |
| 53 | + | |
| 54 | +class CrossPointRepresentation(object): | |
| 55 | + """ | |
| 56 | + This class represents a cross that indicate a point in the surface | |
| 57 | + """ | |
| 58 | + def __init__(self, camera, color=(1, 0, 0), size=1.0): | |
| 59 | + """ | |
| 60 | + color: the color of the representation | |
| 61 | + size: the size of the representation | |
| 62 | + camera: the active camera, to get the orientation to draw the cross | |
| 63 | + """ | |
| 64 | + self.camera = camera | |
| 65 | + self.color = color | |
| 66 | + self.size = size | |
| 67 | + | |
| 68 | + def GetRepresentation(self, x, y, z): | |
| 69 | + pc = self.camera.GetPosition() # camera position | |
| 70 | + pf = self.camera.GetFocalPoint() # focal position | |
| 71 | + pp = (x, y, z) # point where the user clicked | |
| 72 | + | |
| 73 | + # Vector from camera position to user clicked point | |
| 74 | + vcp = [j-i for i,j in zip(pc, pp)] | |
| 75 | + # Vector from camera position to camera focal point | |
| 76 | + vcf = [j-i for i,j in zip(pc, pf)] | |
| 77 | + # the vector where the perpendicular vector will be given | |
| 78 | + n = [0,0,0] | |
| 79 | + # The cross, or vectorial product, give a vector perpendicular to vcp | |
| 80 | + # and vcf, in this case this vector will be in horizontal, this vector | |
| 81 | + # will be stored in the variable "n" | |
| 82 | + vtk.vtkMath.Cross(vcp, vcf, n) | |
| 83 | + # then normalize n to only indicate the direction of this vector | |
| 84 | + vtk.vtkMath.Normalize(n) | |
| 85 | + # then | |
| 86 | + p1 = [i*self.size + j for i,j in zip(n, pp)] | |
| 87 | + p2 = [i*-self.size + j for i,j in zip(n, pp)] | |
| 88 | + | |
| 89 | + sh = vtk.vtkLineSource() | |
| 90 | + sh.SetPoint1(p1) | |
| 91 | + sh.SetPoint2(p2) | |
| 92 | + | |
| 93 | + n = [0,0,0] | |
| 94 | + vcn = [j-i for i,j in zip(p1, pc)] | |
| 95 | + vtk.vtkMath.Cross(vcp, vcn, n) | |
| 96 | + vtk.vtkMath.Normalize(n) | |
| 97 | + p3 = [i*self.size + j for i,j in zip(n, pp)] | |
| 98 | + p4 = [i*-self.size +j for i,j in zip(n, pp)] | |
| 99 | + | |
| 100 | + sv = vtk.vtkLineSource() | |
| 101 | + sv.SetPoint1(p3) | |
| 102 | + sv.SetPoint2(p4) | |
| 103 | + | |
| 104 | + cruz = vtk.vtkAppendPolyData() | |
| 105 | + cruz.AddInput(sv.GetOutput()) | |
| 106 | + cruz.AddInput(sh.GetOutput()) | |
| 107 | + | |
| 108 | + c = vtk.vtkCoordinate() | |
| 109 | + c.SetCoordinateSystemToWorld() | |
| 110 | + | |
| 111 | + m = vtk.vtkPolyDataMapper2D() | |
| 112 | + m.SetInputConnection(cruz.GetOutputPort()) | |
| 113 | + m.SetTransformCoordinate(c) | |
| 114 | + | |
| 115 | + a = vtk.vtkActor2D() | |
| 116 | + a.SetMapper(m) | |
| 117 | + a.GetProperty().SetColor(self.color) | |
| 118 | + return a | |
| 119 | + | |
| 120 | +class LinearMeasure(object): | |
| 121 | + def __init__(self, render, color=(1, 0, 0), representation=None): | |
| 122 | + self.color = color | |
| 123 | + self.points = [] | |
| 124 | + self.point_actor1 = None | |
| 125 | + self.point_actor2 = None | |
| 126 | + self.line_actor = None | |
| 127 | + self.render = render | |
| 128 | + if not representation: | |
| 129 | + representation = CirclePointRepresentation() | |
| 130 | + self.representation = representation | |
| 131 | + print color | |
| 132 | + | |
| 133 | + def SetPoint1(self, x, y, z): | |
| 134 | + self.points.append((x, y, z)) | |
| 135 | + self.point_actor1 = self.representation.GetRepresentation(x, y, z) | |
| 136 | + self.render.AddActor(self.point_actor1) | |
| 137 | + | |
| 138 | + def SetPoint2(self, x, y, z): | |
| 139 | + self.points.append((x, y, z)) | |
| 140 | + self.point_actor2 = self.representation.GetRepresentation(x, y, z) | |
| 141 | + self.render.AddActor(self.point_actor2) | |
| 142 | + self.CreateMeasure() | |
| 143 | + | |
| 144 | + def CreateMeasure(self): | |
| 145 | + self._draw_line() | |
| 146 | + self._draw_text() | |
| 147 | + | |
| 148 | + def _draw_line(self): | |
| 149 | + line = vtk.vtkLineSource() | |
| 150 | + line.SetPoint1(self.points[0]) | |
| 151 | + line.SetPoint2(self.points[1]) | |
| 152 | + | |
| 153 | + c = vtk.vtkCoordinate() | |
| 154 | + c.SetCoordinateSystemToWorld() | |
| 155 | + | |
| 156 | + m = vtk.vtkPolyDataMapper2D() | |
| 157 | + m.SetInputConnection(line.GetOutputPort()) | |
| 158 | + m.SetTransformCoordinate(c) | |
| 159 | + | |
| 160 | + a = vtk.vtkActor2D() | |
| 161 | + a.SetMapper(m) | |
| 162 | + a.GetProperty().SetColor(self.color) | |
| 163 | + self.line_actor = a | |
| 164 | + self.render.AddActor(self.line_actor) | |
| 165 | + | |
| 166 | + def _draw_text(self): | |
| 167 | + p1, p2 = self.points | |
| 168 | + text = ' %.2f mm ' % \ | |
| 169 | + math.sqrt(vtk.vtkMath.Distance2BetweenPoints(p1, p2)) | |
| 170 | + x,y,z=[(i+j)/2 for i,j in zip(p1, p2)] | |
| 171 | + textsource = vtk.vtkTextSource() | |
| 172 | + textsource.SetText(text) | |
| 173 | + textsource.SetBackgroundColor((250/255.0, 247/255.0, 218/255.0)) | |
| 174 | + textsource.SetForegroundColor(self.color) | |
| 175 | + | |
| 176 | + m = vtk.vtkPolyDataMapper2D() | |
| 177 | + m.SetInputConnection(textsource.GetOutputPort()) | |
| 178 | + | |
| 179 | + a = vtk.vtkActor2D() | |
| 180 | + a.SetMapper(m) | |
| 181 | + a.DragableOn() | |
| 182 | + a.GetPositionCoordinate().SetCoordinateSystemToWorld() | |
| 183 | + a.GetPositionCoordinate().SetValue(x,y,z) | |
| 184 | + self.text_actor = a | |
| 185 | + self.render.AddActor(self.text_actor) | |
| 186 | + | |
| 187 | + def GetNumberOfPoints(self): | |
| 188 | + return len(self.points) | |
| 189 | + | |
| 190 | + def GetValue(self): | |
| 191 | + p1, p2 = self.points | |
| 192 | + return math.sqrt(vtk.vtkMath.Distance2BetweenPoints(p1, p2)) | |
| 193 | + | |
| 194 | + def SetVisibility(self, v): | |
| 195 | + self.point_actor1.SetVisibility(v) | |
| 196 | + self.point_actor2.SetVisibility(v) | |
| 197 | + self.line_actor.SetVisibility(v) | |
| 198 | + self.text_actor.SetVisibility(v) | |
| 199 | + | |
| 200 | + | |
| 201 | +class AngularMeasure(object): | |
| 202 | + def __init__(self, render, color=(1, 0, 0), representation=None): | |
| 203 | + self.color = color | |
| 204 | + self.points = [0, 0, 0] | |
| 205 | + self.number_of_points = 0 | |
| 206 | + self.point_actor1 = None | |
| 207 | + self.point_actor2 = None | |
| 208 | + self.point_actor3 = None | |
| 209 | + self.line_actor = None | |
| 210 | + self.render = render | |
| 211 | + if not representation: | |
| 212 | + representation = CirclePointRepresentation() | |
| 213 | + self.representation = representation | |
| 214 | + print color | |
| 215 | + | |
| 216 | + def SetPoint1(self, x, y, z): | |
| 217 | + self.points[0] = (x, y, z) | |
| 218 | + self.number_of_points = 1 | |
| 219 | + self.point_actor1 = self.representation.GetRepresentation(x, y, z) | |
| 220 | + self.render.AddActor(self.point_actor1) | |
| 221 | + | |
| 222 | + def SetPoint2(self, x, y, z): | |
| 223 | + self.number_of_points = 2 | |
| 224 | + self.points[1] = (x, y, z) | |
| 225 | + self.point_actor2 = self.representation.GetRepresentation(x, y, z) | |
| 226 | + self.render.AddActor(self.point_actor2) | |
| 227 | + | |
| 228 | + def SetPoint3(self, x, y, z): | |
| 229 | + self.number_of_points = 3 | |
| 230 | + self.points[2] = (x, y, z) | |
| 231 | + self.point_actor3 = self.representation.GetRepresentation(x, y, z) | |
| 232 | + self.render.AddActor(self.point_actor3) | |
| 233 | + | |
| 234 | + def _draw_line(self): | |
| 235 | + line1 = vtk.vtkLineSource() | |
| 236 | + line1.SetPoint1(self.points[0]) | |
| 237 | + line1.SetPoint2(self.points[1]) | |
| 238 | + | |
| 239 | + line2 = vtk.vtkLineSource() | |
| 240 | + line2.SetPoint1(self.points[1]) | |
| 241 | + line2.SetPoint2(self.points[2]) | |
| 242 | + | |
| 243 | + arc = self.DrawArc() | |
| 244 | + | |
| 245 | + line = vtk.vtkAppendPolyData() | |
| 246 | + line.AddInput(line1.GetOutput()) | |
| 247 | + line.AddInput(line2.GetOutput()) | |
| 248 | + line.AddInput(arc.GetOutput()) | |
| 249 | + | |
| 250 | + c = vtk.vtkCoordinate() | |
| 251 | + c.SetCoordinateSystemToWorld() | |
| 252 | + | |
| 253 | + m = vtk.vtkPolyDataMapper2D() | |
| 254 | + m.SetInputConnection(line.GetOutputPort()) | |
| 255 | + m.SetTransformCoordinate(c) | |
| 256 | + | |
| 257 | + a = vtk.vtkActor2D() | |
| 258 | + a.SetMapper(m) | |
| 259 | + a.GetProperty().SetColor(self.color) | |
| 260 | + self.line_actor = a | |
| 261 | + return a | |
| 262 | + | |
| 263 | + def DrawArc(self): | |
| 264 | + | |
| 265 | + d1 = math.sqrt(vtk.vtkMath.Distance2BetweenPoints(self.points[0], | |
| 266 | + self.points[1])) | |
| 267 | + d2 = math.sqrt(vtk.vtkMath.Distance2BetweenPoints(self.points[2], | |
| 268 | + self.points[1])) | |
| 269 | + | |
| 270 | + if d1 < d2: | |
| 271 | + d = d1 | |
| 272 | + p1 = self.points[0] | |
| 273 | + a,b,c = [j-i for i,j in zip(self.points[1], self.points[2])] | |
| 274 | + else: | |
| 275 | + d = d2 | |
| 276 | + p1 = self.points[2] | |
| 277 | + a,b,c = [j-i for i,j in zip(self.points[1], self.points[0])] | |
| 278 | + | |
| 279 | + t = (d / math.sqrt(a**2 + b**2 + c**2)) | |
| 280 | + x = self.points[1][0] + a*t | |
| 281 | + y = self.points[1][1] + b*t | |
| 282 | + z = self.points[1][2] + c*t | |
| 283 | + p2 = (x, y, z) | |
| 284 | + | |
| 285 | + arc = vtk.vtkArcSource() | |
| 286 | + arc.SetPoint1(p1) | |
| 287 | + arc.SetPoint2(p2) | |
| 288 | + arc.SetCenter(self.points[1]) | |
| 289 | + arc.SetResolution(20) | |
| 290 | + return arc | |
| 291 | + | |
| 292 | + def _draw_text(self): | |
| 293 | + text = u' %.2f ' % \ | |
| 294 | + self.CalculateAngle() | |
| 295 | + x,y,z= self.points[1] | |
| 296 | + textsource = vtk.vtkTextSource() | |
| 297 | + textsource.SetText(text) | |
| 298 | + textsource.SetBackgroundColor((250/255.0, 247/255.0, 218/255.0)) | |
| 299 | + textsource.SetForegroundColor(self.color) | |
| 300 | + | |
| 301 | + m = vtk.vtkPolyDataMapper2D() | |
| 302 | + m.SetInputConnection(textsource.GetOutputPort()) | |
| 303 | + | |
| 304 | + a = vtk.vtkActor2D() | |
| 305 | + a.SetMapper(m) | |
| 306 | + a.DragableOn() | |
| 307 | + a.GetPositionCoordinate().SetCoordinateSystemToWorld() | |
| 308 | + a.GetPositionCoordinate().SetValue(x,y,z) | |
| 309 | + self.text_actor = a | |
| 310 | + return a | |
| 311 | + | |
| 312 | + def GetNumberOfPoints(self): | |
| 313 | + return self.number_of_points | |
| 314 | + | |
| 315 | + def GetValue(self): | |
| 316 | + return self.CalculateAngle() | |
| 317 | + | |
| 318 | + def SetVisibility(self, v): | |
| 319 | + self.point_actor1.SetVisibility(v) | |
| 320 | + self.point_actor2.SetVisibility(v) | |
| 321 | + self.point_actor3.SetVisibility(v) | |
| 322 | + self.line_actor.SetVisibility(v) | |
| 323 | + self.text_actor.SetVisibility(v) | |
| 324 | + | |
| 325 | + def CalculateAngle(self): | |
| 326 | + """ | |
| 327 | + Calculate the angle between 2 vectors in 3D space. It is based on law of | |
| 328 | + cosines for vector. | |
| 329 | + The Alpha Cosine is equal the dot product from two vector divided for | |
| 330 | + product between the magnitude from that vectors. Then the angle is inverse | |
| 331 | + cosine. | |
| 332 | + """ | |
| 333 | + v1 = [j-i for i,j in zip(self.points[0], self.points[1])] | |
| 334 | + v2 = [j-i for i,j in zip(self.points[2], self.points[1])] | |
| 335 | + #print vtk.vtkMath.Normalize(v1) | |
| 336 | + #print vtk.vtkMath.Normalize(v2) | |
| 337 | + cos = vtk.vtkMath.Dot(v1, v2)/(vtk.vtkMath.Norm(v1)*vtk.vtkMath.Norm(v2)) | |
| 338 | + angle = math.degrees(math.acos(cos)) | |
| 339 | + return angle | |
| 340 | + | |
| 341 | + | ... | ... |
invesalius/data/viewer_volume.py
| ... | ... | @@ -30,6 +30,8 @@ import project as prj |
| 30 | 30 | import style as st |
| 31 | 31 | import utils |
| 32 | 32 | |
| 33 | +from data import measures | |
| 34 | + | |
| 33 | 35 | class Viewer(wx.Panel): |
| 34 | 36 | def __init__(self, parent): |
| 35 | 37 | wx.Panel.__init__(self, parent, size=wx.Size(320, 320)) |
| ... | ... | @@ -88,6 +90,10 @@ class Viewer(wx.Panel): |
| 88 | 90 | self.seed_points = [] |
| 89 | 91 | |
| 90 | 92 | self.points_reference = [] |
| 93 | + | |
| 94 | + self.measure_picker = vtk.vtkPointPicker() | |
| 95 | + self.measure_picker.SetTolerance(0.005) | |
| 96 | + self.measures = [] | |
| 91 | 97 | |
| 92 | 98 | |
| 93 | 99 | def __bind_events(self): |
| ... | ... | @@ -287,7 +293,11 @@ class Viewer(wx.Panel): |
| 287 | 293 | const.VOLUME_STATE_SEED: |
| 288 | 294 | { |
| 289 | 295 | "LeftButtonPressEvent": self.OnInsertSeed |
| 290 | - } | |
| 296 | + }, | |
| 297 | + const.STATE_LINEAR_MEASURE: | |
| 298 | + { | |
| 299 | + "LeftButtonPressEvent": self.OnInsertLinearMeasurePoint | |
| 300 | + } | |
| 291 | 301 | } |
| 292 | 302 | |
| 293 | 303 | if state == const.STATE_WL: |
| ... | ... | @@ -309,6 +319,9 @@ class Viewer(wx.Panel): |
| 309 | 319 | self.interactor.SetInteractorStyle(style) |
| 310 | 320 | self.style = style |
| 311 | 321 | |
| 322 | + if state == const.STATE_LINEAR_MEASURE: | |
| 323 | + self.interactor.SetPicker(self.measure_picker) | |
| 324 | + | |
| 312 | 325 | # Check each event available for each mode |
| 313 | 326 | for event in action[state]: |
| 314 | 327 | # Bind event |
| ... | ... | @@ -590,6 +603,21 @@ class Viewer(wx.Panel): |
| 590 | 603 | self.seed_points.append(point_id) |
| 591 | 604 | self.interactor.Render() |
| 592 | 605 | |
| 606 | + def OnInsertLinearMeasurePoint(self, obj, evt): | |
| 607 | + print "Hey, you inserted measure point" | |
| 608 | + x,y = self.interactor.GetEventPosition() | |
| 609 | + self.measure_picker.Pick(x, y, 0, self.ren) | |
| 610 | + x, y, z = self.measure_picker.GetPickPosition() | |
| 611 | + if self.measure_picker.GetPointId() != -1: | |
| 612 | + if not self.measures or self.measures[-1].point_actor2: | |
| 613 | + m = measures.LinearMeasure(self.ren) | |
| 614 | + m.SetPoint1(x, y, z) | |
| 615 | + self.measures.append(m) | |
| 616 | + else: | |
| 617 | + m = self.measures[-1] | |
| 618 | + m.SetPoint2(x, y, z) | |
| 619 | + self.interactor.Render() | |
| 620 | + | |
| 593 | 621 | |
| 594 | 622 | class SlicePlane: |
| 595 | 623 | def __init__(self): | ... | ... |
invesalius/gui/data_notebook.py
| ... | ... | @@ -50,8 +50,8 @@ class NotebookPanel(wx.Panel): |
| 50 | 50 | |
| 51 | 51 | book.AddPage(MaskPage(book), _("Masks")) |
| 52 | 52 | book.AddPage(SurfacePage(book), _("Surfaces")) |
| 53 | - #book.AddPage(MeasuresListCtrlPanel(book), _("Measures")) | |
| 54 | - #book.AddPage(AnnotationsListCtrlPanel(book), _("Annotations")) | |
| 53 | + book.AddPage(MeasuresListCtrlPanel(book), _("Measures")) | |
| 54 | + book.AddPage(AnnotationsListCtrlPanel(book), _("Annotations")) | |
| 55 | 55 | |
| 56 | 56 | book.SetSelection(0) |
| 57 | 57 | ... | ... |
invesalius/gui/default_tasks.py
| ... | ... | @@ -144,15 +144,15 @@ class LowerTaskPanel(wx.Panel): |
| 144 | 144 | # Fold 2 - Tools |
| 145 | 145 | # Measures |
| 146 | 146 | # Text Annotations |
| 147 | - #item = fold_panel.AddFoldPanel(_("Tools"), collapsed=False, | |
| 148 | - # foldIcons=image_list) | |
| 149 | - #style = fold_panel.GetCaptionStyle(item) | |
| 150 | - #col = style.GetFirstColour() | |
| 151 | - #self.enable_items.append(item) | |
| 152 | - # | |
| 153 | - #fold_panel.AddFoldPanelWindow(item, tools.TaskPanel(item), Spacing= 0, | |
| 154 | - # leftSpacing=0, rightSpacing=0) | |
| 155 | - #fold_panel.Expand(fold_panel.GetFoldPanel(1)) | |
| 147 | + item = fold_panel.AddFoldPanel(_("Tools"), collapsed=False, | |
| 148 | + foldIcons=image_list) | |
| 149 | + style = fold_panel.GetCaptionStyle(item) | |
| 150 | + col = style.GetFirstColour() | |
| 151 | + self.enable_items.append(item) | |
| 152 | + | |
| 153 | + fold_panel.AddFoldPanelWindow(item, tools.TaskPanel(item), Spacing= 0, | |
| 154 | + leftSpacing=0, rightSpacing=0) | |
| 155 | + fold_panel.Expand(fold_panel.GetFoldPanel(1)) | |
| 156 | 156 | |
| 157 | 157 | self.SetStateProjectClose() |
| 158 | 158 | self.__bind_events() | ... | ... |
invesalius/gui/task_tools.py
| ... | ... | @@ -18,9 +18,12 @@ |
| 18 | 18 | #-------------------------------------------------------------------------- |
| 19 | 19 | |
| 20 | 20 | import wx |
| 21 | +import wx.lib.embeddedimage as emb | |
| 21 | 22 | import wx.lib.hyperlink as hl |
| 22 | 23 | import wx.lib.platebtn as pbtn |
| 23 | -import wx.lib.embeddedimage as emb | |
| 24 | +import wx.lib.pubsub as ps | |
| 25 | + | |
| 26 | +import constants | |
| 24 | 27 | |
| 25 | 28 | ID_BTN_MEASURE_LINEAR = wx.NewId() |
| 26 | 29 | ID_BTN_MEASURE_ANGULAR = wx.NewId() |
| ... | ... | @@ -118,7 +121,9 @@ class InnerTaskPanel(wx.Panel): |
| 118 | 121 | print "TODO: Send Signal - Add text annotation (both 2d and 3d)" |
| 119 | 122 | |
| 120 | 123 | def OnLinkLinearMeasure(self): |
| 121 | - print "TODO: Send Signal - Add linear measure (both 2d and 3d)" | |
| 124 | + #print "TODO: Send Signal - Add linear measure (both 2d and 3d)" | |
| 125 | + ps.Publisher().sendMessage('Enable style', | |
| 126 | + constants.STATE_LINEAR_MEASURE) | |
| 122 | 127 | |
| 123 | 128 | def OnLinkAngularMeasure(self): |
| 124 | 129 | print "TODO: Send Signal - Add angular measure (both 2d and 3d)" | ... | ... |