mirror of https://github.com/CGAL/cgal
Merge pull request #2136 from afabri/Polygon_mesh_processing-accelerate_isotropic_remeshing-GF
Polygon_mesh_processing: Accelerate Isotropic_remeshing
This commit is contained in:
commit
f8760d591b
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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" )
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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*/);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue