747 views
[CGDI] Geometry Processing: Laplacian smoothing and Tutte Embedding === > [name="David Coeurjolly"] ENS [CGDI](https://perso.liris.cnrs.fr/vincent.nivoliers/cgdi/) [TOC] --- In this practical, the objective is to play with basic mesh iterators/circulators either using the [geometry-central](https://geometry-central.net) (`c++`) or the [pygel3d](http://www2.compute.dtu.dk/projects/GEL/PyGEL/) (in `python`) APIs. # Warm-up 1. Read the last section of [this practical](https://codimd.math.cnrs.fr/s/4HjiHCH9z). 2. Get the code skeleton for this fourth practical (`git pull`) which corresponds to the last part of the third one (OBJ loading); compile or evaluate it. At this point, you should be a able to visualize some [Wavefront OBJ files](https://en.wikipedia.org/wiki/Wavefront_.obj_file) (some examples are given in the folder `data/`). E.g. for `bimba-mix.obj`: ![](https://raw.githubusercontent.com/dcoeurjo/CGDI-Practicals/main/geometry-processing/5-LaplacianSmoothing/bimba-mix.png) :::warning Questions 1 and 2 should take less than 10 minutes... If you get stuck for technical reasons, send us a message ASAP. ::: # Iterators, Circulators... In this practical, we will only consider meshes which are [discrete 2-manifolds](https://en.wikipedia.org/wiki/Surface_(topology)) (with boundaries). We won't go into the topological consequences of that statement but the basic properties are the following combinatorial ones: * The mesh has a graph structure $G(V,E)$ with vertices $V$ and edges $E$. * Faces are non-contractible cycles of $G$. * Each **interior** edge is adjacent to exactly two faces. Edges on the **boundary** are only adjacent to one face. * At each vertex, its adjacent faces define a topological disk. There are many libraries and utilities that load a mesh structure and provide the API and iterators to traverse the mesh. For instance, with [pygel3d](http://www2.compute.dtu.dk/projects/GEL/PyGEL/) and its [hmesh API](http://www2.compute.dtu.dk/projects/GEL/PyGEL/PyGEL/pygel3d/hmesh.html) ```python for f in mesh.faces: #do something on the face f for v in mesh.circulate_face(f): #do something on the vertex v of the face f ``` or ``` python for adjV in mesh.circulate_vertex(v, mode='v'): #... ``` to iterate over adjacent vertices to `v` (`mode='f'` will iterate over the adjacent faces and `mode='h'` over the adjacent halfedges). In [geometry-central](https://geometry-central.net) and its [surface_mesh navigation API](https://geometry-central.net/surface/surface_mesh/navigation/) it looks like: ``` c++ for(auto f: mesh.faces()) { #do something on the face f for(auto v: f.adjacentVertices()) #do something on the vertex v of the face f } ``` 3. Create a simple code that loads the `bimba-mix.obj` file and create a vertex quantity (cf previous practical) which contains to the degree at each vertex (i.e. number of adjacent vertices). 4. Create a simple OBJ debugger that prints a trace such as ``` face 0: has 4 vertices vertex 12 with coordinates (1.2,3.2,4.3) vertex 13 with coordinates (-1.2,3.2,1.3) vertex 22 with coordinates (1.2,13.2,.3) vertex 42 with coordinates (1.22,3.2,7.3) face 1: has 3 vertices .... ``` 5. Create a tool that scans the mesh and detect the vertices belonging to the boundaries of the mesh. `bimba-mix.obj` is a discrete 2-manifold without boundaries. To test your code, use `bunnyhead.obj`. :::warning To visualize such quantities, we encourage you to use the `polyscope` structures/quantities for *visual debugging*. For instance the output of the previous question could be a new point cloud containing the boundary vertices, as [count quantity](https://polyscope.run/structures/surface_mesh/count_quantities/) attached to the mesh vertices, or displaying the boundary edges as a [curve network](https://polyscope.run/structures/curve_network/basics/)... ::: # Laplacian and Taubin smoothing Being able to smooth a noisy geometrical object is one of the most fundamental geometry processing task. We would like you to implement one of the most elementary, yet efficient approach, is called the [Laplacian smoothing](https://en.wikipedia.org/wiki/Laplacian_smoothing). Let's start with the classical formulation (for $0<\lambda<1$): $$ v_{t+1} \leftarrow v_{t} + \lambda {L~}(v_t)$$ with $${L}(v_t)= \left(\sum_{v'\in\mathcal{N}(v_t)} \frac{v'}{|\mathcal{N}(v_t)|}\right) - v_t$$ AKA: Each vertex is displaced in the direction of its adjacent vertices barycenter with a step $\lambda$ ($\mathcal{N}(v)$ denotes the adjacent vertices to $v$). :::info This formulation refers to the *Laplacian* as the operator ${L~}$ is a rough finite difference approximation of the Laplacian operator applied to the mesh vertex positions. We will elaborate on that later. ::: {%youtube bFf9d-GyrR0 %} 6. Implement the Laplacian Smoothing. 7. If you consider an infinite number of steps (and no numerical issues), what shape is the fixed point of the Laplacian smoothing? What kind of *flow* does it imply? :::info As you may have guessed, the ${L~}$ operator can be replaced by more advanced discrete version of the [Laplace-Beltrami](https://en.wikipedia.org/wiki/Laplace–Beltrami_operator) operator such as the classical "cotan" one you have seen in the lecture: $$L(v_i) = \left(\frac{1}{\sum_{j\in\mathcal{N}(v_i)} w_{ij}} \sum_{j\in\mathcal{N}(v_t)} w_{ij} v_j\right) - v_i,\, \text{with}\,\, w_{ij}=\frac{1}{2}(cot \alpha_{ij} + cot \beta_{ij})$$ ::: Without spoiling the question 7, you may have observed that the Laplacian smoothing shrinks the surface. To fix that problem, Taubin[^1] has proposed a simple variation that iterates over the following two smoothing steps: $$ v_{t+1} \leftarrow v_{t} + \lambda {L}(v_t),\quad v_{t+2} \leftarrow v_{t+1} + \mu {L}(v_{t+1})$$ with a negative step $\mu$ such that: $0<\lambda< -\mu< 1$. The rationale behind the second step is to "inflate" the geometry in between to shrinking steps. | Original | Laplacian | Taubin | | -------- | -------- | -------- | | ![](https://raw.githubusercontent.com/dcoeurjo/CGDI-Practicals/main/geometry-processing/5-LaplacianSmoothing/orig.png) | ![](https://raw.githubusercontent.com/dcoeurjo/CGDI-Practicals/main/geometry-processing/5-LaplacianSmoothing/laplacian.png) | ![](https://raw.githubusercontent.com/dcoeurjo/CGDI-Practicals/main/geometry-processing/5-LaplacianSmoothing/taubin.png) | 8. **(extra)** Implement Taubin's approach. # Tutte Embedding Surface parametrization is a classical problem in the Computer Graphics in which you are looking for a new planar parametrization in $[0,1]^2$ of a generic mesh which minimizes a given distortion energy (*e.g.* area-preserving, angle-preserving --aka [conformal mapping](https://en.wikipedia.org/wiki/Conformal_map)--,...). As you may guess, such parametrization may not exist (*e.g.* rule surface for isometric mappings...) or may not be unique. Depending on the distortion model, we may have to consider approximated solutions. ::: info The distortion model is also tightly related to the topology of the input mesh. For instance, a conformal map exists for shapes homeomorphic to a disc but not for higher genius surfaces (embedded in Euclidean space). In that case, we may have to *cut-and-open* the surface, creating seams in the parametrization. ::: A simple algorithm is given by the [Tutte Embedding](https://en.wikipedia.org/wiki/Tutte_embedding)[^2], first designed for planar graph embedding. For short, the algorithm exactly corresponds to the Laplacian smoothing approach: all **boundary vertices** are uniformly distributed on a unit circle and we smooth the interior vertices. 9. Using the code of the question 5 that tags vertices belonging to the boundary of a mesh, implement a first Tutte Embedding where the boundary vertices remain fixes. You can experiment it on the `bunyhead.obj` mesh (which is homeomorphic to a disk). At this point, you have solved a [Laplace's Equation](https://en.wikipedia.org/wiki/Laplace%27s_equation) with boundary conditions :+1: (not the most efficient way but still...). As the Tutte approach solves a Laplace problem, it is closely related to a conformal energy model. {%youtube GY_nc4P8u4g %} 10. Complete the parametrization task, distribute the boundary vertices regularly on a circle and perform the embedding of the interior vertices. ![](https://raw.githubusercontent.com/dcoeurjo/CGDI-Practicals/main/geometry-processing/5-LaplacianSmoothing/tutte.png) # References [^1]: Taubin, Gabriel. "Curve and surface smoothing without shrinkage." Proceedings of IEEE international conference on computer vision. IEEE, 1995. [^2]: Tutte, William Thomas. "How to draw a graph." Proceedings of the London Mathematical Society 3.1 (1963): 743-767.