From 4351ecfb5eb18d231586b95d8e5cba30390bb79d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 30 Sep 2019 12:51:00 +0200 Subject: [PATCH 01/18] Add test for bench --- .../Bounded_distance_placement.h | 4 + .../test_edge_collapse_bounded_distance.cpp | 149 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h create mode 100644 Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h new file mode 100644 index 00000000000..e742d37f13e --- /dev/null +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -0,0 +1,4 @@ +#ifndef BOUNDED_DISTANCE_PLACEMENT_H +#define BOUNDED_DISTANCE_PLACEMENT_H + +#endif // BOUNDED_DISTANCE_PLACEMENT_H diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp new file mode 100644 index 00000000000..b1083f387f1 --- /dev/null +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -0,0 +1,149 @@ +#include +#include + +#include +#include + +// Simplification function +#include +#include +#include +#include + +//AABB_tree +#include +#include +#include + +//Timer +#include + +//filter{ + +typedef CGAL::Simple_cartesian Kernel; +typedef CGAL::Surface_mesh Surface; + +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; + +namespace SMS = CGAL::Surface_mesh_simplification ; + +namespace CGAL { + +namespace Surface_mesh_simplification +{ + +template +class Bounded_distance_placement +{ +public: + + typedef typename Placement::TM TM ; + +public: + + Bounded_distance_placement(const double sq_dist, + const Tree& tree, + const Placement& placement = Placement() ) + : mPlacement(placement), tree(tree), threshold_sq_dist(sq_dist) + { + } + + template + boost::optional + operator()( Profile const& aProfile) const + { + boost::optional op = mPlacement(aProfile); + typedef typename Profile::Point Point; + if(op){ + const Point* p = boost::get(&op); + if(tree.squared_distance(*p) > threshold_sq_dist){ + return boost::none; + } + } + return op; + } + +private: + + Placement mPlacement ; + const Tree& tree; + double threshold_sq_dist; + +}; +} +} +//} end filter + + + +int main( int argc, char** argv ) +{ + Surface surface_mesh; + std::ifstream is(argc > 1 ? argv[1] : "input.off"); + is >> surface_mesh; + // This is a stop predicate (defines when the algorithm terminates). + // In this example, the simplification stops when the number of undirected edges + // left in the surface mesh drops below the specified number (1000) + SMS::Count_stop_predicate stop(num_halfedges(surface_mesh)/10); + + typedef SMS::Bounded_distance_placement, Tree > Filtered_placement; + typedef SMS::LindstromTurk_placement Placement; + double copy_time, tree_time, placement1_time, placement2_time; + + std::cout<<"input has "<()) + .get_placement(placement2) + ); + timer.stop(); + placement2_time=timer.time(); + timer.reset(); + timer.start(); + SMS::edge_collapse( copy_mesh, + stop, + CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) + .get_placement(placement1) + ); + timer.stop(); + placement1_time=timer.time(); + surface_mesh.collect_garbage(); + copy_mesh.collect_garbage(); + std::cout<<"Filtered placement total time = "< Date: Mon, 30 Sep 2019 13:09:18 +0200 Subject: [PATCH 02/18] WIP waiting for the missing intersections --- .../test_edge_collapse_bounded_distance.cpp | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index b1083f387f1..22726ae3afe 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -15,10 +15,11 @@ #include #include + //Timer #include - //filter{ +#include typedef CGAL::Simple_cartesian Kernel; typedef CGAL::Surface_mesh Surface; @@ -34,7 +35,7 @@ namespace CGAL { namespace Surface_mesh_simplification { -template +template class Bounded_distance_placement { public: @@ -44,9 +45,8 @@ public: public: Bounded_distance_placement(const double sq_dist, - const Tree& tree, const Placement& placement = Placement() ) - : mPlacement(placement), tree(tree), threshold_sq_dist(sq_dist) + : mPlacement(placement), threshold_sq_dist(sq_dist) { } @@ -58,17 +58,35 @@ public: typedef typename Profile::Point Point; if(op){ const Point* p = boost::get(&op); - if(tree.squared_distance(*p) > threshold_sq_dist){ + const typename Profile::Triangle_vector& triangles = aProfile.triangles(); + typename Profile::Triangle_vector::const_iterator it = triangles.begin(); + bool does_intersect = false; + CGAL::Sphere_3 s(*p, threshold_sq_dist); + if(aProfile.left_face_exists()){ + ++it; + } + if(aProfile.right_face_exists()){ + ++it; + } + while(it!= triangles.end()){ + typename Profile::Triangle t = *it; + if(CGAL::do_intersect(t, s)){ + does_intersect = true; + break; + } + } + if(!does_intersect) + { return boost::none; } } return op; } + private: Placement mPlacement ; - const Tree& tree; double threshold_sq_dist; }; @@ -88,9 +106,9 @@ int main( int argc, char** argv ) // left in the surface mesh drops below the specified number (1000) SMS::Count_stop_predicate stop(num_halfedges(surface_mesh)/10); - typedef SMS::Bounded_distance_placement, Tree > Filtered_placement; + typedef SMS::Bounded_distance_placement > Filtered_placement; typedef SMS::LindstromTurk_placement Placement; - double copy_time, tree_time, placement1_time, placement2_time; + double placement1_time, placement2_time; std::cout<<"input has "< Date: Mon, 30 Sep 2019 13:37:18 +0200 Subject: [PATCH 03/18] Add Policy for bounded distance placement --- .../Bounded_distance_placement.h | 92 ++++++++++++++++++- .../test_edge_collapse_bounded_distance.cpp | 80 +--------------- 2 files changed, 94 insertions(+), 78 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index e742d37f13e..dddd601bf65 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -1,4 +1,90 @@ -#ifndef BOUNDED_DISTANCE_PLACEMENT_H -#define BOUNDED_DISTANCE_PLACEMENT_H +// Copyright (c) 2017 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 +// 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// Author(s) : Andreas Fabri +// +#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H +#define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H + +#include +#include +#include + +namespace CGAL { + +namespace Surface_mesh_simplification +{ + +template +class Bounded_distance_placement +{ +public: + + typedef typename Placement::TM TM ; + +public: + + Bounded_distance_placement(const double sq_dist, + const Placement& placement = Placement() ) + : mPlacement(placement), threshold_sq_dist(sq_dist) + { + } + + template + boost::optional + operator()( Profile const& aProfile) const + { + boost::optional op = mPlacement(aProfile); + typedef typename Profile::Point Point; + typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; + if(op){ + const Point* p = boost::get(&op); + const typename Profile::Triangle_vector& triangles = aProfile.triangles(); + typename Profile::Triangle_vector::const_iterator it = triangles.begin(); + typename Profile::VertexPointMap ppmap = aProfile.vertex_point_map(); + + bool does_intersect = false; + CGAL::Sphere_3 s(*p, threshold_sq_dist); + while(it!= triangles.end()){ + typename Kernel::Triangle_3 t(get(ppmap, it->v0), get(ppmap, it->v1), get(ppmap, it->v2)); + if(CGAL::do_intersect(t, s)){ + does_intersect = true; + break; + } + ++it; + } + if(!does_intersect) + { + return boost::none; + } + } + return op; + } + + +private: + + Placement mPlacement ; + double threshold_sq_dist; + +}; +} +} + +#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H + -#endif // BOUNDED_DISTANCE_PLACEMENT_H diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 22726ae3afe..1dab340de47 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -19,82 +19,12 @@ //Timer #include //filter{ -#include - -typedef CGAL::Simple_cartesian Kernel; -typedef CGAL::Surface_mesh Surface; - -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Traits; -typedef CGAL::AABB_tree Tree; - -namespace SMS = CGAL::Surface_mesh_simplification ; - -namespace CGAL { - -namespace Surface_mesh_simplification -{ - -template -class Bounded_distance_placement -{ -public: - - typedef typename Placement::TM TM ; - -public: - - Bounded_distance_placement(const double sq_dist, - const Placement& placement = Placement() ) - : mPlacement(placement), threshold_sq_dist(sq_dist) - { - } - - template - boost::optional - operator()( Profile const& aProfile) const - { - boost::optional op = mPlacement(aProfile); - typedef typename Profile::Point Point; - if(op){ - const Point* p = boost::get(&op); - const typename Profile::Triangle_vector& triangles = aProfile.triangles(); - typename Profile::Triangle_vector::const_iterator it = triangles.begin(); - bool does_intersect = false; - CGAL::Sphere_3 s(*p, threshold_sq_dist); - if(aProfile.left_face_exists()){ - ++it; - } - if(aProfile.right_face_exists()){ - ++it; - } - while(it!= triangles.end()){ - typename Profile::Triangle t = *it; - if(CGAL::do_intersect(t, s)){ - does_intersect = true; - break; - } - } - if(!does_intersect) - { - return boost::none; - } - } - return op; - } - - -private: - - Placement mPlacement ; - double threshold_sq_dist; - -}; -} -} +#include //} end filter - +namespace SMS = CGAL::Surface_mesh_simplification ; +typedef CGAL::Simple_cartesian Kernel; +typedef CGAL::Surface_mesh Surface; int main( int argc, char** argv ) { @@ -141,7 +71,7 @@ int main( int argc, char** argv ) placement1_time=timer.time(); surface_mesh.collect_garbage(); copy_mesh.collect_garbage(); - std::cout<<"Filtered placement total time = "< Date: Mon, 30 Sep 2019 14:18:45 +0200 Subject: [PATCH 04/18] Update --- .../Bounded_distance_placement.h | 34 +++---- .../test_edge_collapse_bounded_distance.cpp | 99 ++++++++++--------- 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index dddd601bf65..c2b7ab08750 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017 GeometryFactory (France). All rights reserved. +// Copyright (c) 2019 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 @@ -15,7 +15,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0+ // -// Author(s) : Andreas Fabri +// Author(s) : Maxime Gimeno // #ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H @@ -29,7 +29,7 @@ namespace CGAL { namespace Surface_mesh_simplification { -template +template class Bounded_distance_placement { public: @@ -38,9 +38,10 @@ public: public: - Bounded_distance_placement(const double sq_dist, + Bounded_distance_placement(const double dist, + const Tree& tree, const Placement& placement = Placement() ) - : mPlacement(placement), threshold_sq_dist(sq_dist) + : mPlacement(placement), tree(tree), threshold_dist(dist) { } @@ -53,24 +54,12 @@ public: typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; if(op){ const Point* p = boost::get(&op); - const typename Profile::Triangle_vector& triangles = aProfile.triangles(); - typename Profile::Triangle_vector::const_iterator it = triangles.begin(); - typename Profile::VertexPointMap ppmap = aProfile.vertex_point_map(); - bool does_intersect = false; - CGAL::Sphere_3 s(*p, threshold_sq_dist); - while(it!= triangles.end()){ - typename Kernel::Triangle_3 t(get(ppmap, it->v0), get(ppmap, it->v1), get(ppmap, it->v2)); - if(CGAL::do_intersect(t, s)){ - does_intersect = true; - break; - } - ++it; - } - if(!does_intersect) - { - return boost::none; + + if(tree.do_intersect(CGAL::Sphere_3(*p, threshold_dist*threshold_dist))){ + return op; } + return boost::none; } return op; } @@ -79,7 +68,8 @@ public: private: Placement mPlacement ; - double threshold_sq_dist; + const Tree& tree; + double threshold_dist; }; } diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 1dab340de47..3dc39895ec1 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -15,72 +15,79 @@ #include #include +//bbox +#include + //Timer -#include -//filter{ +//#include #include -//} end filter namespace SMS = CGAL::Surface_mesh_simplification ; typedef CGAL::Simple_cartesian Kernel; typedef CGAL::Surface_mesh Surface; + +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; + + int main( int argc, char** argv ) { - Surface surface_mesh; - std::ifstream is(argc > 1 ? argv[1] : "input.off"); - is >> surface_mesh; - // This is a stop predicate (defines when the algorithm terminates). - // In this example, the simplification stops when the number of undirected edges - // left in the surface mesh drops below the specified number (1000) - SMS::Count_stop_predicate stop(num_halfedges(surface_mesh)/10); + Surface ref_mesh; + std::ifstream is(argc > 1 ? argv[1] : "data/helmet.off"); + is >> ref_mesh; - typedef SMS::Bounded_distance_placement > Filtered_placement; + SMS::Count_stop_predicate stop(num_halfedges(ref_mesh)/10); + + typedef SMS::Bounded_distance_placement, Tree> Filtered_placement; typedef SMS::LindstromTurk_placement Placement; - double placement1_time, placement2_time; + //double placement1_time, placement2_time, tree_time; - std::cout<<"input has "< bbox(CGAL::Polygon_mesh_processing::bbox(ref_mesh)); - SMS::edge_collapse( surface_mesh, + + Kernel::Point_3 cmin = (bbox.min)(); + Kernel::Point_3 cmax = (bbox.max)(); + double diag = std::sqrt(CGAL::squared_distance(cmin,cmax)); + + Surface small_mesh = ref_mesh; + Surface big_mesh = ref_mesh; + Tree tree( faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); + + Placement placement_ref; + Filtered_placement placement_small(0.00005*diag, tree, placement_ref); + Filtered_placement placement_big(50*diag, tree, placement_ref); + + SMS::edge_collapse( small_mesh, stop, CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement2) + .get_placement(placement_small) ); - timer.stop(); - placement2_time=timer.time(); - timer.reset(); - timer.start(); - SMS::edge_collapse( copy_mesh, + + SMS::edge_collapse( big_mesh, stop, CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement1) + .get_placement(placement_big) ); - timer.stop(); - placement1_time=timer.time(); - surface_mesh.collect_garbage(); - copy_mesh.collect_garbage(); - std::cout<<"Filtered placement time = "<()) + .get_placement(placement_ref) + ); + + ref_mesh.collect_garbage(); + small_mesh.collect_garbage(); + big_mesh.collect_garbage(); + //std::cout<<"Filtered placement time = "< Date: Mon, 30 Sep 2019 18:18:06 +0200 Subject: [PATCH 05/18] do an initial try with the closest point since do_intersect is with a sphere and not a ball --- .../Edge_collapse/Bounded_distance_placement.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index c2b7ab08750..35d1dec66db 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -53,10 +53,24 @@ public: typedef typename Profile::Point Point; typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; if(op){ + + CGAL_assertion(!tree.empty()); + const Point* p = boost::get(&op); + tree.accelerate_distance_queries(); + Point cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. + // We could do better by having access to the internal kd-tree + // and call search_any_point with a fuzzy_sphere. - if(tree.do_intersect(CGAL::Sphere_3(*p, threshold_dist*threshold_dist))){ + const double sqtd = threshold_dist*threshold_dist; + + // if no input vertex is closer than the threshold, then + // any face closer than the threshold is intersected by + // the sphere (avoid the inclusion of the mesh into the threshold sphere) + if( CGAL::compare_squared_distance(*p,cp, sqtd)!=LARGER || + tree.do_intersect(CGAL::Sphere_3(*p, sqtd))) + { return op; } return boost::none; From 32e78834eb6d6a41abbda1d4da5753b73ab80bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:21:52 +0100 Subject: [PATCH 06/18] Clean header --- .../Bounded_distance_placement.h | 77 ++++++++----------- 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 35d1dec66db..f71f4aaa10e 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -1,19 +1,10 @@ // Copyright (c) 2019 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 -// 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$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Maxime Gimeno // @@ -21,74 +12,68 @@ #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #include + +#include + #include -#include namespace CGAL { - -namespace Surface_mesh_simplification -{ +namespace Surface_mesh_simplification { template class Bounded_distance_placement { public: - - typedef typename Placement::TM TM ; + typedef typename Placement::TM TM; public: - Bounded_distance_placement(const double dist, - const Tree& tree, - const Placement& placement = Placement() ) - : mPlacement(placement), tree(tree), threshold_dist(dist) - { - } + const Tree& tree, + const Placement& placement = Placement()) + : m_get_placement(placement), m_tree(tree), m_(dist) + { } template boost::optional - operator()( Profile const& aProfile) const + operator()(const Profile& profile) const { - boost::optional op = mPlacement(aProfile); - typedef typename Profile::Point Point; + typedef typename Profile::Point Point; typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; - if(op){ + boost::optional op = m_get_placement(profile); + if(op) + { CGAL_assertion(!tree.empty()); - const Point* p = boost::get(&op); + const Point& p = *op; tree.accelerate_distance_queries(); - Point cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. - // We could do better by having access to the internal kd-tree - // and call search_any_point with a fuzzy_sphere. + const Point& cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. - const double sqtd = threshold_dist*threshold_dist; + // We could do better by having access to the internal kd-tree + // and call search_any_point with a fuzzy_sphere. + const double sqtd = CGAL::square(m_threshold_dist); // if no input vertex is closer than the threshold, then // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) - if( CGAL::compare_squared_distance(*p,cp, sqtd)!=LARGER || - tree.do_intersect(CGAL::Sphere_3(*p, sqtd))) - { + if(CGAL::compare_squared_distance(p, cp, sqtd) != LARGER || + tree.do_intersect(CGAL::Sphere_3(p, sqtd))) return op; - } - return boost::none; + + return boost::optional(); } + return op; } - private: - - Placement mPlacement ; - const Tree& tree; - double threshold_dist; - + const Placement m_get_placement; + const Tree& m_tree; + const double m_threshold_dist; }; -} -} + +} // namespace Surface_mesh_simplification +} // namespace CGAL #endif // CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H - - From 8c26549b65c04d8f6e04741e350cf6007228c228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:22:00 +0100 Subject: [PATCH 07/18] Clean test --- .../test_edge_collapse_bounded_distance.cpp | 76 +++++++------------ 1 file changed, 26 insertions(+), 50 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 3dc39895ec1..17700dd0156 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -1,11 +1,9 @@ -#include -#include - #include #include // Simplification function #include +#include #include #include #include @@ -18,22 +16,24 @@ //bbox #include +#include +#include -//Timer -//#include -#include +namespace SMS = CGAL::Surface_mesh_simplification; -namespace SMS = CGAL::Surface_mesh_simplification ; -typedef CGAL::Simple_cartesian Kernel; -typedef CGAL::Surface_mesh Surface; +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point_3; +typedef CGAL::Surface_mesh Surface; +typedef CGAL::AABB_face_graph_triangle_primitive Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Traits; -typedef CGAL::AABB_tree Tree; +typedef SMS::LindstromTurk_cost Cost; +typedef SMS::LindstromTurk_placement Placement; +typedef SMS::Bounded_distance_placement Filtered_placement; - -int main( int argc, char** argv ) +int main(int argc, char** argv) { Surface ref_mesh; std::ifstream is(argc > 1 ? argv[1] : "data/helmet.off"); @@ -41,54 +41,30 @@ int main( int argc, char** argv ) SMS::Count_stop_predicate stop(num_halfedges(ref_mesh)/10); - typedef SMS::Bounded_distance_placement, Tree> Filtered_placement; - typedef SMS::LindstromTurk_placement Placement; - //double placement1_time, placement2_time, tree_time; - - //std::cout<<"input has "< bbox(CGAL::Polygon_mesh_processing::bbox(ref_mesh)); - - Kernel::Point_3 cmin = (bbox.min)(); - Kernel::Point_3 cmax = (bbox.max)(); - double diag = std::sqrt(CGAL::squared_distance(cmin,cmax)); + Point_3 cmin = (bbox.min)(); + Point_3 cmax = (bbox.max)(); + const double diag = std::sqrt(CGAL::squared_distance(cmin, cmax)); Surface small_mesh = ref_mesh; Surface big_mesh = ref_mesh; - Tree tree( faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); + Tree tree(faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); Placement placement_ref; Filtered_placement placement_small(0.00005*diag, tree, placement_ref); Filtered_placement placement_big(50*diag, tree, placement_ref); - SMS::edge_collapse( small_mesh, - stop, - CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement_small) - ); + SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); + SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); + SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); - SMS::edge_collapse( big_mesh, - stop, - CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement_big) - ); + std::cout << "There are " << num_vertices(surface_mesh) << " vertices left when filtered" + << " and " << num_vertices(copy_mesh) << " when not filtered." << std::endl; - SMS::edge_collapse( ref_mesh, - stop, - CGAL::parameters::get_cost (SMS::LindstromTurk_cost()) - .get_placement(placement_ref) - ); - - ref_mesh.collect_garbage(); - small_mesh.collect_garbage(); - big_mesh.collect_garbage(); - //std::cout<<"Filtered placement time = "< Date: Thu, 2 Jan 2020 15:26:19 +0100 Subject: [PATCH 08/18] Fix compilation / test --- .../Edge_collapse/Bounded_distance_placement.h | 10 +++++----- .../test_edge_collapse_bounded_distance.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index f71f4aaa10e..d022a007790 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -30,7 +30,7 @@ public: Bounded_distance_placement(const double dist, const Tree& tree, const Placement& placement = Placement()) - : m_get_placement(placement), m_tree(tree), m_(dist) + : m_get_placement(placement), m_tree(tree), m_threshold_dist(dist) { } template @@ -43,12 +43,12 @@ public: boost::optional op = m_get_placement(profile); if(op) { - CGAL_assertion(!tree.empty()); + CGAL_assertion(!m_tree.empty()); const Point& p = *op; - tree.accelerate_distance_queries(); - const Point& cp = tree.best_hint(*p).first; // requires accelerate distance query to be called. + m_tree.accelerate_distance_queries(); + const Point& cp = m_tree.best_hint(p).first; // requires accelerate distance query to be called. // We could do better by having access to the internal kd-tree // and call search_any_point with a fuzzy_sphere. @@ -58,7 +58,7 @@ public: // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) if(CGAL::compare_squared_distance(p, cp, sqtd) != LARGER || - tree.do_intersect(CGAL::Sphere_3(p, sqtd))) + m_tree.do_intersect(CGAL::Sphere_3(p, sqtd))) return op; return boost::optional(); diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 17700dd0156..e946d6b8a1b 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -57,14 +57,14 @@ int main(int argc, char** argv) Filtered_placement placement_big(50*diag, tree, placement_ref); SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); - SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); + SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); - std::cout << "There are " << num_vertices(surface_mesh) << " vertices left when filtered" - << " and " << num_vertices(copy_mesh) << " when not filtered." << std::endl; + std::cout << "There are " << vertices(small_mesh).size() << " vertices left when filtered" + << " and " << num_vertices(big_mesh) << " when not filtered." << std::endl; - assert(vertices(big_mesh).size() == vertices(ref_mesh).size()); assert(vertices(small_mesh).size() != vertices(ref_mesh).size()); + assert(vertices(big_mesh).size() == vertices(ref_mesh).size()); return EXIT_SUCCESS; } From 5ab92fef26f3ff1a112e7590bacb45a98398427e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:46:11 +0100 Subject: [PATCH 09/18] Keep the squared value in memory instead of recomputing it on every call --- .../Policies/Edge_collapse/Bounded_distance_placement.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index d022a007790..130c66edc31 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -30,7 +30,7 @@ public: Bounded_distance_placement(const double dist, const Tree& tree, const Placement& placement = Placement()) - : m_get_placement(placement), m_tree(tree), m_threshold_dist(dist) + : m_get_placement(placement), m_tree(tree), m_sq_threshold_dist(CGAL::square(dist)) { } template @@ -52,13 +52,12 @@ public: // We could do better by having access to the internal kd-tree // and call search_any_point with a fuzzy_sphere. - const double sqtd = CGAL::square(m_threshold_dist); // if no input vertex is closer than the threshold, then // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) - if(CGAL::compare_squared_distance(p, cp, sqtd) != LARGER || - m_tree.do_intersect(CGAL::Sphere_3(p, sqtd))) + if(CGAL::compare_squared_distance(p, cp, m_sq_threshold_dist) != LARGER || + m_tree.do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) return op; return boost::optional(); @@ -70,7 +69,7 @@ public: private: const Placement m_get_placement; const Tree& m_tree; - const double m_threshold_dist; + const double m_sq_threshold_dist; }; } // namespace Surface_mesh_simplification From 1ee8e7b83847160c6ef78acdb8f137d9dc2a918b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 2 Jan 2020 15:46:29 +0100 Subject: [PATCH 10/18] Better output in the test --- .../test_edge_collapse_bounded_distance.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index e946d6b8a1b..77fbd23589c 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -60,8 +60,9 @@ int main(int argc, char** argv) SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); - std::cout << "There are " << vertices(small_mesh).size() << " vertices left when filtered" - << " and " << num_vertices(big_mesh) << " when not filtered." << std::endl; + std::cout << "no filtering: " << vertices(ref_mesh).size() << " vertices left" << std::endl; + std::cout << "large filtering distance: " << vertices(big_mesh).size() << " vertices left" << std::endl; + std::cout << "small filtering distance: " << vertices(small_mesh).size() << " vertices left" << std::endl; assert(vertices(small_mesh).size() != vertices(ref_mesh).size()); assert(vertices(big_mesh).size() == vertices(ref_mesh).size()); From 46e7a8f930f34b79bbb086a72183ffcb54434d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 13:54:45 +0100 Subject: [PATCH 11/18] Make it optional to pass the AABB tree --- .../Bounded_distance_placement.h | 140 ++++++++++++++++-- 1 file changed, 124 insertions(+), 16 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 130c66edc31..904492f56ff 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -6,49 +6,105 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Maxime Gimeno +// Author(s) : Maxime Gimeno, +// Mael Rouxel-Labbé // #ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #define CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H #include +#include +#include +#include +#include +#include #include +#include #include namespace CGAL { namespace Surface_mesh_simplification { -template +// An AABB tree can also be passed to the placement instead, see undocumented specialization below +template class Bounded_distance_placement { -public: - typedef typename Placement::TM TM; + typedef typename GeomTraits::Triangle_3 Triangle; + typedef std::vector Triangle_container; + typedef typename Triangle_container::iterator TC_iterator; + typedef CGAL::AABB_triangle_primitive Primitive; + typedef CGAL::AABB_traits Traits; + typedef CGAL::AABB_tree AABB_tree; + +private: + template + void initialize_tree(const Profile& profile) const + { + typedef typename Profile::Geom_traits Geom_traits; + typedef typename Geom_traits::Triangle_3 Triangle; + + typedef typename Profile::Triangle_mesh Triangle_mesh; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + CGAL_precondition(m_tree_ptr == nullptr); + + const Triangle_mesh& tm = profile.surface_mesh(); + const Geom_traits& gt = profile.geom_traits(); + std::vector input_triangles; + + for(face_descriptor f : faces(profile.surface_mesh())) + { + halfedge_descriptor h = halfedge(f, tm); + CGAL_assertion(!is_border(h, tm)); + + input_triangles.push_back(gt.construct_triangle_3_object()( + get(profile.vertex_point_map(), source(h, tm)), + get(profile.vertex_point_map(), target(h, tm)), + get(profile.vertex_point_map(), target(next(h, tm), tm)))); + } + + m_tree_ptr = new AABB_tree(input_triangles.begin(), input_triangles.end()); + const_cast(m_tree_ptr)->build(); + } public: Bounded_distance_placement(const double dist, - const Tree& tree, - const Placement& placement = Placement()) - : m_get_placement(placement), m_tree(tree), m_sq_threshold_dist(CGAL::square(dist)) + const BasePlacement& placement = BasePlacement()) + : + m_sq_threshold_dist(CGAL::square(dist)), + m_tree_ptr(nullptr), + m_base_placement(placement) { } + ~Bounded_distance_placement() + { + if(m_tree_ptr != nullptr) + delete m_tree_ptr; + } + template boost::optional operator()(const Profile& profile) const { - typedef typename Profile::Point Point; - typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel; + typedef typename Profile::Geom_traits Geom_traits; + typedef typename Profile::Point Point; - boost::optional op = m_get_placement(profile); + boost::optional op = m_base_placement(profile); if(op) { - CGAL_assertion(!m_tree.empty()); + if(m_tree_ptr == nullptr) + initialize_tree(profile); + + CGAL_assertion(m_tree_ptr != nullptr); + CGAL_assertion(!m_tree_ptr->empty()); const Point& p = *op; - m_tree.accelerate_distance_queries(); - const Point& cp = m_tree.best_hint(p).first; // requires accelerate distance query to be called. + m_tree_ptr->accelerate_distance_queries(); + const Point& cp = m_tree_ptr->best_hint(p).first; // requires accelerate distance query to be called. // We could do better by having access to the internal kd-tree // and call search_any_point with a fuzzy_sphere. @@ -57,7 +113,7 @@ public: // any face closer than the threshold is intersected by // the sphere (avoid the inclusion of the mesh into the threshold sphere) if(CGAL::compare_squared_distance(p, cp, m_sq_threshold_dist) != LARGER || - m_tree.do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) + m_tree_ptr->do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) return op; return boost::optional(); @@ -67,9 +123,61 @@ public: } private: - const Placement m_get_placement; - const Tree& m_tree; const double m_sq_threshold_dist; + mutable const AABB_tree* m_tree_ptr; + + const BasePlacement m_base_placement; +}; + +// Undocumented specizalization where an _already built_ AABB tree is passed +template +class Bounded_distance_placement > +{ + typedef CGAL::AABB_tree AABB_tree; + +public: + Bounded_distance_placement(const double dist, + const AABB_tree& tree, + const BasePlacement& placement = BasePlacement()) + : + m_sq_threshold_dist(CGAL::square(dist)), + m_tree_ptr(&tree), + m_base_placement(placement) + { } + + template + boost::optional + operator()(const Profile& profile) const + { + typedef typename Profile::Geom_traits Geom_traits; + typedef typename Profile::Point Point; + + boost::optional op = m_base_placement(profile); + if(op) + { + CGAL_assertion(m_tree_ptr != nullptr); + CGAL_assertion(!m_tree_ptr->empty()); + + const Point& p = *op; + + m_tree_ptr->accelerate_distance_queries(); + const Point& cp = m_tree_ptr->best_hint(p).first; // requires accelerate distance query to be called. + + if(CGAL::compare_squared_distance(p, cp, m_sq_threshold_dist) != LARGER || + m_tree_ptr->do_intersect(CGAL::Sphere_3(p, m_sq_threshold_dist))) + return op; + + return boost::optional(); + } + + return op; + } + +private: + const double m_sq_threshold_dist; + mutable const AABB_tree* m_tree_ptr; + + const BasePlacement m_base_placement; }; } // namespace Surface_mesh_simplification From 66b32fa3d13ed63546f72290826dc329200fc48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 13:55:43 +0100 Subject: [PATCH 12/18] Update test --- .../test_edge_collapse_bounded_distance.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index 77fbd23589c..c93208d36bf 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -25,13 +25,15 @@ typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point_3; typedef CGAL::Surface_mesh Surface; +typedef SMS::LindstromTurk_cost Cost; +typedef SMS::LindstromTurk_placement Placement; + typedef CGAL::AABB_face_graph_triangle_primitive Primitive; typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree Tree; -typedef SMS::LindstromTurk_cost Cost; -typedef SMS::LindstromTurk_placement Placement; -typedef SMS::Bounded_distance_placement Filtered_placement; +typedef SMS::Bounded_distance_placement Filtered_placement; +typedef SMS::Bounded_distance_placement Filtered_placement_with_tree; int main(int argc, char** argv) { @@ -48,16 +50,18 @@ int main(int argc, char** argv) Point_3 cmax = (bbox.max)(); const double diag = std::sqrt(CGAL::squared_distance(cmin, cmax)); + Surface mesh_cpy = ref_mesh; // need a copy to keep the AABB tree valid Surface small_mesh = ref_mesh; Surface big_mesh = ref_mesh; - Tree tree(faces(ref_mesh).first, faces(ref_mesh).second, ref_mesh); + Tree tree(faces(mesh_cpy).first, faces(mesh_cpy).second, mesh_cpy); Placement placement_ref; - Filtered_placement placement_small(0.00005*diag, tree, placement_ref); - Filtered_placement placement_big(50*diag, tree, placement_ref); - - SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); SMS::edge_collapse(ref_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_ref)); + + Filtered_placement_with_tree placement_small(0.00005*diag, tree, placement_ref); + SMS::edge_collapse(small_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_small)); + + Filtered_placement placement_big(50*diag, placement_ref); // lazily builds the AABB tree SMS::edge_collapse(big_mesh, stop, CGAL::parameters::get_cost(Cost()).get_placement(placement_big)); std::cout << "no filtering: " << vertices(ref_mesh).size() << " vertices left" << std::endl; From 38b780cdb66737e55f901b9bc3a20bb3fad72e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 14:31:50 +0100 Subject: [PATCH 13/18] Tiny improvement to GH doc --- .../Policies/Edge_collapse/GarlandHeckbert_policies.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h index 07fc7ed0a93..5b4de9dcaf5 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/GarlandHeckbert_policies.h @@ -12,13 +12,13 @@ associating quadrics to vertices. Note however, that they may still be wrapped with slight behavior modifying classes such as `Constrained_placement` or `Bounded_normal_change_placement`. -Note that these policies depend on the third party \ref thirdpartyEigen library. - \tparam TriangleMesh is the type of surface mesh being simplified, and must be a model of the `MutableFaceGraph` and `HalfedgeListGraph` concepts. \tparam GeomTraits must be a model of `Kernel`. If you have passed a traits class in the optional named parameters in the call to `edge_collapse()`, the types must be identical. +These policies depend on the third party \ref thirdpartyEigen library. + */ template class GarlandHeckbert_policies From fa83880b5e30c4ac9f0300e99fb21973ca9fd10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 14:32:23 +0100 Subject: [PATCH 14/18] Document Bounded_distance_placement --- .../Bounded_distance_placement.h | 55 +++++++++++++++++++ .../Concepts/GetPlacement.h | 1 + .../PackageDescription.txt | 1 + 3 files changed, 57 insertions(+) create mode 100644 Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h new file mode 100644 index 00000000000..0a227beabcc --- /dev/null +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -0,0 +1,55 @@ + +namespace CGAL { +namespace Surface_mesh_simplification { + +/*! +\ingroup PkgSurfaceMeshSimplificationRef + +The class `Bounded_distance_placement` is a model for the concept `GetPlacement`. + +This placement class is a wrapper around another (so-called base) placement class. +The position of a vertex resulting from the contraction of an edge is obtained by first querying +the base placement class, and checking whether this tentative position is not too far +(according to a user-provided distance bound) from the input mesh. +If it is too far, the position is rejected and no position is returned; otherwise, +the position is returned. + +\tparam BasePlacement must be a model of `GetPlacement`. +\tparam GeomTraits must be a model of `Kernel` and be identical to the traits specified + in the named parameters of the function `edge_collapse()` (if specified). + +The distance check is performed using an AABB tree and this class thus depends on the package \ref PkgAABBTree. + +\cgalModels `GetPlacement` + +*/ +template +class Bounded_distance_placement + : public BasePlacement +{ +public: + /// + typedef typename GeomTraits::FT FT; + + /// \name Creation + /// + /// @{ + + /// The distance bound `d` is used to control that during simplification, + /// no vertex has a distance to the input that would be greater than `d`. + Bounded_distance_placement(const FT d, const BasePlacement& base_placement = BasePlacement()); + + /// @} + + /// \name Operations + /// @{ + + /// Returns the placement computed by `base_placement`, provided the distance between the input + /// and this placement is smaller than `d`. Otherwise, nothing is returned. + boost::optional operator()(const Edge_profile& profile) const; + + /// @} +}; + +} // namespace Surface_Mesh_Simplification +} // namespace CGAL diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h index f7f0b927f6d..3ca167ecf05 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -18,6 +18,7 @@ or can be intentionally returned to prevent the edge from being collapsed. \cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` \cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt index 9cec933f869..6ff97276f7e 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt @@ -43,6 +43,7 @@ - `CGAL::Surface_mesh_simplification::LindstromTurk_cost` - `CGAL::Surface_mesh_simplification::LindstromTurk_placement` - `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +- `CGAL::Surface_mesh_simplification::Bounded_distance_placement` - `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` - `CGAL::Surface_mesh_simplification::Constrained_placement` */ From 80f1583fa8aca77d3947bb44af4312c89538044b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 14:47:52 +0100 Subject: [PATCH 15/18] Minor doc improvements --- .../Bounded_distance_placement.h | 22 ++++++++++++------- .../test_edge_collapse_bounded_distance.cpp | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 904492f56ff..dad4317af92 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -24,6 +24,9 @@ #include +#include +#include + namespace CGAL { namespace Surface_mesh_simplification { @@ -31,9 +34,13 @@ namespace Surface_mesh_simplification { template class Bounded_distance_placement { + typedef GeomTraits Geom_traits; + typedef typename Geom_traits::FT FT; + typedef typename GeomTraits::Triangle_3 Triangle; typedef std::vector Triangle_container; typedef typename Triangle_container::iterator TC_iterator; + typedef CGAL::AABB_triangle_primitive Primitive; typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree AABB_tree; @@ -42,8 +49,7 @@ private: template void initialize_tree(const Profile& profile) const { - typedef typename Profile::Geom_traits Geom_traits; - typedef typename Geom_traits::Triangle_3 Triangle; + CGAL_static_assertion((std::is_same::value)); typedef typename Profile::Triangle_mesh Triangle_mesh; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -71,7 +77,7 @@ private: } public: - Bounded_distance_placement(const double dist, + Bounded_distance_placement(const FT dist, const BasePlacement& placement = BasePlacement()) : m_sq_threshold_dist(CGAL::square(dist)), @@ -89,7 +95,6 @@ public: boost::optional operator()(const Profile& profile) const { - typedef typename Profile::Geom_traits Geom_traits; typedef typename Profile::Point Point; boost::optional op = m_base_placement(profile); @@ -123,7 +128,7 @@ public: } private: - const double m_sq_threshold_dist; + const FT m_sq_threshold_dist; mutable const AABB_tree* m_tree_ptr; const BasePlacement m_base_placement; @@ -133,10 +138,11 @@ private: template class Bounded_distance_placement > { - typedef CGAL::AABB_tree AABB_tree; + typedef CGAL::AABB_tree AABB_tree; + typedef typename AABB_tree::AABB_traits::FT FT; public: - Bounded_distance_placement(const double dist, + Bounded_distance_placement(const FT dist, const AABB_tree& tree, const BasePlacement& placement = BasePlacement()) : @@ -174,7 +180,7 @@ public: } private: - const double m_sq_threshold_dist; + const FT m_sq_threshold_dist; mutable const AABB_tree* m_tree_ptr; const BasePlacement m_base_placement; diff --git a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp index c93208d36bf..8aaa51a4651 100644 --- a/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp +++ b/Surface_mesh_simplification/test/Surface_mesh_simplification/test_edge_collapse_bounded_distance.cpp @@ -22,6 +22,7 @@ namespace SMS = CGAL::Surface_mesh_simplification; typedef CGAL::Simple_cartesian Kernel; + typedef Kernel::Point_3 Point_3; typedef CGAL::Surface_mesh Surface; @@ -48,7 +49,7 @@ int main(int argc, char** argv) Point_3 cmin = (bbox.min)(); Point_3 cmax = (bbox.max)(); - const double diag = std::sqrt(CGAL::squared_distance(cmin, cmax)); + const double diag = CGAL::approximate_sqrt(CGAL::squared_distance(cmin, cmax)); Surface mesh_cpy = ref_mesh; // need a copy to keep the AABB tree valid Surface small_mesh = ref_mesh; From 3df376ed83c5ee62aee0eafcec5d4ff8968d3962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 10 Jan 2020 19:56:30 +0100 Subject: [PATCH 16/18] Update dependencies enter the commit message for your changes. Lines starting --- .../package_info/Surface_mesh_simplification/dependencies | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies b/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies index f8f2b1e180e..27dd31f34e6 100644 --- a/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies +++ b/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies @@ -1,9 +1,13 @@ +AABB_tree Algebraic_foundations BGL +Cartesian_kernel Circulator Distance_2 Distance_3 Installation +Intersections_2 +Intersections_3 Interval_support Kernel_23 Modular_arithmetic @@ -12,5 +16,6 @@ Profiling_tools Property_map Random_numbers STL_Extension +Spatial_searching Stream_support Surface_mesh_simplification From 0de28e84fffb8cb748389e387f901b1a3d753e36 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 28 Jan 2020 12:42:06 +0100 Subject: [PATCH 17/18] Undocument --- .../Bounded_distance_placement.h | 26 +++++------ .../Concepts/GetPlacement.h | 46 +++++++++---------- .../PackageDescription.txt | 1 - 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h index 0a227beabcc..5fa7e3c3395 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h @@ -2,7 +2,7 @@ namespace CGAL { namespace Surface_mesh_simplification { -/*! +/* \ingroup PkgSurfaceMeshSimplificationRef The class `Bounded_distance_placement` is a model for the concept `GetPlacement`. @@ -28,27 +28,27 @@ class Bounded_distance_placement : public BasePlacement { public: - /// + // typedef typename GeomTraits::FT FT; - /// \name Creation - /// - /// @{ + // \name Creation + // + // @{ - /// The distance bound `d` is used to control that during simplification, - /// no vertex has a distance to the input that would be greater than `d`. + // The distance bound `d` is used to control that during simplification, + // no vertex has a distance to the input that would be greater than `d`. Bounded_distance_placement(const FT d, const BasePlacement& base_placement = BasePlacement()); - /// @} + // @} - /// \name Operations - /// @{ + // \name Operations + // @{ - /// Returns the placement computed by `base_placement`, provided the distance between the input - /// and this placement is smaller than `d`. Otherwise, nothing is returned. + // Returns the placement computed by `base_placement`, provided the distance between the input + // and this placement is smaller than `d`. Otherwise, nothing is returned. boost::optional operator()(const Edge_profile& profile) const; - /// @} + // @} }; } // namespace Surface_Mesh_Simplification diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h index 3ca167ecf05..f9fdbf0d981 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -1,28 +1,28 @@ -/*! -\ingroup PkgSurfaceMeshSimplificationConcepts -\cgalConcept +//! +//!\ingroup PkgSurfaceMeshSimplificationConcepts +//!\cgalConcept +//! +//!The concept `GetPlacement` describes the requirements for the policy +//!function object which gets the collapse placement of an edge, +//!that is, the new position of the vertex that remains after a +//!halfedge-collapse operation. +//! +//!The placement returned is a `boost::optional` value (i.e., it can +//!be absent). An absent result indicates that the edge should not be collapsed. +//!This could be the result of a computational limitation (such as an overflow), +//!or can be intentionally returned to prevent the edge from being collapsed. +//! +//!\cgalRefines `DefaultConstructible` +//!\cgalRefines `CopyConstructible` +//! +//!\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +//\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` +//!\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` -The concept `GetPlacement` describes the requirements for the policy -function object which gets the collapse placement of an edge, -that is, the new position of the vertex that remains after a -halfedge-collapse operation. -The placement returned is a `boost::optional` value (i.e., it can -be absent). An absent result indicates that the edge should not be collapsed. -This could be the result of a computational limitation (such as an overflow), -or can be intentionally returned to prevent the edge from being collapsed. - -\cgalRefines `DefaultConstructible` -\cgalRefines `CopyConstructible` - -\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` -\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` -\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` - -*/ class GetPlacement { public: diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt index 6ff97276f7e..9cec933f869 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt @@ -43,7 +43,6 @@ - `CGAL::Surface_mesh_simplification::LindstromTurk_cost` - `CGAL::Surface_mesh_simplification::LindstromTurk_placement` - `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` -- `CGAL::Surface_mesh_simplification::Bounded_distance_placement` - `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` - `CGAL::Surface_mesh_simplification::Constrained_placement` */ From a8820c69a98a34fab1d453bf8f253238426eef01 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 28 Jan 2020 13:45:27 +0100 Subject: [PATCH 18/18] Doc. --- .../Concepts/GetPlacement.h | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h index f9fdbf0d981..da415685d46 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/Concepts/GetPlacement.h @@ -1,26 +1,26 @@ -//! -//!\ingroup PkgSurfaceMeshSimplificationConcepts -//!\cgalConcept -//! -//!The concept `GetPlacement` describes the requirements for the policy -//!function object which gets the collapse placement of an edge, -//!that is, the new position of the vertex that remains after a -//!halfedge-collapse operation. -//! -//!The placement returned is a `boost::optional` value (i.e., it can -//!be absent). An absent result indicates that the edge should not be collapsed. -//!This could be the result of a computational limitation (such as an overflow), -//!or can be intentionally returned to prevent the edge from being collapsed. -//! -//!\cgalRefines `DefaultConstructible` -//!\cgalRefines `CopyConstructible` -//! -//!\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` -//\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_distance_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` -//!\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` +/*! +\ingroup PkgSurfaceMeshSimplificationConcepts +\cgalConcept + +The concept `GetPlacement` describes the requirements for the policy +function object which gets the collapse placement of an edge, +that is, the new position of the vertex that remains after a +halfedge-collapse operation. + +The placement returned is a `boost::optional` value (i.e., it can +be absent). An absent result indicates that the edge should not be collapsed. +This could be the result of a computational limitation (such as an overflow), +or can be intentionally returned to prevent the edge from being collapsed. + +\cgalRefines `DefaultConstructible` +\cgalRefines `CopyConstructible` + +\cgalHasModel `CGAL::Surface_mesh_simplification::Midpoint_placement` +\cgalHasModel `CGAL::Surface_mesh_simplification::LindstromTurk_placement` +\cgalHasModel `CGAL::Surface_mesh_simplification::GarlandHeckbert_policies` +\cgalHasModel `CGAL::Surface_mesh_simplification::Bounded_normal_change_placement` +\cgalHasModel `CGAL::Surface_mesh_simplification::Constrained_placement` +*/ class GetPlacement