mirror of https://github.com/CGAL/cgal
223 lines
7.8 KiB
C++
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
|