Commit f9d49cf73f43e2e7a801f09dab738305899a1351

Authored by tatiana
1 parent fc5abcbd

ADD: 3D surface export to file

invesalius/constants.py
1 1 import os.path
  2 +
2 3 import wx
  4 +
3 5 from project import Project
4 6  
5 7 # VTK text
... ... @@ -187,3 +189,19 @@ MODE_WW_WL = 4#:"Bright and contrast adjustment"}
187 189 MODE_SLICE_SCROLL = -1
188 190 MODE_SLICE_EDITOR = -2
189 191  
  192 +############
  193 +
  194 +
  195 +FILETYPE_IV = wx.NewId()
  196 +FILETYPE_RIB = wx.NewId()
  197 +FILETYPE_STL = wx.NewId()
  198 +FILETYPE_VRML = wx.NewId()
  199 +FILETYPE_OBJ = wx.NewId()
  200 +
  201 +FILETYPE_BMP = wx.NewId()
  202 +FILETYPE_JPG = wx.NewId()
  203 +FILETYPE_PNG = wx.NewId()
  204 +FILETYPE_PS = wx.NewId()
  205 +FILETYPE_POV = wx.NewId()
  206 +FILETYPE_OBJ = wx.NewId()
  207 +
... ...
invesalius/data/polydata_utils.py
... ... @@ -84,3 +84,17 @@ def CalculateSurfaceArea(polydata):
84 84 measured_polydata = vtk.vtkMassProperties()
85 85 measured_polydata.SetInput(polydata)
86 86 return measured_polydata.GetSurfaceArea()
  87 +
  88 +def Merge(polydata_list):
  89 + append = vtk.vtkAppendPolyData()
  90 +
  91 + for polydata in polydata_list:
  92 + triangle = vtk.TriangleFilter()
  93 + triangle.SetInput(polydata)
  94 + append.AddInput(triangle.GetOutput())
  95 +
  96 + clean = vtk.vtkCleanPolyData()
  97 + clean.SetInput(append.GetOutput())
  98 +
  99 + return append.GetOutput()
  100 +
... ...
invesalius/data/surface.py
... ... @@ -3,7 +3,7 @@ import wx.lib.pubsub as ps
3 3  
4 4 import constants as const
5 5 import imagedata_utils as iu
6   -from project import Project
  6 +import project as prj
7 7 import vtk_utils as vu
8 8 import polydata_utils as pu
9 9 from imagedata_utils import BuildEditedImage
... ... @@ -49,6 +49,7 @@ class SurfaceManager():
49 49  
50 50 ps.Publisher().subscribe(self.OnChangeSurfaceName, 'Change surface name')
51 51 ps.Publisher().subscribe(self.OnShowSurface, 'Show surface')
  52 + ps.Publisher().subscribe(self.OnExportSurface,'Export surface to file')
52 53  
53 54 def AddNewActor(self, pubsub_evt):
54 55 """
... ... @@ -170,13 +171,6 @@ class SurfaceManager():
170 171 UpdateProgress(normals, "Orienting normals..."))
171 172 polydata = normals.GetOutput()
172 173  
173   - #======= Temporary Code =======
174   - stl = vtk.vtkSTLWriter()
175   - stl.SetFileTypeToBinary()
176   - stl.SetInputConnection(normals.GetOutputPort())
177   - stl.SetFileName("surface.stl")
178   - stl.Write()
179   - #==============================
180 174  
181 175 # TODO (Paulo): Why do we need this filter?
182 176 # without this the volume does not appear
... ... @@ -207,7 +201,7 @@ class SurfaceManager():
207 201 actor.GetProperty().SetOpacity(1-surface.transparency)
208 202  
209 203 # Append surface into Project.surface_dict
210   - proj = Project()
  204 + proj = prj.Project()
211 205 proj.surface_dict[surface.index] = surface
212 206  
213 207 # Save actor for future management tasks
... ... @@ -241,13 +235,13 @@ class SurfaceManager():
241 235 ps.Publisher().sendMessage('Remove surface actor from viewer', (index))
242 236 self.actors_dict.pop(index)
243 237 # Remove surface from project's surface_dict
244   - proj = Project()
  238 + proj = prj.Project()
245 239 proj.surface_dict.pop(index)
246 240  
247 241  
248 242 def OnChangeSurfaceName(self, pubsub_evt):
249 243 index, name = pubsub_evt.data
250   - proj = Project()
  244 + proj = prj.Project()
251 245 proj.surface_dict[index].name = name
252 246  
253 247 def OnShowSurface(self, pubsub_evt):
... ... @@ -261,7 +255,7 @@ class SurfaceManager():
261 255 """
262 256 self.actors_dict[index].SetVisibility(value)
263 257 # Update value in project's surface_dict
264   - proj = Project()
  258 + proj = prj.Project()
265 259 proj.surface_dict[index].is_shown = value
266 260 ps.Publisher().sendMessage('Render volume viewer')
267 261  
... ... @@ -273,7 +267,7 @@ class SurfaceManager():
273 267 index, value = pubsub_evt.data
274 268 self.actors_dict[index].GetProperty().SetOpacity(1-value)
275 269 # Update value in project's surface_dict
276   - proj = Project()
  270 + proj = prj.Project()
277 271 proj.surface_dict[index].transparency = value
278 272 ps.Publisher().sendMessage('Render volume viewer')
279 273  
... ... @@ -283,6 +277,32 @@ class SurfaceManager():
283 277 index, colour = pubsub_evt.data
284 278 self.actors_dict[index].GetProperty().SetColor(colour)
285 279 # Update value in project's surface_dict
286   - proj = Project()
  280 + proj = prj.Project()
287 281 proj.surface_dict[index].colour = colour
288 282 ps.Publisher().sendMessage('Render volume viewer')
  283 +
  284 +
  285 + def OnExportSurface(self, pubsub_evt):
  286 + filename, filetype = pubsub_evt.data
  287 +
  288 + if filetype == const.FILETYPE_STL:
  289 + proj = prj.Project()
  290 + polydata_list = []
  291 + for index in proj.surface_dict:
  292 + surface = proj.surface_dict[index]
  293 + if surface.is_shown:
  294 + polydata_list.append(surface.polydata)
  295 + if len(polydata_list) < 0:
  296 + print "oops - no polydata"
  297 + return
  298 + elif len(polydata_list) == 1:
  299 + polydata = polydata_list[0]
  300 + else:
  301 + polydata = pu.Merge(polydata_list)
  302 + writer = vtk.vtkSTLWriter()
  303 + writer.SetFileTypeToBinary()
  304 + writer.SetFileName(filename)
  305 + writer.SetInput(polydata)
  306 + writer.Write()
  307 +
  308 +
... ...
invesalius/data/viewer_volume.py
... ... @@ -158,6 +158,32 @@ class Viewer(wx.Panel):
158 158 ('Set interaction mode',
159 159 const.MODE_SLICE_EDITOR))
160 160  
  161 + ps.Publisher().subscribe(self.OnExportSurface, 'Export surface to file')
  162 +
  163 + def OnExportSurface(self, pubsub_evt):
  164 + filename, filetype = pubsub_evt.data
  165 + renwin = self.interactor.GetRenderWindow()
  166 +
  167 + if filetype == const.FILETYPE_RIB:
  168 + writer = vtk.vtkIVExporter()
  169 + writer.SetFileName(filename)
  170 + writer.SetInput(renwin)
  171 + elif filetype == const.FILETYPE_VRML:
  172 + writer = vtk.vtkVRMLExporter()
  173 + writer.SetFileName(filename)
  174 + writer.SetInput(renwin)
  175 + elif filetype == const.FILETYPE_OBJ:
  176 + writer = vtk.vtkOBJExporter()
  177 + writer.SetFilePrefix(filename.split(".")[-2])
  178 + writer.SetInput(renwin)
  179 + else: # const.FILETYPE_IV:
  180 + writer = vtk.vtkIVExporter()
  181 + writer.SetFileName(filename)
  182 + writer.SetInput(renwin)
  183 + writer.Write()
  184 +
  185 +
  186 +
161 187 def __bind_events_wx(self):
162 188 #self.Bind(wx.EVT_SIZE, self.OnSize)
163 189 pass
... ... @@ -216,7 +242,6 @@ class Viewer(wx.Panel):
216 242 self.ren.ResetCamera()
217 243 self.ren.ResetCameraClippingRange()
218 244  
219   - #self.ShowOrientationCube()
220 245  
221 246 self.UpdateRender()
222 247  
... ... @@ -239,7 +264,7 @@ class Viewer(wx.Panel):
239 264 ren.ResetCameraClippingRange()
240 265  
241 266  
242   - self.ShowOrientationCube()
  267 + #self.ShowOrientationCube()
243 268  
244 269 self.interactor.Render()
245 270  
... ...