diff --git a/BGL/include/CGAL/boost/graph/properties.h b/BGL/include/CGAL/boost/graph/properties.h index b14a7bcde6b..0f6c63e910b 100644 --- a/BGL/include/CGAL/boost/graph/properties.h +++ b/BGL/include/CGAL/boost/graph/properties.h @@ -25,10 +25,12 @@ #include #include #include +#include #include #include + /// 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 - 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 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 diff --git a/BGL/include/CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h b/BGL/include/CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h index c5e801365b0..54ce35cf2c2 100644 --- a/BGL/include/CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h +++ b/BGL/include/CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h @@ -47,27 +47,76 @@ public: typedef value_type& reference; - OM_pmap(Mesh& m) - : mesh(m) + OM_pmap() {} + + OM_pmap(Mesh& m) + : mesh(&m) + { + mesh->add_property(h); + } OM_pmap(Mesh& m, H h) - : mesh(m), h(h) - {} - - inline friend reference get(const OM_pmap& pm, key_type k) + : mesh(&m), h(h) { - return pm.mesh.property(pm.h,k); + mesh->add_property(h); + } + + inline friend reference get(const OM_pmap& pm, + typename boost::graph_traits::vertex_descriptor k) + { + return pm.mesh->property(pm.h,k); } - inline friend void put(const OM_pmap& pm, key_type k, const value_type& v) + inline friend reference get(const OM_pmap& pm, + typename boost::graph_traits::face_descriptor k) { - pm.mesh.property(pm.h,k) = v; + return pm.mesh->property(pm.h,k); + } + + inline friend reference get(const OM_pmap& pm, + typename boost::graph_traits::halfedge_descriptor k) + { + return pm.mesh->property(pm.h,k); + } + + inline friend reference get(const OM_pmap& pm, + typename boost::graph_traits::edge_descriptor k) + { + typename Mesh::EdgeHandle eh(k.idx()); + return pm.mesh->property(pm.h,eh); + } + inline friend void put(const OM_pmap& pm, + typename boost::graph_traits::vertex_descriptor k, + const value_type& v) + { + pm.mesh->property(pm.h,k) = v; + } + + inline friend void put(const OM_pmap& pm, + typename boost::graph_traits::face_descriptor k, + const value_type& v) + { + pm.mesh->property(pm.h,k) = v; + } + + inline friend void put(const OM_pmap& pm, + typename boost::graph_traits::halfedge_descriptor k, + const value_type& v) + { + pm.mesh->property(pm.h,k) = v; + } + inline friend void put(const OM_pmap& pm, + typename boost::graph_traits::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& g, +namespace CGAL { + namespace internal { +template +struct dynamic_property_map, vertex_property_t > +{ + typedef OpenMesh::PolyMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + +template +struct dynamic_property_map, halfedge_property_t > +{ + typedef OpenMesh::PolyMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + +template +struct dynamic_property_map, edge_property_t > +{ + typedef OpenMesh::PolyMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + +template +struct dynamic_property_map, face_property_t > +{ + typedef OpenMesh::PolyMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + + +template +typename dynamic_property_map, vertex_property_t >::const_type +add_property(vertex_property_t, OpenMesh::PolyMesh_ArrayKernelT& om) +{ + typedef OpenMesh::PolyMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + return CGAL::OM_pmap(om); +} + +template +typename dynamic_property_map, halfedge_property_t >::const_type +add_property(halfedge_property_t, OpenMesh::PolyMesh_ArrayKernelT& om) +{ + typedef OpenMesh::PolyMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + return CGAL::OM_pmap(om); +} + +template +typename dynamic_property_map, edge_property_t >::const_type +add_property(edge_property_t, OpenMesh::PolyMesh_ArrayKernelT& om) +{ + typedef OpenMesh::PolyMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + return CGAL::OM_pmap(om); +} + +template +typename dynamic_property_map, face_property_t >::const_type +add_property(face_property_t, OpenMesh::PolyMesh_ArrayKernelT& om) +{ + typedef OpenMesh::PolyMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + return CGAL::OM_pmap(om); +} + +template +void remove_property(Pmap pm, OpenMesh::PolyMesh_ArrayKernelT& om) +{ + om.remove_property(pm.handle()); +} +} // namespace internal +} // namespace CGAL + + #endif /* CGAL_PROPERTIES_POLYMESH_ARRAYKERNELT_H */ diff --git a/BGL/include/CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h b/BGL/include/CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h index 1c99770c8b0..e4b220cf828 100644 --- a/BGL/include/CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h +++ b/BGL/include/CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h @@ -211,4 +211,90 @@ put(boost::vertex_point_t p, OpenMesh::TriMesh_ArrayKernelT& g, + +namespace CGAL { +namespace internal { + +template +struct dynamic_property_map, vertex_property_t > +{ + typedef OpenMesh::TriMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + +template +struct dynamic_property_map, edge_property_t > +{ + typedef OpenMesh::TriMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + +template +struct dynamic_property_map, halfedge_property_t > +{ + typedef OpenMesh::TriMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + +template +struct dynamic_property_map, face_property_t > +{ + typedef OpenMesh::TriMesh_ArrayKernelT SM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef CGAL::OM_pmap type; + typedef type const_type; +}; + + + +template +typename dynamic_property_map, vertex_property_t >::const_type +add_property(vertex_property_t, OpenMesh::TriMesh_ArrayKernelT& om) +{ + typedef OpenMesh::TriMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + return CGAL::OM_pmap(om); +} + +template +typename dynamic_property_map, halfedge_property_t >::const_type +add_property(halfedge_property_t, OpenMesh::TriMesh_ArrayKernelT& om) +{ + typedef OpenMesh::TriMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + return CGAL::OM_pmap(om); +} + +template +typename dynamic_property_map, edge_property_t >::const_type +add_property(edge_property_t, OpenMesh::TriMesh_ArrayKernelT& om) +{ + typedef OpenMesh::TriMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + return CGAL::OM_pmap(om); +} + +template +typename dynamic_property_map, face_property_t >::const_type +add_property(face_property_t, OpenMesh::TriMesh_ArrayKernelT& om) +{ + typedef OpenMesh::TriMesh_ArrayKernelT OM; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + return CGAL::OM_pmap(om); +} + +template +void remove_property(Pmap pm, OpenMesh::TriMesh_ArrayKernelT& om) +{ + om.remove_property(pm.handle()); +} +} // namespace internal +} // namespace CGAL + #endif /* CGAL_PROPERTIES_TRIMESH_ARRAYKERNELT_H */ diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Collinear_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Collinear_3.h new file mode 100644 index 00000000000..b5250e8a363 --- /dev/null +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Collinear_3.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 +#include +#include +#include + +namespace CGAL { namespace internal { namespace Static_filters_predicates { + + +#include + + +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 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 diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h index be4f4912b05..59c87955863 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_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 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. diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h index 336bc5a9cc6..01486477b25 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Static_filters.h @@ -37,6 +37,7 @@ #include #include #include +#include // 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 Orientation_2; typedef Static_filters_predicates::Orientation_3 Orientation_3; #ifndef CGAL_NO_ANGLE_3_STATIC_FILTERS + + typedef Static_filters_predicates::Collinear_3 Collinear_3; + typedef Static_filters_predicates::Angle_3 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 diff --git a/Kernel_23/include/CGAL/Kernel/interface_macros.h b/Kernel_23/include/CGAL/Kernel/interface_macros.h index 329573d08f7..3890b31f67a 100644 --- a/Kernel_23/include/CGAL/Kernel/interface_macros.h +++ b/Kernel_23/include/CGAL/Kernel/interface_macros.h @@ -108,10 +108,10 @@ 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, - collinear_2_object) -CGAL_Kernel_pred(Collinear_3, - collinear_3_object) +CGAL_Kernel_pred_RT(Collinear_2, + collinear_2_object) +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) CGAL_Kernel_pred(Compare_dihedral_angle_3, @@ -548,8 +548,8 @@ CGAL_Kernel_cons(Intersect_3, intersect_3_object) CGAL_Kernel_pred(Is_degenerate_2, is_degenerate_2_object) -CGAL_Kernel_pred(Is_degenerate_3, - is_degenerate_3_object) +CGAL_Kernel_pred_RT(Is_degenerate_3, + is_degenerate_3_object) CGAL_Kernel_pred(Is_horizontal_2, is_horizontal_2_object) CGAL_Kernel_pred(Is_vertical_2, diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 1a433b94520..92d8f80d1ae 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -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" ) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp new file mode 100644 index 00000000000..70bcdcb452d --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp @@ -0,0 +1,79 @@ +#include +#include + +#include +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Surface_mesh Mesh; + +typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; +typedef boost::graph_traits::edge_descriptor edge_descriptor; +typedef boost::graph_traits::face_descriptor face_descriptor; + +namespace PMP = CGAL::Polygon_mesh_processing; + +struct halfedge2edge +{ + halfedge2edge(const Mesh& m, std::vector& 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& 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 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 seed, patch; + Mesh::Property_map selected + = mesh.add_property_map("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; +} diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h index 1cc413af89d..fd3f765bbf0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h @@ -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 #include -#include - #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -155,6 +157,7 @@ namespace internal { } }; + template @@ -166,7 +169,9 @@ namespace internal { typedef EdgeIsConstrainedMap ECMap; typedef Connected_components_pmap CCMap; - boost::unordered_map patch_ids_map; + typedef CGAL::internal::face_property_t Face_property_tag; + typename CGAL::internal::dynamic_property_map::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), - PMP::parameters::edge_is_constrained_map(ecmap) - .face_index_map(fimap)); + 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::value_type Patch_id; typedef std::vector Triangle_list; typedef std::vector Patch_id_list; + typedef std::map Patch_id_to_index_map; typedef CGAL::AABB_triangle_primitive AABB_primitive; typedef CGAL::AABB_traits AABB_traits; typedef CGAL::AABB_tree AABB_tree; + typedef typename CGAL::internal::dynamic_property_map< + PM, CGAL::internal::halfedge_property_t >::type Halfedge_status_pmap; + public: Incremental_remesher(PolygonMesh& pmesh , VertexPointMap& vpmap @@ -277,28 +295,46 @@ 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("PMP_halfedge_status", MESH), + pmesh); CGAL_assertion(CGAL::is_triangle_mesh(mesh_)); } ~Incremental_remesher() { - if (own_tree_) - delete tree_ptr_; + typedef Connected_components_pmap CCPmap; + remove_connected_components_pmap + (CGAL::Boolean_tag::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 void init_remeshing(const FaceRange& face_range) { @@ -308,18 +344,40 @@ 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 + 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 void split_long_edges(const EdgeRange& edge_range, @@ -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 /* 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 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 normals_patch1; std::vector 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_))); - - if (tr.is_degenerate()) + typename boost::property_traits::reference + p = get(vpmap_, target(hd, mesh_)); + hd = next(hd,mesh_); + typename boost::property_traits::reference + q = get(vpmap_, target(hd, mesh_)); + hd = next(hd,mesh_); + typename boost::property_traits::reference + r =get(vpmap_, target(hd, mesh_)); + + 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 normals_patch1; std::vector 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 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_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_; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h index ee47c1a10a6..872134089b8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h @@ -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::%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//default > ::type FPMap; - FPMap fpmap = (boost::is_same >::value) - ? choose_param(get_param(np, internal_np::face_patch), - internal::Connected_components_pmap(pmesh, ecmap, fimap)) - : choose_param(get_param(np, internal_np::face_patch), - internal::Connected_components_pmap());//do not compute cc's + FPMap fpmap = choose_param( + get_param(np, internal_np::face_patch), + internal::Connected_components_pmap(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() - , internal::Connected_components_pmap() + , internal::Connected_components_pmap(pmesh, ecmap, fimap, false) , fimap , false/*need aabb_tree*/); diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 8e937792647..22365eb495a 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -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() + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/remeshing_test_P_SM_OM.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/remeshing_test_P_SM_OM.cpp new file mode 100644 index 00000000000..ac90d328eae --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/remeshing_test_P_SM_OM.cpp @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace PMP = CGAL::Polygon_mesh_processing; + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic; + + +int main() +{ + { + typedef CGAL::Surface_mesh 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 P; + std::map::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 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 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; +} diff --git a/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3.h b/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3.h index 8fa5295751d..a6f9b188415 100644 --- a/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3.h +++ b/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3.h @@ -22,7 +22,6 @@ #include - #include #include #include diff --git a/Property_map/include/CGAL/Dynamic_property_map.h b/Property_map/include/CGAL/Dynamic_property_map.h new file mode 100644 index 00000000000..fd45e0a3a22 --- /dev/null +++ b/Property_map/include/CGAL/Dynamic_property_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 +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +template +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 Map; + boost::shared_ptr map_; + V default_value_; +}; + +template +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 +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 +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 +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 +struct dynamic_property_map{}; + +template +struct dynamic_property_map > +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef CGAL::internal::Dynamic_property_map type; + typedef type const_type; +}; + +template +struct dynamic_property_map > +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef CGAL::internal::Dynamic_property_map type; + typedef type const_type; +}; + + +template +struct dynamic_property_map > +{ + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef CGAL::internal::Dynamic_property_map type; + typedef type const_type; +}; + +template +struct dynamic_property_map > +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef CGAL::internal::Dynamic_property_map type; + typedef type const_type; +}; + + + +template +typename dynamic_property_map >::const_type +add_property(vertex_property_t prop, const G&) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + return internal::Dynamic_property_map(prop.t); +} + +template +typename dynamic_property_map >::const_type +add_property(halfedge_property_t prop, const G&) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + return internal::Dynamic_property_map(prop.t); +} + +template +typename dynamic_property_map >::const_type +add_property(edge_property_t prop, const G&) +{ + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + return internal::Dynamic_property_map(prop.t); +} + +template +typename dynamic_property_map >::const_type +add_property(face_property_t prop, const G&) +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + return internal::Dynamic_property_map(prop.t); +} + +template +void remove_property( + internal::Dynamic_property_map pm, + const G&) +{ + pm.clear(); +} + + + +} // namespace internal +} // namespace CGAL + +#endif // CGAL_DYNAMIC_PROPERTY_MAP_H diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 176fc819b73..5321c329182 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -2401,16 +2401,17 @@ typename Surface_mesh

::size_type Surface_mesh

:: 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 - { - ++count; - } while (++vvit != vvend); + size_type count(0); + Halfedge_index done = h; + do { + ++count; + h = opposite(next(h)); + }while(h != done); return count; } diff --git a/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh.h b/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh.h index 19424635350..7b486040eaa 100644 --- a/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh.h +++ b/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh.h @@ -85,21 +85,7 @@ public: } // CGAL -// overloads and specializations in the boost namespace namespace boost { -#if 1 -template -struct property_map, boost::vertex_property_t > -{ - typedef CGAL::Surface_mesh SM; - typedef typename SM:: template Property_map type; - typedef type const_type; -}; - - -#endif - - // // edge_weight // @@ -321,4 +307,84 @@ namespace boost } //boost + + +namespace CGAL { + +namespace internal { + +template +struct dynamic_property_map, vertex_property_t > +{ + typedef CGAL::Surface_mesh SM; + typedef typename SM:: template Property_map type; + typedef type const_type; +}; + +template +struct dynamic_property_map, face_property_t > +{ + typedef CGAL::Surface_mesh SM; + typedef typename SM:: template Property_map type; + typedef type const_type; +}; + +template +struct dynamic_property_map, halfedge_property_t > +{ + typedef CGAL::Surface_mesh SM; + typedef typename SM:: template Property_map type; + typedef type const_type; +}; + +template +struct dynamic_property_map, edge_property_t > +{ + typedef CGAL::Surface_mesh SM; + typedef typename SM:: template Property_map type; + typedef type const_type; +}; + + +template +typename dynamic_property_map, vertex_property_t >::const_type +add_property(vertex_property_t vprop, CGAL::Surface_mesh& sm) +{ + return sm.template add_property_map::Vertex_index, T>(vprop.s, vprop.t).first; +} + +template +typename dynamic_property_map, face_property_t >::const_type +add_property(face_property_t vprop, CGAL::Surface_mesh& sm) +{ + return sm.template add_property_map::Face_index, T>(vprop.s, vprop.t).first; +} + +template +typename dynamic_property_map, edge_property_t >::const_type +add_property(edge_property_t vprop, CGAL::Surface_mesh& sm) +{ + return sm.template add_property_map::Edge_index, T>(vprop.s, vprop.t).first; +} + +template +typename dynamic_property_map, halfedge_property_t >::const_type +add_property(halfedge_property_t vprop, CGAL::Surface_mesh& sm) +{ + return sm.template add_property_map::Halfedge_index, T>(vprop.s, vprop.t).first; +} + +template +void +remove_property(Pmap pm, CGAL::Surface_mesh

& sm) +{ + return sm.remove_property_map(pm); +} + +} // namespace internal + +} // namespace CGAL + + + #endif /* CGAL_PROPERTIES_SURFACE_MESH_H */