diff --git a/invesalius/gui/task_navigator.py b/invesalius/gui/task_navigator.py index 8cd0bb1..4985295 100644 --- a/invesalius/gui/task_navigator.py +++ b/invesalius/gui/task_navigator.py @@ -201,7 +201,12 @@ class InnerFoldPanel(wx.Panel): # Fold 2 - Object registration panel item = fold_panel.AddFoldPanel(_("Object registration"), collapsed=True) - otw = ObjectRegistrationPanel(item, tracker, pedal_connection) + otw = ObjectRegistrationPanel( + parent=item, + tracker=tracker, + pedal_connection=pedal_connection, + neuronavigation_api=neuronavigation_api, + ) fold_panel.ApplyCaptionStyle(item, style) fold_panel.AddFoldPanelWindow(item, otw, spacing=0, @@ -889,7 +894,7 @@ class NeuronavigationPanel(wx.Panel): class ObjectRegistrationPanel(wx.Panel): - def __init__(self, parent, tracker, pedal_connection): + def __init__(self, parent, tracker, pedal_connection, neuronavigation_api): wx.Panel.__init__(self, parent) try: default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) @@ -901,6 +906,7 @@ class ObjectRegistrationPanel(wx.Panel): self.tracker = tracker self.pedal_connection = pedal_connection + self.neuronavigation_api = neuronavigation_api self.nav_prop = None self.obj_fiducials = None @@ -917,7 +923,7 @@ class ObjectRegistrationPanel(wx.Panel): btn_new = wx.Button(self, -1, _("New"), size=wx.Size(65, 23)) btn_new.SetToolTip(tooltip) btn_new.Enable(1) - btn_new.Bind(wx.EVT_BUTTON, self.OnLinkCreate) + btn_new.Bind(wx.EVT_BUTTON, self.OnCreateNewCoil) self.btn_new = btn_new # Button for import config coil file @@ -1060,13 +1066,16 @@ class ObjectRegistrationPanel(wx.Panel): coil_index = evt.GetSelection() Publisher.sendMessage('Change selected coil', self.coil_list[coil_index][1]) - def OnLinkCreate(self, event=None): + def OnCreateNewCoil(self, event=None): if self.tracker.IsTrackerInitialized(): dialog = dlg.ObjectCalibrationDialog(self.tracker, self.pedal_connection) try: if dialog.ShowModal() == wx.ID_OK: self.obj_fiducials, self.obj_orients, self.obj_ref_mode, self.obj_name, polydata, use_default_object = dialog.GetValue() + + self.neuronavigation_api.update_coil_mesh(polydata) + if np.isfinite(self.obj_fiducials).all() and np.isfinite(self.obj_orients).all(): self.checktrack.Enable(1) Publisher.sendMessage('Update object registration', diff --git a/invesalius/net/neuronavigation_api.py b/invesalius/net/neuronavigation_api.py index 60b81da..dfc99de 100644 --- a/invesalius/net/neuronavigation_api.py +++ b/invesalius/net/neuronavigation_api.py @@ -20,6 +20,9 @@ from invesalius.pubsub import pub as Publisher from invesalius.utils import Singleton +import numpy as np +from vtk.numpy_interface import dataset_adapter + class NeuronavigationApi(metaclass=Singleton): """ An API used internally in InVesalius to communicate with the @@ -34,6 +37,8 @@ class NeuronavigationApi(metaclass=Singleton): If connection object is not given or it is None, skip doing the updates. """ + N_VERTICES_IN_POLYGON = 3 + def __init__(self, connection=None): if connection is not None: assert self._hasmethod(connection, 'update_coil_pose') @@ -65,3 +70,28 @@ class NeuronavigationApi(metaclass=Singleton): position=position, orientation=orientation, ) + + def update_coil_mesh(self, polydata): + wrapped = dataset_adapter.WrapDataObject(polydata) + + points = np.asarray(wrapped.Points) + polygons_raw = np.asarray(wrapped.Polygons) + + # The polygons are returned as 1d-array of the form + # + # [n_0, id_0(0), id_0(1), ..., id_0(n_0), + # n_1, id_1(0), id_1(1), ..., id_1(n_1), + # ...] + # + # where n_i is the number of vertices in polygon i, and id_i's are indices to the vertex list. + # + # Assert that all polygons have an equal number of vertices, reshape the array, and drop n_i's. + # + assert np.all(polygons_raw[0::self.N_VERTICES_IN_POLYGON + 1] == self.N_VERTICES_IN_POLYGON) + + polygons = polygons_raw.reshape(-1, self.N_VERTICES_IN_POLYGON + 1)[:, 1:] + + self.connection.update_coil_mesh( + points=points, + polygons=polygons, + ) -- libgit2 0.21.2