Merge pull request #1929 from sgiraudot/Point_set_processing-Optimize_grid_simplify-GF

Optimizations for grid simplication
This commit is contained in:
Laurent Rineau 2017-03-02 16:55:08 +01:00
commit 52a2242b60
3 changed files with 118 additions and 27 deletions

View File

@ -152,6 +152,12 @@
defined(BOOST_NO_CXX11_HDR_ARRAY) || BOOST_VERSION < 104000
#define CGAL_CFG_NO_CPP0X_ARRAY 1
#endif
#if defined(BOOST_NO_0X_HDR_UNORDERED_SET) || \
defined(BOOST_NO_0X_HDR_UNORDERED_MAP) || \
defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) || \
defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
#define CGAL_CFG_NO_CPP0X_UNORDERED 1
#endif
#if defined(BOOST_NO_DECLTYPE) || \
defined(BOOST_NO_CXX11_DECLTYPE) || (BOOST_VERSION < 103600)
#define CGAL_CFG_NO_CPP0X_DECLTYPE 1

View File

@ -26,9 +26,10 @@
#include <CGAL/property_map.h>
#include <CGAL/Kernel_traits.h>
#include <CGAL/point_set_processing_assertions.h>
#include <CGAL/unordered.h>
#include <boost/functional/hash.hpp>
#include <iterator>
#include <set>
#include <deque>
#include <algorithm>
#include <cmath>
@ -44,11 +45,17 @@ namespace CGAL {
namespace internal {
/// Utility class for grid_simplify_point_set():
/// Less_epsilon_points_3 defines a 3D points order / 2 points are equal
/// iff they belong to the same cell of a grid of cell size = epsilon.
// Round number to multiples of epsilon
inline double round_epsilon(double value, double epsilon)
{
return std::floor(value / epsilon);
}
/// Utility class for grid_simplify_point_set(): Hash_epsilon_points_3
/// defines a 3D point hash / 2 points are equal iff they belong to
/// the same cell of a grid of cell size = epsilon.
template <class Point_3, class PointPMap>
struct Less_epsilon_points_3
struct Hash_epsilon_points_3
{
private:
@ -57,7 +64,37 @@ private:
typedef typename boost::property_traits<PointPMap>::value_type Point;
public:
Less_epsilon_points_3 (double epsilon, PointPMap p_pmap)
Hash_epsilon_points_3 (double epsilon, PointPMap p_pmap)
: m_epsilon (epsilon), point_pmap(p_pmap)
{
CGAL_point_set_processing_precondition(epsilon > 0);
}
std::size_t operator() (const Point_3& a) const
{
const Point& pa = get(point_pmap,a);
std::size_t result = boost::hash_value(round_epsilon(pa.x(), m_epsilon));
boost::hash_combine(result, boost::hash_value(round_epsilon(pa.y(), m_epsilon)));
boost::hash_combine(result, boost::hash_value(round_epsilon(pa.z(), m_epsilon)));
return result;
}
};
/// Utility class for grid_simplify_point_set(): Hash_epsilon_points_3
/// defines a 3D point equality / 2 points are equal iff they belong
/// to the same cell of a grid of cell size = epsilon.
template <class Point_3, class PointPMap>
struct Equal_epsilon_points_3
{
private:
const double m_epsilon;
PointPMap point_pmap;
typedef typename boost::property_traits<PointPMap>::value_type Point;
public:
Equal_epsilon_points_3 (const double& epsilon, PointPMap p_pmap)
: m_epsilon (epsilon), point_pmap(p_pmap)
{
CGAL_point_set_processing_precondition(epsilon > 0);
@ -65,29 +102,24 @@ public:
bool operator() (const Point_3& a, const Point_3& b) const
{
// Round points to multiples of m_epsilon, then compare.
return round_epsilon( get(point_pmap,a), m_epsilon ) <
round_epsilon( get(point_pmap,b), m_epsilon );
}
const Point& pa = get(point_pmap,a);
const Point& pb = get(point_pmap,b);
private:
// Round number to multiples of epsilon
static inline double round_epsilon(double value, double epsilon)
{
return std::floor(value/epsilon) * epsilon;
}
static inline Point round_epsilon(const Point& p, double epsilon)
{
return Point( round_epsilon(p.x(), epsilon),
round_epsilon(p.y(), epsilon),
round_epsilon(p.z(), epsilon) );
double ra = round_epsilon(pa.x(), m_epsilon);
double rb = round_epsilon(pb.x(), m_epsilon);
if (ra != rb)
return false;
ra = round_epsilon(pa.y(), m_epsilon);
rb = round_epsilon(pb.y(), m_epsilon);
if (ra != rb)
return false;
ra = round_epsilon(pa.z(), m_epsilon);
rb = round_epsilon(pb.z(), m_epsilon);
return ra == rb;
}
};
} /* namespace internal */
@ -106,17 +138,22 @@ private:
template <class Point_3, class PointPMap>
class Epsilon_point_set_3
: public std::set<Point_3, internal::Less_epsilon_points_3<Point_3, PointPMap> >
: public cpp11::unordered_set<Point_3,
internal::Hash_epsilon_points_3<Point_3, PointPMap>,
internal::Equal_epsilon_points_3<Point_3, PointPMap> >
{
private:
// superclass
typedef std::set<Point_3, internal::Less_epsilon_points_3<Point_3, PointPMap> > Base;
typedef cpp11::unordered_set<Point_3,
internal::Hash_epsilon_points_3<Point_3, PointPMap>,
internal::Equal_epsilon_points_3<Point_3, PointPMap> > Base;
public:
Epsilon_point_set_3 (double epsilon, PointPMap point_pmap)
: Base( internal::Less_epsilon_points_3<Point_3, PointPMap>(epsilon, point_pmap) )
: Base(10, internal::Hash_epsilon_points_3<Point_3, PointPMap>(epsilon, point_pmap),
internal::Equal_epsilon_points_3<Point_3, PointPMap>(epsilon, point_pmap))
{
CGAL_point_set_processing_precondition(epsilon > 0);
}

View File

@ -0,0 +1,48 @@
// Copyright (c) 2017 GeometryFactory Sarl (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) : Simon Giraudot
#ifndef CGAL_UNORDERED_H
#define CGAL_UNORDERED_H
#include <CGAL/config.h>
#ifndef CGAL_CFG_NO_CPP0X_UNORDERED
# include <unordered_set>
# include <unordered_map>
#else
# include <boost/unordered_set.hpp>
# include <boost/unordered_map.hpp>
#endif
namespace CGAL {
namespace cpp11 {
#ifndef CGAL_CFG_NO_CPP0X_UNORDERED
using std::unordered_set;
using std::unordered_map;
#else
using boost::unordered_set;
using boost::unordered_map;
#endif
} // cpp11
} //namespace CGAL
#endif // CGAL_UNORDERED_H