def reduceMesh(mymesh, reductionFactor): """Reduce the number of triangles in a mesh using VTK's QuadricDecimation filter.""" try: t = time.perf_counter() deci = vtk.vtkQuadricDecimation() deci.SetTargetReduction(reductionFactor) if vtk.vtkVersion.GetVTKMajorVersion() >= 6: deci.SetInputData(mymesh) else: deci.SetInput(mymesh) deci.Update() print("Surface reduced") m2 = deci.GetOutput() del deci deci = None print(" ", m2.GetNumberOfPolys(), "polygons") elapsedTime(t) return m2 except: print("Surface reduction failed") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) return None
def Decimate(self, target_reduction): """ Reduces the number of triangles in a triangular mesh using vtkQuadricDecimation. Parameters ---------- mesh : vtk.PolyData Mesh to decimate target_reduction : float Fraction of the original mesh to remove. TargetReduction is set to 0.9, this filter will try to reduce the data set to 10% of its original size and will remove 90% of the input triangles. Returns ------- outmesh : vtkInterface.PolyData Decimated mesh """ # create decimation filter decimate = vtk.vtkQuadricDecimation() # vtkDecimatePro as well decimate.SetInputData(self) decimate.SetTargetReduction(target_reduction) decimate.Update() return PolyData(decimate.GetOutput())
def create_mesh(label_pix, labels_to_use, inds_to_phys=None): # convert the numpy representation to VTK, so we can create a mesh # using marching cubes for display later vtk_import = vtkImageImport() vtk_import.SetImportVoidPointer(label_pix, True) vtk_import.SetDataScalarType(VTK_UNSIGNED_CHAR) vtk_import.SetNumberOfScalarComponents(1) vtk_import.SetDataExtent(0, label_pix.shape[2] - 1, 0, label_pix.shape[1] - 1, 0, label_pix.shape[0] - 1) vtk_import.SetWholeExtent(0, label_pix.shape[2] - 1, 0, label_pix.shape[1] - 1, 0, label_pix.shape[0] - 1) vtk_import.Update() flipper = vtkImageFlip() flipper.SetInputData(vtk_import.GetOutput()) flipper.SetFilteredAxis(1) flipper.FlipAboutOriginOff() flipper.Update() vtk_img = flipper.GetOutput() marching_cubes = vtkDiscreteMarchingCubes() marching_cubes.SetInputData(vtk_img) num_labels_to_use = len(labels_to_use) marching_cubes.SetNumberOfContours(num_labels_to_use) for i in range(num_labels_to_use): marching_cubes.SetValue(i, labels_to_use[i]) marching_cubes.Update() smoother = vtkWindowedSincPolyDataFilter() smoother.SetInputData(marching_cubes.GetOutput()) smoother.SetNumberOfIterations(25) smoother.SetPassBand(0.1) smoother.SetBoundarySmoothing(False) smoother.SetFeatureEdgeSmoothing(False) smoother.SetFeatureAngle(120.0) smoother.SetNonManifoldSmoothing(True) smoother.NormalizeCoordinatesOn() smoother.Update() mesh_reduce = vtkQuadricDecimation() mesh_reduce.SetInputData(smoother.GetOutput()) mesh_reduce.SetTargetReduction(0.25) mesh_reduce.Update() vertex_xform = np.mat(np.eye(4)) vertex_xform[1, 1] = -1 vertex_xform[1, 3] = label_pix.shape[1] + 1 vertex_xform = inds_to_phys * vertex_xform return xform_mesh(mesh_reduce.GetOutput(), vertex_xform)
def eval_decimation(_reduction, _model): deci = vtk.vtkQuadricDecimation() deci.SetInputConnection(_model.mesh.GetOutputPort()) deci.VolumePreservationOn() deci.SetTargetReduction(_reduction / 100) # percent of removed triangles deci.Update() return deci.GetOutput().GetNumberOfPoints()
def run(neuron_num): file = "meshes-with-axons-filled-assembled/n%02d.vtp" % neuron_num readerVolume = vtk.vtkXMLPolyDataReader() readerVolume.SetFileName(file) readerVolume.Update() decimate = readerVolume nlod = 5 for i in range(nlod): smoother = vtk.vtkWindowedSincPolyDataFilter() smoother.SetInputConnection(decimate.GetOutputPort()) smoother.SetNumberOfIterations(20) # This has little effect on the error! smoother.BoundarySmoothingOff() smoother.FeatureEdgeSmoothingOff() smoother.SetPassBand(.1) # This increases the error a lot! .001 smoother.NonManifoldSmoothingOn() smoother.NormalizeCoordinatesOn() smoother.GenerateErrorScalarsOn() smoother.Update() decimate = vtk.vtkQuadricDecimation () decimate.SetInputData(smoother.GetOutput()) decimate.SetTargetReduction(.7) decimate.Update() full_out_name = 'meshes-with-axons-filled-assembled-lod/n%02d_LOD%d.obj' % (neuron_num, i - 1) writer = vtk.vtkOBJWriter() writer.SetFileName(full_out_name) writer.SetInputData(decimate.GetOutput()) writer.Write()
def simplify_polydata(polydata, num_simplify_iter=0, smooth=False): for simplify_iter in range(num_simplify_iter): t = time.time() deci = vtk.vtkQuadricDecimation() deci.SetInputData(polydata) deci.SetTargetReduction(0.8) # 0.8 means each iteration causes the point number to drop to 20% the original deci.Update() polydata = deci.GetOutput() if smooth: smoother = vtk.vtkWindowedSincPolyDataFilter() # smoother.NormalizeCoordinatesOn() smoother.SetPassBand(.1) smoother.SetNumberOfIterations(20) smoother.SetInputData(polydata) smoother.Update() polydata = smoother.GetOutput() n_pts = polydata.GetNumberOfPoints() if polydata.GetNumberOfPoints() < 200: break sys.stderr.write('simplify %d @ %d: %.2f seconds\n' % (simplify_iter, n_pts, time.time() - t)) # return polydata
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__( self, module_manager, vtk.vtkQuadricDecimation(), 'Processing.', ('vtkPolyData',), ('vtkPolyData',), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def extract_smooth_mesh(imageVTK, label_range, smoothing_iterations=30, pass_band_param=0.01, target_reduction=0.95): '''Extract mesh/contour for labels in imageVTK, smooth and decimate. Multiple labels can be extracted at once, however touching labels will share vertices and the label ids are lost during smoothing/decimation. Processing is slow for small objects in a large volume and should be cropped beforehand. Args: imageVTK: vtk image data label_range: range of labels to extract. A tuple (l,l) will extract a mesh for a single label id l smoothing_iterations: number of iterations for vtkWindowedSincPolyDataFilter pass_band_param: pass band param in range [0.,2.] for vtkWindowedSincPolyDataFilter. Lower value remove higher frequencies. target_reduction: target reduction for vtkQuadricDecimation ''' n_contours = label_range[1] - label_range[0] + 1 # alternative vtkDiscreteMarchingCubes is slower and creates some weird missalignment lines when applied to tight crops dfe = vtk.vtkDiscreteFlyingEdges3D() dfe.SetInputData(imageVTK) dfe.ComputeScalarsOff( ) # numpy image labels --> cells (faces) scalar values dfe.ComputeNormalsOff() dfe.ComputeGradientsOff() dfe.InterpolateAttributesOff() dfe.GenerateValues(n_contours, label_range[0], label_range[1]) # numContours, rangeStart, rangeEnd dfe.Update() smoother = vtk.vtkWindowedSincPolyDataFilter() smoother.SetInputConnection(dfe.GetOutputPort()) smoother.SetNumberOfIterations( smoothing_iterations) #this has little effect on the error! smoother.BoundarySmoothingOff() smoother.FeatureEdgeSmoothingOff() # smoother.SetFeatureAngle(120) smoother.SetPassBand( pass_band_param) # from 0 to 2, 2 keeps high frequencies smoother.NonManifoldSmoothingOn() smoother.NormalizeCoordinatesOn() smoother.GenerateErrorScalarsOff() smoother.GenerateErrorVectorsOff() smoother.Update() # vtkQuadricDecimation looks cleaner than vtkDecimatePro (no unexpected sharp edges) # but drop points scalar value --> can be added back if doing one instance a time decimate = vtk.vtkQuadricDecimation() decimate.SetInputConnection(smoother.GetOutputPort()) decimate.SetTargetReduction(target_reduction) decimate.VolumePreservationOn() decimate.Update() return decimate.GetOutput()
def decimation(self, reduction=50): decimation = vtk.vtkQuadricDecimation() decimation.SetInputConnection(self.mesh.GetOutputPort()) decimation.VolumePreservationOn() decimation.SetTargetReduction(reduction / 100) # percent of removed triangles decimation.Update() self.mesh = decimation
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__(self, module_manager, vtk.vtkQuadricDecimation(), 'Processing.', ('vtkPolyData', ), ('vtkPolyData', ), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def MarchingCubes(image,threshold): # marching cubes mc = vtk.vtkMarchingCubes() mc.SetInputData(image) mc.ComputeNormalsOn() mc.ComputeGradientsOn() mc.SetValue(0, threshold) mc.Update() # To remain largest region #confilter = vtk.vtkPolyDataConnectivityFilter() #confilter.SetInputData(mc.GetOutput()) #confilter.SetExtractionModeToLargestRegion() #confilter.Update() # reduce poly data inputPoly = vtk.vtkPolyData() inputPoly.ShallowCopy(mc.GetOutput()) print("Before decimation\n" "-----------------\n" "There are " + str(inputPoly.GetNumberOfPoints()) + "points.\n" "There are " + str(inputPoly.GetNumberOfPolys()) + "polygons.\n") #decimate = vtk.vtkDecimatePro() decimate = vtk.vtkQuadricDecimation() decimate.SetInputData(inputPoly) decimate.SetTargetReduction(.90) decimate.Update() decimatedPoly = vtk.vtkPolyData() decimatedPoly.ShallowCopy(decimate.GetOutput()) print("After decimation \n" "-----------------\n" "There are " + str(decimatedPoly.GetNumberOfPoints()) + "points.\n" "There are " + str(decimatedPoly.GetNumberOfPolys()) + "polygons.\n") # smooth surface smoothFilter = vtk.vtkSmoothPolyDataFilter() smoothFilter.SetInputData(decimatedPoly) smoothFilter.SetNumberOfIterations(15) smoothFilter.SetRelaxationFactor(0.1) smoothFilter.FeatureEdgeSmoothingOff() smoothFilter.BoundarySmoothingOn() smoothFilter.Update() decimatedPoly = vtk.vtkPolyData() decimatedPoly.ShallowCopy(smoothFilter.GetOutput()) return decimatedPoly#confilter.GetOutput()
def mesh_decimation(self, reduction_rate): decimate_reader = vtk.vtkQuadricDecimation() decimate_reader.SetInputData(self.vtkPolyData) decimate_reader.SetTargetReduction(reduction_rate) decimate_reader.VolumePreservationOn() decimate_reader.Update() self.vtkPolyData = decimate_reader.GetOutput() self.get_mesh_data_from_vtkPolyData() if self.warning: print( 'Warning! self.cell_attributes are reset and need to be updated!' ) self.cell_attributes = dict() #reset self.point_attributes = dict() #reset
def quadric_decimation(data,ratio): sim = vtk.vtkQuadricDecimation(); sim.SetTargetReduction(ratio); sim.SetInputData(data); """ sim.AttributeErrorMetricOn(); sim.VectorsAttributeOff(); sim.NormalsAttributeOn(); sim.TensorsAttributeOff(); sim.TCoordsAttributeOff(); sim.ScalarsAttributeOff(); """ sim.Update() return sim.GetOutput();
def ApplyDecimationFilter(polydata, reduction_factor): """ Reduce number of triangles of the given vtkPolyData, based on reduction_factor. """ # Important: vtkQuadricDecimation presented better results than # vtkDecimatePro decimation = vtk.vtkQuadricDecimation() decimation.SetInputData(polydata) decimation.SetTargetReduction(reduction_factor) decimation.GetOutput().ReleaseDataFlagOn() decimation.AddObserver("ProgressEvent", lambda obj, evt: UpdateProgress(decimation, "Reducing number of triangles...")) return decimation.GetOutput()
def decimation(poly, rate): """ Simplifies a VTK PolyData Args: poly: vtk PolyData rate: target rate reduction """ decimate = vtk.vtkQuadricDecimation() decimate.SetInputData(poly) decimate.AttributeErrorMetricOn() decimate.ScalarsAttributeOn() decimate.SetTargetReduction(rate) decimate.VolumePreservationOff() decimate.Update() output = decimate.GetOutput() #output = cleanPolyData(output, 0.) return output
def get(self): volumeData = self.reader.get("SURF", self.subj, name=self.get_argument("name", None), scalars="aparc") decimate = vtk.vtkQuadricDecimation() decimate.SetInputData(volumeData) decimate.SetTargetReduction(float(self.get_argument("res", 0))) decimate.Update() volumeData2 = decimate.GetOutput() volumeData2 = volumeData resultado = {} resultado['subject'] = self.subj resultado['type'] = 'volume' resultado['bounds'] = volumeData2.GetBounds() resultado['points'] = numpy_support.vtk_to_numpy(volumeData2.GetPoints().GetData()).flatten().tolist() resultado['faces'] = np.delete(numpy_support.vtk_to_numpy(volumeData2.GetPolys().GetData()), slice(None, None, 4)).tolist() resultado['scalars'] = numpy_support.vtk_to_numpy(volumeData2.GetPointData().GetScalars()).flatten().tolist() self.set_header("Content-Type","application/json") self.write(json.dumps(resultado, separators=(',',':')))
def decimate_mesh(V, F, params, fun=None): """Decimate mesh by a given factor Returns deccimated arrays Vd (vertices), Fd (faces) and optionally Fund (functional values) """ factor = params['factor'] Vol_preser = params['Vol_preser'] F2 = F.flatten() F2 = np.insert(F2, range(0, len(F2), 3), int(3), axis=0) vtk_mesh = createPolyData(V, F2, fun) decimate = vtk.vtkQuadricDecimation() decimate.SetInputData(vtk_mesh) decimate.SetTargetReduction(factor) decimate.SetVolumePreservation(Vol_preser) if fun is not None: Fun_Error_Metric = params['Fun_Error_Metric'] Fun_weight = params['Fun_weigth'] decimate.SetAttributeErrorMetric(Fun_Error_Metric) decimate.SetScalarsWeight(Fun_weight) decimate.Update() decimated = vtk.vtkPolyData() decimated.ShallowCopy(decimate.GetOutput()) Vd_vtk = decimated.GetPoints().GetData() Vd = numpy_support.vtk_to_numpy(Vd_vtk) Fd_vtk = decimated.GetPolys().GetData() Fd = numpy_support.vtk_to_numpy(Fd_vtk) Fd = np.delete(Fd, slice(None, None, 4)) Fd = Fd.reshape(int(len(Fd) / 3), 3) if fun is not None: fund_vtk = decimated.GetPointData().GetScalars() fund = numpy_support.vtk_to_numpy(fund_vtk) return Vd, Fd, fund else: return Vd, Fd
def reduceMesh(mymesh, reductionFactor): try: deci = vtk.vtkQuadricDecimation() deci.SetTargetReduction(reductionFactor) if vtk.vtkVersion.GetVTKMajorVersion() >= 6: deci.SetInputData(mymesh) else: deci.SetInput(mymesh) deci.Update() print("Surface reduced") m2 = deci.GetOutput() del deci print(" ", m2.GetNumberOfPolys(), "polygons") return m2 except: print("Surface reduction failed") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception( exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) return None
def decimate_mesh(mesh, reduction=0.75, type_reduction='quadric', **kwargs): """ Decimate this mesh specifying the percentage (0,1) of triangles to be removed Parameters ---------- reduction: float (default: 0.75) The percentage of triangles to be removed. It should be in (0, 1) type_reduction : str (default: quadric) The type of decimation as: 'quadric' : Quadric decimation 'progressive : Progressive decimation Returns ------- mesh : :map:`TriMesh` A new mesh that has been decimated. """ import vtk if type_reduction == 'quadric': decimate = vtk.vtkQuadricDecimation() elif type_reduction == 'progressive': decimate = vtk.vtkDecimatePro() else: raise Exception( 'Wrong type of reduction. It should be quadric or progressive') inputPolyData = trimesh_to_vtk(mesh) decimate.SetInputData(inputPolyData) decimate.SetTargetReduction(reduction) if kwargs.get('preserve_topology', False) and type_reduction == 'progressive': decimate.PreserveTopologyOn() decimate.Update() return trimesh_from_vtk(decimate.GetOutput())
def reduceMesh(mymesh, reductionFactor): try: t = time.clock() deci = vtk.vtkQuadricDecimation() deci.SetTargetReduction( reductionFactor ) if vtk.vtkVersion.GetVTKMajorVersion() >= 6: deci.SetInputData( mymesh ) else: deci.SetInput( mymesh ) deci.Update() print ("Surface reduced") m2 = deci.GetOutput() del deci deci = None print " ", m2.GetNumberOfPolys(), "polygons" elapsedTime(t) return m2 except: print "Surface reduction failed" exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) return None
def decimate(poly_data, reduction, data_is_big): decimator = None #decimator = vtk.vtkDecimatePro() #decimator.PreserveTopologyOn() #decimator.SplittingOff() #decimator.BoundaryVertexDeletionOff() #decimator.SetMaximumError(vtk.VTK_DOUBLE_MAX) if data_is_big: decimator = vtk.vtkQuadricClustering() decimator.SetNumberOfXDivisions(1024) decimator.SetNumberOfYDivisions(1024) decimator.SetNumberOfZDivisions(1024) else: decimator = vtk.vtkQuadricDecimation() decimator.SetTargetReduction(reduction) decimator.SetInputData(poly_data) decimator.Update() decimated = vtk.vtkPolyData() decimated.ShallowCopy(decimator.GetOutput()) print("Decimated:", decimated.GetNumberOfPoints(), "points", decimated.GetNumberOfPolys(), "polygons, by ", type(decimator)) # draw(decimated, color_scale='Rainbow', write_file=True, file_name='after.png') return decimated
def main(): parser = argparse.ArgumentParser( description='Convert label image into polygon mesh files.') parser.add_argument('input', help='Input filename', metavar='<input>') parser.add_argument( '-o', '--output', help='Output filename. Optional. Defaulted to input filename.', metavar='<output>') parser.add_argument('--ext', help='File extension. Default:%(default)s', metavar='<extension>', default='vtk') parser.add_argument('--reduce', help='Target reduction rate. Default:%(default)s', metavar='<rate>', default=0.9, type=float) parser.add_argument( '--smooth', help='# of iteration for smoothing. Default:%(default)s', metavar='<n>', default=10, type=int) parser.add_argument('--cap', help="Cap on the image border", action='store_true') args = parser.parse_args() if args.output is None: output_format = os.path.splitext(os.path.basename( args.input))[0] + '_{}.' + args.ext reader = vtk.vtkMetaImageReader() reader.SetFileName(args.input) reader.Update() n_labels = int(reader.GetOutput().GetScalarRange()[1]) contour = vtk.vtkDiscreteMarchingCubes() if args.cap: padder = vtk.vtkImageConstantPad() padder.SetInputConnection(reader.GetOutputPort()) padder.SetConstant(0) extent = reader.GetOutput().GetExtent() padder.SetOutputWholeExtent(-1, extent[1] + 1, -1, extent[3] + 1, -1, extent[5] + 1) contour.SetInputConnection(padder.GetOutputPort()) else: contour.SetInputConnection(reader.GetOutputPort()) contour.ComputeNormalsOff() writer = { 'vtk': vtk.vtkPolyDataWriter, 'ply': vtk.vtkPLYWriter, 'stl': vtk.vtkSTLWriter }.get(args.ext, lambda: (print('Unknown file type:' + args.ext), sys.exit(1)))() writer.SetFileTypeToBinary() for index in tqdm.trange(1, n_labels + 1): contour.SetValue(0, index) contour.Update() decimate = vtk.vtkQuadricDecimation() decimate.SetInputConnection(contour.GetOutputPort()) decimate.SetTargetReduction(args.reduce) decimate.Update() smoother = vtk.vtkWindowedSincPolyDataFilter() smoother.SetInputConnection(decimate.GetOutputPort()) smoother.SetNumberOfIterations(args.smooth) smoother.NonManifoldSmoothingOn() smoother.NormalizeCoordinatesOn() smoother.Update() normals = vtk.vtkPolyDataNormals() normals.SetInputData(smoother.GetOutput()) normals.ComputePointNormalsOn() normals.ComputeCellNormalsOff() normals.SplittingOff() normals.ConsistencyOn() normals.Update() writer.SetFileName(output_format.format(index)) writer.SetInputData(normals.GetOutput()) writer.Write()
pl3d.SetQFileName("" + str(VTK_DATA_ROOT) + "/Data/combq.bin") pl3d.SetScalarFunctionNumber(100) pl3d.SetVectorFunctionNumber(202) pl3d.Update() pl3d_output = pl3d.GetOutput().GetBlock(0) gf = vtk.vtkGeometryFilter() gf.SetInputData(pl3d_output) tf = vtk.vtkTriangleFilter() tf.SetInputConnection(gf.GetOutputPort()) gMapper = vtk.vtkPolyDataMapper() gMapper.SetInputConnection(gf.GetOutputPort()) gMapper.SetScalarRange(pl3d_output.GetScalarRange()) gActor = vtk.vtkActor() gActor.SetMapper(gMapper) # Don't look at attributes mesh = vtk.vtkQuadricDecimation() mesh.SetInputConnection(tf.GetOutputPort()) mesh.SetTargetReduction(.90) mesh.AttributeErrorMetricOn() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(mesh.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) # This time worry about attributes mesh2 = vtk.vtkQuadricDecimation() mesh2.SetInputConnection(tf.GetOutputPort()) mesh2.SetTargetReduction(.90) mesh2.AttributeErrorMetricOff() mapper2 = vtk.vtkPolyDataMapper() mapper2.SetInputConnection(mesh2.GetOutputPort()) actor2 = vtk.vtkActor()
def vtkQuadricDecimation(poly, targetReduction): deci = vtk.vtkQuadricDecimation() deci.SetInput(poly) deci.SetTargetReduction(targetReduction) return deci.GetOutput()
print("\nERROR: zero cells in mesh") sys.exit(1) del mesh # free memory smooth1 = vtk.vtkSmoothPolyDataFilter() smooth1.SetInputConnection(conn.GetOutputPort()) smooth1.SetNumberOfIterations(7) smooth1.SetRelaxationFactor(0.2) smooth1.FeatureEdgeSmoothingOff() smooth1.BoundarySmoothingOff() smooth1.Update() del conn # free memory print('Decimating mesh ', end='') reduction = 1. - 1. / interpolation decimate = vtk.vtkQuadricDecimation() decimate.SetInputConnection(smooth1.GetOutputPort()) decimate.SetTargetReduction(reduction) decimate.Update() ncells = decimate.GetOutput().GetNumberOfCells() if ncells > 0: print(" --> Remaining %d cells" % ncells) else: print("\nERROR: zero cells in mesh") sys.exit(1) del smooth1 # free memory smooth2 = vtk.vtkSmoothPolyDataFilter() smooth2.SetInputConnection(decimate.GetOutputPort()) smooth2.SetNumberOfIterations(7) smooth2.SetRelaxationFactor(0.2) smooth2.FeatureEdgeSmoothingOff()
def CreateSurface(self): _ = i18n.InstallLanguage(self.language) reader = vtk.vtkXMLImageDataReader() reader.SetFileName(self.filename) reader.Update() image = reader.GetOutput() if (self.flip_image): # Flip original vtkImageData flip = vtk.vtkImageFlip() flip.SetInput(reader.GetOutput()) flip.SetFilteredAxis(1) flip.FlipAboutOriginOn() image = flip.GetOutput() # Create vtkPolyData from vtkImageData if self.mode == "CONTOUR": contour = vtk.vtkContourFilter() contour.SetInput(image) contour.SetValue(0, self.min_value) # initial threshold contour.SetValue(1, self.max_value) # final threshold contour.GetOutput().ReleaseDataFlagOn() contour.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = contour.GetOutput() else: #mode == "GRAYSCALE": mcubes = vtk.vtkMarchingCubes() mcubes.SetInput(image) mcubes.SetValue(0, 255) mcubes.ComputeScalarsOn() mcubes.ComputeGradientsOn() mcubes.ComputeNormalsOn() mcubes.ThresholdBetween(self.min_value, self.max_value) mcubes.GetOutput().ReleaseDataFlagOn() mcubes.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = mcubes.GetOutput() if self.decimate_reduction: decimation = vtk.vtkQuadricDecimation() decimation.SetInput(polydata) decimation.SetTargetReduction(self.decimate_reduction) decimation.GetOutput().ReleaseDataFlagOn() decimation.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = decimation.GetOutput() if self.smooth_iterations and self.smooth_relaxation_factor: smoother = vtk.vtkSmoothPolyDataFilter() smoother.SetInput(polydata) smoother.SetNumberOfIterations(self.smooth_iterations) smoother.SetFeatureAngle(80) smoother.SetRelaxationFactor(self.smooth_relaxation_factor) smoother.FeatureEdgeSmoothingOn() smoother.BoundarySmoothingOn() smoother.GetOutput().ReleaseDataFlagOn() smoother.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = smoother.GetOutput() if self.keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInput(polydata) conn.SetExtractionModeToLargestRegion() conn.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = conn.GetOutput() # Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from # polydata_utils.FillSurfaceHole, we need to review this. if self.fill_holes: filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.SetInput(polydata) filled_polydata.SetHoleSize(300) filled_polydata.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = filled_polydata.GetOutput() filename = tempfile.mktemp() writer = vtk.vtkXMLPolyDataWriter() writer.SetInput(polydata) writer.SetFileName(filename) writer.Write() self.pipe.send(None) self.pipe.send(filename)
tf = vtk.vtkTriangleFilter() tf.SetInputConnection(ps.GetOutputPort()) attr = vtk.vtkRandomAttributeGenerator() attr.SetInputConnection(tf.GetOutputPort()) attr.GeneratePointScalarsOn() attr.SetMinimumComponentValue(-0.05) attr.SetMaximumComponentValue(0.05) # This jitters the geometry warp = vtk.vtkWarpScalar() warp.SetInputConnection(attr.GetOutputPort()) warp.SetScaleFactor(0.02) # Decimator without volume constraint deci = vtk.vtkQuadricDecimation() deci.SetInputConnection(warp.GetOutputPort()) deci.SetTargetReduction(.95) deci.AttributeErrorMetricOn() deci.VolumePreservationOff() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(warp.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) # Decimator with volume constraint deci2 = vtk.vtkQuadricDecimation() deci2.SetInputConnection(warp.GetOutputPort()) deci2.SetTargetReduction(.95)
def vtk_quadric_decimation(inputdata, target_reduction=.9, volume_preservation=False, attribute_error_metric=False, scalars_weight=.1, vectors_weight=.1, normals_weight=.1, tcoords_weight=.1, tensors_weight=.1, verbose=False): """Wrapper for VTK QuadricDecimation Based on Garland and Heckbert (1997) See documentation: https://www.vtk.org/doc/nightly/html/classvtkQuadricDecimation.html#details Arguments: inputdata (vtk.vtkPolyData): vtk object containing vertices and simplices target_reduction (double): Desired reduction (expressed as a fraction of the original number of triangles) (default: .9). volume_preservation (bool): Decide whether to activate volume preservation which greatly reduces errors in triangle normal direction (default: False). attribute_error_metric (bool): Decide whether to include data attributes in the error metric. If False, the attribute weights will be ignored (default False). scalars_weight (double): (default .1). vectors_weight (double): (default .1). normals_weight (double): (default .1). tcoords_weight (double): (default .1). tensors_weight (double): (default .1). If a weight is set to None, it will be deactivated. verbose (bool): Print out steps and basic statistics (default False). Returns: decimatedPoly: vtkPolyData object """ title_string = 'VTK Quadric Decimation' if not isinstance(inputdata, vtkPolyData): raise TypeError( 'Unknown dtype for inputdata! vtk.vtkPolyData expected.') inputPoly = vtkPolyData() inputPoly.ShallowCopy(inputdata) decimate = vtkQuadricDecimation() decimate.SetInputData(inputPoly) # set parameters decimate.SetTargetReduction(target_reduction) decimate.SetVolumePreservation(volume_preservation) decimate.SetAttributeErrorMetric(attribute_error_metric) if scalars_weight != None: decimate.SetScalarsAttribute(True) decimate.SetScalarsWeight(scalars_weight) else: decimate.SetScalarsAttribute(False) if vectors_weight != None: decimate.SetVectorsAttribute(True) decimate.SetVectorsWeight(vectors_weight) else: decimate.SetVectorsAttribute(False) if normals_weight != None: decimate.SetNormalsAttribute(True) decimate.SetNormalsWeight(normals_weight) else: decimate.SetNormalsAttribute(False) if tcoords_weight != None: decimate.SetTCoordsAttribute(True) decimate.SetTCoordsWeight(tcoords_weight) else: decimate.SetTCoordsAttribute(False) if tensors_weight != None: decimate.SetTensorsAttribute(True) decimate.SetTensorsWeight(tensors_weight) else: decimate.SetTensorsAttribute(False) # execute decimate.Update() decimatedPoly = vtkPolyData() decimatedPoly.ShallowCopy(decimate.GetOutput()) if verbose: print_decimation_result(title_string, inputPoly, decimatedPoly, ('target_reduction=' + str(target_reduction))) return decimatedPoly
def AddNewActor(self, slice_, mask, surface_parameters): """ Create surface actor, save into project and send it to viewer. """ matrix = slice_.matrix filename_img = slice_.matrix_filename spacing = slice_.spacing algorithm = surface_parameters['method']['algorithm'] options = surface_parameters['method']['options'] surface_name = surface_parameters['options']['name'] quality = surface_parameters['options']['quality'] fill_holes = surface_parameters['options']['fill'] keep_largest = surface_parameters['options']['keep_largest'] mode = 'CONTOUR' # 'GRAYSCALE' min_value, max_value = mask.threshold_range colour = mask.colour[:3] try: overwrite = surface_parameters['options']['overwrite'] except KeyError: overwrite = False mask.matrix.flush() if quality in const.SURFACE_QUALITY.keys(): imagedata_resolution = const.SURFACE_QUALITY[quality][0] smooth_iterations = const.SURFACE_QUALITY[quality][1] smooth_relaxation_factor = const.SURFACE_QUALITY[quality][2] decimate_reduction = const.SURFACE_QUALITY[quality][3] #if imagedata_resolution: #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) pipeline_size = 4 if decimate_reduction: pipeline_size += 1 if (smooth_iterations and smooth_relaxation_factor): pipeline_size += 1 if fill_holes: pipeline_size += 1 if keep_largest: pipeline_size += 1 ## Update progress value in GUI UpdateProgress = vu.ShowProgress(pipeline_size) UpdateProgress(0, _("Creating 3D surface...")) language = ses.Session().language if (prj.Project().original_orientation == const.CORONAL): flip_image = False else: flip_image = True n_processors = multiprocessing.cpu_count() pipe_in, pipe_out = multiprocessing.Pipe() o_piece = 1 piece_size = 2000 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) q_in = multiprocessing.Queue() q_out = multiprocessing.Queue() p = [] for i in range(n_processors): sp = surface_process.SurfaceProcess( pipe_in, filename_img, matrix.shape, matrix.dtype, mask.temp_file, mask.matrix.shape, mask.matrix.dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, smooth_iterations, language, flip_image, q_in, q_out, algorithm != 'Default', algorithm, imagedata_resolution) p.append(sp) sp.start() for i in range(n_pieces): init = i * piece_size end = init + piece_size + o_piece roi = slice(init, end) q_in.put(roi) print("new_piece", roi) for i in p: q_in.put(None) none_count = 1 while 1: msg = pipe_out.recv() if (msg is None): none_count += 1 else: UpdateProgress(msg[0] / (n_pieces * pipeline_size), msg[1]) if none_count > n_pieces: break polydata_append = vtk.vtkAppendPolyData() # polydata_append.ReleaseDataFlagOn() t = n_pieces while t: filename_polydata = q_out.get() reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filename_polydata) # reader.ReleaseDataFlagOn() reader.Update() # reader.GetOutput().ReleaseDataFlagOn() polydata = reader.GetOutput() # polydata.SetSource(None) polydata_append.AddInputData(polydata) del reader del polydata t -= 1 polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append if algorithm == 'ca_smoothing': normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) normals_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) clean_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) smoother_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( smoother_ref(), _("Creating 3D surface..."))) smoother.SetInputData(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() # smoother.ReleaseDataFlagOn() # smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del smoother if decimate_reduction: print("Decimating", decimate_reduction) decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) decimation_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) conn_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) filled_polydata_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata # If InVesalius is running without GUI if wx.GetApp() is None: proj = prj.Project() #Create Surface instance if overwrite: surface = Surface(index=self.last_surface_index) proj.ChangeSurface(surface) else: surface = Surface(name=surface_name) index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index surface.colour = colour surface.polydata = polydata # With GUI else: normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() normals_ref = weakref.ref(normals) normals_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() # stripper.ReleaseDataFlagOn() stripper_ref = weakref.ref(stripper) stripper_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( stripper_ref(), _("Creating 3D surface..."))) stripper.SetInputData(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() # stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del stripper # Map polygonal data (vtkPolyData) to graphics primitives. mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(polydata) mapper.ScalarVisibilityOff() # mapper.ReleaseDataFlagOn() mapper.ImmediateModeRenderingOn() # improve performance # Represent an object (geometry & properties) in the rendered scene actor = vtk.vtkActor() actor.SetMapper(mapper) del mapper #Create Surface instance if overwrite: surface = Surface(index=self.last_surface_index) else: surface = Surface(name=surface_name) surface.colour = colour surface.polydata = polydata del polydata # Set actor colour and transparency actor.GetProperty().SetColor(colour) actor.GetProperty().SetOpacity(1 - surface.transparency) prop = actor.GetProperty() interpolation = int(ses.Session().surface_interpolation) prop.SetInterpolation(interpolation) proj = prj.Project() if overwrite: proj.ChangeSurface(surface) else: index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index session = ses.Session() session.ChangeProject() measured_polydata = vtk.vtkMassProperties() # measured_polydata.ReleaseDataFlagOn() measured_polydata.SetInputData(to_measure) volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) surface.volume = volume surface.area = area self.last_surface_index = surface.index del measured_polydata del to_measure Publisher.sendMessage('Load surface actor into viewer', actor=actor) # Send actor by pubsub to viewer's render if overwrite and self.actors_dict.keys(): old_actor = self.actors_dict[self.last_surface_index] Publisher.sendMessage('Remove surface actor from viewer', actor=old_actor) # Save actor for future management tasks self.actors_dict[surface.index] = actor Publisher.sendMessage('Update surface info in GUI', surface=surface) #When you finalize the progress. The bar is cleaned. UpdateProgress = vu.ShowProgress(1) UpdateProgress(0, _("Ready")) Publisher.sendMessage('Update status text in GUI', label=_("Ready")) Publisher.sendMessage('End busy cursor') del actor
def volume_to_polydata(volume, origin=(0, 0, 0), num_simplify_iter=0, smooth=False, level=0.): vol = volume > level # vol_padded = np.zeros(vol.shape+(10,10,10), np.bool) # vol_padded[5:-5, 5:-5, 5:-5] = vol vol_padded = np.pad( vol, ((5, 5), (5, 5), (5, 5)), 'constant' ) # need this otherwise the sides of volume will not close and expose the hollow inside of structures t = time.time() vs, fs = mcubes.marching_cubes( vol_padded, 0 ) # more than 5 times faster than skimage.marching_cube + correct_orientation sys.stderr.write('marching cube: %.2f seconds\n' % (time.time() - t)) # t = time.time() # vs, faces = marching_cubes(vol_padded, 0) # y,x,z # sys.stderr.write('marching cube: %.2f seconds\n' % (time.time() - t)) # t = time.time() # fs = correct_mesh_orientation(vol_padded, vs, faces) # sys.stderr.write('correct orientation: %.2f seconds\n' % (time.time() - t)) vs = vs[:, [1, 0, 2]] + origin - (5, 5, 5) # vs = vs[:, [1,0,2]] + origin # t = time.time() # area = mesh_surface_area(vs, fs) # # print 'area: %.2f' % area # sys.stderr.write('compute surface area: %.2f seconds\n' % (time.time() - t)) # t = time.time() polydata = mesh_to_polydata(vs, fs) sys.stderr.write('mesh_to_polydata: %.2f seconds\n' % (time.time() - t)) # for simplify_iter in range(num_simplify_iter): t = time.time() deci = vtk.vtkQuadricDecimation() deci.SetInputData(polydata) deci.SetTargetReduction(0.8) # 0.8 means each iteration causes the point number to drop to 20% the original deci.Update() polydata = deci.GetOutput() if smooth: smoother = vtk.vtkWindowedSincPolyDataFilter() # smoother.NormalizeCoordinatesOn() smoother.SetPassBand(.1) smoother.SetNumberOfIterations(20) smoother.SetInputData(polydata) smoother.Update() polydata = smoother.GetOutput() n_pts = polydata.GetNumberOfPoints() if polydata.GetNumberOfPoints() < 200: break sys.stderr.write('simplify %d @ %d: %.2f seconds\n' % (simplify_iter, n_pts, time.time() - t)) # return polydata
def quadric_decimation(data,ratio): sim = vtk.vtkQuadricDecimation(); sim.SetTargetReduction(ratio); sim.SetInputData(data); sim.Update() return sim.GetOutput();
def Decimate(self, target_reduction, volume_preservation=False, attribute_error=False, scalars=True, vectors=True, normals=False, tcoords=True, tensors=True, scalars_weight=0.1, vectors_weight=0.1, normals_weight=0.1, tcoords_weight=0.1, tensors_weight=0.1, inplace=True): """ Reduces the number of triangles in a triangular mesh using vtkQuadricDecimation. Parameters ---------- mesh : vtk.PolyData Mesh to decimate target_reduction : float Fraction of the original mesh to remove. TargetReduction is set to 0.9, this filter will try to reduce the data set to 10% of its original size and will remove 90% of the input triangles. volume_preservation : bool, optional Decide whether to activate volume preservation which greatly reduces errors in triangle normal direction. If off, volume preservation is disabled and if AttributeErrorMetric is active, these errors can be large. Defaults to False. attribute_error : bool, optional Decide whether to include data attributes in the error metric. If off, then only geometric error is used to control the decimation. Defaults to False. scalars : bool, optional If attribute errors are to be included in the metric (i.e., AttributeErrorMetric is on), then the following flags control which attributes are to be included in the error calculation. Defaults to True. vectors : bool, optional See scalars parameter. Defaults to True. normals : bool, optional See scalars parameter. Defaults to False. tcoords : bool, optional See scalars parameter. Defaults to True. tensors : bool, optional See scalars parameter. Defaults to True. scalars_weight : float, optional The scaling weight contribution of the scalar attribute. These values are used to weight the contribution of the attributes towards the error metric. Defaults to 0.1. vectors_weight : float, optional See scalars weight parameter. Defaults to 0.1. normals_weight : float, optional See scalars weight parameter. Defaults to 0.1. tcoords_weight : float, optional See scalars weight parameter. Defaults to 0.1. tensors_weight : float, optional See scalars weight parameter. Defaults to 0.1. inplace : bool, optional Updates mesh in-place while returning nothing. Returns ------- outmesh : vtkInterface.PolyData Decimated mesh. None when inplace=True. """ # create decimation filter decimate = vtk.vtkQuadricDecimation() # vtkDecimatePro as well decimate.SetVolumePreservation(volume_preservation) decimate.SetAttributeErrorMetric(attribute_error) decimate.SetScalarsAttribute(scalars) decimate.SetVectorsAttribute(vectors) decimate.SetNormalsAttribute(normals) decimate.SetTCoordsAttribute(tcoords) decimate.SetTensorsAttribute(tensors) decimate.SetScalarsWeight(scalars_weight) decimate.SetVectorsWeight(vectors_weight) decimate.SetNormalsWeight(normals_weight) decimate.SetTCoordsWeight(tcoords_weight) decimate.SetTensorsWeight(tensors_weight) decimate.SetTargetReduction(target_reduction) decimate.SetInputData(self) decimate.Update() if inplace: self.Overwrite(decimate.GetOutput()) else: return PolyData(decimate.GetOutput())
def AddNewActor(self, pubsub_evt): """ Create surface actor, save into project and send it to viewer. """ slice_, mask, surface_parameters = pubsub_evt.data matrix = slice_.matrix filename_img = slice_.matrix_filename spacing = slice_.spacing algorithm = surface_parameters['method']['algorithm'] options = surface_parameters['method']['options'] surface_name = surface_parameters['options']['name'] quality = surface_parameters['options']['quality'] fill_holes = surface_parameters['options']['fill'] keep_largest = surface_parameters['options']['keep_largest'] mode = 'CONTOUR' # 'GRAYSCALE' min_value, max_value = mask.threshold_range colour = mask.colour try: overwrite = surface_parameters['options']['overwrite'] except KeyError: overwrite = False mask.matrix.flush() if quality in const.SURFACE_QUALITY.keys(): imagedata_resolution = const.SURFACE_QUALITY[quality][0] smooth_iterations = const.SURFACE_QUALITY[quality][1] smooth_relaxation_factor = const.SURFACE_QUALITY[quality][2] decimate_reduction = const.SURFACE_QUALITY[quality][3] #if imagedata_resolution: #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) pipeline_size = 4 if decimate_reduction: pipeline_size += 1 if (smooth_iterations and smooth_relaxation_factor): pipeline_size += 1 if fill_holes: pipeline_size += 1 if keep_largest: pipeline_size += 1 ## Update progress value in GUI UpdateProgress = vu.ShowProgress(pipeline_size) UpdateProgress(0, _("Creating 3D surface...")) language = ses.Session().language if (prj.Project().original_orientation == const.CORONAL): flip_image = False else: flip_image = True n_processors = multiprocessing.cpu_count() pipe_in, pipe_out = multiprocessing.Pipe() o_piece = 1 piece_size = 2000 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) q_in = multiprocessing.Queue() q_out = multiprocessing.Queue() p = [] for i in xrange(n_processors): sp = surface_process.SurfaceProcess(pipe_in, filename_img, matrix.shape, matrix.dtype, mask.temp_file, mask.matrix.shape, mask.matrix.dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, smooth_iterations, language, flip_image, q_in, q_out, algorithm != 'Default', algorithm, imagedata_resolution) p.append(sp) sp.start() for i in xrange(n_pieces): init = i * piece_size end = init + piece_size + o_piece roi = slice(init, end) q_in.put(roi) print "new_piece", roi for i in p: q_in.put(None) none_count = 1 while 1: msg = pipe_out.recv() if(msg is None): none_count += 1 else: UpdateProgress(msg[0]/(n_pieces * pipeline_size), msg[1]) if none_count > n_pieces: break polydata_append = vtk.vtkAppendPolyData() polydata_append.ReleaseDataFlagOn() t = n_pieces while t: filename_polydata = q_out.get() reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filename_polydata) reader.ReleaseDataFlagOn() reader.Update() reader.GetOutput().ReleaseDataFlagOn() polydata = reader.GetOutput() polydata.SetSource(None) polydata_append.AddInput(polydata) del reader del polydata t -= 1 polydata_append.Update() polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) polydata.SetSource(None) del polydata_append if algorithm == 'ca_smoothing': normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) normals_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInput(polydata) normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() clean.ReleaseDataFlagOn() clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) clean_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInput(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() polydata.SetSource(None) del clean try: polydata.BuildLinks() except TypeError: polydata.BuildLinks(0) polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], options['max distance'], options['min weight'], options['steps']) polydata.SetSource(None) polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) smoother.SetInput(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() smoother.ReleaseDataFlagOn() smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) polydata.SetSource(None) del smoother if decimate_reduction: print "Decimating", decimate_reduction decimation = vtk.vtkQuadricDecimation() decimation.ReleaseDataFlagOn() decimation.SetInput(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) polydata.SetSource(None) del decimation to_measure = polydata #to_measure.Register(None) to_measure.SetSource(None) if keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInput(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) conn_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInput(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) polydata.SetSource(None) polydata.DebugOn() del filled_polydata normals = vtk.vtkPolyDataNormals() normals.ReleaseDataFlagOn() normals_ref = weakref.ref(normals) normals_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInput(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() stripper.ReleaseDataFlagOn() stripper_ref = weakref.ref(stripper) stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) stripper.SetInput(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) polydata.SetSource(None) del stripper # Map polygonal data (vtkPolyData) to graphics primitives. mapper = vtk.vtkPolyDataMapper() mapper.SetInput(polydata) mapper.ScalarVisibilityOff() mapper.ReleaseDataFlagOn() mapper.ImmediateModeRenderingOn() # improve performance # Represent an object (geometry & properties) in the rendered scene actor = vtk.vtkActor() actor.SetMapper(mapper) del mapper #Create Surface instance if overwrite: surface = Surface(index = self.last_surface_index) else: surface = Surface(name=surface_name) surface.colour = colour surface.polydata = polydata del polydata # Set actor colour and transparency actor.GetProperty().SetColor(colour) actor.GetProperty().SetOpacity(1-surface.transparency) prop = actor.GetProperty() interpolation = int(ses.Session().surface_interpolation) prop.SetInterpolation(interpolation) proj = prj.Project() if overwrite: proj.ChangeSurface(surface) else: index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index session = ses.Session() session.ChangeProject() # The following lines have to be here, otherwise all volumes disappear measured_polydata = vtk.vtkMassProperties() measured_polydata.ReleaseDataFlagOn() measured_polydata.SetInput(to_measure) volume = float(measured_polydata.GetVolume()) surface.volume = volume self.last_surface_index = surface.index del measured_polydata del to_measure Publisher.sendMessage('Load surface actor into viewer', actor) # Send actor by pubsub to viewer's render if overwrite and self.actors_dict.keys(): old_actor = self.actors_dict[self.last_surface_index] Publisher.sendMessage('Remove surface actor from viewer', old_actor) # Save actor for future management tasks self.actors_dict[surface.index] = actor Publisher.sendMessage('Update surface info in GUI', (surface.index, surface.name, surface.colour, surface.volume, surface.transparency)) #When you finalize the progress. The bar is cleaned. UpdateProgress = vu.ShowProgress(1) UpdateProgress(0, _("Ready")) Publisher.sendMessage('Update status text in GUI', _("Ready")) Publisher.sendMessage('End busy cursor') del actor
def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxation_factor, decimate_reduction, keep_largest, fill_holes, options, msg_queue): def send_message(msg): try: msg_queue.put_nowait(msg) except queue.Full as e: print(e) log_path = tempfile.mktemp('vtkoutput.txt') fow = vtk.vtkFileOutputWindow() fow.SetFileName(log_path) ow = vtk.vtkOutputWindow() ow.SetInstance(fow) send_message('Joining surfaces ...') polydata_append = vtk.vtkAppendPolyData() for f in filenames: reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(f) reader.Update() polydata = reader.GetOutput() polydata_append.AddInputData(polydata) del reader del polydata polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append send_message('Cleaning surface ...') clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean if algorithm == 'ca_smoothing': send_message('Calculating normals ...') normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) send_message('Context Aware smoothing ...') mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() # else: # #smoother = vtk.vtkWindowedSincPolyDataFilter() # send_message('Smoothing ...') # smoother = vtk.vtkSmoothPolyDataFilter() # smoother_ref = weakref.ref(smoother) # # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: # # UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) # smoother.SetInputData(polydata) # smoother.SetNumberOfIterations(smooth_iterations) # smoother.SetRelaxationFactor(smooth_relaxation_factor) # smoother.SetFeatureAngle(80) # #smoother.SetEdgeAngle(90.0) # #smoother.SetPassBand(0.1) # smoother.BoundarySmoothingOn() # smoother.FeatureEdgeSmoothingOn() # #smoother.NormalizeCoordinatesOn() # #smoother.NonManifoldSmoothingOn() # # smoother.ReleaseDataFlagOn() # # smoother.GetOutput().ReleaseDataFlagOn() # smoother.Update() # del polydata # polydata = smoother.GetOutput() # #polydata.Register(None) # # polydata.SetSource(None) # del smoother if not decimate_reduction: print("Decimating", decimate_reduction) send_message('Decimating ...') decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) # decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: send_message('Finding the largest ...') conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) # conn_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: send_message('Filling holes ...') filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) # filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() # normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) normals.SetFeatureAngle(80) normals.SplittingOn() normals.AutoOrientNormalsOn() normals.NonManifoldTraversalOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # # Improve performance # stripper = vtk.vtkStripper() # # stripper.ReleaseDataFlagOn() # # stripper_ref = weakref.ref(stripper) # # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: # # UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) # stripper.SetInputData(polydata) # stripper.PassThroughCellIdsOn() # stripper.PassThroughPointIdsOn() # # stripper.GetOutput().ReleaseDataFlagOn() # stripper.Update() # del polydata # polydata = stripper.GetOutput() # #polydata.Register(None) # # polydata.SetSource(None) # del stripper send_message('Calculating area and volume ...') measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInputData(to_measure) measured_polydata.Update() volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) del measured_polydata filename = tempfile.mktemp(suffix='_full.vtp') writer = vtk.vtkXMLPolyDataWriter() writer.SetInputData(polydata) writer.SetFileName(filename) writer.Write() del writer print("MY PID", os.getpid()) return filename, {'volume': volume, 'area': area}
def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxation_factor, decimate_reduction, keep_largest, fill_holes, options, msg_queue): def send_message(msg): try: msg_queue.put_nowait(msg) except queue.Full as e: print(e) send_message('Joining surfaces ...') polydata_append = vtk.vtkAppendPolyData() for f in filenames: reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(f) reader.Update() polydata = reader.GetOutput() polydata_append.AddInputData(polydata) del reader del polydata polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append send_message('Cleaning surface ...') clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean if algorithm == 'ca_smoothing': send_message('Calculating normals ...') normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) send_message('Context Aware smoothing ...') mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() send_message('Smoothing ...') smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) smoother.SetInputData(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() # smoother.ReleaseDataFlagOn() # smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del smoother if decimate_reduction: print("Decimating", decimate_reduction) send_message('Decimating ...') decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) # decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: send_message('Finding the largest ...') conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) # conn_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: send_message('Filling holes ...') filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) # filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() # normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.SetFeatureAngle(80) # normals.SplittingOff() # normals.AutoOrientNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() # stripper.ReleaseDataFlagOn() # stripper_ref = weakref.ref(stripper) # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) stripper.SetInputData(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() # stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del stripper send_message('Calculating area and volume ...') measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInputData(to_measure) measured_polydata.Update() volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) del measured_polydata filename = tempfile.mktemp(suffix='_full.vtp') writer = vtk.vtkXMLPolyDataWriter() writer.SetInputData(polydata) writer.SetFileName(filename) writer.Write() del writer print("MY PID", os.getpid()) return filename, {'volume': volume, 'area': area}
def decimation(vtk_poly_data, reduction=0.95, verbose=False): """ Call of vtkQuadricDecimation on a vtk_poly_data to decimate the mesh Parameters ---------- vtk_poly_data : vtkPolyData vtkPolyData is a data object that is a concrete implementation of vtkDataSet. vtkPolyData represents a geometric structure consisting of vertices, lines, polygons, and/or triangle strips. Point and cell attribute values (e.g., scalars, vectors, etc.) also are represented. reduction : float, optional Percentage of reduction for the decimation 0.95 will reduce the vtk_poly_date of 95% verbose : bool, optional If True, print for some information of each part of the algorithms Returns ------- out : vtkPolyData vtkPolyData is a data object that is a concrete implementation of vtkDataSet. vtkPolyData represents a geometric structure consisting of vertices, lines, polygons, and/or triangle strips. Point and cell attribute values (e.g., scalars, vectors, etc.) """ if verbose: print(("=" * 80 + "\n" + "Decimation : \n" "\tReduction (percentage) :{}\n" "\n" "\tBefore decimation\n" "\t-----------------\n" "\tThere are {} points.\n" "\tThere are {} polygons.\n").format( reduction, vtk_poly_data.GetNumberOfPoints(), vtk_poly_data.GetNumberOfPolys())) decimate = vtk.vtkQuadricDecimation() decimate.SetTargetReduction(reduction) if vtk.VTK_MAJOR_VERSION <= 5: decimate.SetInputConnection(vtk_poly_data.GetProducerPort()) decimate.SetInput(vtk_poly_data) else: decimate.SetInputData(vtk_poly_data) decimate.Update() vtk_poly_decimated = vtk.vtkPolyData() vtk_poly_decimated.ShallowCopy(decimate.GetOutput()) if verbose: print(("\tAfter decimation\n" "\t-----------------\n" "\tThere are {} points.\n" "\tThere are {} polygons.\n" + 80 * "=").format( reduction, vtk_poly_data.GetNumberOfPoints(), vtk_poly_data.GetNumberOfPolys())) return vtk_poly_decimated