ShapeDNA: comparing two shapes#
Compute the ShapeDNA fingerprint (the Laplace–Beltrami spectrum) of two synthetic surfaces and quantify how different they are with the ShapeDNA distance. This example uses only matplotlib, so it is fast and dependency-light.
import matplotlib.pyplot as plt
import numpy as np
import pyvista as pv
import spectralbrain as sb
def _fingerprint(mesh_pv, k=60):
v = np.asarray(mesh_pv.points)
f = mesh_pv.faces.reshape(-1, 4)[:, 1:]
decomp = sb.BrainMesh(v, f).decompose(k=k)
return sb.compute_shapedna(decomp), decomp
Two shapes: a sphere and an ellipsoid (the sphere stretched along z).
sphere = pv.Icosphere(nsub=4)
ellipsoid = pv.Icosphere(nsub=4)
ellipsoid.points[:, 2] *= 1.8
sdna_a, dec_a = _fingerprint(sphere)
sdna_b, dec_b = _fingerprint(ellipsoid)
Compare the fingerprints with the ShapeDNA distance.
Plot the two spectra; the gap between them is what the distance summarizes.
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(sdna_a, "-o", ms=3, label="sphere")
ax.plot(sdna_b, "-s", ms=3, label="ellipsoid")
ax.set_xlabel("eigenvalue index $i$")
ax.set_ylabel(r"normalized $\lambda_i$")
ax.set_title(f"ShapeDNA spectra — distance = {dist:.3f}")
ax.legend(frameon=False)
fig.tight_layout()
plt.show()