-
Notifications
You must be signed in to change notification settings - Fork 0
/
YamabeFlow.h
138 lines (106 loc) · 2.79 KB
/
YamabeFlow.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#pragma once
/*! \file TangentialRicciFlow.h
* \brief General Euclidean Ricci flow algorithm
* \author David Gu
* \date documented on 10/17/2010
*
* Algorithm for general Ricci Flow
*/
#ifndef _EQUIVALENCE_RICCI_FLOW_H_
#define _EQUIVALENCE_RICCI_FLOW_H_
#include <map>
#include <vector>
#include <Eigen/Sparse>
#include "EuclideanFlow.h"
namespace OpenMesh
{
/*! \brief Class CYamabeFlow
*
* Algorithm for computing Ricci flow
*/
class CYamabeFlow : public EuclideanFlow
{
public:
/*! \brief CYamabeFlow constructor
* \param p_mesh the input mesh
*/
CYamabeFlow(MeshFlow* p_mesh);
/*! \brief CYamabeFlow destructor
*/
~CYamabeFlow() {};
/*! Computing the metric
*/
void CalculateMetric();
protected:
/*!
* Calculate each edge Length, has to be defined in the derivated classes
*/
void Length(double u1, double u2, EdgeHandle e);
//void Normalization();
/*!
* Calculate the edge weight
*/
void CalculateEdgeWeight();
void CalculateInitialMetric();
};
inline CYamabeFlow::CYamabeFlow(MeshFlow* p_mesh) :EuclideanFlow(p_mesh)
{
};
//Compute the edge Length
inline void CYamabeFlow::Length(double u1, double u2, EdgeHandle e)
{
m_pMesh->Length(e) = exp(u1) * exp(u2) * m_pMesh->OriginalLength(e);
};
//Calculate edge weight
inline void CYamabeFlow::CalculateEdgeWeight()
{
for (MeshFlow::EdgeIter eiter = m_pMesh->edges_begin(); eiter != m_pMesh->edges_end(); eiter++) {
double weight = 0.0;
EdgeHandle e = *eiter;
HalfedgeHandle h0 = m_pMesh->EdgeHalfedge(e, 0);
HalfedgeHandle h1 = m_pMesh->EdgeHalfedge(e, 1);
if (!m_pMesh->is_boundary(h0)) {
double angle = m_pMesh->Angle(m_pMesh->next_halfedge_handle(h0));
if (abs(angle) > 1e-5 && abs(angle - PI) > 1e-5) {
double cotan = 1 / tan(angle);
if (!isnan(cotan))
weight += cotan;
}
}
if (!m_pMesh->is_boundary(h1)) {
double angle = m_pMesh->Angle(m_pMesh->next_halfedge_handle(h1));
if (abs(angle) > 1e-5 && abs(angle - PI) > 1e-5) {
double cotan = 1 / tan(angle);
weight += cotan;
}
}
m_pMesh->Weight(e) = weight;
}
}
inline void CYamabeFlow::CalculateInitialMetric()
{
CalculateOriginalEdgeLength();
for (MeshFlow::VertexIter viter = m_pMesh->vertices_begin(); viter != m_pMesh->vertices_end(); ++viter) {
VertexHandle v = *viter;
m_pMesh->U(v) = 0.0;
}
}
inline void CYamabeFlow::CalculateMetric()
{
double error = NEWTON_ERROR;
if (m_pMesh->boundaries.size() == 0) {
error = error * 0.1;
}
CalculateInitialMetric();
SetTargetCurvature();
CalculateEdgeLength();
if (boundary_mode == Circle) {
double result = SetCircleCurvature();
}
if (boundary_mode != Free) {
Newton(error, 1.0);
}
AcceleratedGradientDescent(error, 1.0);
}
}
#endif _EQUIVALENCE_RICCI_FLOW_H_