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 | 150 | Publisher.subscribe(self.OnRemove,"Remove surfaces") |
151 | 151 | Publisher.subscribe(self.UpdateSurfaceInterpolation, 'Update Surface Interpolation') |
152 | 152 | |
153 | + Publisher.subscribe(self.OnImportSurfaceFile, 'Import surface file') | |
154 | + | |
153 | 155 | def OnDuplicate(self, pubsub_evt): |
154 | 156 | selected_items = pubsub_evt.data |
155 | 157 | proj = prj.Project() |
... | ... | @@ -241,6 +243,31 @@ class SurfaceManager(): |
241 | 243 | new_index = self.CreateSurfaceFromPolydata(new_polydata) |
242 | 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 | 271 | def CreateSurfaceFromPolydata(self, polydata, overwrite=False, |
245 | 272 | name=None, colour=None, |
246 | 273 | transparency=None, volume=None, area=None): | ... | ... |
invesalius/gui/data_notebook.py
... | ... | @@ -40,7 +40,7 @@ import invesalius.gui.widgets.listctrl as listmix |
40 | 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 | 45 | TYPE = {const.LINEAR: _(u"Linear"), |
46 | 46 | const.ANGULAR: _(u"Angular"), |
... | ... | @@ -594,6 +594,9 @@ class SurfaceButtonControlPanel(wx.Panel): |
594 | 594 | BMP_DUPLICATE = wx.Bitmap(os.path.join(const.ICON_DIR, "data_duplicate.png"), |
595 | 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 | 600 | # Plate buttons based on previous bitmaps |
598 | 601 | button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT |
599 | 602 | button_new = pbtn.PlateButton(self, BTN_NEW, "", |
... | ... | @@ -608,12 +611,17 @@ class SurfaceButtonControlPanel(wx.Panel): |
608 | 611 | BMP_DUPLICATE, |
609 | 612 | style=button_style, |
610 | 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 | 619 | # Add all controls to gui |
613 | 620 | sizer = wx.BoxSizer(wx.HORIZONTAL) |
614 | 621 | sizer.Add(button_new, 0, wx.GROW|wx.EXPAND|wx.LEFT) |
615 | 622 | sizer.Add(button_remove, 0, wx.GROW|wx.EXPAND) |
616 | 623 | sizer.Add(button_duplicate, 0, wx.GROW|wx.EXPAND) |
624 | + sizer.Add(button_open, 0, wx.GROW|wx.EXPAND) | |
617 | 625 | self.SetSizer(sizer) |
618 | 626 | self.Fit() |
619 | 627 | |
... | ... | @@ -628,6 +636,8 @@ class SurfaceButtonControlPanel(wx.Panel): |
628 | 636 | self.OnRemove() |
629 | 637 | elif id == BTN_DUPLICATE: |
630 | 638 | self.OnDuplicate() |
639 | + elif id == BTN_OPEN: | |
640 | + self.OnOpenMesh() | |
631 | 641 | |
632 | 642 | def OnNew(self): |
633 | 643 | sl = slice_.Slice() |
... | ... | @@ -659,6 +669,11 @@ class SurfaceButtonControlPanel(wx.Panel): |
659 | 669 | else: |
660 | 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 | 678 | class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
664 | 679 | ... | ... |
invesalius/gui/dialogs.py
... | ... | @@ -223,6 +223,11 @@ WILDCARD_NIFTI = "NIfTI 1 (*.nii)|*.nii|" \ |
223 | 223 | WILDCARD_PARREC = "PAR/REC (*.par)|*.par|" \ |
224 | 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 | 232 | def ShowOpenProjectDialog(): |
228 | 233 | # Default system path |
... | ... | @@ -376,6 +381,40 @@ def ShowImportOtherFilesDialog(id_type): |
376 | 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 | 418 | def ShowSaveAsProjectDialog(default_filename=None): |
380 | 419 | current_dir = os.path.abspath(".") |
381 | 420 | dlg = wx.FileDialog(None, | ... | ... |