diff --git a/invesalius/constants.py b/invesalius/constants.py index 9ff2271..9c76305 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -28,7 +28,7 @@ from project import Project #--------------- # Measurements -MEASURE_NAME_PATTERN = _("M %d") +MEASURE_NAME_PATTERN = _("M %d") MEASURE_LINEAR = 101 MEASURE_ANGULAR = 102 @@ -79,6 +79,10 @@ SAGITAL = 3 VOLUME = 4 SURFACE = 5 +# Measure type +LINEAR = 6 +ANGULAR = 7 + # Colour representing each orientation ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red 'CORONAL': (0,1,0), # Green diff --git a/invesalius/control.py b/invesalius/control.py index c468ae9..14b50c4 100755 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -24,16 +24,16 @@ import tempfile import wx.lib.pubsub as ps import constants as const -import project as prj - import data.imagedata_utils as utils import data.mask as msk +import data.measures import data.surface as srf import data.volume as volume -import reader.dicom_grouper as dg import gui.dialogs as dialog -import reader.dicom_reader as dcm +import project as prj import reader.analyze_reader as analyze +import reader.dicom_grouper as dg +import reader.dicom_reader as dcm import session as ses from utils import debug @@ -51,6 +51,8 @@ class Controller(): self.cancel_import = False #Init session session = ses.Session() + self.measure_manager = data.measures.MeasurementManager() + def __bind_events(self): ps.Publisher().subscribe(self.OnImportMedicalImages, 'Import directory') diff --git a/invesalius/data/measures.py b/invesalius/data/measures.py index 3ad7aac..7e6d868 100644 --- a/invesalius/data/measures.py +++ b/invesalius/data/measures.py @@ -1,23 +1,89 @@ #!/usr/bin/env python # -*- coding: UTF-8 -*- -# This example demonstrates the use of vtkSTLReader to load data into -# VTK from a file. This example also uses vtkLODActor which changes -# its graphical representation of the data to maintain interactive -# performance. - - -from itertools import cycle import math -import os -import sys -import time +import random -import wx +import wx.lib.pubsub as ps import vtk import constants as const +TYPE = {const.LINEAR: _(u"Linear"), + const.ANGULAR: _(u"Angular"), + } + +LOCATION = {const.SURFACE: _(u"3D"), + const.AXIAL: _(u"Axial"), + const.CORONAL: _(u"Coronal"), + const.SAGITAL: _(u"Sagittal") + } + +class MeasurementManager(object): + """ + A class to manage the use (Addition, remotion and visibility) from + measures. + """ + def __init__(self): + self.current = None + self.measures = [] + self._bind_events() + + def _bind_events(self): + ps.Publisher().subscribe(self._add_point, "Add measurement point") + + def _add_point(self, pubsub_evt): + position = pubsub_evt.data[0] + type = pubsub_evt.data[1] # Linear or Angular + location = pubsub_evt.data[2] # 3D, AXIAL, SAGITAL, CORONAL + try: + slice_number = pubsub_evt.data[3] + except IndexError: + slice_number = 0 + + if self.current is None: + to_create = True + elif self.current[0].slice_number != slice_number: + to_create = True + elif self.current[0].location != location: + to_create = True + else: + to_create = False + + if to_create: + m = Measurement() + m.location = location + m.points.append(position) + m.slice_number = slice_number + if type == const.LINEAR: + mr = LinearMeasure(m.colour) + else: + mr = AngularMeasure(m.colour) + self.current = (m, mr) + + x, y, z = position + actors = self.current[1].AddPoint(x, y, z) + ps.Publisher().sendMessage(("Add Actors", location), actors) + + if self.current[1].IsComplete(): + self.measures.append(self.current) + index = self.current[0].index + name = self.current[0].name + colour = self.current[0].colour + self.current[0].value = self.current[1].GetValue() + type_ = TYPE[type] + location = LOCATION[location] + value = u"%.2f mm"% self.current[0].value + + msg = 'Update measurement info in GUI', + ps.Publisher().sendMessage(msg, + (index, name, colour, + type_, location, + value)) + self.current = None + + + class Measurement(): general_index = -1 def __init__(self): @@ -28,6 +94,7 @@ class Measurement(): self.value = None self.location = const.SURFACE # AXIAL, CORONAL, SAGITTAL self.type = const.LINEAR # ANGULAR + self.slice_number = 0 self.points = [] self.is_shown = False @@ -131,16 +198,15 @@ class CrossPointRepresentation(object): return a class LinearMeasure(object): - def __init__(self, render, colour=(1, 0, 0), representation=None): + def __init__(self, colour=(1, 0, 0), representation=None): self.colour = colour self.points = [] self.point_actor1 = None self.point_actor2 = None self.line_actor = None self.text_actor = None - self.render = render if not representation: - representation = CirclePointRepresentation() + representation = CirclePointRepresentation(colour) self.representation = representation print colour @@ -153,18 +219,18 @@ class LinearMeasure(object): def AddPoint(self, x, y, z): if not self.point_actor1: self.SetPoint1(x, y, z) + return (self.point_actor1, ) elif not self.point_actor2: self.SetPoint2(x, y, z) + return (self.point_actor2, self.line_actor, self.text_actor) def SetPoint1(self, x, y, z): self.points.append((x, y, z)) self.point_actor1 = self.representation.GetRepresentation(x, y, z) - self.render.AddActor(self.point_actor1) def SetPoint2(self, x, y, z): self.points.append((x, y, z)) self.point_actor2 = self.representation.GetRepresentation(x, y, z) - self.render.AddActor(self.point_actor2) self.CreateMeasure() def CreateMeasure(self): @@ -187,7 +253,6 @@ class LinearMeasure(object): a.SetMapper(m) a.GetProperty().SetColor(self.colour) self.line_actor = a - self.render.AddActor(self.line_actor) def _draw_text(self): p1, p2 = self.points @@ -207,8 +272,8 @@ class LinearMeasure(object): a.DragableOn() a.GetPositionCoordinate().SetCoordinateSystemToWorld() a.GetPositionCoordinate().SetValue(x,y,z) + a.GetProperty().SetColor((0, 1, 0)) self.text_actor = a - self.render.AddActor(self.text_actor) def GetNumberOfPoints(self): return len(self.points) @@ -264,7 +329,7 @@ class LinearMeasure(object): class AngularMeasure(object): - def __init__(self, render, colour=(1, 0, 0), representation=None): + def __init__(self, colour=(1, 0, 0), representation=None): self.colour = colour self.points = [0, 0, 0] self.number_of_points = 0 @@ -273,9 +338,8 @@ class AngularMeasure(object): self.point_actor3 = None self.line_actor = None self.text_actor = None - self.render = render if not representation: - representation = CirclePointRepresentation() + representation = CirclePointRepresentation(colour) self.representation = representation print colour @@ -285,28 +349,28 @@ class AngularMeasure(object): def AddPoint(self, x, y, z): if not self.point_actor1: self.SetPoint1(x, y, z) + return (self.point_actor1,) elif not self.point_actor2: self.SetPoint2(x, y, z) + return (self.point_actor2,) elif not self.point_actor3: self.SetPoint3(x, y, z) + return (self.point_actor3, self.line_actor, self.text_actor) def SetPoint1(self, x, y, z): self.points[0] = (x, y, z) self.number_of_points = 1 self.point_actor1 = self.representation.GetRepresentation(x, y, z) - self.render.AddActor(self.point_actor1) def SetPoint2(self, x, y, z): self.number_of_points = 2 self.points[1] = (x, y, z) self.point_actor2 = self.representation.GetRepresentation(x, y, z) - self.render.AddActor(self.point_actor2) def SetPoint3(self, x, y, z): self.number_of_points = 3 self.points[2] = (x, y, z) self.point_actor3 = self.representation.GetRepresentation(x, y, z) - self.render.AddActor(self.point_actor3) self.CreateMeasure() def CreateMeasure(self): @@ -340,7 +404,6 @@ class AngularMeasure(object): a.SetMapper(m) a.GetProperty().SetColor(self.colour) self.line_actor = a - self.render.AddActor(self.line_actor) def DrawArc(self): @@ -389,7 +452,6 @@ class AngularMeasure(object): a.GetPositionCoordinate().SetCoordinateSystemToWorld() a.GetPositionCoordinate().SetValue(x,y,z) self.text_actor = a - self.render.AddActor(self.text_actor) def GetNumberOfPoints(self): return self.number_of_points diff --git a/invesalius/data/viewer_slice.py b/invesalius/data/viewer_slice.py index e902bb6..b38959a 100755 --- a/invesalius/data/viewer_slice.py +++ b/invesalius/data/viewer_slice.py @@ -44,9 +44,9 @@ ID_TO_TOOL_ITEM = {} STR_WL = "WL: %d WW: %d" ORIENTATIONS = { - "AXIAL": _("Axial"), - "CORONAL": _("Coronal"), - "SAGITAL": _("Sagital"), + "AXIAL": const.AXIAL, + "CORONAL": const.CORONAL, + "SAGITAL": const.SAGITAL, } class Viewer(wx.Panel): @@ -863,6 +863,8 @@ class Viewer(wx.Panel): ps.Publisher().subscribe(self.OnExportPicture,'Export picture to file') ps.Publisher().subscribe(self.SetDefaultCursor, 'Set interactor default cursor') + ps.Publisher().subscribe(self.AddActors, ('Add Actors', ORIENTATIONS[self.orientation])) + def SetDefaultCursor(self, pusub_evt): self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) @@ -1444,17 +1446,21 @@ class Viewer(wx.Panel): x, y, z = self.pick.GetPickPosition() if self.pick.GetViewProp(): print "Hey, you inserted measure point" - if not self.measures or self.measures[-1][1].IsComplete(): - m = measures.LinearMeasure(render) - m.AddPoint(x, y, z) - self.measures.append((slice_number, m)) - else: - m = self.measures[-1][1] - m.AddPoint(x, y, z) - if m.IsComplete(): - ps.Publisher().sendMessage("Add measure to list", - (ORIENTATIONS[self.orientation], - _(u"%.3f mm" % m.GetValue()))) + # if not self.measures or self.measures[-1][1].IsComplete(): + # m = measures.LinearMeasure(render) + # m.AddPoint(x, y, z) + # self.measures.append((slice_number, m)) + # else: + # m = self.measures[-1][1] + # m.AddPoint(x, y, z) + # if m.IsComplete(): + # ps.Publisher().sendMessage("Add measure to list", + # (ORIENTATIONS[self.orientation], + # _(u"%.3f mm" % m.GetValue()))) + self.render_to_add = slice_data.renderer + ps.Publisher().sendMessage("Add measurement point", + ((x, y,z), const.LINEAR, ORIENTATIONS[self.orientation], + slice_number)) self.interactor.Render() def OnInsertAngularMeasurePoint(self, obj, evt): @@ -1466,15 +1472,25 @@ class Viewer(wx.Panel): self.pick.Pick(x, y, 0, render) x, y, z = self.pick.GetPickPosition() if self.pick.GetViewProp(): - if not self.measures or self.measures[-1][1].IsComplete(): - m = measures.AngularMeasure(render) - m.AddPoint(x, y, z) - self.measures.append((slice_number, m)) - else: - m = self.measures[-1][1] - m.AddPoint(x, y, z) - if m.IsComplete(): - ps.Publisher().sendMessage("Add measure to list", - (ORIENTATIONS[self.orientation], - _(u"%.3fº" % m.GetValue()))) + # if not self.measures or self.measures[-1][1].IsComplete(): + # m = measures.AngularMeasure(render) + # m.AddPoint(x, y, z) + # self.measures.append((slice_number, m)) + # else: + # m = self.measures[-1][1] + # m.AddPoint(x, y, z) + # if m.IsComplete(): + # ps.Publisher().sendMessage("Add measure to list", + # (ORIENTATIONS[self.orientation], + # _(u"%.3fº" % m.GetValue()))) + self.render_to_add = slice_data.renderer + ps.Publisher().sendMessage("Add measurement point", + ((x, y,z), const.ANGULAR, ORIENTATIONS[self.orientation], + slice_number)) self.interactor.Render() + + def AddActors(self, pubsub_evt): + "Inserting actors" + actors = pubsub_evt.data + for actor in actors: + self.render_to_add.AddActor(actor) diff --git a/invesalius/data/viewer_volume.py b/invesalius/data/viewer_volume.py index fc8ba0e..f280191 100755 --- a/invesalius/data/viewer_volume.py +++ b/invesalius/data/viewer_volume.py @@ -142,6 +142,8 @@ class Viewer(wx.Panel): ps.Publisher().subscribe(self.OnHideText, 'Hide text actors on viewers') + ps.Publisher().subscribe(self.AddActors, ('Add Actors', const.SURFACE)) + ps.Publisher().subscribe(self.OnShowText, 'Show text actors on viewers') ps.Publisher().subscribe(self.OnCloseProject, 'Close project data') @@ -225,6 +227,12 @@ class Viewer(wx.Panel): self.text.Show() self.interactor.Render() + def AddActors(self, pubsub_evt): + "Inserting actors" + actors = pubsub_evt.data + for actor in actors: + self.ren.AddActor(actor) + def AddPointReference(self, position, radius=1, colour=(1, 0, 0)): """ Add a point representation in the given x,y,z position with a optional @@ -628,26 +636,18 @@ class Viewer(wx.Panel): self.measure_picker.Pick(x, y, 0, self.ren) x, y, z = self.measure_picker.GetPickPosition() if self.measure_picker.GetActor(): - if not self.measures or self.measures[-1].IsComplete(): - m = measures.LinearMeasure(self.ren) - m.AddPoint(x, y, z) - self.measures.append(m) - else: - m = self.measures[-1] - m.AddPoint(x, y, z) - if m.IsComplete(): - index = len(self.measures) - 1 - name = "M" - colour = m.colour - type_ = _("Linear") - location = u"3D" - value = u"%.2f mm"% m.GetValue() - - msg = 'Update measurement info in GUI', - ps.Publisher().sendMessage(msg, - (index, name, colour, - type_, location, - value)) + # if not self.measures or self.measures[-1].IsComplete(): + # m = measures.LinearMeasure(self.ren) + # m.AddPoint(x, y, z) + # self.measures.append(m) + # else: + # m = self.measures[-1] + # m.AddPoint(x, y, z) + # if m.IsComplete(): + # ps.Publisher().sendMessage("Add measure to list", + # (u"3D", _(u"%.3f mm" % m.GetValue()))) + ps.Publisher().sendMessage("Add measurement point", + ((x, y,z), const.LINEAR, const.SURFACE)) self.interactor.Render() def OnInsertAngularMeasurePoint(self, obj, evt): @@ -656,25 +656,27 @@ class Viewer(wx.Panel): self.measure_picker.Pick(x, y, 0, self.ren) x, y, z = self.measure_picker.GetPickPosition() if self.measure_picker.GetActor(): - if not self.measures or self.measures[-1].IsComplete(): - m = measures.AngularMeasure(self.ren) - m.AddPoint(x, y, z) - self.measures.append(m) - else: - m = self.measures[-1] - m.AddPoint(x, y, z) - if m.IsComplete(): - index = len(self.measures) - 1 - name = "M" - colour = m.colour - type_ = _("Angular") - location = u"3D" - value = u"%.2f˚"% m.GetValue() - msg = 'Update measurement info in GUI', - ps.Publisher().sendMessage(msg, - (index, name, colour, - type_, location, - value)) + # if not self.measures or self.measures[-1].IsComplete(): + # m = measures.AngularMeasure(self.ren) + # m.AddPoint(x, y, z) + # self.measures.append(m) + # else: + # m = self.measures[-1] + # m.AddPoint(x, y, z) + # if m.IsComplete(): + # index = len(self.measures) - 1 + # name = "M" + # colour = m.colour + # type_ = _("Angular") + # location = u"3D" + # value = u"%.2f˚"% m.GetValue() + # msg = 'Update measurement info in GUI', + # ps.Publisher().sendMessage(msg, + # (index, name, colour, + # type_, location, + # value)) + ps.Publisher().sendMessage("Add measurement point", + ((x, y,z), const.ANGULAR, const.SURFACE)) self.interactor.Render() -- libgit2 0.21.2