Rev 663 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* harmonics.cpp
* GEL
*
* Created by J. Andreas Bærentzen on 01/09/08.
* Copyright 2008 __MyCompanyName__. All rights reserved.
*
*/
#include <iostream>
#include "harmonics.h"
#if USE_SPARSE_MATRIX
#include <arlgsym.h>
#endif
#include <CGLA/Vec3d.h>
#include <CGLA/Mat2x2d.h>
#include <LinAlg/Matrix.h>
#include <LinAlg/Vector.h>
#include <LinAlg/LapackFunc.h>
#include <GL/glew.h>
#include <GLGraphics/glsl_shader.h>
#include <HMesh/mesh_optimization.h>
#include <HMesh/curvature.h>
#include <HMesh/triangulate.h>
#include <HMesh/load.h>
#include <HMesh/x3d_save.h>
using namespace CGLA;
using namespace std;
using namespace HMesh;
using namespace Geometry;
using namespace LinAlg;
void Harmonics::make_laplace_operator()
{
Q.Resize(mani.no_vertices(), mani.no_vertices());
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
if(!boundary(mani, *v)){
int i = vtouched[*v];
double area_i = voronoi_area(mani, *v);
Vec3d vertex(mani.pos(*v));
Vec3d curv_normal(0);
double a_sum = 0;
for(Walker wv = mani.walker(*v); !wv.full_circle(); wv = wv.circulate_vertex_cw())
{
int j = vtouched[wv.vertex()];
double area_j = voronoi_area(mani, wv.vertex());
Vec3d nbr(mani.pos(wv.vertex()));
Vec3d left(mani.pos(wv.next().vertex()));
Vec3d right(mani.pos(wv.opp().prev().opp().vertex()));
double d_left = dot(normalize(nbr-left),
normalize(vertex-left));
double d_right = dot(normalize(nbr-right),
normalize(vertex-right));
double a_left = acos(min(1.0, max(-1.0, d_left)));
double a_right = acos(min(1.0, max(-1.0, d_right)));
double w = 1.0/tan(a_left) + 1.0/tan(a_right);
Q[i][j] = -w/sqrt(area_i*area_j);
//Q[i][j] = -1;
a_sum += Q[i][j];
}
Q[i][i] = -a_sum;
}
EigenSolutionsSym(Q,V);
}
Harmonics::Harmonics(HMesh::Manifold& _mani):mani(_mani), vtouched(_mani.allocated_vertices(), 0)
{
int i = 0;
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v, ++i)
vtouched[*v] = i;
maximum_eigenvalue = mani.no_vertices()-1;
make_laplace_operator();
proj.resize(maximum_eigenvalue);
max_eig_values.resize(maximum_eigenvalue, 1e-10f);
cout << "Projection magnitude" << endl;
for(int es=0; es<maximum_eigenvalue; ++es)
{
proj[es] = Vec3d(0.0);
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
{
proj[es] += Vec3d(mani.pos(*v)) * Q[es][vtouched[*v]];
max_eig_values[es] = max(max_eig_values[es], static_cast<float>(abs(Q[es][vtouched[*v]])));
}
}
}
void Harmonics::add_frequency(int es, float scale)
{
if(es<maximum_eigenvalue)
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v){
Vec3d p = Vec3d(proj[es]);
double Qval = Q[es][vtouched[*v]];
mani.pos(*v) += p * Qval * scale;
}
}
void Harmonics::reset_shape()
{
for(VertexIDIterator v = mani.vertices_begin(); v != mani.vertices_end(); ++v)
mani.pos(*v) = Vec3d(0);
}
void Harmonics::partial_reconstruct(int E0, int E1, float scale)
{
for(int es=E0;es<=E1;++es)
add_frequency(es, scale);
}
double Harmonics::compute_adf(HMesh::VertexAttributeVector<double>& F, double t)
{
double F_max = 0;
for(VertexID vid : mani.vertices()){
for(int e = 1; e < V.Length(); ++e)
F[vid] += sqr(Q[e][vtouched[vid]]) * exp(-t*V[e]/V[1]);
F_max = max(F[vid], F_max);
}
return F_max;
}