Discrete Laplacian

If you look in the first example file I posted above - cotanweight_example.gh and inside the function:
double[] cotanWeights(PlanktonMesh P, int i)
you can see how these weights can be calculated. It looks at a single vertex of the mesh and the ring of connected neighbouring vertices, and returns an array of scalar values, one for each of these surrounding vertices.

One simple way of thinking about it is as a way of weighting the vertices so that they properly take into account the areas of the triangles.
Say we are looking at a vertex surrounded by a ring like this:


If we have a value on each of the surrounding vertices and we take a simple unweighted average of these values (by just adding up all their values and dividing by how many of them there are), then the right side would have a much bigger influence, because there are more vertices bunched together there, even though the total area of the triangles is fairly symmetrically distributed around the central vertex.
If we are trying to average some property over the surface area of the mesh, this simple uniform average causes unwanted distortion, depending on the mesh quality, as you can see with the way the colours on spread on the left in that first animation.
So instead we can calculate weightings to multiply the surrounding vertices by the area that ‘belongs’ to that connecting edge. Using the cotangent of the tips of the 2 adjacent triangles to the edge is just a geometric way of calculating this area:

(also, if you are confused why you don’t see any actual calls to trig functions in the code of my function - it’s because the cotangent of 2 vectors can be calculated efficiently by taking their dot product divided by their cross product)

7 Likes