Commit 65bab099998acaa3f81070ebdf95fbc293756604
1 parent
da24d361
Exists in
import_mesh
Importing mesh file to invesalius
Showing
3 changed files
with
82 additions
and
1 deletions
Show diff stats
invesalius/data/surface.py
@@ -150,6 +150,8 @@ class SurfaceManager(): | @@ -150,6 +150,8 @@ class SurfaceManager(): | ||
150 | Publisher.subscribe(self.OnRemove,"Remove surfaces") | 150 | Publisher.subscribe(self.OnRemove,"Remove surfaces") |
151 | Publisher.subscribe(self.UpdateSurfaceInterpolation, 'Update Surface Interpolation') | 151 | Publisher.subscribe(self.UpdateSurfaceInterpolation, 'Update Surface Interpolation') |
152 | 152 | ||
153 | + Publisher.subscribe(self.OnImportSurfaceFile, 'Import surface file') | ||
154 | + | ||
153 | def OnDuplicate(self, pubsub_evt): | 155 | def OnDuplicate(self, pubsub_evt): |
154 | selected_items = pubsub_evt.data | 156 | selected_items = pubsub_evt.data |
155 | proj = prj.Project() | 157 | proj = prj.Project() |
@@ -241,6 +243,31 @@ class SurfaceManager(): | @@ -241,6 +243,31 @@ class SurfaceManager(): | ||
241 | new_index = self.CreateSurfaceFromPolydata(new_polydata) | 243 | new_index = self.CreateSurfaceFromPolydata(new_polydata) |
242 | Publisher.sendMessage('Show single surface', (new_index, True)) | 244 | Publisher.sendMessage('Show single surface', (new_index, True)) |
243 | 245 | ||
246 | + def OnImportSurfaceFile(self, pubsub_evt): | ||
247 | + """ | ||
248 | + Creates a new surface from a surface file (STL, PLY or VTP) | ||
249 | + """ | ||
250 | + filename = pubsub_evt.data | ||
251 | + self.CreateSurfaceFromFile(filename) | ||
252 | + | ||
253 | + def CreateSurfaceFromFile(self, filename): | ||
254 | + if filename.lower().endswith('.stl'): | ||
255 | + reader = vtk.vtkSTLReader() | ||
256 | + elif filename.lower().endswith('.ply'): | ||
257 | + reader = vtk.vtkPLYReader() | ||
258 | + elif filename.lower().endswith('.vtp'): | ||
259 | + reader = vtk.vtkXMLPolyDataReader() | ||
260 | + else: | ||
261 | + return | ||
262 | + | ||
263 | + reader.SetFileName(filename) | ||
264 | + reader.Update() | ||
265 | + polydata = reader.GetOutput() | ||
266 | + | ||
267 | + name = os.path.splitext(os.path.split(filename)[-1])[0] | ||
268 | + | ||
269 | + self.CreateSurfaceFromPolydata(polydata, name=name) | ||
270 | + | ||
244 | def CreateSurfaceFromPolydata(self, polydata, overwrite=False, | 271 | def CreateSurfaceFromPolydata(self, polydata, overwrite=False, |
245 | name=None, colour=None, | 272 | name=None, colour=None, |
246 | transparency=None, volume=None, area=None): | 273 | transparency=None, volume=None, area=None): |
invesalius/gui/data_notebook.py
@@ -40,7 +40,7 @@ import invesalius.gui.widgets.listctrl as listmix | @@ -40,7 +40,7 @@ import invesalius.gui.widgets.listctrl as listmix | ||
40 | import invesalius.utils as ul | 40 | import invesalius.utils as ul |
41 | 41 | ||
42 | 42 | ||
43 | -BTN_NEW, BTN_REMOVE, BTN_DUPLICATE = [wx.NewId() for i in xrange(3)] | 43 | +BTN_NEW, BTN_REMOVE, BTN_DUPLICATE, BTN_OPEN = [wx.NewId() for i in xrange(4)] |
44 | 44 | ||
45 | TYPE = {const.LINEAR: _(u"Linear"), | 45 | TYPE = {const.LINEAR: _(u"Linear"), |
46 | const.ANGULAR: _(u"Angular"), | 46 | const.ANGULAR: _(u"Angular"), |
@@ -594,6 +594,9 @@ class SurfaceButtonControlPanel(wx.Panel): | @@ -594,6 +594,9 @@ class SurfaceButtonControlPanel(wx.Panel): | ||
594 | BMP_DUPLICATE = wx.Bitmap(os.path.join(const.ICON_DIR, "data_duplicate.png"), | 594 | BMP_DUPLICATE = wx.Bitmap(os.path.join(const.ICON_DIR, "data_duplicate.png"), |
595 | wx.BITMAP_TYPE_PNG) | 595 | wx.BITMAP_TYPE_PNG) |
596 | 596 | ||
597 | + BMP_OPEN = wx.Bitmap(os.path.join(const.ICON_DIR, "data_duplicate.png"), | ||
598 | + wx.BITMAP_TYPE_PNG) | ||
599 | + | ||
597 | # Plate buttons based on previous bitmaps | 600 | # Plate buttons based on previous bitmaps |
598 | button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT | 601 | button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT |
599 | button_new = pbtn.PlateButton(self, BTN_NEW, "", | 602 | button_new = pbtn.PlateButton(self, BTN_NEW, "", |
@@ -608,12 +611,17 @@ class SurfaceButtonControlPanel(wx.Panel): | @@ -608,12 +611,17 @@ class SurfaceButtonControlPanel(wx.Panel): | ||
608 | BMP_DUPLICATE, | 611 | BMP_DUPLICATE, |
609 | style=button_style, | 612 | style=button_style, |
610 | size = wx.Size(24, 20)) | 613 | size = wx.Size(24, 20)) |
614 | + button_open = pbtn.PlateButton(self, BTN_OPEN, "", | ||
615 | + BMP_OPEN, | ||
616 | + style=button_style, | ||
617 | + size = wx.Size(24, 20)) | ||
611 | 618 | ||
612 | # Add all controls to gui | 619 | # Add all controls to gui |
613 | sizer = wx.BoxSizer(wx.HORIZONTAL) | 620 | sizer = wx.BoxSizer(wx.HORIZONTAL) |
614 | sizer.Add(button_new, 0, wx.GROW|wx.EXPAND|wx.LEFT) | 621 | sizer.Add(button_new, 0, wx.GROW|wx.EXPAND|wx.LEFT) |
615 | sizer.Add(button_remove, 0, wx.GROW|wx.EXPAND) | 622 | sizer.Add(button_remove, 0, wx.GROW|wx.EXPAND) |
616 | sizer.Add(button_duplicate, 0, wx.GROW|wx.EXPAND) | 623 | sizer.Add(button_duplicate, 0, wx.GROW|wx.EXPAND) |
624 | + sizer.Add(button_open, 0, wx.GROW|wx.EXPAND) | ||
617 | self.SetSizer(sizer) | 625 | self.SetSizer(sizer) |
618 | self.Fit() | 626 | self.Fit() |
619 | 627 | ||
@@ -628,6 +636,8 @@ class SurfaceButtonControlPanel(wx.Panel): | @@ -628,6 +636,8 @@ class SurfaceButtonControlPanel(wx.Panel): | ||
628 | self.OnRemove() | 636 | self.OnRemove() |
629 | elif id == BTN_DUPLICATE: | 637 | elif id == BTN_DUPLICATE: |
630 | self.OnDuplicate() | 638 | self.OnDuplicate() |
639 | + elif id == BTN_OPEN: | ||
640 | + self.OnOpenMesh() | ||
631 | 641 | ||
632 | def OnNew(self): | 642 | def OnNew(self): |
633 | sl = slice_.Slice() | 643 | sl = slice_.Slice() |
@@ -659,6 +669,11 @@ class SurfaceButtonControlPanel(wx.Panel): | @@ -659,6 +669,11 @@ class SurfaceButtonControlPanel(wx.Panel): | ||
659 | else: | 669 | else: |
660 | dlg.SurfaceSelectionRequiredForDuplication() | 670 | dlg.SurfaceSelectionRequiredForDuplication() |
661 | 671 | ||
672 | + def OnOpenMesh(self): | ||
673 | + filename = dlg.ShowImportMeshFilesDialog() | ||
674 | + if filename: | ||
675 | + Publisher.sendMessage('Import surface file', filename) | ||
676 | + | ||
662 | 677 | ||
663 | class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): | 678 | class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
664 | 679 |
invesalius/gui/dialogs.py
@@ -223,6 +223,11 @@ WILDCARD_NIFTI = "NIfTI 1 (*.nii)|*.nii|" \ | @@ -223,6 +223,11 @@ WILDCARD_NIFTI = "NIfTI 1 (*.nii)|*.nii|" \ | ||
223 | WILDCARD_PARREC = "PAR/REC (*.par)|*.par|" \ | 223 | WILDCARD_PARREC = "PAR/REC (*.par)|*.par|" \ |
224 | "All files (*.*)|*.*" | 224 | "All files (*.*)|*.*" |
225 | 225 | ||
226 | +WILDCARD_MESH_FILES = "STL (*.stl)|*.stl|" \ | ||
227 | + "PLY (*.ply)|*.ply|" \ | ||
228 | + "VTP (*.vtp)|*.vtp|" \ | ||
229 | + "All files (*.*)|*.*" | ||
230 | + | ||
226 | 231 | ||
227 | def ShowOpenProjectDialog(): | 232 | def ShowOpenProjectDialog(): |
228 | # Default system path | 233 | # Default system path |
@@ -376,6 +381,40 @@ def ShowImportOtherFilesDialog(id_type): | @@ -376,6 +381,40 @@ def ShowImportOtherFilesDialog(id_type): | ||
376 | return filename | 381 | return filename |
377 | 382 | ||
378 | 383 | ||
384 | +def ShowImportMeshFilesDialog(): | ||
385 | + # Default system path | ||
386 | + current_dir = os.path.abspath(".") | ||
387 | + dlg = wx.FileDialog(None, message=_("Import surface file"), | ||
388 | + defaultDir="", | ||
389 | + defaultFile="", wildcard=WILDCARD_MESH_FILES, | ||
390 | + style=wx.FD_OPEN | wx.FD_CHANGE_DIR) | ||
391 | + | ||
392 | + # stl filter is default | ||
393 | + dlg.SetFilterIndex(0) | ||
394 | + | ||
395 | + # Show the dialog and retrieve the user response. If it is the OK response, | ||
396 | + # process the data. | ||
397 | + filename = None | ||
398 | + try: | ||
399 | + if dlg.ShowModal() == wx.ID_OK: | ||
400 | + # GetPath returns in unicode, if a path has non-ascii characters a | ||
401 | + # UnicodeEncodeError is raised. To avoid this, path is encoded in utf-8 | ||
402 | + if sys.platform == "win32": | ||
403 | + filename = dlg.GetPath() | ||
404 | + else: | ||
405 | + filename = dlg.GetPath().encode('utf-8') | ||
406 | + | ||
407 | + except(wx._core.PyAssertionError): # TODO: error win64 | ||
408 | + if (dlg.GetPath()): | ||
409 | + filename = dlg.GetPath() | ||
410 | + | ||
411 | + # Destroy the dialog. Don't do this until you are done with it! | ||
412 | + # BAD things can happen otherwise! | ||
413 | + dlg.Destroy() | ||
414 | + os.chdir(current_dir) | ||
415 | + return filename | ||
416 | + | ||
417 | + | ||
379 | def ShowSaveAsProjectDialog(default_filename=None): | 418 | def ShowSaveAsProjectDialog(default_filename=None): |
380 | current_dir = os.path.abspath(".") | 419 | current_dir = os.path.abspath(".") |
381 | dlg = wx.FileDialog(None, | 420 | dlg = wx.FileDialog(None, |