• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pmp-library / pmp-library / 15070098106

16 May 2025 01:52PM UTC coverage: 91.027% (-0.07%) from 91.097%
15070098106

push

github

mbotsch
improve curvature example GUI

5204 of 5717 relevant lines covered (91.03%)

646093.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.98
/src/pmp/algorithms/smoothing.cpp
1
// Copyright 2011-2020 the Polygon Mesh Processing Library developers.
2
// Distributed under a MIT-style license, see LICENSE.txt for details.
3

4
#include "pmp/algorithms/smoothing.h"
5
#include "pmp/algorithms/differential_geometry.h"
6
#include "pmp/algorithms/laplace.h"
7

8
namespace pmp {
9

10
void explicit_smoothing(SurfaceMesh& mesh, unsigned int iterations,
2✔
11
                        bool use_uniform_laplace)
12
{
13
    if (!mesh.n_vertices())
2✔
14
        return;
×
15

16
    // Laplace matrix (clamp negative cotan weights to zero)
17
    SparseMatrix L;
2✔
18
    if (use_uniform_laplace)
2✔
19
        uniform_laplace_matrix(mesh, L);
1✔
20
    else
21
        laplace_matrix(mesh, L, true);
1✔
22

23
    // normalize each row by sum of weights
24
    // scale by 0.5 to make it more robust
25
    // multiply by -1 to make it neg. definite again
26
    DiagonalMatrix D = -0.5 * L.diagonal().asDiagonal().inverse();
2✔
27
    L = D * L;
2✔
28

29
    // cancel out boundary vertices
30
    SparseMatrix S;
2✔
31
    auto is_inner = [&](Vertex v) { return !mesh.is_boundary(v); };
18✔
32
    selector_matrix(mesh, is_inner, S);
2✔
33
    L = S.transpose() * S * L;
2✔
34

35
    // copy vertex coordinates to matrix
36
    DenseMatrix X;
2✔
37
    coordinates_to_matrix(mesh, X);
2✔
38

39
    // perform some iterations
40
    for (unsigned int i = 0; i < iterations; ++i)
22✔
41
        X += L * X;
20✔
42

43
    // copy matrix back to vertex coordinates
44
    matrix_to_coordinates(X, mesh);
2✔
45
}
2✔
46

47
void implicit_smoothing(SurfaceMesh& mesh, Scalar timestep,
2✔
48
                        unsigned int iterations, bool use_uniform_laplace,
49
                        bool rescale)
50
{
51
    if (!mesh.n_vertices())
2✔
52
        return;
×
53

54
    // store center and area
55
    Point center_before(0, 0, 0);
2✔
56
    Scalar area_before(0);
2✔
57
    if (rescale)
2✔
58
    {
59
        center_before = centroid(mesh);
1✔
60
        area_before = surface_area(mesh);
1✔
61
    }
62

63
    // build system matrix A (clamp negative cotan weights to zero)
64
    SparseMatrix L;
2✔
65
    DiagonalMatrix M;
2✔
66
    if (use_uniform_laplace)
2✔
67
    {
68
        uniform_laplace_matrix(mesh, L);
×
69
        uniform_mass_matrix(mesh, M);
×
70
    }
71
    else
72
    {
73
        laplace_matrix(mesh, L);
2✔
74
        mass_matrix(mesh, M);
2✔
75
    }
76
    SparseMatrix A = SparseMatrix(M) - timestep * L;
2✔
77
    DenseMatrix X, B;
2✔
78

79
    for (unsigned int iter = 0; iter < iterations; ++iter)
4✔
80
    {
81
        if (!use_uniform_laplace)
2✔
82
        {
83
            mass_matrix(mesh, M);
2✔
84
            A = SparseMatrix(M) - timestep * L;
2✔
85
        }
86

87
        // build right-hand side B
88
        coordinates_to_matrix(mesh, X);
2✔
89
        B = M * X;
2✔
90

91
        // solve system
92
        auto is_constrained = [&](unsigned int i) {
36✔
93
            return mesh.is_boundary(Vertex(i));
36✔
94
        };
2✔
95
        X = cholesky_solve(A, B, is_constrained, X);
2✔
96
        matrix_to_coordinates(X, mesh);
2✔
97

98
        if (rescale)
2✔
99
        {
100
            // restore original surface area
101
            const Scalar area_after = surface_area(mesh);
1✔
102
            const Scalar scale = sqrt(area_before / area_after);
1✔
103
            for (auto v : mesh.vertices())
19✔
104
                mesh.position(v) *= scale;
9✔
105

106
            // restore original center
107
            const Point center_after = centroid(mesh);
1✔
108
            const Point trans = center_before - center_after;
1✔
109
            for (auto v : mesh.vertices())
19✔
110
                mesh.position(v) += trans;
9✔
111
        }
112
    }
113
}
2✔
114

115
} // namespace pmp
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc