Rev 601 | Rev 632 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* ----------------------------------------------------------------------- *
* This file is part of GEL, http://www.imm.dtu.dk/GEL
* Copyright (C) the authors and DTU Informatics
* For license and list of authors, see ../../doc/intro.pdf
* ----------------------------------------------------------------------- */
/**
* @file mesh_optimization.h
* @brief Functions for energy minimization based mesh optimization.
*/
#ifndef __HMESH_MESH_OPTIMIZATION_H
#define __HMESH_MESH_OPTIMIZATION_H
#include "Manifold.h"
#include "../CGLA/Vec3d.h"
namespace HMesh
{
// forward declarations
//class Manifold;
//class HalfEdgeID;
/// This class represents the energy of an edge. It is used in optimization schemes where edges are swapped (aka flipped). */
class EnergyFun
{
public:
virtual double delta_energy(const Manifold& m, HalfEdgeID h) const = 0;
virtual double energy(const Manifold& m, HalfEdgeID h) const {return 0;}
};
class MinAngleEnergy: public EnergyFun
{
double min_angle(const CGLA::Vec3d& v0, const CGLA::Vec3d& v1, const CGLA::Vec3d& v2) const;
double thresh;
public:
MinAngleEnergy(double _thresh): thresh(_thresh) {}
double delta_energy(const HMesh::Manifold& m, HMesh::HalfEdgeID h) const;
};
class DihedralEnergy: public EnergyFun
{
const double gamma;
const bool use_alpha;
double cos_ang(const CGLA::Vec3d& n1, const CGLA::Vec3d& n2) const
{
return CGLA::s_max(-1.0, CGLA::s_min(1.0, CGLA::dot(n1, n2)));
}
double edge_alpha_energy(CGLA::Vec3d v1, CGLA::Vec3d v2, double ca) const
{
return pow(CGLA::length(v1-v2)*(acos(ca)), 1.0f/gamma);
}
double edge_c_energy(CGLA::Vec3d v1, CGLA::Vec3d v2, double ca) const
{
return pow(length(v1-v2)*(1-ca), 1.0f/gamma);
}
void compute_angles(const HMesh::Manifold & m, HMesh::HalfEdgeID h) const;
mutable double ab_12;
mutable double ab_a1;
mutable double ab_b1;
mutable double ab_2c;
mutable double ab_2d;
mutable double aa_12;
mutable double aa_b1;
mutable double aa_c1;
mutable double aa_2a;
mutable double aa_2d;
public:
DihedralEnergy(double _gamma = 4.0, bool _use_alpha=false):
gamma(_gamma), use_alpha(_use_alpha) {}
double energy(const HMesh::Manifold& m, HMesh::HalfEdgeID h) const;
double delta_energy(const HMesh::Manifold& m, HMesh::HalfEdgeID h) const;
double min_angle(const HMesh::Manifold& m, HMesh::HalfEdgeID h) const
{
compute_angles(m, h);
return CGLA::s_min(CGLA::s_min(CGLA::s_min(CGLA::s_min(aa_12, aa_b1), aa_c1), aa_2a), aa_2d);
}
};
class CurvatureEnergy: public EnergyFun
{
double abs_mean_curv(const CGLA::Vec3d& v, const std::vector<CGLA::Vec3d>& ring) const;
public:
double delta_energy(const HMesh::Manifold& m, HMesh::HalfEdgeID h) const;
};
class ValencyEnergy: public EnergyFun
{
public:
double delta_energy(const Manifold& m, HalfEdgeID h) const;
};
/// Optimize in a greedy fashion.
void priority_queue_optimization(Manifold& m, const EnergyFun& efun);
/// Optimize with simulated annealing. Avoids getting trapped in local minima
void simulated_annealing_optimization(Manifold& m, const EnergyFun& efun, int max_iter=10000);
/// Minimize the angle between adjacent triangles. Almost the same as mean curvature minimization
void minimize_dihedral_angle(Manifold& m, int max_iter=10000, bool anneal=false, bool alpha=false, double gamma=4.0);
/// Minimizes mean curvature. This is really the same as dihedral angle optimization except that we weight by edge length
void minimize_curvature(Manifold& m, bool anneal=false);
/// Minimizes gaussian curvature. Probably less useful than mean curvature.
void minimize_gauss_curvature(Manifold& m, bool anneal=false);
/// Maximizes the minimum angle of triangles. Makes the mesh more Delaunay.
void maximize_min_angle(Manifold& m, float thresh, bool anneal=false);
/// Tries to achieve valence 6 internally and 4 along edges.
void optimize_valency(Manifold& m, bool anneal=false);
/// Make radom flips. Useful for generating synthetic test cases.
void randomize_mesh(Manifold& m, int max_iter);
}
#endif