688 |
khor |
1 |
/*
|
|
|
2 |
* harmonics.cpp
|
|
|
3 |
* GEL
|
|
|
4 |
*
|
|
|
5 |
* Created by J. Andreas Bærentzen on 01/09/08.
|
|
|
6 |
* Copyright 2008 __MyCompanyName__. All rights reserved.
|
|
|
7 |
*
|
|
|
8 |
*/
|
|
|
9 |
|
|
|
10 |
#include <iostream>
|
|
|
11 |
|
|
|
12 |
#include "harmonics.h"
|
|
|
13 |
|
|
|
14 |
#if USE_SPARSE_MATRIX
|
|
|
15 |
#include <arlgsym.h>
|
|
|
16 |
#endif
|
|
|
17 |
|
|
|
18 |
#include <CGLA/Vec3d.h>
|
|
|
19 |
#include <CGLA/Mat2x2d.h>
|
|
|
20 |
#include <LinAlg/Matrix.h>
|
|
|
21 |
#include <LinAlg/Vector.h>
|
|
|
22 |
#include <LinAlg/LapackFunc.h>
|
|
|
23 |
|
|
|
24 |
#include <GL/glew.h>
|
|
|
25 |
#include <GLGraphics/glsl_shader.h>
|
|
|
26 |
|
|
|
27 |
#include <HMesh/mesh_optimization.h>
|
|
|
28 |
#include <HMesh/curvature.h>
|
|
|
29 |
#include <HMesh/triangulate.h>
|
|
|
30 |
#include <HMesh/load.h>
|
|
|
31 |
#include <HMesh/x3d_save.h>
|
|
|
32 |
|
|
|
33 |
using namespace CGLA;
|
|
|
34 |
using namespace std;
|
|
|
35 |
using namespace HMesh;
|
|
|
36 |
using namespace Geometry;
|
|
|
37 |
using namespace LinAlg;
|
|
|
38 |
|
|
|
39 |
|
|
|
40 |
void Harmonics::make_laplace_operator()
|
|
|
41 |
{
|
|
|
42 |
Q.Resize(mani.no_vertices(), mani.no_vertices());
|
|
|
43 |
|
|
|
44 |
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
|
|
|
45 |
if(!boundary(mani, *v)){
|
|
|
46 |
int i = vtouched[*v];
|
|
|
47 |
double area_i = mixed_area(mani, *v);
|
|
|
48 |
Vec3d vertex(mani.pos(*v));
|
|
|
49 |
Vec3d curv_normal(0);
|
|
|
50 |
double a_sum = 0;
|
|
|
51 |
for(Walker wv = mani.walker(*v); !wv.full_circle(); wv = wv.circulate_vertex_cw())
|
|
|
52 |
{
|
|
|
53 |
int j = vtouched[wv.vertex()];
|
|
|
54 |
double area_j = mixed_area(mani, wv.vertex());
|
|
|
55 |
|
|
|
56 |
Vec3d nbr(mani.pos(wv.vertex()));
|
|
|
57 |
Vec3d left(mani.pos(wv.next().vertex()));
|
|
|
58 |
Vec3d right(mani.pos(wv.opp().prev().opp().vertex()));
|
|
|
59 |
|
|
|
60 |
double d_left = dot(normalize(nbr-left),
|
|
|
61 |
normalize(vertex-left));
|
|
|
62 |
double d_right = dot(normalize(nbr-right),
|
|
|
63 |
normalize(vertex-right));
|
|
|
64 |
double a_left = acos(min(1.0, max(-1.0, d_left)));
|
|
|
65 |
double a_right = acos(min(1.0, max(-1.0, d_right)));
|
|
|
66 |
|
|
|
67 |
double w = 1.0/tan(a_left) + 1.0/tan(a_right);
|
|
|
68 |
|
|
|
69 |
Q[i][j] = -w/sqrt(area_i*area_j);
|
|
|
70 |
//Q[i][j] = -1;
|
|
|
71 |
a_sum += Q[i][j];
|
|
|
72 |
}
|
|
|
73 |
Q[i][i] = -a_sum;
|
|
|
74 |
}
|
|
|
75 |
EigenSolutionsSym(Q,V);
|
|
|
76 |
}
|
|
|
77 |
|
|
|
78 |
vector<Vec3d> Harmonics::analyze_signal(const VertexAttributeVector<Vec3d>& sig) {
|
|
|
79 |
vector<Vec3d> sig_proj(maximum_eigenvalue, Vec3d(0));
|
|
|
80 |
|
|
|
81 |
for(int es=0; es<maximum_eigenvalue; ++es)
|
|
|
82 |
for(VertexID v: mani.vertices())
|
|
|
83 |
sig_proj[es] += sig[v] * Q[es][vtouched[v]];
|
|
|
84 |
|
|
|
85 |
return sig_proj;
|
|
|
86 |
}
|
|
|
87 |
|
|
|
88 |
VertexAttributeVector<Vec3d> Harmonics::reconstruct_signal(const vector<Vec3d>& sig_proj, int max_es) {
|
|
|
89 |
VertexAttributeVector<Vec3d> sig(mani.allocated_vertices(), Vec3d(0));
|
|
|
90 |
for(int es=0; es<max_es; ++es)
|
|
|
91 |
for(VertexID v: mani.vertices())
|
|
|
92 |
sig[v] += sig_proj[es] * Q[es][vtouched[v]];
|
|
|
93 |
return sig;
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
|
|
|
97 |
|
|
|
98 |
Harmonics::Harmonics(HMesh::Manifold& _mani):mani(_mani), vtouched(_mani.allocated_vertices(), 0)
|
|
|
99 |
{
|
|
|
100 |
|
|
|
101 |
int i = 0;
|
|
|
102 |
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v, ++i)
|
|
|
103 |
vtouched[*v] = i;
|
|
|
104 |
maximum_eigenvalue = mani.no_vertices()-1;
|
|
|
105 |
make_laplace_operator();
|
|
|
106 |
|
|
|
107 |
proj.resize(maximum_eigenvalue);
|
|
|
108 |
max_eig_values.resize(maximum_eigenvalue, 1e-10f);
|
|
|
109 |
|
|
|
110 |
cout << "Projection magnitude" << endl;
|
|
|
111 |
for(int es=0; es<maximum_eigenvalue; ++es)
|
|
|
112 |
{
|
|
|
113 |
proj[es] = Vec3d(0.0);
|
|
|
114 |
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
|
|
|
115 |
{
|
|
|
116 |
proj[es] += Vec3d(mani.pos(*v)) * Q[es][vtouched[*v]];
|
|
|
117 |
max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][vtouched[*v]])));
|
|
|
118 |
}
|
|
|
119 |
}
|
|
|
120 |
}
|
|
|
121 |
|
|
|
122 |
void Harmonics::add_frequency(int es, float scale)
|
|
|
123 |
{
|
|
|
124 |
if(es<maximum_eigenvalue)
|
|
|
125 |
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v){
|
|
|
126 |
Vec3d p = Vec3d(proj[es]);
|
|
|
127 |
double Qval = Q[es][vtouched[*v]];
|
|
|
128 |
|
|
|
129 |
mani.pos(*v) += p * Qval * scale;
|
|
|
130 |
}
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
void Harmonics::reset_shape()
|
|
|
134 |
{
|
|
|
135 |
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
|
|
|
136 |
mani.pos(*v) = Vec3d(0);
|
|
|
137 |
}
|
|
|
138 |
void Harmonics::partial_reconstruct(int E0, int E1, float scale)
|
|
|
139 |
{
|
|
|
140 |
for(int es=E0;es<=E1;++es)
|
|
|
141 |
add_frequency(es, scale);
|
|
|
142 |
}
|
|
|
143 |
|
|
|
144 |
|
|
|
145 |
double Harmonics::compute_adf(HMesh::VertexAttributeVector<double>& F, double t, double fiedler_boost)
|
|
|
146 |
{
|
|
|
147 |
double F_max = 0;
|
|
|
148 |
for(VertexID vid : mani.vertices())
|
|
|
149 |
F[vid]=0;
|
|
|
150 |
|
|
|
151 |
for(VertexID vid : mani.vertices()){
|
|
|
152 |
for(int e = 1; e < V.Length(); ++e)
|
|
|
153 |
F[vid] += sqr(Q[e][vtouched[vid]]) * exp(-t*V[e]/V[1]);
|
|
|
154 |
if(fiedler_boost>0)
|
|
|
155 |
for(int e = 1; e < V.Length(); ++e)
|
|
|
156 |
F[vid] += sqr(Q[e][vtouched[vid]]) * exp(-t) * fiedler_boost;
|
|
|
157 |
|
|
|
158 |
F_max = max(F[vid], F_max);
|
|
|
159 |
}
|
|
|
160 |
return F_max;
|
|
|
161 |
}
|
|
|
162 |
|
|
|
163 |
double Harmonics::compute_esum(HMesh::VertexAttributeVector<double>& F, int e0, int e1)
|
|
|
164 |
{
|
|
|
165 |
double F_max = 0;
|
|
|
166 |
for(VertexID vid : mani.vertices())
|
|
|
167 |
F[vid]=0;
|
|
|
168 |
|
|
|
169 |
for(VertexID vid : mani.vertices()){
|
|
|
170 |
for(int e = e0; e < e1; ++e)
|
|
|
171 |
F[vid] += sqr(Q[e][vtouched[vid]]);
|
|
|
172 |
|
|
|
173 |
F_max = max(F[vid], F_max);
|
|
|
174 |
}
|
|
|
175 |
return F_max;
|
|
|
176 |
}
|