Package: robust-laplacian
A Python package for high-quality Laplace matrices on meshes and point clouds.pip install robust_laplacianThe Laplacian is at the heart of many algorithms across geometry processing, simulation, and machine learning. This library builds a high-quality, robust Laplace matrix which often improves the performance of these algorithms, and wraps it all up in a simple, single-function API!Sample: computing eigenvectors of the point cloud LaplacianGiven as input a triangle mesh with arbitrary connectivity (could be nonmanifold, have boundary, etc), OR a point cloud, this library builds anNxNsparse Laplace matrix, whereNis the number of vertices/points. This Laplace matrix is similar to thecotan-Laplacianused widely in geometric computing, but internally the algorithm constructs anintrinsic Delaunay triangulationof the surface, which gives the Laplace matrix great numerical properties. The resulting Laplacian is always a symmetric positive-definite matrix, with all positive edge weights. Additionally, this library performsintrinsic mollificationto alleviate floating-point issues with degenerate triangles.The resulting Laplace matrixLis a "weak" Laplace matrix, so we also generate a diagonal lumped mass matrixM, where each diagonal entry holds an area associated with the mesh element. The "strong" Laplacian can then be formed asM^-1 L, or a Poisson problem could be solved asL x = M y.AC++ implementation and demois available.This library implements the algorithm described inA Laplacian for Nonmanifold Triangle MeshesbyNicholas SharpandKeenan Craneat SGP 2020 (where it won a best paper award!). See the paper for more details, and please use the citation given at the bottom if it contributes to academic work.ExampleBuild a point cloud Laplacian, compute its first 10 eigenvectors, and visualize withPolyscopepipinstallnumpyscipyplyfilepolyscoperobust_laplacianimportrobust_laplacianfromplyfileimportPlyDataimportnumpyasnpimportpolyscopeaspsimportscipy.sparse.linalgassla# Read inputplydata=PlyData.read("/path/to/cloud.ply")points=np.vstack((plydata['vertex']['x'],plydata['vertex']['y'],plydata['vertex']['z'])).T# Build point cloud LaplacianL,M=robust_laplacian.point_cloud_laplacian(points)# (or for a mesh)# L, M = robust_laplacian.mesh_laplacian(verts, faces)# Compute some eigenvectorsn_eig=10evals,evecs=sla.eigsh(L,n_eig,M,sigma=1e-8)# Visualizeps.init()ps_cloud=ps.register_point_cloud("my cloud",points)foriinrange(n_eig):ps_cloud.add_scalar_quantity("eigenvector_"+str(i),evecs[:,i],enabled=True)ps.show()NOTE:No one can agree on the sign convention for the Laplacian. This library builds thepositive semi-definiteLaplace matrix, where the diagonal entries are positive and off-diagonal entries are negative. This is theoppositeof the sign used by e.g. libIGL inigl.cotmatrix, so you may need to flip a sign when converting code.APIThis package exposes just two functions:mesh_laplacian(verts, faces, mollify_factor=1e-5)vertsis anV x 3numpy array of vertex positionsfacesis anF x 3numpy array of face indices, where each is a 0-based index referring to a vertexmollify_factoramount of intrinsic mollifcation to perform.0disables, larger values will increase numerical stability, while very large values will slightly implicitly smooth out the geometry. The range of reasonable settings is roughly0to1e-3.  The default value should usually be sufficient.return L, Ma pair of scipy sparse matrices for the LaplacianLand mass matrixMpoint_cloud_laplacian(points, mollify_factor=1e-5, n_neighbors=30)pointsis anV x 3numpy array of point positionsmollify_factoramount of intrinsic mollifcation to perform.0disables, larger values will increase numerical stability, while very large values will slightly implicitly smooth out the geometry. The range of reasonable settings is roughly0to1e-3.  The default value should usually be sufficient.n_neighborsis the number of nearest neighbors to use when constructing local triangulations. This parameter has little effect on the resulting matrices, and the default value is almost always sufficient.return L, Ma pair of scipy sparse matrices for the LaplacianLand mass matrixMInstallationThe package is availabe viapippip install robust_laplacianThe underlying algorithm is implemented in C++; the pypi entry includes precompiled binaries for many platforms.Very old versions ofpipmight need to be upgraded likepip install pip --upgradeto use the precompiled binaries.Alternately, if no precompiled binary matches your systempipwill attempt to compile from source on your machine.  This requires a working C++ toolchain, including cmake.Known limitationsFor point clouds, this repo uses a simple method to generate planar Delaunay triangulations, which may not be totally robust to collinear or degenerate point clouds.DependenciesThis python library is mainly a wrapper around the implementation in thegeometry-centrallibrary; see there for further dependencies. Additionally, this library usespybind11to generate bindings, andjc_voronoifor 2D Delaunay triangulation on point clouds. All are permissively licensed.Citation@article{Sharp:2020:LNT,
  author={Nicholas Sharp and Keenan Crane},
  title={{A Laplacian for Nonmanifold Triangle Meshes}},
  journal={Computer Graphics Forum (SGP)},
  volume={39},
  number={5},
  year={2020}
}For developersThis repo is configured with CI on github actions to build wheels across platform.Deploy a new versionCommit the desired version to themasterbranch, be sure the version string insetup.pycorresponds to the new version number. Include the string[ci build]in the commit message to ensure a build happens.Watch th github actions builds to ensure the test & build stages succeed and all wheels are compiled.While you're waiting, update the docs.Tag the commit with a tag likev1.2.3, matching the version insetup.py. This will kick off a new github actions build which deploys the wheels to PyPI after compilation.