Merge pull request #2136 from afabri/Polygon_mesh_processing-accelerate_isotropic_remeshing-GF

Polygon_mesh_processing: Accelerate Isotropic_remeshing
This commit is contained in:
Laurent Rineau 2017-07-21 10:45:32 +02:00
commit f8760d591b
17 changed files with 1203 additions and 164 deletions

View File

@ -25,10 +25,12 @@
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/foreach.hpp>
#include <CGAL/Dynamic_property_map.h>
#include <CGAL/basic.h>
#include <string>
/// Boost Namespace
namespace boost {
@ -54,15 +56,7 @@ enum halfedge_external_index_t { halfedge_external_index } ;
enum face_index_t { face_index };
enum face_external_index_t { face_external_index } ;
template <typename T>
struct vertex_property_t
{
vertex_property_t(const std::string s, const T& t = T())
: s(s), t(t)
{}
std::string s;
T t;
};
template<typename Graph, typename PropertyTag>
struct graph_has_property : CGAL::Tag_false {};
@ -104,7 +98,6 @@ using boost::face_index_t;
using boost::face_index;
using boost::face_external_index_t;
using boost::face_external_index;
using boost::vertex_property_t;
} // CGAL
namespace CGAL{
@ -227,7 +220,9 @@ void init_halfedge_indices(PolygonMesh& pm, HalfedgeIndexMap hid)
>::type >::type() );
}
} } //end of namespace CGAL::helpers
} //namespace helpers
} // namespace CGAL
#endif // CGAL_BOOST_GRAPH_BGL_PROPERTIES_H

View File

@ -47,27 +47,76 @@ public:
typedef value_type& reference;
OM_pmap()
{}
OM_pmap(Mesh& m)
: mesh(m)
{}
OM_pmap(Mesh& m, H h)
: mesh(m), h(h)
{}
inline friend reference get(const OM_pmap<Mesh,Descriptor,Value>& pm, key_type k)
: mesh(&m)
{
return pm.mesh.property(pm.h,k);
mesh->add_property(h);
}
inline friend void put(const OM_pmap<Mesh,Descriptor,Value>& pm, key_type k, const value_type& v)
OM_pmap(Mesh& m, H h)
: mesh(&m), h(h)
{
pm.mesh.property(pm.h,k) = v;
mesh->add_property(h);
}
inline friend reference get(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::vertex_descriptor k)
{
return pm.mesh->property(pm.h,k);
}
inline friend reference get(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::face_descriptor k)
{
return pm.mesh->property(pm.h,k);
}
inline friend reference get(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::halfedge_descriptor k)
{
return pm.mesh->property(pm.h,k);
}
inline friend reference get(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::edge_descriptor k)
{
typename Mesh::EdgeHandle eh(k.idx());
return pm.mesh->property(pm.h,eh);
}
inline friend void put(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::vertex_descriptor k,
const value_type& v)
{
pm.mesh->property(pm.h,k) = v;
}
inline friend void put(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::face_descriptor k,
const value_type& v)
{
pm.mesh->property(pm.h,k) = v;
}
inline friend void put(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::halfedge_descriptor k,
const value_type& v)
{
pm.mesh->property(pm.h,k) = v;
}
inline friend void put(const OM_pmap<Mesh,Descriptor,Value>& pm,
typename boost::graph_traits<Mesh>::edge_descriptor k,
const value_type& v)
{
typename Mesh::EdgeHandle eh(k.idx());
pm.mesh->property(pm.h,eh) = v;
}
reference operator[](key_type k)
{
return mesh.property(h,k);
return mesh->property(h,k);
}
H handle() const
@ -80,7 +129,7 @@ public:
return h;
}
Mesh& mesh;
Mesh* mesh;
H h;
};
@ -117,6 +166,9 @@ public:
typedef unsigned int reference;
typedef VEF key_type;
OM_index_pmap()
{}
value_type operator[](const key_type& vd) const
{
return vd.idx();
@ -383,4 +435,88 @@ put(boost::vertex_point_t p, OpenMesh::PolyMesh_ArrayKernelT<K>& g,
namespace CGAL {
namespace internal {
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, vertex_property_t<V> >
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::vertex_descriptor vertex_descriptor;
typedef CGAL::OM_pmap<SM,vertex_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, halfedge_property_t<V> >
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::halfedge_descriptor halfedge_descriptor;
typedef CGAL::OM_pmap<SM,halfedge_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, edge_property_t<V> >
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::edge_descriptor edge_descriptor;
typedef CGAL::OM_pmap<SM,edge_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, face_property_t<V> >
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::face_descriptor face_descriptor;
typedef CGAL::OM_pmap<SM,face_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, vertex_property_t<V> >::const_type
add_property(vertex_property_t<V>, OpenMesh::PolyMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::vertex_descriptor vertex_descriptor;
return CGAL::OM_pmap<OM,vertex_descriptor, V>(om);
}
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, halfedge_property_t<V> >::const_type
add_property(halfedge_property_t<V>, OpenMesh::PolyMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::halfedge_descriptor halfedge_descriptor;
return CGAL::OM_pmap<OM,halfedge_descriptor, V>(om);
}
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, edge_property_t<V> >::const_type
add_property(edge_property_t<V>, OpenMesh::PolyMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::edge_descriptor edge_descriptor;
return CGAL::OM_pmap<OM,edge_descriptor, V>(om);
}
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::PolyMesh_ArrayKernelT<K>, face_property_t<V> >::const_type
add_property(face_property_t<V>, OpenMesh::PolyMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::PolyMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::face_descriptor face_descriptor;
return CGAL::OM_pmap<OM,face_descriptor, V>(om);
}
template <typename Pmap, typename K>
void remove_property(Pmap pm, OpenMesh::PolyMesh_ArrayKernelT<K>& om)
{
om.remove_property(pm.handle());
}
} // namespace internal
} // namespace CGAL
#endif /* CGAL_PROPERTIES_POLYMESH_ARRAYKERNELT_H */

View File

@ -211,4 +211,90 @@ put(boost::vertex_point_t p, OpenMesh::TriMesh_ArrayKernelT<K>& g,
namespace CGAL {
namespace internal {
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, vertex_property_t<V> >
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::vertex_descriptor vertex_descriptor;
typedef CGAL::OM_pmap<SM,vertex_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, edge_property_t<V> >
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::edge_descriptor edge_descriptor;
typedef CGAL::OM_pmap<SM,edge_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, halfedge_property_t<V> >
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::halfedge_descriptor halfedge_descriptor;
typedef CGAL::OM_pmap<SM,halfedge_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
struct dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, face_property_t<V> >
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> SM;
typedef typename boost::graph_traits<SM>::face_descriptor face_descriptor;
typedef CGAL::OM_pmap<SM,face_descriptor, V> type;
typedef type const_type;
};
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, vertex_property_t<V> >::const_type
add_property(vertex_property_t<V>, OpenMesh::TriMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::vertex_descriptor vertex_descriptor;
return CGAL::OM_pmap<OM,vertex_descriptor, V>(om);
}
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, halfedge_property_t<V> >::const_type
add_property(halfedge_property_t<V>, OpenMesh::TriMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::halfedge_descriptor halfedge_descriptor;
return CGAL::OM_pmap<OM,halfedge_descriptor, V>(om);
}
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, edge_property_t<V> >::const_type
add_property(edge_property_t<V>, OpenMesh::TriMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::edge_descriptor edge_descriptor;
return CGAL::OM_pmap<OM,edge_descriptor, V>(om);
}
template <typename K, typename V>
typename dynamic_property_map<OpenMesh::TriMesh_ArrayKernelT<K>, face_property_t<V> >::const_type
add_property(face_property_t<V>, OpenMesh::TriMesh_ArrayKernelT<K>& om)
{
typedef OpenMesh::TriMesh_ArrayKernelT<K> OM;
typedef typename boost::graph_traits<OM>::face_descriptor face_descriptor;
return CGAL::OM_pmap<OM,face_descriptor, V>(om);
}
template <typename Pmap, typename K>
void remove_property(Pmap pm, OpenMesh::TriMesh_ArrayKernelT<K>& om)
{
om.remove_property(pm.handle());
}
} // namespace internal
} // namespace CGAL
#endif /* CGAL_PROPERTIES_TRIMESH_ARRAYKERNELT_H */

View File

@ -0,0 +1,188 @@
// Copyright (c) 2017 GeometryFactory
// 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 Lesser 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) : Simon Giraudot
#ifndef CGAL_INTERNAL_STATIC_FILTERS_COLLINEAR_3_H
#define CGAL_INTERNAL_STATIC_FILTERS_COLLINEAR_3_H
#include <CGAL/Profile_counter.h>
#include <CGAL/internal/Static_filters/Static_filter_error.h>
#include <CGAL/internal/Static_filters/tools.h>
#include <cmath>
namespace CGAL { namespace internal { namespace Static_filters_predicates {
#include <iostream>
template < typename K_base >
class Collinear_3
: public K_base::Collinear_3
{
typedef typename K_base::Point_3 Point_3;
typedef typename K_base::Vector_3 Vector_3;
typedef typename K_base::Sphere_3 Sphere_3;
typedef typename K_base::Tetrahedron_3 Tetrahedron_3;
typedef typename K_base::Collinear_3 Base;
public:
typedef typename Base::result_type result_type;
result_type
operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
{
CGAL_BRANCH_PROFILER_3("semi-static failures/attempts/calls to : Collinear_3", tmp);
Get_approx<Point_3> get_approx; // Identity functor for all points
// but lazy points.
double px, py, pz, qx, qy, qz, rx, ry, rz;
if (fit_in_double(get_approx(p).x(), px) && fit_in_double(get_approx(p).y(), py) &&
fit_in_double(get_approx(p).z(), pz) &&
fit_in_double(get_approx(q).x(), qx) && fit_in_double(get_approx(q).y(), qy) &&
fit_in_double(get_approx(q).z(), qz) &&
fit_in_double(get_approx(r).x(), rx) && fit_in_double(get_approx(r).y(), ry) &&
fit_in_double(get_approx(r).z(), rz))
{
double dpx = (px - rx);
double dqx = (qx - rx);
double dpy = (py - ry);
double dqy = (qy - ry);
double double_tmp_result = ((dpx * dqy) - (dpy * dqx));
double max1 = CGAL::abs(dpx);
if (max1 < CGAL::abs(dqx))
max1 = CGAL::abs(dqx);
double max2 = CGAL::abs(dpy);
if (max2 < CGAL::abs(dqy))
max2 = CGAL::abs(dqy);
double lower_bound_1 = max2;
double upper_bound_1 = max2;
if (max1 < lower_bound_1)
lower_bound_1 = max1;
else if (max1 > upper_bound_1)
upper_bound_1 = max1;
int int_tmp_result;
if (lower_bound_1 < 5.00368081960964635413e-147)
return Base::operator()(p, q, r);
else
{
if (upper_bound_1 > 1.67597599124282407923e+153)
return Base::operator()(p, q, r);
double eps = (8.88720573725927976811e-16 * (max1 * max2));
if (double_tmp_result > eps)
int_tmp_result = 1;
else
{
if (double_tmp_result < -eps)
int_tmp_result = -1;
else
return Base::operator()(p, q, r);
}
}
int sign_of_determinant_return_value = int_tmp_result;
if (sign_of_determinant_return_value != 0)
return false;
double dpz = (pz - rz);
double dqz = (qz - rz);
int int_tmp_result_3SPBwDj;
double double_tmp_result_k3Lzf6g = ((dpx * dqz) - (dpz * dqx));
double max3 = CGAL::abs(dpz);
if (max3 < CGAL::abs(dqz))
max3 = CGAL::abs(dqz);
lower_bound_1 = max1;
upper_bound_1 = max1;
if (max3 < lower_bound_1)
lower_bound_1 = max3;
else if (max3 > upper_bound_1)
upper_bound_1 = max3;
if (lower_bound_1 < 5.00368081960964635413e-147)
return Base::operator()(p, q, r);
else
{
if (upper_bound_1 > 1.67597599124282407923e+153)
return Base::operator()(p, q, r);
double eps = (8.88720573725927976811e-16 * (max1 * max3));
if (double_tmp_result_k3Lzf6g > eps)
int_tmp_result_3SPBwDj = 1;
else
{
if (double_tmp_result_k3Lzf6g < -eps)
int_tmp_result_3SPBwDj = -1;
else
return Base::operator()(p, q, r);
}
}
int sign_of_determinant_return_value_FFWKCAA = int_tmp_result_3SPBwDj;
int int_tmp_result_Gx4H;
double double_tmp_result_AvrrXBP = ((dpy * dqz) - (dpz * dqy));
lower_bound_1 = max2;
upper_bound_1 = max2;
if (max3 < lower_bound_1)
lower_bound_1 = max3;
else if (max3 > upper_bound_1)
upper_bound_1 = max3;
if (lower_bound_1 < 5.00368081960964635413e-147)
return Base::operator()(p, q, r);
else
{
if (upper_bound_1 > 1.67597599124282407923e+153)
return Base::operator()(p, q, r);
double eps = (8.88720573725927976811e-16 * (max2 * max3));
if (double_tmp_result_AvrrXBP > eps)
int_tmp_result_Gx4H = 1;
else
{
if (double_tmp_result_AvrrXBP < -eps)
int_tmp_result_Gx4H = -1;
else
return Base::operator()(p, q, r);
}
}
int sign_of_determinant_return_value_k60Ocge = int_tmp_result_Gx4H;
return ((sign_of_determinant_return_value_FFWKCAA == 0) && (sign_of_determinant_return_value_k60Ocge == 0));
}
return Base::operator()(p, q, r);
}
};
} } } // namespace CGAL::internal::Static_filters_predicates
#endif // CGAL_INTERNAL_STATIC_FILTERS_COLLINEAR_3_H

View File

@ -51,6 +51,7 @@ class Do_intersect_3
typedef typename K_base::Ray_3 Ray_3;
typedef typename K_base::Segment_3 Segment_3;
typedef typename K_base::Triangle_3 Triangle_3;
typedef typename K_base::Sphere_3 Sphere_3;
typedef typename K_base::Do_intersect_3 Base;
public:
@ -180,6 +181,118 @@ public:
return Base::operator()(r,b);
}
result_type
operator()(const Bbox_3& b, const Sphere_3 &s) const
{
return this->operator()(s, b);
}
result_type
operator()(const Sphere_3 &s, const Bbox_3& b) const
{
CGAL_BRANCH_PROFILER_3(std::string("semi-static failures/attempts/calls to : ") +
std::string(CGAL_PRETTY_FUNCTION), tmp);
Get_approx<Point_3> get_approx; // Identity functor for all points
const Point_3& c = s.center();
double scx, scy, scz, ssr, bxmin, bymin, bzmin, bxmax, bymax, bzmax;
if (fit_in_double(get_approx(c).x(), scx) &&
fit_in_double(get_approx(c).y(), scy) &&
fit_in_double(get_approx(c).z(), scz) &&
fit_in_double(s.squared_radius(), ssr) &&
fit_in_double(b.xmin(), bxmin) &&
fit_in_double(b.ymin(), bymin) &&
fit_in_double(b.zmin(), bzmin) &&
fit_in_double(b.xmax(), bxmax) &&
fit_in_double(b.ymax(), bymax) &&
fit_in_double(b.zmax(), bzmax))
{
CGAL_BRANCH_PROFILER_BRANCH_1(tmp);
double distance = 0;
double max1 = 0;
if(scx < bxmin)
{
double bxmin_scx = bxmin - scx;
max1 = bxmin_scx;
distance = square(bxmin_scx);
}
else if(scx > bxmax)
{
double scx_bxmax = scx - bxmax;
max1 = scx_bxmax;
distance = square(scx_bxmax);
}
if(scy < bymin)
{
double bymin_scy = bymin - scy;
if(max1 < bymin_scy)
max1 = bymin_scy;
distance += square(bymin_scy);
}
else if(scy > bymax)
{
double scy_bymax = scy - bymax;
if(max1 < scy_bymax)
max1 = scy_bymax;
distance += square(scy_bymax);
}
if(scz < bzmin)
{
double bzmin_scz = bzmin - scz;
if(max1 < bzmin_scz)
max1 = bzmin_scz;
distance += square(bzmin_scz);
}
else if(scz > bzmax)
{
double scz_bzmax = scz - bzmax;
if(max1 < scz_bzmax)
max1 = scz_bzmax;
distance += square(scz_bzmax);
}
double double_tmp_result = (distance - ssr);
double max2 = CGAL::abs(ssr);
if ((max1 < 3.33558365626356687717e-147) || (max2 < 1.11261183279326254436e-293)){
CGAL_BRANCH_PROFILER_BRANCH_2(tmp);
return Base::operator()(s,b);
}
if ((max1 > 1.67597599124282407923e+153) || (max2 > 2.80889552322236673473e+306)){
CGAL_BRANCH_PROFILER_BRANCH_2(tmp);
return Base::operator()(s,b);
}
double eps = 1.99986535548615598560e-15 * (std::max) (max2, (max1 * max1));
if (double_tmp_result > eps)
return false;
else
{
if (double_tmp_result < -eps)
return true;
else {
CGAL_BRANCH_PROFILER_BRANCH_2(tmp);
return Base::operator()(s,b);
}
}
CGAL_BRANCH_PROFILER_BRANCH_2(tmp);
}
return Base::operator()(s,b);
}
// Computes the epsilon for Bbox_3_Segment_3_do_intersect.

View File

@ -37,6 +37,7 @@
#include <CGAL/internal/Static_filters/tools.h>
#include <CGAL/internal/Static_filters/Orientation_2.h>
#include <CGAL/internal/Static_filters/Orientation_3.h>
#include <CGAL/internal/Static_filters/Collinear_3.h>
// for static filters added nov./dec. 2011
#ifdef CGAL_DISABLE_STATIC_FILTERS_ADDED_2011
@ -133,6 +134,9 @@ public:
typedef Static_filters_predicates::Orientation_2<K_base> Orientation_2;
typedef Static_filters_predicates::Orientation_3<K_base> Orientation_3;
#ifndef CGAL_NO_ANGLE_3_STATIC_FILTERS
typedef Static_filters_predicates::Collinear_3<K_base> Collinear_3;
typedef Static_filters_predicates::Angle_3<K_base> Angle_3;
#endif // NOT CGAL_NO_ANGLE_3_STATIC_FILTERS
#ifndef CGAL_NO_DO_INTERSECT_3_STATIC_FILTERS
@ -153,6 +157,10 @@ public:
orientation_3_object() const
{ return Orientation_3(); }
Collinear_3
collinear_3_object() const
{ return Collinear_3(); }
#ifndef CGAL_NO_EQUAL_3_STATIC_FILTERS
Equal_2
equal_2_object() const

View File

@ -108,9 +108,9 @@ CGAL_Kernel_pred(Collinear_are_strictly_ordered_along_line_3,
collinear_are_strictly_ordered_along_line_3_object)
CGAL_Kernel_pred(Collinear_has_on_2,
collinear_has_on_2_object)
CGAL_Kernel_pred(Collinear_2,
CGAL_Kernel_pred_RT(Collinear_2,
collinear_2_object)
CGAL_Kernel_pred(Collinear_3,
CGAL_Kernel_pred_RT(Collinear_3,
collinear_3_object)
CGAL_Kernel_pred(Compare_angle_with_x_axis_2,
compare_angle_with_x_axis_2_object)
@ -548,7 +548,7 @@ CGAL_Kernel_cons(Intersect_3,
intersect_3_object)
CGAL_Kernel_pred(Is_degenerate_2,
is_degenerate_2_object)
CGAL_Kernel_pred(Is_degenerate_3,
CGAL_Kernel_pred_RT(Is_degenerate_3,
is_degenerate_3_object)
CGAL_Kernel_pred(Is_horizontal_2,
is_horizontal_2_object)

View File

@ -96,6 +96,7 @@ create_single_source_cgal_program( "triangulate_polyline_example.cpp")
create_single_source_cgal_program( "mesh_slicer_example.cpp")
#create_single_source_cgal_program( "remove_degeneracies_example.cpp")
create_single_source_cgal_program( "isotropic_remeshing_example.cpp")
create_single_source_cgal_program( "isotropic_remeshing_of_patch_example.cpp")
create_single_source_cgal_program( "surface_mesh_intersection.cpp")
create_single_source_cgal_program( "corefinement_SM.cpp")
create_single_source_cgal_program( "corefinement_consecutive_bool_op.cpp" )

View File

@ -0,0 +1,79 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/border.h>
#include <boost/function_output_iterator.hpp>
#include <fstream>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
namespace PMP = CGAL::Polygon_mesh_processing;
struct halfedge2edge
{
halfedge2edge(const Mesh& m, std::vector<edge_descriptor>& edges)
: m_mesh(m), m_edges(edges)
{}
void operator()(const halfedge_descriptor& h) const
{
m_edges.push_back(edge(h, m_mesh));
}
const Mesh& m_mesh;
std::vector<edge_descriptor>& m_edges;
};
int main(int argc, char* argv[])
{
const char* filename = (argc > 1) ? argv[1] : "data/pig.off";
std::ifstream input(filename);
Mesh mesh;
if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) {
std::cerr << "Not a valid input file." << std::endl;
return 1;
}
double target_edge_length = 0.1;
unsigned int nb_iter = 3;
std::cout << "Split border...";
std::vector<edge_descriptor> border;
PMP::border_halfedges(faces(mesh),
mesh,
boost::make_function_output_iterator(halfedge2edge(mesh, border)));
PMP::split_long_edges(border, target_edge_length, mesh);
std::cout << "done." << std::endl;
std::cout << "Start remeshing of " << filename
<< " (" << num_faces(mesh) << " faces,";
std::vector<face_descriptor> seed, patch;
Mesh::Property_map<face_descriptor,int> selected
= mesh.add_property_map<face_descriptor,int>("f:selected",0).first;
seed.push_back(*(faces(mesh).first));
selected[seed.front()] = true;
CGAL::expand_face_selection(seed, mesh, 5, selected, std::back_inserter(patch));
std::cout << " and patch of size " << patch.size() << std::endl;
PMP::isotropic_remeshing(patch,
target_edge_length,
mesh,
PMP::parameters::number_of_iterations(nb_iter)
.face_patch_map(selected)
.protect_constraints(true)//i.e. protect border, here
);
std::cout << "Remeshing done." << std::endl;
return 0;
}

View File

@ -18,6 +18,7 @@
//
// Author(s) : Jane Tournois
#ifndef CGAL_POLYGON_MESH_PROCESSING_REMESH_IMPL_H
#define CGAL_POLYGON_MESH_PROCESSING_REMESH_IMPL_H
@ -33,18 +34,19 @@
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_triangle_primitive.h>
#include <CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/AABB_filtered_projection_traits.h>
#include <CGAL/property_map.h>
#include <CGAL/iterator.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/properties.h>
#include <boost/graph/graph_traits.hpp>
#include <boost/foreach.hpp>
#include <CGAL/tags.h>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/range.hpp>
#include <boost/range/join.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/shared_ptr.hpp>
@ -155,6 +157,7 @@ namespace internal {
}
};
template <typename PM,
typename EdgeIsConstrainedMap,
typename FaceIndexMap>
@ -166,7 +169,9 @@ namespace internal {
typedef EdgeIsConstrainedMap ECMap;
typedef Connected_components_pmap<PM, ECMap, FIMap> CCMap;
boost::unordered_map<face_descriptor, Patch_id> patch_ids_map;
typedef CGAL::internal::face_property_t<Patch_id> Face_property_tag;
typename CGAL::internal::dynamic_property_map<PM, Face_property_tag >::type patch_ids_map;
std::size_t nb_cc;
public:
typedef face_descriptor key_type;
@ -174,33 +179,42 @@ namespace internal {
typedef Patch_id& reference;
typedef boost::read_write_property_map_tag category;
Connected_components_pmap()
: patch_ids_map()
{}
Connected_components_pmap(const PM& pmesh
//note pmesh is a non-const ref because add_property() and remove_property()
//modify the mesh data structure, but not the mesh itself
Connected_components_pmap(PM& pmesh
, EdgeIsConstrainedMap ecmap
, FIMap fimap)
: patch_ids_map()
, FIMap fimap
, const bool do_init = true)
{
PMP::connected_components(pmesh,
boost::make_assoc_property_map(patch_ids_map),
patch_ids_map = CGAL::internal::add_property(Face_property_tag("PMP_patch_id"), pmesh);
if (do_init)
{
nb_cc
= PMP::connected_components(pmesh,
patch_ids_map,
PMP::parameters::edge_is_constrained_map(ecmap)
.face_index_map(fimap));
if(nb_cc == 1){
CGAL::internal::remove_property(patch_ids_map, pmesh);
}
}
}
friend void remove(CCMap m, PM& pmesh)
{
CGAL::internal::remove_property(m.patch_ids_map, pmesh);
}
friend value_type get(const CCMap& m, const key_type& f)
{
CGAL_assertion(!m.patch_ids_map.empty());
CGAL_assertion(m.patch_ids_map.find(f) != m.patch_ids_map.end());
return m.patch_ids_map.at(f);
if (m.nb_cc == 1)
return 0;
return get(m.patch_ids_map, f);
}
friend void put(CCMap& m, const key_type& f, const value_type i)
{
if (m.patch_ids_map.find(f) == m.patch_ids_map.end())
m.patch_ids_map.insert(std::make_pair(f, i));
else
m.patch_ids_map[f] = i;
if (m.nb_cc != 1)
put(m.patch_ids_map, f, i);
}
};
@ -263,12 +277,16 @@ namespace internal {
typedef typename boost::property_traits<FacePatchMap>::value_type Patch_id;
typedef std::vector<Triangle_3> Triangle_list;
typedef std::vector<Patch_id> Patch_id_list;
typedef std::map<Patch_id,std::size_t> Patch_id_to_index_map;
typedef CGAL::AABB_triangle_primitive<GeomTraits,
typename Triangle_list::iterator> AABB_primitive;
typedef CGAL::AABB_traits<GeomTraits, AABB_primitive> AABB_traits;
typedef CGAL::AABB_tree<AABB_traits> AABB_tree;
typedef typename CGAL::internal::dynamic_property_map<
PM, CGAL::internal::halfedge_property_t<Halfedge_status> >::type Halfedge_status_pmap;
public:
Incremental_remesher(PolygonMesh& pmesh
, VertexPointMap& vpmap
@ -277,26 +295,44 @@ namespace internal {
, VertexIsConstrainedMap vcmap
, FacePatchMap fpmap
, FaceIndexMap fimap
, const bool own_tree = true)//built by the remesher
, const bool build_tree = true)//built by the remesher
: mesh_(pmesh)
, vpmap_(vpmap)
, own_tree_(own_tree)
, build_tree_(build_tree)
, has_border_(false)
, input_triangles_()
, input_patch_ids_()
, halfedge_status_map_()
, protect_constraints_(protect_constraints)
, patch_ids_map_(fpmap)
, ecmap_(ecmap)
, vcmap_(vcmap)
, fimap_(fimap)
{
halfedge_status_pmap_ = CGAL::internal::add_property(
CGAL::internal::halfedge_property_t<Halfedge_status>("PMP_halfedge_status", MESH),
pmesh);
CGAL_assertion(CGAL::is_triangle_mesh(mesh_));
}
~Incremental_remesher()
{
if (own_tree_)
delete tree_ptr_;
typedef Connected_components_pmap<PM, EdgeIsConstrainedMap, FaceIndexMap> CCPmap;
remove_connected_components_pmap
(CGAL::Boolean_tag<boost::is_same<FacePatchMap, CCPmap>::value>());
CGAL::internal::remove_property(halfedge_status_pmap_, mesh_);
if (build_tree_){
for(std::size_t i=0; i < trees.size();++i){
delete trees[i];
}
}
}
void remove_connected_components_pmap(CGAL::Tag_false) {}
void remove_connected_components_pmap(CGAL::Tag_true)
{
remove(patch_ids_map_, mesh_);
}
template<typename FaceRange>
@ -308,17 +344,39 @@ namespace internal {
BOOST_FOREACH(face_descriptor f, face_range)
{
Triangle_3 t = triangle(f);
if (t.is_degenerate()) continue;
input_triangles_.push_back(t);
input_patch_ids_.push_back(get_patch_id(f));
if (is_degenerate_triangle_face(halfedge(f,mesh_),mesh_,vpmap_,GeomTraits())){
continue;
}
Patch_id pid = get_patch_id(f);
input_triangles_.push_back(triangle(f));
input_patch_ids_.push_back(pid);
std::pair<typename Patch_id_to_index_map::iterator, bool>
res = patch_id_to_index_map.insert(std::make_pair(pid,0));
if(res.second){
res.first->second = patch_id_to_index_map.size()-1;
}
}
CGAL_assertion(input_triangles_.size() == input_patch_ids_.size());
tree_ptr_ = new AABB_tree(input_triangles_.begin(),
input_triangles_.end());
tree_ptr_->accelerate_distance_queries();
if (!build_tree_)
return;
trees.resize(patch_id_to_index_map.size());
for(std::size_t i=0; i < trees.size(); ++i){
trees[i] = new AABB_tree();
}
typename Triangle_list::iterator it;
typename Patch_id_list::iterator pit;
for(it = input_triangles_.begin(), pit = input_patch_ids_.begin();
it != input_triangles_.end();
++it, ++pit){
trees[patch_id_to_index_map[*pit]]->insert(it);
}
for(std::size_t i=0; i < trees.size(); ++i){
trees[i]->build();
trees[i]->accelerate_distance_queries();
}
}
// split edges of edge_range that have their length > high
template<typename EdgeRange>
@ -565,10 +623,8 @@ namespace internal {
Boost_bimap short_edges;
BOOST_FOREACH(edge_descriptor e, edges(mesh_))
{
if (!is_collapse_allowed(e))
continue;
double sqlen = sqlength(e);
if (sqlen < sq_low)
if( (sqlen < sq_low) && is_collapse_allowed(e) )
short_edges.insert(short_edge(halfedge(e, mesh_), sqlen));
}
@ -725,10 +781,8 @@ namespace internal {
//insert new/remaining short edges
BOOST_FOREACH(halfedge_descriptor ht, halfedges_around_target(vkept, mesh_))
{
if (!is_collapse_allowed(edge(ht, mesh_)))
continue;
double sqlen = sqlength(ht);
if (sqlen < sq_low)
if( (sqlen < sq_low) && is_collapse_allowed(edge(ht, mesh_)) )
short_edges.insert(short_edge(ht, sqlen));
}
}//end if(collapse_ok)
@ -774,10 +828,14 @@ namespace internal {
vertex_descriptor vc = target(next(he, mesh_), mesh_);
vertex_descriptor vd = target(next(opposite(he, mesh_), mesh_), mesh_);
int deviation_pre = CGAL::abs(valence(va) - target_valence(va))
+ CGAL::abs(valence(vb) - target_valence(vb))
+ CGAL::abs(valence(vc) - target_valence(vc))
+ CGAL::abs(valence(vd) - target_valence(vd));
int vva = valence(va), tvva = target_valence(va);
int vvb = valence(vb), tvvb = target_valence(vb);
int vvc = valence(vc), tvvc = target_valence(vc);
int vvd = valence(vd), tvvd = target_valence(vd);
int deviation_pre = CGAL::abs(vva - tvva)
+ CGAL::abs(vvb - tvvb)
+ CGAL::abs(vvc - tvvc)
+ CGAL::abs(vvd - tvvd);
CGAL_assertion_code(Halfedge_status s1 = status(he));
CGAL_assertion_code(Halfedge_status s1o = status(opposite(he, mesh_)));
@ -785,6 +843,10 @@ namespace internal {
Patch_id pid = get_patch_id(face(he, mesh_));
CGAL::Euler::flip_edge(he, mesh_);
vva -= 1;
vvb -= 1;
vvc += 1;
vvd += 1;
++nb_flips;
#ifdef CGAL_PMP_REMESHING_VERBOSE_PROGRESS
@ -801,10 +863,10 @@ namespace internal {
(vc == target(he, mesh_) && vd == source(he, mesh_))
|| (vd == target(he, mesh_) && vc == source(he, mesh_)));
int deviation_post = CGAL::abs(valence(va) - target_valence(va))
+ CGAL::abs(valence(vb) - target_valence(vb))
+ CGAL::abs(valence(vc) - target_valence(vc))
+ CGAL::abs(valence(vd) - target_valence(vd));
int deviation_post = CGAL::abs(vva - tvva)
+ CGAL::abs(vvb - tvvb)
+ CGAL::abs(vvc - tvvc)
+ CGAL::abs(vvd - tvvd);
//check that mesh does not become non-triangle,
//nor has inverted faces
@ -988,18 +1050,7 @@ namespace internal {
continue;
//note if v is constrained, it has not moved
Patch_id_property_map pid_pmap(*this);
internal::Filtered_projection_traits<typename AABB_tree::AABB_traits,
Patch_id_property_map,
true> /* keep primitives with matching IDs */
projection_traits(
get_patch_id(face(halfedge(v, mesh_), mesh_)),
tree_ptr_->traits(),
pid_pmap
);
tree_ptr_->traversal(get(vpmap_, v), projection_traits);
CGAL_assertion(projection_traits.found());
Point proj = projection_traits.closest_point();
Point proj = trees[patch_id_to_index_map[get_patch_id(face(halfedge(v, mesh_), mesh_))]]->closest_point(get(vpmap_, v));
put(vpmap_, v, proj);
}
CGAL_assertion(is_valid(mesh_));
@ -1105,7 +1156,7 @@ private:
int target_valence(const vertex_descriptor& v) const
{
return (is_border(v, mesh_)) ? 4 : 6;
return (has_border_ && is_border(v, mesh_)) ? 4 : 6;
}
bool is_on_triangle(const halfedge_descriptor& h) const
@ -1158,6 +1209,9 @@ private:
halfedge_descriptor he = halfedge(e, mesh_);
halfedge_descriptor hopp = opposite(he, mesh_);
if (is_on_mesh(he) && is_on_mesh(hopp))
return false;
if (protect_constraints_ && is_constrained(e))
return false;
if (is_on_patch(he)) //hopp is also on patch
@ -1296,22 +1350,17 @@ private:
//move source at target
put(vpmap_, vs, get(vpmap_, vt));
//collect halfedges around vs and vt
std::vector<halfedge_descriptor> hedges;
BOOST_FOREACH(halfedge_descriptor hd,
halfedges_around_target(h, mesh_))
hedges.push_back(hd);
BOOST_FOREACH(halfedge_descriptor hd,
halfedges_around_target(opposite(h, mesh_), mesh_))
hedges.push_back(hd);
//collect normals to faces around vs AND vt
//vertices are at the same location, but connectivity is still be same,
//with plenty of degenerate triangles (which are common to both stars)
std::vector<Vector_3> normals_patch1;
std::vector<Vector_3> normals_patch2;
normals_patch1.reserve(8);
normals_patch2.reserve(8);
Patch_id patch1 = -1, patch2 = -1;
BOOST_FOREACH(halfedge_descriptor hd, hedges)
BOOST_FOREACH(halfedge_descriptor hd,
boost::range::join(halfedges_around_target(h, mesh_),
halfedges_around_target(opposite(h, mesh_), mesh_)))
{
Vector_3 n = compute_normal(face(hd, mesh_));
if (n == CGAL::NULL_VECTOR) //for degenerate faces
@ -1349,6 +1398,9 @@ private:
bool is_corner(const vertex_descriptor& v) const
{
if(! has_border_){
return false;
}
unsigned int nb_incident_features = 0;
BOOST_FOREACH(halfedge_descriptor h, halfedges_around_target(v, mesh_))
{
@ -1366,12 +1418,16 @@ private:
return CGAL::NULL_VECTOR;
halfedge_descriptor hd = halfedge(f, mesh_);
typename GeomTraits::Triangle_3
tr(get(vpmap_, target(hd, mesh_)),
get(vpmap_, target(next(hd, mesh_), mesh_)),
get(vpmap_, target(next(next(hd, mesh_), mesh_), mesh_)));
typename boost::property_traits<VertexPointMap>::reference
p = get(vpmap_, target(hd, mesh_));
hd = next(hd,mesh_);
typename boost::property_traits<VertexPointMap>::reference
q = get(vpmap_, target(hd, mesh_));
hd = next(hd,mesh_);
typename boost::property_traits<VertexPointMap>::reference
r =get(vpmap_, target(hd, mesh_));
if (tr.is_degenerate())
if (GeomTraits().collinear_3_object()(p,q,r))
return CGAL::NULL_VECTOR;
else
return PMP::compute_face_normal(f, mesh_);
@ -1422,8 +1478,10 @@ private:
BOOST_FOREACH(halfedge_descriptor h, halfedges(mesh_))
{
//being part of the border of the mesh is predominant
if (is_border(h, mesh_))
if (is_border(h, mesh_)){
set_status(h, MESH_BORDER); //erase previous value if exists
has_border_ = true;
}
}
//tag PATCH, //h and hopp belong to the patch to be remeshed
@ -1449,33 +1507,31 @@ private:
{
//deal with h and hopp for borders that are sharp edges to be preserved
halfedge_descriptor h = halfedge(e, mesh_);
if (status(h) == PATCH)
if (status(h) == PATCH){
set_status(h, PATCH_BORDER);
has_border_ = true;
}
halfedge_descriptor hopp = opposite(h, mesh_);
if (status(hopp) == PATCH)
if (status(hopp) == PATCH){
set_status(hopp, PATCH_BORDER);
has_border_ = true;
}
}
}
}
// for a Surface_mesh::Property_map we make MESH the default value
Halfedge_status status(const halfedge_descriptor& h) const
{
typename boost::unordered_map <
halfedge_descriptor, Halfedge_status >::const_iterator
it = halfedge_status_map_.find(h);
if (it == halfedge_status_map_.end())
return MESH;
return it->second;
return get(halfedge_status_pmap_,h);
}
void set_status(const halfedge_descriptor& h,
const Halfedge_status& s)
{
if (s == MESH)
halfedge_status_map_.erase(h);
else
halfedge_status_map_[h] = s;
put(halfedge_status_pmap_,h,s);
}
void merge_status(const halfedge_descriptor& en,
@ -1551,7 +1607,7 @@ private:
CGAL::Euler::flip_edge(hf, mesh_);
CGAL_assertion_code(++nb_done);
//update halfedge_status_map_
//update status
set_status(h_ab, merge_status(h_ab, hf, hfo));
set_status(h_ca, merge_status(h_ca, hf, hfo));
if (is_on_patch(h_ca) || is_on_patch_border(h_ca))
@ -1638,6 +1694,9 @@ private:
bool is_on_patch(const vertex_descriptor& v) const
{
if(! has_border_){
return true;
}
BOOST_FOREACH(halfedge_descriptor h,
halfedges_around_target(v, mesh_))
{
@ -1667,6 +1726,9 @@ public:
}
bool is_on_patch_border(const vertex_descriptor& v) const
{
if(! has_border_){
return false;
}
BOOST_FOREACH(halfedge_descriptor h, halfedges_around_target(v, mesh_))
{
if (is_on_patch_border(h) || is_on_patch_border(opposite(h, mesh_)))
@ -1698,13 +1760,16 @@ private:
void halfedge_added(const halfedge_descriptor& h,
const Halfedge_status& s)
{
halfedge_status_map_.insert(std::make_pair(h, s));
// AF: Can s be MESH?
if(s != MESH){
set_status(h, s);
}
}
void halfedge_and_opp_removed(const halfedge_descriptor& h)
{
halfedge_status_map_.erase(h);
halfedge_status_map_.erase(opposite(h, mesh_));
set_status(h,MESH);
set_status(opposite(h, mesh_),MESH);
}
std::size_t nb_valid_halfedges() const
@ -1720,15 +1785,12 @@ private:
unsigned int nb_patch = 0;
unsigned int nb_patch_border = 0;
typedef typename boost::unordered_map <
halfedge_descriptor, Halfedge_status>::value_type
HD_pair;
BOOST_FOREACH(const HD_pair& hs, halfedge_status_map_)
BOOST_FOREACH(halfedge_descriptor h, halfedges(mesh_))
{
if(is_on_patch(hs.first)) nb_patch++;
else if(is_on_patch_border(hs.first)) nb_patch_border++;
else if(is_on_mesh(hs.first)) nb_mesh++;
else if(is_on_border(hs.first)) nb_border++;
if(is_on_patch(h)) nb_patch++;
else if(is_on_patch_border(h)) nb_patch_border++;
else if(is_on_mesh(h)) nb_mesh++;
else if(is_on_border(h)) nb_border++;
else CGAL_assertion(false);
}
}
@ -1770,6 +1832,8 @@ private:
std::vector<Vector_3> normals_patch1;
std::vector<Vector_3> normals_patch2;
normals_patch1.reserve(8);
normals_patch2.reserve(8);
Patch_id patch1 = -1, patch2 = -1;
BOOST_FOREACH(halfedge_descriptor hd,
halfedges_around_target(halfedge(v, mesh_), mesh_))
@ -1841,11 +1905,14 @@ private:
private:
PolygonMesh& mesh_;
VertexPointMap& vpmap_;
const AABB_tree* tree_ptr_;
bool own_tree_;
bool build_tree_;
bool has_border_;
std::vector<AABB_tree*> trees;
Patch_id_to_index_map patch_id_to_index_map;
Triangle_list input_triangles_;
Patch_id_list input_patch_ids_;
boost::unordered_map<halfedge_descriptor, Halfedge_status> halfedge_status_map_;
Patch_id_to_index_map patch_id_to_index_map_;
Halfedge_status_pmap halfedge_status_pmap_;
bool protect_constraints_;
FacePatchMap patch_ids_map_;
EdgeIsConstrainedMap ecmap_;

View File

@ -50,14 +50,14 @@ namespace Polygon_mesh_processing {
* models of `Hashable`.
* If `PolygonMesh` has an internal property map for `CGAL::face_index_t`,
* and no `face_index_map` is given
* as a named parameter, then the internal one should be initialized
* as a named parameter, then the internal one must be initialized
* @tparam FaceRange range of `boost::graph_traits<PolygonMesh>::%face_descriptor`,
model of `Range`. Its iterator type is `ForwardIterator`.
* @tparam NamedParameters a sequence of \ref namedparameters
*
* @param pmesh a polygon mesh with triangulated surface patches to be remeshed
* @param faces the range of triangular faces defining one or several surface patches to be remeshed
* @param target_edge_length the edge length that is targetted in the remeshed patch.
* @param target_edge_length the edge length that is targeted in the remeshed patch.
* If `0` is passed then only the edge-flip, tangential relaxation, and projection steps will be done.
* @param np optional sequence of \ref namedparameters among the ones listed below
*
@ -178,11 +178,10 @@ void isotropic_remeshing(const FaceRange& faces
NamedParameters,
internal::Connected_components_pmap<PM, ECMap, FIMap>//default
> ::type FPMap;
FPMap fpmap = (boost::is_same<FPMap, internal::Connected_components_pmap<PM, ECMap, FIMap> >::value)
? choose_param(get_param(np, internal_np::face_patch),
internal::Connected_components_pmap<PM, ECMap, FIMap>(pmesh, ecmap, fimap))
: choose_param(get_param(np, internal_np::face_patch),
internal::Connected_components_pmap<PM, ECMap, FIMap>());//do not compute cc's
FPMap fpmap = choose_param(
get_param(np, internal_np::face_patch),
internal::Connected_components_pmap<PM, ECMap, FIMap>(pmesh, ecmap, fimap,
boost::is_default_param(get_param(np, internal_np::face_patch))));
double low = 4. / 5. * target_edge_length;
double high = 4. / 3. * target_edge_length;
@ -339,7 +338,7 @@ void split_long_edges(const EdgeRange& edges
remesher(pmesh, vpmap, false/*protect constraints*/
, ecmap
, internal::No_constraint_pmap<vertex_descriptor>()
, internal::Connected_components_pmap<PM, ECMap, FIMap>()
, internal::Connected_components_pmap<PM, ECMap, FIMap>(pmesh, ecmap, fimap, false)
, fimap
, false/*need aabb_tree*/);

View File

@ -70,6 +70,14 @@ if (EIGEN3_FOUND)
create_single_source_cgal_program("triangulate_hole_Polyhedron_3_test.cpp")
endif(EIGEN3_FOUND)
find_package( OpenMesh QUIET )
if ( OpenMesh_FOUND )
include( UseOpenMesh )
else()
message(STATUS "Examples that use OpenMesh will not be compiled.")
endif()
create_single_source_cgal_program("connected_component_polyhedron.cpp")
create_single_source_cgal_program("connected_component_surface_mesh.cpp")
create_single_source_cgal_program("pmp_compute_normals_test.cpp")
@ -96,3 +104,9 @@ endif(EIGEN3_FOUND)
create_single_source_cgal_program("test_pmp_clip.cpp")
create_single_source_cgal_program("triangulate_hole_polyline_test.cpp")
create_single_source_cgal_program("surface_intersection_sm_poly.cpp" )
if(OpenMesh_FOUND)
create_single_source_cgal_program("remeshing_test_P_SM_OM.cpp" )
target_link_libraries( remeshing_test_P_SM_OM ${OPENMESH_LIBRARIES} )
endif()

View File

@ -0,0 +1,80 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polyhedron_3.h>
#include <fstream>
#include <map>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/graph_traits_TriMesh_ArrayKernelT.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
namespace PMP = CGAL::Polygon_mesh_processing;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic;
int main()
{
{
typedef CGAL::Surface_mesh<typename Epic::Point_3> SM;
SM sm;
std::ifstream in("data/elephant.off");
in >> sm;
PMP::isotropic_remeshing(faces(sm),
0.02,
sm);
std::ofstream out("sm.off");
out << sm << std::endl;
}
{
typedef CGAL::Polyhedron_3<Epic> P;
std::map<boost::graph_traits<P>::face_descriptor, std::size_t> fim;
P p;
std::ifstream in("data/elephant.off");
in >> p;
PMP::isotropic_remeshing(faces(p),
0.02,
p,
PMP::parameters::face_index_map(boost::make_assoc_property_map(fim)));
std::ofstream out("p.off");
out << p << std::endl;
}
{
typedef OpenMesh::PolyMesh_ArrayKernelT</* MyTraits*/> OM;
OM om;
OpenMesh::IO::read_mesh(om, "data/elephant.off");
om.request_face_status();
om.request_edge_status();
om.request_vertex_status();
PMP::isotropic_remeshing(faces(om),
0.02,
om);
om.garbage_collection();
OpenMesh::IO::write_mesh(om, "pm.off");
}
{
typedef OpenMesh::TriMesh_ArrayKernelT</* MyTraits*/> OM;
OM om;
OpenMesh::IO::read_mesh(om, "data/elephant.off");
om.request_face_status();
om.request_edge_status();
om.request_vertex_status();
PMP::isotropic_remeshing(faces(om),
0.02,
om);
om.garbage_collection();
OpenMesh::IO::write_mesh(om, "tm.off");
}
return 0;
}

View File

@ -22,7 +22,6 @@
#include <CGAL/license/Polyhedron.h>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/Unique_hash_map.h>

View File

@ -0,0 +1,207 @@
// Copyright (c) 2007 GeometryFactory (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 Lesser 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) : Andreas Fabri
#ifndef CGAL_DYNAMIC_PROPERTY_MAP_H
#define CGAL_DYNAMIC_PROPERTY_MAP_H
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/property_map.h>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
namespace CGAL {
namespace internal {
template <typename K, typename V>
struct Dynamic_property_map {
typedef K key_type;
typedef V value_type;
typedef const value_type& reference;
typedef boost::read_write_property_map_tag category;
Dynamic_property_map(const V& default_value = V())
: map_(new Map()), default_value_(default_value)
{}
void clear()
{
if(map_){
map_->clear();
}
}
friend reference get(const Dynamic_property_map& m, const key_type& k)
{
typename Map::const_iterator it = m.map_->find(k);
if(it == m.map_->end()){
return m.default_value();
}
return it->second;
}
friend void put(Dynamic_property_map& m, const key_type& k, const value_type& v)
{
if(v != m.default_value()){
(*(m.map_))[k] = v;
}
}
const V& default_value() const
{
return default_value_;
}
typedef boost::unordered_map<K,V> Map;
boost::shared_ptr<Map> map_;
V default_value_;
};
template <typename T>
struct vertex_property_t
{
vertex_property_t(const std::string s, const T& t = T())
: s(s), t(t)
{}
std::string s;
T t;
};
template <typename T>
struct halfedge_property_t
{
halfedge_property_t(const std::string s, const T& t = T())
: s(s), t(t)
{}
std::string s;
T t;
};
template <typename T>
struct edge_property_t
{
edge_property_t(const std::string s, const T& t = T())
: s(s), t(t)
{}
std::string s;
T t;
};
template <typename T>
struct face_property_t
{
face_property_t(const std::string s, const T& t = T())
: s(s), t(t)
{}
std::string s;
T t;
};
template <typename G, typename Tag>
struct dynamic_property_map{};
template <typename G, typename T>
struct dynamic_property_map<G,vertex_property_t<T> >
{
typedef typename boost::graph_traits<G>::vertex_descriptor vertex_descriptor;
typedef CGAL::internal::Dynamic_property_map<vertex_descriptor,T> type;
typedef type const_type;
};
template <typename G, typename T>
struct dynamic_property_map<G,halfedge_property_t<T> >
{
typedef typename boost::graph_traits<G>::halfedge_descriptor halfedge_descriptor;
typedef CGAL::internal::Dynamic_property_map<halfedge_descriptor,T> type;
typedef type const_type;
};
template <typename G, typename T>
struct dynamic_property_map<G,edge_property_t<T> >
{
typedef typename boost::graph_traits<G>::edge_descriptor edge_descriptor;
typedef CGAL::internal::Dynamic_property_map<edge_descriptor,T> type;
typedef type const_type;
};
template <typename G, typename T>
struct dynamic_property_map<G,face_property_t<T> >
{
typedef typename boost::graph_traits<G>::face_descriptor face_descriptor;
typedef CGAL::internal::Dynamic_property_map<face_descriptor,T> type;
typedef type const_type;
};
template <typename T, typename G>
typename dynamic_property_map<G,vertex_property_t<T> >::const_type
add_property(vertex_property_t<T> prop, const G&)
{
typedef typename boost::graph_traits<G>::vertex_descriptor vertex_descriptor;
return internal::Dynamic_property_map<vertex_descriptor,T>(prop.t);
}
template <typename T, typename G>
typename dynamic_property_map<G,halfedge_property_t<T> >::const_type
add_property(halfedge_property_t<T> prop, const G&)
{
typedef typename boost::graph_traits<G>::halfedge_descriptor halfedge_descriptor;
return internal::Dynamic_property_map<halfedge_descriptor,T>(prop.t);
}
template <typename T, typename G>
typename dynamic_property_map<G,edge_property_t<T> >::const_type
add_property(edge_property_t<T> prop, const G&)
{
typedef typename boost::graph_traits<G>::edge_descriptor edge_descriptor;
return internal::Dynamic_property_map<edge_descriptor,T>(prop.t);
}
template <typename T, typename G>
typename dynamic_property_map<G,face_property_t<T> >::const_type
add_property(face_property_t<T> prop, const G&)
{
typedef typename boost::graph_traits<G>::face_descriptor face_descriptor;
return internal::Dynamic_property_map<face_descriptor,T>(prop.t);
}
template<class G, class T, typename Descriptor>
void remove_property(
internal::Dynamic_property_map<Descriptor, T> pm,
const G&)
{
pm.clear();
}
} // namespace internal
} // namespace CGAL
#endif // CGAL_DYNAMIC_PROPERTY_MAP_H

View File

@ -2401,16 +2401,17 @@ typename Surface_mesh<P>::size_type
Surface_mesh<P>::
degree(Vertex_index v) const
{
size_type count(0);
if(halfedge(v) == null_halfedge()){
Halfedge_index h = halfedge(v);
if(h == null_halfedge()){
return 0;
}
Vertex_around_target_circulator vvit(halfedge(v), *this);
Vertex_around_target_circulator vvend = vvit;
if(vvit) do
{
size_type count(0);
Halfedge_index done = h;
do {
++count;
} while (++vvit != vvend);
h = opposite(next(h));
}while(h != done);
return count;
}

View File

@ -85,21 +85,7 @@ public:
} // CGAL
// overloads and specializations in the boost namespace
namespace boost {
#if 1
template <typename Point, typename T>
struct property_map<CGAL::Surface_mesh<Point>, boost::vertex_property_t<T> >
{
typedef CGAL::Surface_mesh<Point> SM;
typedef typename SM:: template Property_map<typename SM::vertex_index,T> type;
typedef type const_type;
};
#endif
//
// edge_weight
//
@ -321,4 +307,84 @@ namespace boost
} //boost
namespace CGAL {
namespace internal {
template <typename Point, typename T>
struct dynamic_property_map<CGAL::Surface_mesh<Point>, vertex_property_t<T> >
{
typedef CGAL::Surface_mesh<Point> SM;
typedef typename SM:: template Property_map<typename SM::Vertex_index,T> type;
typedef type const_type;
};
template <typename Point, typename T>
struct dynamic_property_map<CGAL::Surface_mesh<Point>, face_property_t<T> >
{
typedef CGAL::Surface_mesh<Point> SM;
typedef typename SM:: template Property_map<typename SM::Face_index,T> type;
typedef type const_type;
};
template <typename Point, typename T>
struct dynamic_property_map<CGAL::Surface_mesh<Point>, halfedge_property_t<T> >
{
typedef CGAL::Surface_mesh<Point> SM;
typedef typename SM:: template Property_map<typename SM::Halfedge_index,T> type;
typedef type const_type;
};
template <typename Point, typename T>
struct dynamic_property_map<CGAL::Surface_mesh<Point>, edge_property_t<T> >
{
typedef CGAL::Surface_mesh<Point> SM;
typedef typename SM:: template Property_map<typename SM::Edge_index,T> type;
typedef type const_type;
};
template <typename Point, typename T>
typename dynamic_property_map<CGAL::Surface_mesh<Point>, vertex_property_t<T> >::const_type
add_property(vertex_property_t<T> vprop, CGAL::Surface_mesh<Point>& sm)
{
return sm.template add_property_map<typename CGAL::Surface_mesh<Point>::Vertex_index, T>(vprop.s, vprop.t).first;
}
template <typename Point, typename T>
typename dynamic_property_map<CGAL::Surface_mesh<Point>, face_property_t<T> >::const_type
add_property(face_property_t<T> vprop, CGAL::Surface_mesh<Point>& sm)
{
return sm.template add_property_map<typename CGAL::Surface_mesh<Point>::Face_index, T>(vprop.s, vprop.t).first;
}
template <typename Point, typename T>
typename dynamic_property_map<CGAL::Surface_mesh<Point>, edge_property_t<T> >::const_type
add_property(edge_property_t<T> vprop, CGAL::Surface_mesh<Point>& sm)
{
return sm.template add_property_map<typename CGAL::Surface_mesh<Point>::Edge_index, T>(vprop.s, vprop.t).first;
}
template <typename Point, typename T>
typename dynamic_property_map<CGAL::Surface_mesh<Point>, halfedge_property_t<T> >::const_type
add_property(halfedge_property_t<T> vprop, CGAL::Surface_mesh<Point>& sm)
{
return sm.template add_property_map<typename CGAL::Surface_mesh<Point>::Halfedge_index, T>(vprop.s, vprop.t).first;
}
template <typename Pmap,typename P>
void
remove_property(Pmap pm, CGAL::Surface_mesh<P>& sm)
{
return sm.remove_property_map(pm);
}
} // namespace internal
} // namespace CGAL
#endif /* CGAL_PROPERTIES_SURFACE_MESH_H */