Blender V4.3
cotmatrix.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Alec Jacobson
2 *
3 * SPDX-License-Identifier: MPL-2.0 */
4
9#include "cotmatrix.h"
10#include "edge_lengths.h"
11
12#include <vector>
13
14namespace slim {
15
16/* Inputs:
17 * V #V by dim list of rest domain positions
18 * F #F by 3 list of triangle indices into V
19 * Outputs:
20 * C #F by 3 list of 1/2*cotangents corresponding angles
21 * for triangles, columns correspond to edges [1,2],[2,0],[0,1]
22 */
23template<typename DerivedV, typename DerivedF, typename DerivedC>
24static inline void cotmatrix_entries(const Eigen::PlainObjectBase<DerivedV> &V,
25 const Eigen::PlainObjectBase<DerivedF> &F,
26 Eigen::PlainObjectBase<DerivedC> &C)
27{
28 using namespace std;
29 using namespace Eigen;
30 /* Number of elements. */
31 int m = F.rows();
32
33 assert(F.cols() == 3);
34
35 /* Law of cosines + law of sines. */
36 /* Compute Squared Edge lenghts. */
37 Matrix<typename DerivedC::Scalar, Dynamic, 3> l2;
38 squared_edge_lengths(V, F, l2);
39 /* Compute Edge lenghts. */
40 Matrix<typename DerivedC::Scalar, Dynamic, 3> l;
41 l = l2.array().sqrt();
42
43 /* Double area. */
44 Matrix<typename DerivedC::Scalar, Dynamic, 1> dblA;
45 doublearea(l, dblA);
46 /* Cotangents and diagonal entries for element matrices.
47 * correctly divided by 4. */
48 C.resize(m, 3);
49 for (int i = 0; i < m; i++) {
50 C(i, 0) = (l2(i, 1) + l2(i, 2) - l2(i, 0)) / dblA(i) / 4.0;
51 C(i, 1) = (l2(i, 2) + l2(i, 0) - l2(i, 1)) / dblA(i) / 4.0;
52 C(i, 2) = (l2(i, 0) + l2(i, 1) - l2(i, 2)) / dblA(i) / 4.0;
53 }
54}
55
56template<typename DerivedV, typename DerivedF, typename Scalar>
57inline void cotmatrix(const Eigen::PlainObjectBase<DerivedV> &V,
58 const Eigen::PlainObjectBase<DerivedF> &F,
59 Eigen::SparseMatrix<Scalar> &L)
60{
61 using namespace Eigen;
62 using namespace std;
63
64 L.resize(V.rows(), V.rows());
65 Matrix<int, Dynamic, 2> edges;
66 /* 3 for triangles. */
67 assert(F.cols() == 3);
68
69 /* This is important! it could decrease the comptuation time by a factor of 2
70 * Laplacian for a closed 2d manifold mesh will have on average 7 entries per
71 * row. */
72 L.reserve(10 * V.rows());
73 edges.resize(3, 2);
74 edges << 1, 2, 2, 0, 0, 1;
75
76 /* Gather cotangents. */
77 Matrix<Scalar, Dynamic, Dynamic> C;
78 cotmatrix_entries(V, F, C);
79
81 IJV.reserve(F.rows() * edges.rows() * 4);
82 /* Loop over triangles. */
83 for (int i = 0; i < F.rows(); i++) {
84 /* Loop over edges of element. */
85 for (int e = 0; e < edges.rows(); e++) {
86 int source = F(i, edges(e, 0));
87 int dest = F(i, edges(e, 1));
88 IJV.push_back(Triplet<Scalar>(source, dest, C(i, e)));
89 IJV.push_back(Triplet<Scalar>(dest, source, C(i, e)));
90 IJV.push_back(Triplet<Scalar>(source, source, -C(i, e)));
91 IJV.push_back(Triplet<Scalar>(dest, dest, -C(i, e)));
92 }
93 }
94 L.setFromTriplets(IJV.begin(), IJV.end());
95}
96
97} // namespace slim
#define C
Definition RandGen.cpp:29
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
Eigen::Triplet< Scalar > Triplet
#define F
#define L
static void cotmatrix_entries(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C)
Definition cotmatrix.cpp:24
void cotmatrix(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< Scalar > &L)
Definition cotmatrix.cpp:57
void doublearea(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
void squared_edge_lengths(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedL > &L)
CCL_NAMESPACE_BEGIN struct Window V