Merge branch 'Surface_mesh_parametrisation-OpenNL_Eigen-GF-old' into Surface_mesh_parametrisation-OpenNL_Eigen-GF

This commit is contained in:
Simon Giraudot 2015-09-18 10:06:13 +02:00
commit b9bbadf631
9 changed files with 591 additions and 19 deletions

View File

@ -57,6 +57,12 @@ if(Qt5_FOUND)
endif(Qt5_FOUND)
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
if (EIGEN3_FOUND)
include( ${EIGEN3_USE_FILE} )

View File

@ -37,7 +37,7 @@
<x>0</x>
<y>0</y>
<width>978</width>
<height>21</height>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -95,6 +95,7 @@
</property>
<addaction name="actionMVC"/>
<addaction name="actionDCP"/>
<addaction name="actionLSC"/>
</widget>
<widget class="QMenu" name="menuPCA">
<property name="title">
@ -652,6 +653,11 @@
<string>&amp;Preferences</string>
</property>
</action>
<action name="actionLSC">
<property name="text">
<string>Least square conformal maps</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -12,6 +12,7 @@
#include <CGAL/Parameterization_polyhedron_adaptor_3.h>
#include <CGAL/parameterize.h>
#include <CGAL/Discrete_conformal_map_parameterizer_3.h>
#include <CGAL/LSCM_parameterizer_3.h>
#include <CGAL/Two_vertices_parameterizer_3.h>
#include <CGAL/Textured_polyhedron_builder.h>
@ -35,7 +36,8 @@ public:
// used by Polyhedron_demo_plugin_helper
QStringList actionsNames() const {
return QStringList() << "actionMVC"
<< "actionDCP";
<< "actionDCP"
<< "actionLSC";
}
bool applicable(QAction*) const {
@ -45,9 +47,10 @@ public:
public Q_SLOTS:
void on_actionMVC_triggered();
void on_actionDCP_triggered();
void on_actionLSC_triggered();
protected:
enum Parameterization_method { PARAM_MVC, PARAM_DCP };
enum Parameterization_method { PARAM_MVC, PARAM_DCP, PARAM_LSC };
void parameterize(Parameterization_method method);
}; // end Polyhedron_demo_parameterization_plugin
@ -91,6 +94,13 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
typedef CGAL::Discrete_conformal_map_parameterizer_3<Adaptor> Parameterizer;
Parameterizer::Error_code err = CGAL::parameterize(adaptor,Parameterizer());
success = err == Parameterizer::OK;
}
case PARAM_LSC:
{
std::cout << "Parameterize (LSC)...";
typedef CGAL::LSCM_parameterizer_3<Adaptor> Parameterizer;
Parameterizer::Error_code err = CGAL::parameterize(adaptor,Parameterizer());
success = err == Parameterizer::OK;
}
}
@ -148,4 +158,10 @@ void Polyhedron_demo_parameterization_plugin::on_actionDCP_triggered()
parameterize(PARAM_DCP);
}
void Polyhedron_demo_parameterization_plugin::on_actionLSC_triggered()
{
std::cerr << "LSC...";
parameterize(PARAM_LSC);
}
#include "Polyhedron_demo_parameterization_plugin.moc"

View File

@ -0,0 +1,335 @@
// Copyright (c) 2005-2008 Inria Loria (France).
/*
* author: Bruno Levy, INRIA, project ALICE
* website: http://www.loria.fr/~levy/software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Scientific work that use this software can reference the website and
* the following publication:
*
* @INPROCEEDINGS {levy:NMDGP:05,
* AUTHOR = Bruno Levy,
* TITLE = Numerical Methods for Digital Geometry Processing,
* BOOKTITLE =Israel Korea Bi-National Conference,
* YEAR=November 2005,
* URL=http://www.loria.fr/~levy/php/article.php?pub=../publications/papers/2005/Numerics
* }
*
* Laurent Saboret 2005-2006: Changes for CGAL:
* - Added OpenNL namespace
* - DefaultLinearSolverTraits is now a model of the SparseLinearAlgebraTraits_d concept
* - Added SymmetricLinearSolverTraits
* - copied Jacobi preconditioner from Graphite 1.9 code
*/
#ifndef __EIGEN_LEAST_SQUARES_SOLVER__
#define __EIGEN_LEAST_SQUARES_SOLVER__
#include <CGAL/Eigen_solver_traits.h>
#include <vector>
#include <iostream>
#include <cstdlib>
namespace CGAL {
/*
* Solves a linear system or minimizes a quadratic form.
*/
class EigenLeastSquaresSolver
{
protected:
enum State {
INITIAL, IN_SYSTEM, IN_ROW, CONSTRUCTED, SOLVED
} ;
public:
// typedef Eigen_solver_traits<Eigen::ConjugateGradient<Eigen_sparse_symmetric_matrix<double>::EigenType,
// Eigen::Lower|Eigen::Upper> > Solver;
typedef Eigen_solver_traits<Eigen::SimplicialLDLT<Eigen_sparse_symmetric_matrix<double>::EigenType> > Solver;
typedef typename Solver::Matrix Matrix ;
typedef typename Solver::Vector Vector ;
typedef typename Solver::NT CoeffType ;
class Variable {
public:
Variable() : x_(0), index_(-1), locked_(false) { }
double value() const { return x_; }
void set_value(double x_in) { x_ = x_in ; }
void lock() { locked_ = true ; }
void unlock() { locked_ = false ; }
bool is_locked() const { return locked_ ; }
unsigned int index() const {
CGAL_assertion(index_ != -1) ;
return (unsigned int)(index_) ;
}
void set_index(unsigned int index_in) {
index_ = index_in ;
}
private:
CoeffType x_ ;
int index_ ;
bool locked_ ;
} ;
EigenLeastSquaresSolver(unsigned int nb_variables) {
state_ = INITIAL ;
nb_variables_ = nb_variables ;
variable_ = new Variable[nb_variables] ;
A_ = NULL ;
x_ = NULL ;
b_ = NULL ;
}
~EigenLeastSquaresSolver() {
delete[] variable_ ;
delete A_ ;
delete x_ ;
delete b_ ;
}
// __________________ Parameters ________________________
void set_least_squares(bool x) { }
// __________________ Access ____________________________
int nb_variables() const { return nb_variables_ ; }
Variable& variable(unsigned int idx) {
CGAL_assertion(idx < nb_variables_) ;
return variable_[idx] ;
}
const Variable& variable(unsigned int idx) const {
CGAL_assertion(idx < nb_variables_) ;
return variable_[idx] ;
}
// _________________ Construction _______________________
void begin_system() {
current_row_ = 0 ;
transition(INITIAL, IN_SYSTEM) ;
// Enumerate free variables.
unsigned int index = 0 ;
for(int ii=0; ii < nb_variables() ; ii++) {
Variable& v = variable(ii) ;
if(!v.is_locked()) {
v.set_index(index) ;
index++ ;
}
}
unsigned int n = index ;
A_ = new Matrix(static_cast<int>(n),static_cast<int>(n)) ;
x_ = new Vector(n) ;
b_ = new Vector(n) ;
for(unsigned int i=0; i<n; i++) {
x_->set(i, 0.);
b_->set(i, 0.);
}
variables_to_vector() ;
}
void begin_row() {
transition(IN_SYSTEM, IN_ROW) ;
af_.clear() ;
if_.clear() ;
al_.clear() ;
xl_.clear() ;
bk_ = 0 ;
}
void set_right_hand_side(double b) {
check_state(IN_ROW) ;
bk_ = b ;
}
void add_coefficient(unsigned int iv, double a) {
check_state(IN_ROW) ;
Variable& v = variable(iv) ;
if(v.is_locked()) {
al_.push_back(a) ;
xl_.push_back(v.value()) ;
} else {
af_.push_back(a) ;
if_.push_back(v.index()) ;
}
}
void normalize_row(CoeffType weight = 1) {
check_state(IN_ROW) ;
CoeffType norm = 0.0 ;
unsigned int nf = af_.size() ;
for(unsigned int i=0; i<nf; i++) {
norm += af_[i] * af_[i] ;
}
unsigned int nl = al_.size() ;
for(unsigned int i=0; i<nl; i++) {
norm += al_[i] * al_[i] ;
}
norm = sqrt(norm) ;
CGAL_assertion( fabs(norm)>1e-40 );
scale_row(weight / norm) ;
}
void scale_row(CoeffType s) {
check_state(IN_ROW) ;
unsigned int nf = af_.size() ;
for(unsigned int i=0; i<nf; i++) {
af_[i] *= s ;
}
unsigned int nl = al_.size() ;
for(unsigned int i=0; i<nl; i++) {
al_[i] *= s ;
}
bk_ *= s ;
}
void end_row() {
unsigned int nf = af_.size() ;
unsigned int nl = al_.size() ;
for(unsigned int i=0; i<nf; i++) {
for(unsigned int j=0; j<nf; j++) {
A_->add_coef (if_[i], if_[j], af_[i] * af_[j]);
}
}
CoeffType S = - bk_ ;
for(unsigned int j=0; j<nl; j++) {
S += al_[j] * xl_[j] ;
}
for(unsigned int i=0; i<nf; i++) {
b_->set(if_[i], b_->get(if_[i]) - af_[i] * S);
}
current_row_++ ;
transition(IN_ROW, IN_SYSTEM) ;
}
void end_system() {
A_->assemble_matrix ();
transition(IN_SYSTEM, CONSTRUCTED) ;
}
// ----------------------------- Solver -------------------------------
// Solves a linear system or minimizes a quadratic form.
// Return true on success.
// (modified for SparseLinearAlgebraTraits_d concept)
bool solve()
{
check_state(CONSTRUCTED) ;
// Solve the sparse linear system "A*X = B". On success, the solution is (1/D) * X.
Solver solver_;
CoeffType D;
bool success = solver_.linear_solver(*A_, *b_, *x_, D) ;
CGAL_assertion(D == 1.0); // WARNING: this library does not support homogeneous coordinates!
vector_to_variables() ;
transition(CONSTRUCTED, SOLVED) ;
delete A_ ; A_ = NULL ;
delete b_ ; b_ = NULL ;
delete x_ ; x_ = NULL ;
return success;
}
protected:
// ----------- Converting between user representation and the internal representation -----
void vector_to_variables() {
for(int ii=0; ii < nb_variables(); ii++) {
Variable& v = variable(ii) ;
if(!v.is_locked()) {
v.set_value( x_->get(v.index()) ) ;
}
}
}
void variables_to_vector() {
for(int ii=0; ii < nb_variables(); ii++) {
Variable& v = variable(ii) ;
if(!v.is_locked()) {
x_->set(v.index(), v.value());
}
}
}
// ----------- Finite state automaton (checks that calling sequence is respected) ---------
std::string state_to_string(State s) {
switch(s) {
case INITIAL:
return "initial" ;
case IN_SYSTEM:
return "in system" ;
case IN_ROW:
return "in row" ;
case CONSTRUCTED:
return "constructed" ;
case SOLVED:
return "solved" ;
}
// Should not go there.
CGAL_error();
return "undefined" ;
}
void check_state(State s) {
CGAL_USE(s);
CGAL_assertion(state_ == s) ;
}
void transition(State from, State to) {
check_state(from) ;
state_ = to ;
}
private:
// --------------- user representation --------------
unsigned int nb_variables_ ;
Variable* variable_ ;
// --------------- construction -----------------------
State state_ ;
unsigned int current_row_ ;
std::vector<CoeffType> af_ ;
std::vector<unsigned int> if_ ;
std::vector<CoeffType> al_ ;
std::vector<CoeffType> xl_ ;
double bk_ ;
// --------------- internal representation ---------
Matrix* A_ ;
Vector* x_ ;
Vector* b_ ;
} ;
} // namespace OpenNL
#endif

View File

@ -49,10 +49,20 @@ namespace internal {
};
template <class FT,class EigenMatrix>
struct Get_eigen_matrix< ::Eigen::ConjugateGradient<EigenMatrix>,FT>{
struct Get_eigen_matrix< ::Eigen::ConjugateGradient<EigenMatrix, ::Eigen::Lower|::Eigen::Upper>,FT>{
typedef Eigen_sparse_symmetric_matrix<FT> type;
};
template <class FT,class EigenMatrix>
struct Get_eigen_matrix< ::Eigen::SimplicialLDLT<EigenMatrix>,FT>{
typedef Eigen_sparse_symmetric_matrix<FT> type;
};
template <class FT,class EigenMatrix>
struct Get_eigen_matrix< ::Eigen::LeastSquaresConjugateGradient<EigenMatrix>,FT>{
typedef Eigen_sparse_matrix<FT> type;
};
template <class FT,class EigenMatrix>
struct Get_eigen_matrix< ::Eigen::SimplicialCholesky<EigenMatrix>,FT>{
typedef Eigen_sparse_symmetric_matrix<FT> type;
@ -89,6 +99,7 @@ public:
Eigen_solver_traits():m_mat(NULL), m_solver_sptr(new EigenSolverT)
{
}
EigenSolverT& solver() { return *m_solver_sptr; }
@ -110,6 +121,13 @@ public:
X = m_solver_sptr->solve(B);
if (m_solver_sptr->info() == Eigen::NumericalIssue)
std::cerr << "Numerical Issue" << std::endl;
if (m_solver_sptr->info() == Eigen::NoConvergence)
std::cerr << "No Convergence" << std::endl;
if (m_solver_sptr->info() == Eigen::InvalidInput)
std::cerr << "Invalid Input" << std::endl;
return m_solver_sptr->info() == Eigen::Success;
}

View File

@ -86,6 +86,10 @@ public:
void set(std::size_t i,NT value) {
this->operator[](static_cast<int>(i))=value;
}
NT get(std::size_t i) const {
return this->operator[](static_cast<int>(i));
}
NT* vector() {return this->data();}

View File

@ -3,7 +3,7 @@
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Parameterization_polyhedron_adaptor_3.h>
#include <CGAL/parameterize.h>
#include <CGAL/Timer.h>
#include <CGAL/Eigen_solver_traits.h>
#include <iostream>
@ -17,7 +17,7 @@
typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
typedef CGAL::Timer Timer;
// ----------------------------------------------------------------------------
// main()
@ -65,7 +65,8 @@ int main(int argc, char * argv[])
typedef CGAL::Parameterization_polyhedron_adaptor_3<Polyhedron>
Parameterization_polyhedron_adaptor;
Timer t;
t.start();
Parameterization_polyhedron_adaptor mesh_adaptor(mesh);
//***************************************
@ -77,16 +78,17 @@ int main(int argc, char * argv[])
typedef CGAL::Circular_border_arc_length_parameterizer_3<Parameterization_polyhedron_adaptor>
Border_parameterizer;
// Eigen solver
typedef CGAL::Eigen_solver_traits<> Solver;
typedef CGAL::Eigen_solver_traits<Eigen::BiCGSTAB<CGAL::Eigen_sparse_matrix<double>::EigenType, Eigen::IncompleteLUT< double > > > Solver;
// Floater Mean Value Coordinates parameterization
// (circular border) with Eigen solver
typedef CGAL::Mean_value_coordinates_parameterizer_3<Parameterization_polyhedron_adaptor,
Border_parameterizer,
Solver>
Solver>
Parameterizer;
Parameterizer::Error_code err = CGAL::parameterize(mesh_adaptor, Parameterizer());
t.stop();
switch(err) {
case Parameterizer::OK: // Success
@ -119,6 +121,6 @@ int main(int argc, char * argv[])
double v = mesh_adaptor.info(pVertex->halfedge())->uv().y();
std::cout << "(u,v) = (" << u << "," << v << ")" << std::endl;
}
std::cerr << t.time() << "sec." << std::endl;
return EXIT_SUCCESS;
}

View File

@ -32,6 +32,12 @@
#include <CGAL/Parameterization_mesh_feature_extractor.h>
#include <iostream>
#ifdef CGAL_EIGEN3_ENABLED
#include <CGAL/internal/Eigen_least_squares_solver.h>
#endif
#define DEBUG_TRACE
/// \file LSCM_parameterizer_3.h
namespace CGAL {
@ -136,8 +142,7 @@ private:
typedef typename Sparse_LA::Vector Vector;
typedef typename Sparse_LA::Matrix Matrix;
typedef typename OpenNL::LinearSolver<Sparse_LA>
LeastSquaresSolver ;
typedef CGAL::internal::Eigen_least_squares_solver LeastSquaresSolver;
// Public operations
public:
@ -289,7 +294,6 @@ parameterize(Adaptor& mesh)
// Create sparse linear system "A*X = B" of size 2*nbVertices x 2*nbVertices
// (in fact, we need only 2 lines per triangle x 1 column per vertex)
LeastSquaresSolver solver(2*nbVertices);
solver.set_least_squares(true) ;
// Initialize the "A*X = B" linear system after
// (at least two) border vertices parameterization
@ -412,13 +416,13 @@ initialize_system_from_mesh_border(LeastSquaresSolver& solver,
// Write (u,v) in X (meaningless if vertex is not parameterized)
// Note : 2*index --> u
// 2*index + 1 --> v
solver.variable(2*index ).set_value(uv.x()) ;
solver.variable(2*index + 1).set_value(uv.y()) ;
solver.set_value (2*index, uv.x());
solver.set_value (2*index + 1, uv.y());
// Copy (u,v) in B if vertex is parameterized
if (mesh.is_vertex_parameterized(it)) {
solver.variable(2*index ).lock() ;
solver.variable(2*index + 1).lock() ;
solver.lock (2*index);
solver.lock (2*index + 1);
}
}
}
@ -574,8 +578,8 @@ set_mesh_uv_from_system(Adaptor& mesh,
// Note : 2*index --> u
// 2*index + 1 --> v
NT u = solver.variable(2*index ).value() ;
NT v = solver.variable(2*index + 1).value() ;
NT u = solver.value (2*index);
NT v = solver.value (2*index + 1);
// Fill vertex (u,v) and mark it as "parameterized"
mesh.set_vertex_uv(vertexIt, Point_2(u,v));

View File

@ -0,0 +1,181 @@
#ifndef __EIGEN_LEAST_SQUARES_SOLVER__
#define __EIGEN_LEAST_SQUARES_SOLVER__
#include <CGAL/Eigen_solver_traits.h>
#include <CGAL/tuple.h>
#include <vector>
#include <iostream>
#include <cstdlib>
namespace CGAL {
namespace internal
{
class Eigen_least_squares_solver
{
public:
typedef Eigen_solver_traits<Eigen::SimplicialLDLT<Eigen_sparse_symmetric_matrix<double>::EigenType> > Solver;
typedef typename Solver::Matrix Matrix ;
typedef typename Solver::Vector Vector ;
typedef typename Solver::NT Scalar ;
typedef typename CGAL::cpp11::tuple<Scalar, std::size_t, bool> Indexed_scalar;
private:
std::vector<Indexed_scalar> _indexed_scalars;
std::vector<Scalar> _af;
std::vector<unsigned int> _if;
std::vector<Scalar> _al;
std::vector<Scalar> _xl;
Matrix* _A ;
Vector* _x ;
Vector* _b ;
public:
Eigen_least_squares_solver (unsigned int n_bvariables)
{
_indexed_scalars.resize (n_bvariables);
for (std::size_t i = 0; i < _indexed_scalars.size (); ++ i)
{
_indexed_scalars[i].get<0>() = 0.;
_indexed_scalars[i].get<1>() = -1;
_indexed_scalars[i].get<2>() = false;
}
_A = NULL ;
_x = NULL ;
_b = NULL ;
}
~Eigen_least_squares_solver()
{
if (_A != NULL) delete _A ;
if (_x != NULL) delete _x ;
if (_b != NULL) delete _b ;
}
const Scalar& value (std::size_t index) const
{
return _indexed_scalars[index].get<0>();
}
void set_value (std::size_t index, Scalar value)
{
_indexed_scalars[index].get<0>() = value;
}
void lock (std::size_t index)
{
_indexed_scalars[index].get<2>() = true;
}
void store_scalars_in_x ()
{
for (std::size_t i = 0; i < _indexed_scalars.size (); ++ i)
if (!(_indexed_scalars[i].get<2>()))
_x->set (_indexed_scalars[i].get<1>(), _indexed_scalars[i].get<0>());
}
void get_result ()
{
for (std::size_t i = 0; i < _indexed_scalars.size (); ++ i)
if (!(_indexed_scalars[i].get<2>()))
_indexed_scalars[i].get<0>() = _x->get(_indexed_scalars[i].get<1>());
}
void begin_system ()
{
std::size_t index = 0;
for (std::size_t i = 0; i < _indexed_scalars.size (); ++ i)
if(!(_indexed_scalars[i].get<2>()))
_indexed_scalars[i].get<1>() = index ++;
_A = new Matrix (index, index);
_x = new Vector (index);
_b = new Vector (index);
for (std::size_t i = 0; i < index; ++ i)
{
_x->set(i, 0.);
_b->set(i, 0.);
}
store_scalars_in_x() ;
}
void begin_row ()
{
_af.clear() ;
_if.clear() ;
_al.clear() ;
_xl.clear() ;
}
void add_coefficient (unsigned int iv, double a)
{
if(_indexed_scalars[iv].get<2>())
{
_al.push_back(a) ;
_xl.push_back(_indexed_scalars[iv].get<0>());
}
else
{
_af.push_back(a) ;
_if.push_back(_indexed_scalars[iv].get<1>());
}
}
void end_row ()
{
std::size_t nf = _af.size() ;
std::size_t nl = _al.size() ;
for (std::size_t i = 0; i < nf; ++ i)
for (std::size_t j = 0; j < nf; ++ j)
_A->add_coef (_if[i], _if[j], _af[i] * _af[j]);
Scalar S = 0.;
for (std::size_t j = 0; j < nl; ++ j)
S += _al[j] * _xl[j] ;
for (std::size_t i = 0; i < nf; ++ i)
_b->set(_if[i], _b->get(_if[i]) - _af[i] * S);
}
void end_system ()
{
_A->assemble_matrix ();
}
bool solve ()
{
Scalar D;
Solver solver;
bool success = solver.linear_solver(*_A, *_b, *_x, D) ;
get_result() ;
delete _A ; _A = NULL ;
delete _b ; _b = NULL ;
delete _x ; _x = NULL ;
return success;
}
} ;
} // namespace internal
} // namespace CGAL
#endif