This commit is contained in:
Maxime Gimeno 2019-09-30 14:18:45 +02:00
parent 5907ec9a18
commit a17c5b1eb2
2 changed files with 65 additions and 68 deletions

View File

@ -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). // This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU // You can redistribute it and/or modify it under the terms of the GNU
@ -15,7 +15,7 @@
// $Id$ // $Id$
// SPDX-License-Identifier: GPL-3.0+ // 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 #ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_POLICIES_EDGE_COLLAPSE_BOUNDED_DISTANCE_PLACEMENT_H
#define 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 namespace Surface_mesh_simplification
{ {
template<class Placement> template<class Placement, class Tree>
class Bounded_distance_placement class Bounded_distance_placement
{ {
public: public:
@ -38,9 +38,10 @@ public:
public: public:
Bounded_distance_placement(const double sq_dist, Bounded_distance_placement(const double dist,
const Tree& tree,
const Placement& placement = Placement() ) 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; typedef typename CGAL::Kernel_traits< Point >::Kernel Kernel;
if(op){ if(op){
const Point* p = boost::get<Point>(&op); const Point* p = boost::get<Point>(&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<Kernel> s(*p, threshold_sq_dist); if(tree.do_intersect(CGAL::Sphere_3<Kernel>(*p, threshold_dist*threshold_dist))){
while(it!= triangles.end()){ return op;
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 boost::none;
} }
return op; return op;
} }
@ -79,7 +68,8 @@ public:
private: private:
Placement mPlacement ; Placement mPlacement ;
double threshold_sq_dist; const Tree& tree;
double threshold_dist;
}; };
} }

View File

@ -15,72 +15,79 @@
#include <CGAL/AABB_traits.h> #include <CGAL/AABB_traits.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h> #include <CGAL/AABB_face_graph_triangle_primitive.h>
//bbox
#include <CGAL/Polygon_mesh_processing/bbox.h>
//Timer //Timer
#include <CGAL/Timer.h> //#include <CGAL/Timer.h>
//filter{
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h> #include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h>
//} end filter
namespace SMS = CGAL::Surface_mesh_simplification ; namespace SMS = CGAL::Surface_mesh_simplification ;
typedef CGAL::Simple_cartesian<double> Kernel; typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> Surface; typedef CGAL::Surface_mesh<Kernel::Point_3> Surface;
typedef CGAL::AABB_face_graph_triangle_primitive<Surface> Primitive;
typedef CGAL::AABB_traits<Kernel, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
Surface surface_mesh; Surface ref_mesh;
std::ifstream is(argc > 1 ? argv[1] : "input.off"); std::ifstream is(argc > 1 ? argv[1] : "data/helmet.off");
is >> surface_mesh; is >> ref_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<Surface> stop(num_halfedges(surface_mesh)/10);
typedef SMS::Bounded_distance_placement<SMS::LindstromTurk_placement<Surface> > Filtered_placement; SMS::Count_stop_predicate<Surface> stop(num_halfedges(ref_mesh)/10);
typedef SMS::Bounded_distance_placement<SMS::LindstromTurk_placement<Surface>, Tree> Filtered_placement;
typedef SMS::LindstromTurk_placement<Surface> Placement; typedef SMS::LindstromTurk_placement<Surface> Placement;
double placement1_time, placement2_time; //double placement1_time, placement2_time, tree_time;
std::cout<<"input has "<<num_vertices(surface_mesh)<<" vertices."<<std::endl; //std::cout<<"input has "<<num_vertices(ref_mesh)<<" vertices."<<std::endl;
double input_sq_dist=0.000000001; CGAL::Iso_cuboid_3<Kernel> bbox(CGAL::Polygon_mesh_processing::bbox(ref_mesh));
std::cout<<"threshold squared distance = "<<input_sq_dist<<std::endl;
CGAL::Timer timer;
// This the actual call to the simplification algorithm.
// The surface mesh and stop conditions are mandatory arguments.
// The index maps are needed because the vertices and edges
// of this surface mesh lack an "id()" field.
Surface copy_mesh = surface_mesh;
Placement placement1;
Filtered_placement placement2(input_sq_dist, placement1);
timer.start();
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, stop,
CGAL::parameters::get_cost (SMS::LindstromTurk_cost<Surface>()) CGAL::parameters::get_cost (SMS::LindstromTurk_cost<Surface>())
.get_placement(placement2) .get_placement(placement_small)
); );
timer.stop();
placement2_time=timer.time(); SMS::edge_collapse( big_mesh,
timer.reset();
timer.start();
SMS::edge_collapse( copy_mesh,
stop, stop,
CGAL::parameters::get_cost (SMS::LindstromTurk_cost<Surface>()) CGAL::parameters::get_cost (SMS::LindstromTurk_cost<Surface>())
.get_placement(placement1) .get_placement(placement_big)
); );
timer.stop();
placement1_time=timer.time(); SMS::edge_collapse( ref_mesh,
surface_mesh.collect_garbage(); stop,
copy_mesh.collect_garbage(); CGAL::parameters::get_cost (SMS::LindstromTurk_cost<Surface>())
std::cout<<"Filtered placement time = "<<placement2_time<<"s."<<std::endl; .get_placement(placement_ref)
std::cout<<" Not filtered placement took "<<placement1_time<<"s."<<std::endl; );
std::cout<<"There are "<<num_vertices(surface_mesh)<<" vertices left when filtered and "<<num_vertices(copy_mesh)<<" when not filtered."<<std::endl;
std::ofstream os( "out_filtered.off" ); ref_mesh.collect_garbage();
os.precision(17); small_mesh.collect_garbage();
os << surface_mesh; big_mesh.collect_garbage();
os.close(); //std::cout<<"Filtered placement time = "<<placement2_time<<"s."<<std::endl;
os.open("out_clear.off"); //std::cout<<" Not filtered placement took "<<placement1_time<<"s."<<std::endl;
os << copy_mesh; //std::cout<<"There are "<<num_vertices(surface_mesh)<<" vertices left when filtered and "<<num_vertices(copy_mesh)<<" when not filtered."<<std::endl;
os.close(); assert(num_vertices(big_mesh) == num_vertices(ref_mesh));
assert(num_vertices(small_mesh) != num_vertices(ref_mesh));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }