cgal/Surface_mesh_parameterization/include/CGAL/Two_vertices_parameterizer_3.h

253 lines
7.5 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_TWO_VERTICES_PARAMETERIZER_3_H_INCLUDED
#define CGAL_TWO_VERTICES_PARAMETERIZER_3_H_INCLUDED
#include <CGAL/license/Surface_mesh_parameterization.h>
#include <CGAL/Parameterizer_traits_3.h>
#include <cfloat>
#include <climits>
/// \file Two_vertices_parameterizer_3.h
namespace CGAL {
//
// Declaration
//
/// \ingroup PkgSurfaceParameterizationBorderParameterizationMethods
///
/// The class `Two_vertices_parameterizer_3`
/// parameterizes two extreme vertices of a 3D surface.
/// This kind of border parameterization is used by free border parameterizations.
///
/// Implementation note:
/// To simplify the implementation, `BorderParameterizer_3` models know only the
/// `TriangleMesh` class. They do not know the parameterization algorithm
/// requirements or the kind of sparse linear system used.
///
/// \cgalModels `BorderParameterizer_3`
///
template<class TriangleMesh> //< 3D surface
class Two_vertices_parameterizer_3
{
// Public types
public:
/// Export TriangleMesh template parameter
//typedef TriangleMesh TriangleMesh;
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
// Private types
private:
typedef Parameterizer_traits_3<TriangleMesh> Adaptor;
typedef typename Adaptor::Point_2 Point_2;
typedef typename Adaptor::Point_3 Point_3;
typedef typename Adaptor::Vector_3 Vector_3;
vertex_descriptor vxmin, vxmax;
bool vertices_given;
// Public operations
public:
// Default constructor, copy constructor and operator =() are fine.
Two_vertices_parameterizer_3()
: vertices_given(false)
{ }
Two_vertices_parameterizer_3(vertex_descriptor v1, vertex_descriptor v2)
: vxmin(v1), vxmax(v2), vertices_given(true)
{ }
/// Map two extreme vertices of the 3D mesh and mark them as <i>parameterized</i>.
template <typename VertexUVmap, typename VertexParameterizedMap>
typename Parameterizer_traits_3<TriangleMesh>::Error_code
parameterize_border(const TriangleMesh& mesh,
halfedge_descriptor,
VertexUVmap uvmap,
VertexParameterizedMap vpmap)
{
if(vertices_given){
put(uvmap, vxmin, Point_2(0, 0.5));
put(uvmap, vxmax, Point_2(1, 0.5));
put(vpmap, vxmin, true);
put(vpmap, vxmax, true);
return Parameterizer_traits_3<TriangleMesh>::OK;
}
typedef typename boost::property_map<TriangleMesh, boost::vertex_point_t>::const_type PPmap;
PPmap ppmap = get(vertex_point, mesh);
// Get mesh's bounding box
double xmin = (std::numeric_limits<double>::max)();
double ymin = (std::numeric_limits<double>::max)();
double zmin = (std::numeric_limits<double>::max)();
double xmax = (std::numeric_limits<double>::min)();
double ymax = (std::numeric_limits<double>::min)();
double zmax = (std::numeric_limits<double>::min)();
BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)){
Point_3 position = get(ppmap,vd);
xmin = (std::min)(position.x(), xmin);
ymin = (std::min)(position.y(), ymin);
zmin = (std::min)(position.z(), zmin);
xmax = (std::max)(position.x(), xmax);
ymax = (std::max)(position.y(), ymax);
zmax = (std::max)(position.z(), zmax);
}
// Find longest bounding box axes
double dx = xmax - xmin;
double dy = ymax - ymin;
double dz = zmax - zmin;
enum { X_AXIS, Y_AXIS, Z_AXIS } longest_axis, second_longest_axis;
if(dx < dy && dx < dz) {
if(dy > dz) {
longest_axis = Y_AXIS;
second_longest_axis = Z_AXIS;
} else {
longest_axis = Z_AXIS;
second_longest_axis = Y_AXIS;
}
} else if(dy < dx && dy < dz) {
if(dx > dz) {
longest_axis = X_AXIS;
second_longest_axis = Z_AXIS;
} else {
longest_axis = Z_AXIS;
second_longest_axis = X_AXIS;
}
} else { // (dz < dx && dz < dy)
if(dx > dy) {
longest_axis = X_AXIS;
second_longest_axis = Y_AXIS;
} else {
longest_axis = Y_AXIS;
second_longest_axis = X_AXIS;
}
}
Vector_3 V1, // bounding box' longest axis
V2 ; // bounding box' 2nd longest axis
double V1_min=0, V1_max=0; // bounding box' dimensions along V1
double V2_min=0, V2_max=0; // bounding box' dimensions along V2
switch (longest_axis)
{
case X_AXIS:
V1 = Vector_3(1,0,0);
V1_min = xmin;
V1_max = xmax;
break;
case Y_AXIS:
V1 = Vector_3(0,1,0);
V1_min = ymin;
V1_max = ymax;
break;
case Z_AXIS:
V1 = Vector_3(0,0,1);
V1_min = zmin;
V1_max = zmax;
break;
default:
CGAL_assertion(false);
}
switch (second_longest_axis)
{
case X_AXIS:
V2 = Vector_3(1,0,0) ;
V2_min = xmin;
V2_max = xmax;
break;
case Y_AXIS:
V2 = Vector_3(0,1,0) ;
V2_min = ymin;
V2_max = ymax;
break;
case Z_AXIS:
V2 = Vector_3(0,0,1) ;
V2_min = zmin;
V2_max = zmax;
break;
default:
CGAL_assertion(false);
}
// Project onto longest bounding box axes,
// Set extrema vertices' (u,v) in unit square and mark them as "parameterized"
double umin = (std::numeric_limits<double>::max)();
double umax = (std::numeric_limits<double>::min)();
double vmin = (std::numeric_limits<double>::max)();
double vmax = (std::numeric_limits<double>::min)();
BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)){
Point_3 position = get(ppmap,vd);
Vector_3 position_as_vector = position - Point_3(0,0,0);
// coordinate along the bounding box' main axes
double u = position_as_vector * V1 ;
double v = position_as_vector * V2 ;
// convert to unit square coordinates
CGAL_assertion(V1_max > V1_min);
CGAL_assertion(V2_max > V2_min);
u = (u - V1_min) / (V1_max - V1_min);
v = (v - V2_min) / (V2_max - V2_min);
if(u < umin || (u==umin && v < vmin)){
vxmin = vd ;
umin = u ;
vmin = v ;
}
if(u > umax || (u==umax && v > vmax)){
vxmax = vd ;
umax = u ;
vmax = v ;
}
}
put(uvmap, vxmin, Point_2(umin,vmin)) ; // useful only for vxmin and vxmax
put(uvmap, vxmax, Point_2(umax,vmax)) ; // useful only for vxmin and vxmax
put(vpmap, vxmin, true);
put(vpmap, vxmax, true);
#ifdef DEBUG_TRACE
std::cerr << " map two vertices..." << std::endl;
#endif
return Parameterizer_traits_3<TriangleMesh>::OK;
}
/// Indicate if border's shape is convex.
/// Meaningless for free border parameterization algorithms.
bool is_border_convex () { return false; }
};
} // namespace CGAL
#endif // CGAL_TWO_VERTICES_PARAMETERIZER_3_H_INCLUDED