Commit f5d0049f3c1f7c22f6839fa0a54443fc83b8618c
1 parent
2fb6b86d
Exists in
master
and in
68 other branches
FIX: Error generate 3D surface FIX #98
Showing
3 changed files
with
138 additions
and
129 deletions
Show diff stats
.gitattributes
| @@ -116,6 +116,7 @@ invesalius/data/slice_.py -text | @@ -116,6 +116,7 @@ invesalius/data/slice_.py -text | ||
| 116 | invesalius/data/slice_data.py -text | 116 | invesalius/data/slice_data.py -text |
| 117 | invesalius/data/styles.py -text | 117 | invesalius/data/styles.py -text |
| 118 | invesalius/data/surface.py -text | 118 | invesalius/data/surface.py -text |
| 119 | +invesalius/data/surface_process.py -text | ||
| 119 | invesalius/data/viewer.py -text | 120 | invesalius/data/viewer.py -text |
| 120 | invesalius/data/viewer_slice.py -text | 121 | invesalius/data/viewer_slice.py -text |
| 121 | invesalius/data/viewer_volume.py -text | 122 | invesalius/data/viewer_volume.py -text |
invesalius/data/surface.py
| @@ -31,110 +31,9 @@ import imagedata_utils as iu | @@ -31,110 +31,9 @@ import imagedata_utils as iu | ||
| 31 | import polydata_utils as pu | 31 | import polydata_utils as pu |
| 32 | import project as prj | 32 | import project as prj |
| 33 | import session as ses | 33 | import session as ses |
| 34 | +import surface_process | ||
| 34 | import vtk_utils as vu | 35 | import vtk_utils as vu |
| 35 | 36 | ||
| 36 | -#------------------------------------------------------------------ | ||
| 37 | -class SurfaceProcess(multiprocessing.Process): | ||
| 38 | - | ||
| 39 | - def __init__(self, pipe, filename, mode, min_value, max_value, | ||
| 40 | - decimate_reduction, smooth_relaxation_factor, | ||
| 41 | - smooth_iterations): | ||
| 42 | - | ||
| 43 | - multiprocessing.Process.__init__(self) | ||
| 44 | - self.pipe = pipe | ||
| 45 | - self.filename = filename | ||
| 46 | - self.mode = mode | ||
| 47 | - self.min_value = min_value | ||
| 48 | - self.max_value = max_value | ||
| 49 | - self.decimate_reduction = decimate_reduction | ||
| 50 | - self.smooth_relaxation_factor = smooth_relaxation_factor | ||
| 51 | - self.smooth_iterations = smooth_iterations | ||
| 52 | - | ||
| 53 | - def run(self): | ||
| 54 | - self.CreateSurface() | ||
| 55 | - | ||
| 56 | - def SendProgress(self, obj, msg): | ||
| 57 | - prog = obj.GetProgress() | ||
| 58 | - self.pipe.send([prog, msg]) | ||
| 59 | - | ||
| 60 | - def CreateSurface(self): | ||
| 61 | - | ||
| 62 | - reader = vtk.vtkXMLImageDataReader() | ||
| 63 | - reader.SetFileName(self.filename) | ||
| 64 | - reader.Update() | ||
| 65 | - | ||
| 66 | - # Flip original vtkImageData | ||
| 67 | - flip = vtk.vtkImageFlip() | ||
| 68 | - flip.SetInput(reader.GetOutput()) | ||
| 69 | - flip.SetFilteredAxis(1) | ||
| 70 | - flip.FlipAboutOriginOn() | ||
| 71 | - | ||
| 72 | - # Create vtkPolyData from vtkImageData | ||
| 73 | - if self.mode == "CONTOUR": | ||
| 74 | - contour = vtk.vtkContourFilter() | ||
| 75 | - contour.SetInput(flip.GetOutput()) | ||
| 76 | - contour.SetValue(0, self.min_value) # initial threshold | ||
| 77 | - contour.SetValue(1, self.max_value) # final threshold | ||
| 78 | - contour.GetOutput().ReleaseDataFlagOn() | ||
| 79 | - contour.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 80 | - self.SendProgress(obj, "Generating 3D surface...")) | ||
| 81 | - polydata = contour.GetOutput() | ||
| 82 | - else: #mode == "GRAYSCALE": | ||
| 83 | - mcubes = vtk.vtkMarchingCubes() | ||
| 84 | - mcubes.SetInput(flip.GetOutput()) | ||
| 85 | - mcubes.SetValue(0, 255) | ||
| 86 | - mcubes.ComputeScalarsOn() | ||
| 87 | - mcubes.ComputeGradientsOn() | ||
| 88 | - mcubes.ComputeNormalsOn() | ||
| 89 | - mcubes.ThresholdBetween(self.min_value, self.max_value) | ||
| 90 | - mcubes.GetOutput().ReleaseDataFlagOn() | ||
| 91 | - mcubes.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 92 | - self.SendProgress(obj, "Generating 3D surface...")) | ||
| 93 | - polydata = mcubes.GetOutput() | ||
| 94 | - | ||
| 95 | - if self.decimate_reduction: | ||
| 96 | - decimation = vtk.vtkQuadricDecimation() | ||
| 97 | - decimation.SetInput(polydata) | ||
| 98 | - decimation.SetTargetReduction(self.decimate_reduction) | ||
| 99 | - decimation.GetOutput().ReleaseDataFlagOn() | ||
| 100 | - decimation.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 101 | - self.SendProgress(obj, "Generating 3D surface...")) | ||
| 102 | - polydata = decimation.GetOutput() | ||
| 103 | - | ||
| 104 | - if self.smooth_iterations and self.smooth_relaxation_factor: | ||
| 105 | - smoother = vtk.vtkSmoothPolyDataFilter() | ||
| 106 | - smoother.SetInput(polydata) | ||
| 107 | - smoother.SetNumberOfIterations(self.smooth_iterations) | ||
| 108 | - smoother.SetFeatureAngle(80) | ||
| 109 | - smoother.SetRelaxationFactor(self.smooth_relaxation_factor) | ||
| 110 | - smoother.FeatureEdgeSmoothingOn() | ||
| 111 | - smoother.BoundarySmoothingOn() | ||
| 112 | - smoother.GetOutput().ReleaseDataFlagOn() | ||
| 113 | - smoother.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 114 | - self.SendProgress(obj, "Generating 3D surface...")) | ||
| 115 | - polydata = smoother.GetOutput() | ||
| 116 | - | ||
| 117 | - # Filter used to detect and fill holes. Only fill boundary edges holes. | ||
| 118 | - #TODO: Hey! This piece of code is the same from | ||
| 119 | - # polydata_utils.FillSurfaceHole, we need to review this. | ||
| 120 | - filled_polydata = vtk.vtkFillHolesFilter() | ||
| 121 | - filled_polydata.SetInput(polydata) | ||
| 122 | - filled_polydata.SetHoleSize(500) | ||
| 123 | - filled_polydata.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 124 | - self.SendProgress(obj, "Generating 3D surface...")) | ||
| 125 | - polydata = filled_polydata.GetOutput() | ||
| 126 | - | ||
| 127 | - | ||
| 128 | - filename = tempfile.mktemp() | ||
| 129 | - writer = vtk.vtkXMLPolyDataWriter() | ||
| 130 | - writer.SetInput(polydata) | ||
| 131 | - writer.SetFileName(filename) | ||
| 132 | - writer.Write() | ||
| 133 | - | ||
| 134 | - self.pipe.send(None) | ||
| 135 | - self.pipe.send(filename) | ||
| 136 | - | ||
| 137 | -#---------------------------------------------------------------------------------------------- | ||
| 138 | class Surface(): | 37 | class Surface(): |
| 139 | """ | 38 | """ |
| 140 | Represent both vtkPolyData and associated properties. | 39 | Represent both vtkPolyData and associated properties. |
| @@ -161,8 +60,8 @@ class Surface(): | @@ -161,8 +60,8 @@ class Surface(): | ||
| 161 | surface[key] = {'$vtp': os.path.split(img_name)[1]} | 60 | surface[key] = {'$vtp': os.path.split(img_name)[1]} |
| 162 | else: | 61 | else: |
| 163 | surface[key] = d[key] | 62 | surface[key] = d[key] |
| 164 | - | ||
| 165 | - | 63 | + |
| 64 | + | ||
| 166 | plistlib.writePlist(surface, filename + '.plist') | 65 | plistlib.writePlist(surface, filename + '.plist') |
| 167 | return os.path.split(filename)[1] + '.plist' | 66 | return os.path.split(filename)[1] + '.plist' |
| 168 | 67 | ||
| @@ -225,18 +124,18 @@ class SurfaceManager(): | @@ -225,18 +124,18 @@ class SurfaceManager(): | ||
| 225 | for key in surface_dict: | 124 | for key in surface_dict: |
| 226 | surface = surface_dict[key] | 125 | surface = surface_dict[key] |
| 227 | # Map polygonal data (vtkPolyData) to graphics primitives. | 126 | # Map polygonal data (vtkPolyData) to graphics primitives. |
| 228 | - | 127 | + |
| 229 | normals = vtk.vtkPolyDataNormals() | 128 | normals = vtk.vtkPolyDataNormals() |
| 230 | normals.SetInput(surface.polydata) | 129 | normals.SetInput(surface.polydata) |
| 231 | normals.SetFeatureAngle(80) | 130 | normals.SetFeatureAngle(80) |
| 232 | normals.AutoOrientNormalsOn() | 131 | normals.AutoOrientNormalsOn() |
| 233 | normals.GetOutput().ReleaseDataFlagOn() | 132 | normals.GetOutput().ReleaseDataFlagOn() |
| 234 | - | 133 | + |
| 235 | stripper = vtk.vtkStripper() | 134 | stripper = vtk.vtkStripper() |
| 236 | stripper.SetInput(normals.GetOutput()) | 135 | stripper.SetInput(normals.GetOutput()) |
| 237 | stripper.PassThroughCellIdsOn() | 136 | stripper.PassThroughCellIdsOn() |
| 238 | stripper.PassThroughPointIdsOn() | 137 | stripper.PassThroughPointIdsOn() |
| 239 | - | 138 | + |
| 240 | mapper = vtk.vtkPolyDataMapper() | 139 | mapper = vtk.vtkPolyDataMapper() |
| 241 | mapper.SetInput(stripper.GetOutput()) | 140 | mapper.SetInput(stripper.GetOutput()) |
| 242 | mapper.ScalarVisibilityOff() | 141 | mapper.ScalarVisibilityOff() |
| @@ -257,7 +156,7 @@ class SurfaceManager(): | @@ -257,7 +156,7 @@ class SurfaceManager(): | ||
| 257 | 156 | ||
| 258 | ps.Publisher().sendMessage('Update status text in GUI', | 157 | ps.Publisher().sendMessage('Update status text in GUI', |
| 259 | "Surface created.") | 158 | "Surface created.") |
| 260 | - | 159 | + |
| 261 | # The following lines have to be here, otherwise all volumes disappear | 160 | # The following lines have to be here, otherwise all volumes disappear |
| 262 | 161 | ||
| 263 | ps.Publisher().sendMessage('Update surface info in GUI', | 162 | ps.Publisher().sendMessage('Update surface info in GUI', |
| @@ -275,7 +174,7 @@ class SurfaceManager(): | @@ -275,7 +174,7 @@ class SurfaceManager(): | ||
| 275 | imagedata, colour, [min_value, max_value], edited_points = pubsub_evt.data | 174 | imagedata, colour, [min_value, max_value], edited_points = pubsub_evt.data |
| 276 | quality=_('Optimal *') | 175 | quality=_('Optimal *') |
| 277 | mode = 'CONTOUR' # 'GRAYSCALE' | 176 | mode = 'CONTOUR' # 'GRAYSCALE' |
| 278 | - | 177 | + |
| 279 | imagedata_tmp = None | 178 | imagedata_tmp = None |
| 280 | if (edited_points): | 179 | if (edited_points): |
| 281 | imagedata_tmp = vtk.vtkImageData() | 180 | imagedata_tmp = vtk.vtkImageData() |
| @@ -299,49 +198,51 @@ class SurfaceManager(): | @@ -299,49 +198,51 @@ class SurfaceManager(): | ||
| 299 | pipeline_size += 1 | 198 | pipeline_size += 1 |
| 300 | 199 | ||
| 301 | # Update progress value in GUI | 200 | # Update progress value in GUI |
| 302 | - | 201 | + |
| 303 | filename_img = tempfile.mktemp() | 202 | filename_img = tempfile.mktemp() |
| 304 | - | 203 | + |
| 305 | writer = vtk.vtkXMLImageDataWriter() | 204 | writer = vtk.vtkXMLImageDataWriter() |
| 306 | writer.SetFileName(filename_img) | 205 | writer.SetFileName(filename_img) |
| 307 | writer.SetInput(imagedata) | 206 | writer.SetInput(imagedata) |
| 308 | writer.Write() | 207 | writer.Write() |
| 309 | - | 208 | + |
| 310 | #pipeline_size = 4 | 209 | #pipeline_size = 4 |
| 311 | UpdateProgress = vu.ShowProgress(pipeline_size) | 210 | UpdateProgress = vu.ShowProgress(pipeline_size) |
| 312 | - | 211 | + |
| 212 | + language = ses.Session().language | ||
| 213 | + | ||
| 313 | pipe_in, pipe_out = multiprocessing.Pipe() | 214 | pipe_in, pipe_out = multiprocessing.Pipe() |
| 314 | - sp = SurfaceProcess(pipe_in, filename_img, mode, min_value, max_value, | ||
| 315 | - decimate_reduction, smooth_relaxation_factor, | ||
| 316 | - smooth_iterations) | 215 | + sp = surface_process.SurfaceProcess(pipe_in, filename_img, mode, min_value, max_value, |
| 216 | + decimate_reduction, smooth_relaxation_factor, | ||
| 217 | + smooth_iterations, language) | ||
| 317 | sp.start() | 218 | sp.start() |
| 318 | - | 219 | + |
| 319 | while 1: | 220 | while 1: |
| 320 | msg = pipe_out.recv() | 221 | msg = pipe_out.recv() |
| 321 | if(msg is None): | 222 | if(msg is None): |
| 322 | break | 223 | break |
| 323 | UpdateProgress(msg[0],msg[1]) | 224 | UpdateProgress(msg[0],msg[1]) |
| 324 | - | 225 | + |
| 325 | filename_polydata = pipe_out.recv() | 226 | filename_polydata = pipe_out.recv() |
| 326 | - | 227 | + |
| 327 | reader = vtk.vtkXMLPolyDataReader() | 228 | reader = vtk.vtkXMLPolyDataReader() |
| 328 | reader.SetFileName(filename_polydata) | 229 | reader.SetFileName(filename_polydata) |
| 329 | reader.Update() | 230 | reader.Update() |
| 330 | - | 231 | + |
| 331 | polydata = reader.GetOutput() | 232 | polydata = reader.GetOutput() |
| 332 | - | 233 | + |
| 333 | # Orient normals from inside to outside | 234 | # Orient normals from inside to outside |
| 334 | normals = vtk.vtkPolyDataNormals() | 235 | normals = vtk.vtkPolyDataNormals() |
| 335 | normals.SetInput(polydata) | 236 | normals.SetInput(polydata) |
| 336 | normals.SetFeatureAngle(80) | 237 | normals.SetFeatureAngle(80) |
| 337 | normals.AutoOrientNormalsOn() | 238 | normals.AutoOrientNormalsOn() |
| 338 | normals.GetOutput().ReleaseDataFlagOn() | 239 | normals.GetOutput().ReleaseDataFlagOn() |
| 339 | - | 240 | + |
| 340 | stripper = vtk.vtkStripper() | 241 | stripper = vtk.vtkStripper() |
| 341 | stripper.SetInput(normals.GetOutput()) | 242 | stripper.SetInput(normals.GetOutput()) |
| 342 | stripper.PassThroughCellIdsOn() | 243 | stripper.PassThroughCellIdsOn() |
| 343 | stripper.PassThroughPointIdsOn() | 244 | stripper.PassThroughPointIdsOn() |
| 344 | - | 245 | + |
| 345 | # Map polygonal data (vtkPolyData) to graphics primitives. | 246 | # Map polygonal data (vtkPolyData) to graphics primitives. |
| 346 | mapper = vtk.vtkPolyDataMapper() | 247 | mapper = vtk.vtkPolyDataMapper() |
| 347 | mapper.SetInput(stripper.GetOutput()) | 248 | mapper.SetInput(stripper.GetOutput()) |
| @@ -360,8 +261,8 @@ class SurfaceManager(): | @@ -360,8 +261,8 @@ class SurfaceManager(): | ||
| 360 | # Set actor colour and transparency | 261 | # Set actor colour and transparency |
| 361 | actor.GetProperty().SetColor(colour) | 262 | actor.GetProperty().SetColor(colour) |
| 362 | actor.GetProperty().SetOpacity(1-surface.transparency) | 263 | actor.GetProperty().SetOpacity(1-surface.transparency) |
| 363 | - | ||
| 364 | - # Remove temporary files | 264 | + |
| 265 | + # Remove temporary files | ||
| 365 | if sys.platform == "win32": | 266 | if sys.platform == "win32": |
| 366 | try: | 267 | try: |
| 367 | os.remove(filename_img) | 268 | os.remove(filename_img) |
| @@ -371,7 +272,7 @@ class SurfaceManager(): | @@ -371,7 +272,7 @@ class SurfaceManager(): | ||
| 371 | else: | 272 | else: |
| 372 | os.remove(filename_img) | 273 | os.remove(filename_img) |
| 373 | os.remove(filename_polydata) | 274 | os.remove(filename_polydata) |
| 374 | - | 275 | + |
| 375 | # Append surface into Project.surface_dict | 276 | # Append surface into Project.surface_dict |
| 376 | proj = prj.Project() | 277 | proj = prj.Project() |
| 377 | index = proj.AddSurface(surface) | 278 | index = proj.AddSurface(surface) |
| @@ -494,12 +395,12 @@ class SurfaceManager(): | @@ -494,12 +395,12 @@ class SurfaceManager(): | ||
| 494 | writer = vtk.vtkXMLPolyDataWriter() | 395 | writer = vtk.vtkXMLPolyDataWriter() |
| 495 | #elif filetype == const.FILETYPE_IV: | 396 | #elif filetype == const.FILETYPE_IV: |
| 496 | # writer = vtk.vtkIVWriter() | 397 | # writer = vtk.vtkIVWriter() |
| 497 | - elif filetype == const.FILETYPE_PLY: | 398 | + elif filetype == const.FILETYPE_PLY: |
| 498 | writer = vtk.vtkPLYWriter() | 399 | writer = vtk.vtkPLYWriter() |
| 499 | writer.SetFileTypeToBinary() | 400 | writer.SetFileTypeToBinary() |
| 500 | writer.SetDataByteOrderToLittleEndian() | 401 | writer.SetDataByteOrderToLittleEndian() |
| 501 | #writer.SetColorModeToUniformCellColor() | 402 | #writer.SetColorModeToUniformCellColor() |
| 502 | - #writer.SetColor(255, 0, 0) | 403 | + #writer.SetColor(255, 0, 0) |
| 503 | 404 | ||
| 504 | if filetype == const.FILETYPE_STL: | 405 | if filetype == const.FILETYPE_STL: |
| 505 | # Invert normals | 406 | # Invert normals |
| @@ -508,7 +409,7 @@ class SurfaceManager(): | @@ -508,7 +409,7 @@ class SurfaceManager(): | ||
| 508 | normals.SetFeatureAngle(80) | 409 | normals.SetFeatureAngle(80) |
| 509 | normals.AutoOrientNormalsOn() | 410 | normals.AutoOrientNormalsOn() |
| 510 | normals.GetOutput().ReleaseDataFlagOn() | 411 | normals.GetOutput().ReleaseDataFlagOn() |
| 511 | - normals.UpdateInformation() | 412 | + normals.UpdateInformation() |
| 512 | polydata = normals.GetOutput() | 413 | polydata = normals.GetOutput() |
| 513 | 414 | ||
| 514 | writer.SetFileName(filename) | 415 | writer.SetFileName(filename) |
| @@ -0,0 +1,107 @@ | @@ -0,0 +1,107 @@ | ||
| 1 | +import vtk | ||
| 2 | +import multiprocessing | ||
| 3 | +import tempfile | ||
| 4 | + | ||
| 5 | +import i18n | ||
| 6 | + | ||
| 7 | +class SurfaceProcess(multiprocessing.Process): | ||
| 8 | + | ||
| 9 | + def __init__(self, pipe, filename, mode, min_value, max_value, | ||
| 10 | + decimate_reduction, smooth_relaxation_factor, | ||
| 11 | + smooth_iterations, language): | ||
| 12 | + | ||
| 13 | + multiprocessing.Process.__init__(self) | ||
| 14 | + self.pipe = pipe | ||
| 15 | + self.filename = filename | ||
| 16 | + self.mode = mode | ||
| 17 | + self.min_value = min_value | ||
| 18 | + self.max_value = max_value | ||
| 19 | + self.decimate_reduction = decimate_reduction | ||
| 20 | + self.smooth_relaxation_factor = smooth_relaxation_factor | ||
| 21 | + self.smooth_iterations = smooth_iterations | ||
| 22 | + _ = i18n.InstallLanguage(language) | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + def run(self): | ||
| 26 | + self.CreateSurface() | ||
| 27 | + | ||
| 28 | + def SendProgress(self, obj, msg): | ||
| 29 | + prog = obj.GetProgress() | ||
| 30 | + self.pipe.send([prog, msg]) | ||
| 31 | + | ||
| 32 | + def CreateSurface(self): | ||
| 33 | + | ||
| 34 | + reader = vtk.vtkXMLImageDataReader() | ||
| 35 | + reader.SetFileName(self.filename) | ||
| 36 | + reader.Update() | ||
| 37 | + | ||
| 38 | + # Flip original vtkImageData | ||
| 39 | + flip = vtk.vtkImageFlip() | ||
| 40 | + flip.SetInput(reader.GetOutput()) | ||
| 41 | + flip.SetFilteredAxis(1) | ||
| 42 | + flip.FlipAboutOriginOn() | ||
| 43 | + | ||
| 44 | + # Create vtkPolyData from vtkImageData | ||
| 45 | + if self.mode == "CONTOUR": | ||
| 46 | + contour = vtk.vtkContourFilter() | ||
| 47 | + contour.SetInput(flip.GetOutput()) | ||
| 48 | + contour.SetValue(0, self.min_value) # initial threshold | ||
| 49 | + contour.SetValue(1, self.max_value) # final threshold | ||
| 50 | + contour.GetOutput().ReleaseDataFlagOn() | ||
| 51 | + contour.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 52 | + self.SendProgress(obj, _("Generating 3D surface..."))) | ||
| 53 | + polydata = contour.GetOutput() | ||
| 54 | + else: #mode == "GRAYSCALE": | ||
| 55 | + mcubes = vtk.vtkMarchingCubes() | ||
| 56 | + mcubes.SetInput(flip.GetOutput()) | ||
| 57 | + mcubes.SetValue(0, 255) | ||
| 58 | + mcubes.ComputeScalarsOn() | ||
| 59 | + mcubes.ComputeGradientsOn() | ||
| 60 | + mcubes.ComputeNormalsOn() | ||
| 61 | + mcubes.ThresholdBetween(self.min_value, self.max_value) | ||
| 62 | + mcubes.GetOutput().ReleaseDataFlagOn() | ||
| 63 | + mcubes.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 64 | + self.SendProgress(obj, _("Generating 3D surface..."))) | ||
| 65 | + polydata = mcubes.GetOutput() | ||
| 66 | + | ||
| 67 | + if self.decimate_reduction: | ||
| 68 | + decimation = vtk.vtkQuadricDecimation() | ||
| 69 | + decimation.SetInput(polydata) | ||
| 70 | + decimation.SetTargetReduction(self.decimate_reduction) | ||
| 71 | + decimation.GetOutput().ReleaseDataFlagOn() | ||
| 72 | + decimation.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 73 | + self.SendProgress(obj, _("Generating 3D surface..."))) | ||
| 74 | + polydata = decimation.GetOutput() | ||
| 75 | + | ||
| 76 | + if self.smooth_iterations and self.smooth_relaxation_factor: | ||
| 77 | + smoother = vtk.vtkSmoothPolyDataFilter() | ||
| 78 | + smoother.SetInput(polydata) | ||
| 79 | + smoother.SetNumberOfIterations(self.smooth_iterations) | ||
| 80 | + smoother.SetFeatureAngle(80) | ||
| 81 | + smoother.SetRelaxationFactor(self.smooth_relaxation_factor) | ||
| 82 | + smoother.FeatureEdgeSmoothingOn() | ||
| 83 | + smoother.BoundarySmoothingOn() | ||
| 84 | + smoother.GetOutput().ReleaseDataFlagOn() | ||
| 85 | + smoother.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 86 | + self.SendProgress(obj, _("Generating 3D surface..."))) | ||
| 87 | + polydata = smoother.GetOutput() | ||
| 88 | + | ||
| 89 | + # Filter used to detect and fill holes. Only fill boundary edges holes. | ||
| 90 | + #TODO: Hey! This piece of code is the same from | ||
| 91 | + # polydata_utils.FillSurfaceHole, we need to review this. | ||
| 92 | + filled_polydata = vtk.vtkFillHolesFilter() | ||
| 93 | + filled_polydata.SetInput(polydata) | ||
| 94 | + filled_polydata.SetHoleSize(500) | ||
| 95 | + filled_polydata.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 96 | + self.SendProgress(obj, _("Generating 3D surface..."))) | ||
| 97 | + polydata = filled_polydata.GetOutput() | ||
| 98 | + | ||
| 99 | + | ||
| 100 | + filename = tempfile.mktemp() | ||
| 101 | + writer = vtk.vtkXMLPolyDataWriter() | ||
| 102 | + writer.SetInput(polydata) | ||
| 103 | + writer.SetFileName(filename) | ||
| 104 | + writer.Write() | ||
| 105 | + | ||
| 106 | + self.pipe.send(None) | ||
| 107 | + self.pipe.send(filename) | ||
| 0 | \ No newline at end of file | 108 | \ No newline at end of file |