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).
// 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<class Placement>
template<class Placement, class Tree>
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<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);
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<Kernel>(*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;
};
}

View File

@ -15,72 +15,79 @@
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
//bbox
#include <CGAL/Polygon_mesh_processing/bbox.h>
//Timer
#include <CGAL/Timer.h>
//filter{
//#include <CGAL/Timer.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_distance_placement.h>
//} end filter
namespace SMS = CGAL::Surface_mesh_simplification ;
typedef CGAL::Simple_cartesian<double> Kernel;
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 )
{
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<Surface> 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<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;
double placement1_time, placement2_time;
//double placement1_time, placement2_time, tree_time;
std::cout<<"input has "<<num_vertices(surface_mesh)<<" vertices."<<std::endl;
double input_sq_dist=0.000000001;
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();
//std::cout<<"input has "<<num_vertices(ref_mesh)<<" vertices."<<std::endl;
CGAL::Iso_cuboid_3<Kernel> 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<Surface>())
.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<Surface>())
.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 = "<<placement2_time<<"s."<<std::endl;
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" );
os.precision(17);
os << surface_mesh;
os.close();
os.open("out_clear.off");
os << copy_mesh;
os.close();
SMS::edge_collapse( ref_mesh,
stop,
CGAL::parameters::get_cost (SMS::LindstromTurk_cost<Surface>())
.get_placement(placement_ref)
);
ref_mesh.collect_garbage();
small_mesh.collect_garbage();
big_mesh.collect_garbage();
//std::cout<<"Filtered placement time = "<<placement2_time<<"s."<<std::endl;
//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;
assert(num_vertices(big_mesh) == num_vertices(ref_mesh));
assert(num_vertices(small_mesh) != num_vertices(ref_mesh));
return EXIT_SUCCESS;
}