Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
667 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];
677 janba 47
			double area_i = mixed_area(mani, *v);
667 khor 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()];
677 janba 54
				double area_j = mixed_area(mani, wv.vertex());
667 khor 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
 
677 janba 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
 
667 khor 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
 
677 janba 145
double Harmonics::compute_adf(HMesh::VertexAttributeVector<double>& F, double t, double fiedler_boost)
667 khor 146
{
147
	double F_max = 0;
677 janba 148
    for(VertexID vid : mani.vertices())
149
        F[vid]=0;
150
 
667 khor 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]);
677 janba 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
 
667 khor 158
		F_max = max(F[vid], F_max);
159
	}
160
    return F_max;
161
}
677 janba 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
}