cgal/Surface_mesh_parameterization/include/CGAL/Parameterizer_traits_3.h

223 lines
7.8 KiB
C++

// Copyright (c) 2005 INRIA (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Saboret, Pierre Alliez, Bruno Levy
#ifndef CGAL_PARAMETERIZER_3_H
#define CGAL_PARAMETERIZER_3_H
#include <CGAL/license/Surface_mesh_parameterization.h>
#include <CGAL/Kernel/global_functions.h>
#include <CGAL/assertions.h>
/// \file Parameterizer_traits_3.h
namespace CGAL {
/// \ingroup PkgSurfaceParameterizationMethods
///
/// The class `Parameterizer_traits_3`
/// is the base class of all parameterization methods.
/// This class is a pure virtual class and thus cannot be instantiated.
///
/// This class does not do much. Its main goal is to ensure that subclasses
/// will be proper models of the `ParameterizerTraits_3` concept:
/// - `Parameterizer_traits_3` defines the Error_code list of errors detected by this package
/// - `Parameterizer_traits_3` declares a pure virtual method parameterize()
///
/// \cgalModels `ParameterizerTraits_3`
///
/// ## Design Pattern ##
/// `ParameterizerTraits_3` models are *Strategies* \cgalCite{cgal:ghjv-dpero-95}: they implement
/// a strategy of surface parameterization for models of `TriangleMesh`.
///
/// \tparam TriangleMesh must be a model of `FaceGraph`.
///
/// \sa `CGAL::ARAP_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
/// \sa `CGAL::Fixed_border_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
/// \sa `CGAL::Barycentric_mapping_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
/// \sa `CGAL::Discrete_authalic_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
/// \sa `CGAL::Discrete_conformal_map_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
/// \sa `CGAL::LSCM_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
/// \sa `CGAL::Mean_value_coordinates_parameterizer_3<TriangleMesh, BorderParameterizer_3, SparseLinearAlgebraTraits_d>`
///
template <class TriangleMesh>
class Parameterizer_traits_3
{
// Public types
public:
/// List of errors detected by this package
enum Error_code
{
OK, ///< Success
ERROR_EMPTY_MESH, ///< Input mesh is empty
ERROR_NON_TRIANGULAR_MESH, ///< Input mesh is not triangular
ERROR_NO_TOPOLOGICAL_DISC, ///< Input mesh is not a topological disc
ERROR_BORDER_TOO_SHORT, ///< This border parameterization requires a longer border
ERROR_NON_CONVEX_BORDER, ///< This parameterization method requires a convex border
ERROR_CANNOT_SOLVE_LINEAR_SYSTEM,///< Cannot solve linear system
ERROR_NO_1_TO_1_MAPPING, ///< Parameterization failed: no one-to-one mapping
ERROR_OUT_OF_MEMORY, ///< Not enough memory
ERROR_WRONG_PARAMETER ///< A method received an unexpected parameter
};
typedef typename boost::property_map<TriangleMesh, CGAL::vertex_point_t>::const_type VPM;
typedef typename boost::property_traits<VPM>::value_type Point_3;
typedef typename Kernel_traits<Point_3>::Kernel Kernel;
// Kernel subtypes:
typedef typename Kernel::Point_2 Point_2;
typedef typename Kernel::Vector_3 Vector_3;
typedef typename Kernel::Vector_2 Vector_2;
typedef typename Kernel::FT NT;
// Protected types
protected:
// Public operations
public:
/// Destructor of base class should be virtual.
virtual ~Parameterizer_traits_3() {}
// Default constructor, copy constructor and operator =() are fine
/// Compute a one-to-one mapping from a 3D surface mesh
/// to a piece of the 2D space.
/// The mapping is linear by pieces (linear in each triangle).
/// The result is the (u,v) pair image of each vertex of the 3D surface.
///
/// \pre `mesh` must be a surface with one connected component.
/// \pre `mesh` must be a triangular mesh.
//virtual Error_code parameterize (TriangleMesh& mesh) = 0;
/// Get message corresponding to an error code
/// \param error_code The code returned by `parameterize()`
/// \return The string describing the error code
static const char* get_error_message(int error_code)
{
// Messages corresponding to Error_code list above. Must be kept in sync!
static const char* error_message[ERROR_WRONG_PARAMETER+1] = {
"Success",
"Input mesh is empty",
"Input mesh is not triangular",
"Input mesh is not a topological disc",
"This border parameterization requires a longer border",
"This parameterization method requires a convex border",
"Cannot solve linear system",
"Parameterization failed: no one-to-one mapping",
"Not enough memory",
"A method received an unexpected parameter"
};
if(error_code > ERROR_WRONG_PARAMETER || error_code < 0)
return "Unknown error";
else
return error_message[error_code];
}
// Protected operations
/// @cond SKIP_IN_MANUAL
protected:
// -> ->
/// Return cotangent of (P,Q,R) corner (i.e. cotan of QP,QR angle).
double cotangent(const Point_3& P,
const Point_3& Q,
const Point_3& R) const
{
// std::cerr << P << " " << Q << " " << R << std::endl;
Vector_3 u = P - Q;
Vector_3 v = R - Q;
// (u . v)/((u x v).len)
double dot = (u*v);
Vector_3 cross_vector = CGAL::cross_product(u,v);
double cross_norm = std::sqrt(cross_vector*cross_vector);
if(cross_norm != 0.0)
return (dot / cross_norm);
else
return 0.0; // undefined
}
// -> ->
/// Return tangent of (P,Q,R) corner (i.e. tangent of QP,QR angle).
double tangent(const Point_3& P,
const Point_3& Q,
const Point_3& R) const
{
Vector_3 u = P - Q;
Vector_3 v = R - Q;
// (u . v)/((u x v).len)
double dot = (u*v);
Vector_3 cross_vector = CGAL::cross_product(u,v);
double cross_norm = std::sqrt(cross_vector*cross_vector);
if(dot != 0.0)
return (cross_norm / dot);
else
return 0.0; // undefined
}
// -> ->
/// Return angle (in radians) of of (P,Q,R) corner (i.e. QP,QR angle).
static double compute_angle_rad(const Point_3& P,
const Point_3& Q,
const Point_3& R)
{
static const double PI = 3.14159265359;
Vector_3 u = P - Q;
Vector_3 v = R - Q;
// check
double product = std::sqrt(u*u) * std::sqrt(v*v);
if(product == 0)
return 0.0;
// cosine
double dot = (u*v);
double cosine = dot / product;
// sine
Vector_3 w = CGAL::cross_product(u,v);
double AbsSine = std::sqrt(w*w) / product;
if(cosine >= 0)
return std::asin(fix_sine(AbsSine));
else
return PI-std::asin(fix_sine(AbsSine));
}
/// @endcond
// Private operations
private:
/// Fix sine.
static double fix_sine(double sine)
{
if(sine >= 1)
return 1;
else if(sine <= -1)
return -1;
else
return sine;
}
};
} // namespace CGAL
#endif // CGAL_PARAMETERIZER_3_H