Package: fast-simplification
This is a python wrapping of theFast-Quadric-Mesh-Simplification Library. Having
arrived at the same problem as the original author, but needing a Python
library, this project seeks to extend the work of the original library while
adding integration to Python and thePyVistaproject.For the full documentation visit:https://pyvista.github.io/fast-simplification/InstallationFast Simplification can be installed from PyPI using pip on Python >= 3.7:pip install fast-simplificationSee theContributingfor more details regarding development or if the installation through pip doesn’t work out.Basic UsageThe basic interface is quite straightforward and can work directly
with arrays of points and triangles:points=[[0.5,-0.5,0.0],[0.0,-0.5,0.0],[-0.5,-0.5,0.0],[0.5,0.0,0.0],[0.0,0.0,0.0],[-0.5,0.0,0.0],[0.5,0.5,0.0],[0.0,0.5,0.0],[-0.5,0.5,0.0]]faces=[[0,1,3],[4,3,1],[1,2,4],[5,4,2],[3,4,6],[7,6,4],[4,5,7],[8,7,5]]points_out,faces_out=fast_simplification.simplify(points,faces,0.5)Advanced UsageThis library supports direct integration with VTK through PyVista to
provide a simplistic interface to the library. As this library
provides a 4-5x improvement to the VTK decimation algorithms.>>>frompyvistaimportexamples>>>mesh=examples.download_nefertiti()>>>out=fast_simplification.simplify_mesh(mesh,target_reduction=0.9)Comparewithbuilt-inVTK/PyVistamethods:>>>fas_sim=fast_simplification.simplify_mesh(mesh,target_reduction=0.9)>>>dec_std=mesh.decimate(0.9)# vtkQuadricDecimation>>>dec_pro=mesh.decimate_pro(0.9)# vtkDecimatePro>>>pv.set_plot_theme('document')>>>pl=pv.Plotter(shape=(2,2),window_size=(1000,1000))>>>pl.add_text('Original','upper_right',color='w')>>>pl.add_mesh(mesh,show_edges=True)>>>pl.camera_position=cpos>>>pl.subplot(0,1)>>>pl.add_text(...'Fast-Quadric-Mesh-Simplification\n~2.2 seconds','upper_right',color='w'...)>>>pl.add_mesh(fas_sim,show_edges=True)>>>pl.camera_position=cpos>>>pl.subplot(1,0)>>>pl.add_mesh(dec_std,show_edges=True)>>>pl.add_text(...'vtkQuadricDecimation\n~9.5 seconds','upper_right',color='w'...)>>>pl.camera_position=cpos>>>pl.subplot(1,1)>>>pl.add_mesh(dec_pro,show_edges=True)>>>pl.add_text(...'vtkDecimatePro\n11.4~ seconds','upper_right',color='w'...)>>>pl.camera_position=cpos>>>pl.show()Comparison to other librariesThepyfqmrlibrary wraps the same header file as this library and has similar capabilities.
In this library, the decision was made to write the Cython layer on top of an
additional C++ layer rather than directly interfacing with wrapper from Cython.
This results in a mild performance improvement.Reusing the example above:Setupatimingfunction.>>>importpyfqmr>>>vertices=mesh.points>>>faces=mesh.faces.reshape(-1,4)[:,1:]>>>deftime_pyfqmr():...mesh_simplifier=pyfqmr.Simplify()...mesh_simplifier.setMesh(vertices,faces)...mesh_simplifier.simplify_mesh(...target_count=out.n_faces,aggressiveness=7,verbose=0...)...vertices_out,faces_out,normals_out=mesh_simplifier.getMesh()...returnvertices_out,faces_out,normals_outNow, time it and compare with the non-VTK API of this library:>>>timeittime_pyfqmr()2.75s±5.35msperloop(mean±std.dev.of7runs,1loopeach)>>>timeitvout,fout=fast_simplification.simplify(vertices,faces,0.9)2.05s±3.18msperloop(mean±std.dev.of7runs,1loopeach)Additionally, thefast-simplificationlibrary has direct plugins
to thepyvistalibrary, making it easy to read and write meshes:>>>importpyvista>>>importfast_simplification>>>mesh=pyvista.read('my_mesh.stl')>>>simple=fast_simplification.simplify_mesh(mesh)>>>simple.save('my_simple_mesh.stl')Since both libraries are based on the same core C++ code, feel free to
use whichever gives you the best performance and interoperability.Replay decimation functionalityThis library also provides an interface to keep track of the successive
collapses that occur during the decimation process and to replay the
decimation process. This can be useful for different applications, such
as:applying the same decimation to a collection of meshes that share the
same topologycomputing a correspondence map between the vertices of the original
mesh and the vertices of the decimated mesh, to transfer field data from
one to the other for examplereplaying the decimation process with a smaller target reduction than
the original one, faster than decimating the original mesh with the
smaller target reductionTo use this functionality, you need to set thereturn_collapsesparameter toTruewhen callingsimplify. This will return the
successive collapses of the decimation process in addition to points
and faces.>>>importfast_simplification>>>importpyvista>>>mesh=pyvista.Sphere()>>>points,faces=mesh.points,mesh.faces.reshape(-1,4)[:,1:]>>>points_out,faces_out,collapses=fast_simplification.simplify(points,faces,0.9,return_collapses=True)Now you can callreplay_simplificationto replay the decimation process
and obtain the mapping between the vertices of the original mesh and the
vertices of the decimated mesh.>>>points_out,faces_out,indice_mapping=fast_simplification.replay_simplification(points,faces,collapses)>>>i=3>>>print(f'Vertex{i}of the original mesh is mapped to{indice_mapping[i]}of the decimated mesh')You can also use thereplay_simplificationfunction to replay the
decimation process with a smaller target reduction than the original one.
This is faster than decimating the original mesh with the smaller target
reduction. To do so, you need to pass a subset of the collapses to thereplay_simplificationfunction. For example, to replay the decimation
process with a target reduction of 50% the initial rate, you can run:>>>importnumpyasnp>>>collapses_half=collapses[:int(0.5*len(collapses))]>>>points_out,faces_out,indice_mapping=fast_simplification.replay_simplification(points,faces,collapses_half)If you have a collection of meshes that share the same topology, you can
apply the same decimation to all of them by callingreplay_simplificationwith the same collapses for each mesh. This ensure that the decimated meshes
will share the same topology.>>>importnumpyasnp>>># Assume that you have a collection of meshes stored in a list meshes>>>_,_,collapses=fast_simplification.simplify(meshes[0].points,meshes[0].faces,...0.9,return_collapses=True)>>>decimated_meshes=[]>>>formeshinmeshes:...points_out,faces_out,_=fast_simplification.replay_simplification(mesh.points,mesh.faces,collapses)...decimated_meshes.append(pyvista.PolyData(points_out,faces_out))ContributingContribute to this repository by forking this repository and installing in
development mode with:git clone https://github.com/<USERNAME>/fast-simplification
pip install -e .
pip install -r requirements_test.txtYou can then add your feature or commit your bug fix and then run your unit
testing with:pytestUnit testing will automatically enforce minimum code coverage standards.Next, to ensure your code meets minimum code styling standards, run:pip install pre-commit
pre-commit run --all-filesFinally,create a pull requestfrom your fork and I’ll be sure to review it.