mirror of https://github.com/CGAL/cgal
Update branch from master after trailing whitespaces and tabs removal
This commit is contained in:
commit
a0345b135c
|
|
@ -407,7 +407,7 @@ public:
|
||||||
Point_3_from_sample()),
|
Point_3_from_sample()),
|
||||||
boost::make_transform_iterator (m_samples.end(),
|
boost::make_transform_iterator (m_samples.end(),
|
||||||
Point_3_from_sample())),
|
Point_3_from_sample())),
|
||||||
3);
|
3, CGAL::parameters::point_map (CGAL::Identity_property_map_no_lvalue<K::Point_3>()));
|
||||||
std::cerr << "Average spacing = " << spacing << std::endl;
|
std::cerr << "Average spacing = " << spacing << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
// Copyright (c) 2018 GeometryFactory (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
|
//
|
||||||
|
// Author(s) : Simon Giraudot
|
||||||
|
|
||||||
|
#ifndef CGAL_PSP_INTERNAL_CALLBACK_WRAPPER_H
|
||||||
|
#define CGAL_PSP_INTERNAL_CALLBACK_WRAPPER_H
|
||||||
|
|
||||||
|
#include <CGAL/license/Point_set_processing_3.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <CGAL/thread.h>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Point_set_processing_3 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename ConcurrencyTag>
|
||||||
|
class Callback_wrapper
|
||||||
|
{
|
||||||
|
std::size_t m_advancement;
|
||||||
|
bool m_interrupted;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Callback_wrapper (const std::function<bool(double)>&, std::size_t, std::size_t, bool = false) { }
|
||||||
|
void reset (std::size_t, std::size_t, bool = false) { }
|
||||||
|
std::size_t& advancement() { return m_advancement; }
|
||||||
|
bool& interrupted() { return m_interrupted; }
|
||||||
|
void join() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class Callback_wrapper<CGAL::Sequential_tag>
|
||||||
|
{
|
||||||
|
const std::function<bool(double)>& m_callback;
|
||||||
|
std::size_t m_advancement;
|
||||||
|
bool m_interrupted;
|
||||||
|
std::size_t m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Callback_wrapper (const std::function<bool(double)>& callback,
|
||||||
|
std::size_t size,
|
||||||
|
std::size_t advancement = 0,
|
||||||
|
bool interrupted = false)
|
||||||
|
: m_callback (callback)
|
||||||
|
, m_advancement (advancement)
|
||||||
|
, m_interrupted (interrupted)
|
||||||
|
, m_size (size)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Callback_wrapper (const Callback_wrapper& other)
|
||||||
|
: m_callback (other.m_callback)
|
||||||
|
, m_advancement (other.m_advancement)
|
||||||
|
, m_interrupted (other.m_interrupted)
|
||||||
|
, m_size (other.m_size)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Callback_wrapper () { }
|
||||||
|
|
||||||
|
void reset (std::size_t size, std::size_t advancement, bool interrupted = false)
|
||||||
|
{
|
||||||
|
m_size = size;
|
||||||
|
m_advancement = advancement;
|
||||||
|
m_interrupted = interrupted;
|
||||||
|
}
|
||||||
|
std::size_t& advancement()
|
||||||
|
{
|
||||||
|
return m_advancement;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool& interrupted()
|
||||||
|
{
|
||||||
|
if (m_callback)
|
||||||
|
m_interrupted = !(m_callback(m_advancement / double(m_size)));
|
||||||
|
return m_interrupted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void join() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
template <>
|
||||||
|
class Callback_wrapper<CGAL::Parallel_tag>
|
||||||
|
{
|
||||||
|
const std::function<bool(double)>& m_callback;
|
||||||
|
cpp11::atomic<std::size_t>* m_advancement;
|
||||||
|
cpp11::atomic<bool>* m_interrupted;
|
||||||
|
std::size_t m_size;
|
||||||
|
bool m_creator;
|
||||||
|
cpp11::thread* m_thread;
|
||||||
|
|
||||||
|
// assignment operator shouldn't be used (m_callback is const ref)
|
||||||
|
Callback_wrapper& operator= (const Callback_wrapper&)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Callback_wrapper (const std::function<bool(double)>& callback,
|
||||||
|
std::size_t size,
|
||||||
|
std::size_t advancement = 0,
|
||||||
|
bool interrupted = false)
|
||||||
|
: m_callback (callback)
|
||||||
|
, m_advancement (new cpp11::atomic<std::size_t>())
|
||||||
|
, m_interrupted (new cpp11::atomic<bool>())
|
||||||
|
, m_size (size)
|
||||||
|
, m_creator (true)
|
||||||
|
, m_thread (nullptr)
|
||||||
|
{
|
||||||
|
// cpp11::atomic only has default constructor, initialization done in two steps
|
||||||
|
*m_advancement = advancement;
|
||||||
|
*m_interrupted = interrupted;
|
||||||
|
if (m_callback)
|
||||||
|
m_thread = new cpp11::thread (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Callback_wrapper (const Callback_wrapper& other)
|
||||||
|
: m_callback (other.m_callback)
|
||||||
|
, m_advancement (other.m_advancement)
|
||||||
|
, m_interrupted (other.m_interrupted)
|
||||||
|
, m_size (other.m_size)
|
||||||
|
, m_creator (false)
|
||||||
|
, m_thread (nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~Callback_wrapper ()
|
||||||
|
{
|
||||||
|
if (m_creator)
|
||||||
|
{
|
||||||
|
delete m_advancement;
|
||||||
|
delete m_interrupted;
|
||||||
|
}
|
||||||
|
if (m_thread != nullptr)
|
||||||
|
delete m_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset (std::size_t size, std::size_t advancement, bool interrupted = false)
|
||||||
|
{
|
||||||
|
m_size = size;
|
||||||
|
*m_advancement = advancement;
|
||||||
|
*m_interrupted = interrupted;
|
||||||
|
if (m_callback)
|
||||||
|
m_thread = new cpp11::thread (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpp11::atomic<std::size_t>& advancement() { return *m_advancement; }
|
||||||
|
cpp11::atomic<bool>& interrupted() { return *m_interrupted; }
|
||||||
|
void join()
|
||||||
|
{
|
||||||
|
if (m_thread != nullptr)
|
||||||
|
m_thread->join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
while (*m_advancement != m_size)
|
||||||
|
{
|
||||||
|
if (m_callback && !m_callback (*m_advancement / double(m_size)))
|
||||||
|
*m_interrupted = true;
|
||||||
|
if (*m_interrupted)
|
||||||
|
return;
|
||||||
|
cpp11::sleep_for (0.00001);
|
||||||
|
}
|
||||||
|
if (m_callback)
|
||||||
|
m_callback (1.);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace Point_set_processing_3
|
||||||
|
} // namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_PSP_INTERNAL_CALLBACK_WRAPPER_H
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
// Copyright (c) 2019 GeometryFactory Sarl (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
|
//
|
||||||
|
// Author(s) : Simon Giraudot
|
||||||
|
|
||||||
|
#ifndef CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H
|
||||||
|
#define CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H
|
||||||
|
|
||||||
|
#include <CGAL/license/Point_set_processing_3.h>
|
||||||
|
|
||||||
|
#include <CGAL/Search_traits_3.h>
|
||||||
|
#include <CGAL/Fuzzy_sphere.h>
|
||||||
|
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
||||||
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
|
|
||||||
|
#include <CGAL/iterator.h>
|
||||||
|
|
||||||
|
#include <boost/function_output_iterator.hpp>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Point_set_processing_3 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
struct Maximum_points_reached_exception : public std::exception { };
|
||||||
|
|
||||||
|
template <typename Kernel_, typename PointRangeRef, typename PointMap>
|
||||||
|
class Neighbor_query
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef Kernel_ Kernel;
|
||||||
|
typedef PointRangeRef Point_range;
|
||||||
|
typedef PointMap Point_map;
|
||||||
|
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
typedef typename Kernel::Point_3 Point_3;
|
||||||
|
|
||||||
|
typedef typename Range_iterator_type<PointRangeRef>::type input_iterator;
|
||||||
|
typedef typename input_iterator::value_type value_type;
|
||||||
|
|
||||||
|
typedef CGAL::Prevent_deref<input_iterator> iterator;
|
||||||
|
|
||||||
|
struct Deref_point_map
|
||||||
|
{
|
||||||
|
typedef input_iterator key_type;
|
||||||
|
typedef typename boost::property_traits<PointMap>::reference reference;
|
||||||
|
typedef typename boost::property_traits<PointMap>::value_type value_type;
|
||||||
|
typedef typename boost::property_traits<PointMap>::category category;
|
||||||
|
|
||||||
|
PointMap point_map;
|
||||||
|
|
||||||
|
Deref_point_map () { }
|
||||||
|
Deref_point_map (PointMap point_map) : point_map(point_map) { }
|
||||||
|
|
||||||
|
friend reference get (const Deref_point_map& map, key_type it)
|
||||||
|
{
|
||||||
|
return get(map.point_map, *it);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef CGAL::Search_traits_3<Kernel> Tree_traits_base;
|
||||||
|
typedef CGAL::Search_traits_adapter<input_iterator, Deref_point_map, Tree_traits_base> Tree_traits;
|
||||||
|
typedef CGAL::Sliding_midpoint<Tree_traits> Splitter;
|
||||||
|
typedef CGAL::Distance_adapter<input_iterator, Deref_point_map, CGAL::Euclidean_distance<Tree_traits_base> > Distance;
|
||||||
|
typedef CGAL::Kd_tree<Tree_traits, Splitter, CGAL::Tag_true, CGAL::Tag_true> Tree;
|
||||||
|
typedef CGAL::Fuzzy_sphere<Tree_traits> Sphere;
|
||||||
|
|
||||||
|
typedef CGAL::Orthogonal_k_neighbor_search<Tree_traits, Distance, Splitter, Tree> Neighbor_search;
|
||||||
|
typedef typename Neighbor_search::iterator Search_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PointRangeRef m_points;
|
||||||
|
PointMap m_point_map;
|
||||||
|
Deref_point_map m_deref_map;
|
||||||
|
Tree_traits m_traits;
|
||||||
|
Tree m_tree;
|
||||||
|
Distance m_distance;
|
||||||
|
|
||||||
|
// Forbid copy
|
||||||
|
Neighbor_query (const Neighbor_query&) { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Neighbor_query (PointRangeRef points, PointMap point_map)
|
||||||
|
: m_points (points)
|
||||||
|
, m_point_map (point_map)
|
||||||
|
, m_deref_map (point_map)
|
||||||
|
, m_traits (m_deref_map)
|
||||||
|
, m_tree (iterator(m_points.begin()), iterator(m_points.end()), Splitter(), m_traits)
|
||||||
|
, m_distance (m_deref_map)
|
||||||
|
{
|
||||||
|
m_tree.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
PointMap point_map() const { return m_point_map; }
|
||||||
|
|
||||||
|
template <typename OutputIterator>
|
||||||
|
void get_iterators (const Point_3& query, unsigned int k, FT neighbor_radius,
|
||||||
|
OutputIterator output) const
|
||||||
|
{
|
||||||
|
if (neighbor_radius != FT(0))
|
||||||
|
{
|
||||||
|
Sphere fs (query, neighbor_radius, 0, m_traits);
|
||||||
|
|
||||||
|
// if k=0, no limit on the number of neighbors returned
|
||||||
|
if (k == 0)
|
||||||
|
k = (std::numeric_limits<unsigned int>::max)();
|
||||||
|
|
||||||
|
unsigned int nb = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::function<void(const input_iterator&)> output_iterator_with_limit
|
||||||
|
= [&](const input_iterator& it)
|
||||||
|
{
|
||||||
|
*(output ++) = it;
|
||||||
|
if (++ nb == k)
|
||||||
|
throw Maximum_points_reached_exception();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto function_output_iterator
|
||||||
|
= boost::make_function_output_iterator (output_iterator_with_limit);
|
||||||
|
|
||||||
|
m_tree.search (function_output_iterator, fs);
|
||||||
|
}
|
||||||
|
catch (const Maximum_points_reached_exception&)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
// Fallback, if less than 3 points are return, search for the 3
|
||||||
|
// first points
|
||||||
|
if (nb < 3)
|
||||||
|
k = 3;
|
||||||
|
// Else, no need to search for K nearest neighbors
|
||||||
|
else
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k != 0)
|
||||||
|
{
|
||||||
|
// Gather set of (k+1) neighboring points.
|
||||||
|
// Perform k+1 queries (as in point set, the query point is
|
||||||
|
// output first). Search may be aborted if k is greater
|
||||||
|
// than number of input points.
|
||||||
|
|
||||||
|
Neighbor_search search (m_tree, query, k+1, 0, true, m_distance);
|
||||||
|
Search_iterator search_iterator = search.begin();
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < (k+1); ++ i)
|
||||||
|
{
|
||||||
|
if(search_iterator == search.end())
|
||||||
|
break; // premature ending
|
||||||
|
*(output ++) = search_iterator->first;
|
||||||
|
search_iterator++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIterator>
|
||||||
|
void get_points (const Point_3& query, unsigned int k, FT neighbor_radius,
|
||||||
|
OutputIterator output) const
|
||||||
|
{
|
||||||
|
return get_iterators(query, k, neighbor_radius,
|
||||||
|
boost::make_function_output_iterator
|
||||||
|
([&](const input_iterator& it)
|
||||||
|
{
|
||||||
|
*(output ++) = get (m_point_map, *it);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} } } // namespace CGAL::Point_set_processing_3::internal
|
||||||
|
|
||||||
|
#endif // CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
// Copyright (c) 2018 GeometryFactory (France).
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// This file is part of CGAL (www.cgal.org).
|
|
||||||
//
|
|
||||||
// $URL$
|
|
||||||
// $Id$
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
|
||||||
//
|
|
||||||
// Author(s) : Simon Giraudot
|
|
||||||
|
|
||||||
#ifndef CGAL_PSP_INTERNAL_PARALLEL_CALLBACK_H
|
|
||||||
#define CGAL_PSP_INTERNAL_PARALLEL_CALLBACK_H
|
|
||||||
|
|
||||||
#include <CGAL/license/Point_set_processing_3.h>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include <CGAL/thread.h>
|
|
||||||
|
|
||||||
namespace CGAL {
|
|
||||||
namespace Point_set_processing_3 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
class Parallel_callback
|
|
||||||
{
|
|
||||||
const std::function<bool(double)>& m_callback;
|
|
||||||
cpp11::atomic<std::size_t>* m_advancement;
|
|
||||||
cpp11::atomic<bool>* m_interrupted;
|
|
||||||
std::size_t m_size;
|
|
||||||
bool m_creator;
|
|
||||||
cpp11::thread* m_thread;
|
|
||||||
|
|
||||||
// assignment operator shouldn't be used (m_callback is const ref)
|
|
||||||
Parallel_callback& operator= (const Parallel_callback&)
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Parallel_callback (const std::function<bool(double)>& callback,
|
|
||||||
std::size_t size,
|
|
||||||
std::size_t advancement = 0,
|
|
||||||
bool interrupted = false)
|
|
||||||
: m_callback (callback)
|
|
||||||
, m_advancement (new cpp11::atomic<std::size_t>())
|
|
||||||
, m_interrupted (new cpp11::atomic<bool>())
|
|
||||||
, m_size (size)
|
|
||||||
, m_creator (true)
|
|
||||||
, m_thread (nullptr)
|
|
||||||
{
|
|
||||||
// cpp11::atomic only has default constructor, initialization done in two steps
|
|
||||||
*m_advancement = advancement;
|
|
||||||
*m_interrupted = interrupted;
|
|
||||||
if (m_callback)
|
|
||||||
m_thread = new cpp11::thread (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Parallel_callback (const Parallel_callback& other)
|
|
||||||
: m_callback (other.m_callback)
|
|
||||||
, m_advancement (other.m_advancement)
|
|
||||||
, m_interrupted (other.m_interrupted)
|
|
||||||
, m_size (other.m_size)
|
|
||||||
, m_creator (false)
|
|
||||||
, m_thread (nullptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
~Parallel_callback ()
|
|
||||||
{
|
|
||||||
if (m_creator)
|
|
||||||
{
|
|
||||||
delete m_advancement;
|
|
||||||
delete m_interrupted;
|
|
||||||
}
|
|
||||||
if (m_thread != nullptr)
|
|
||||||
delete m_thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpp11::atomic<std::size_t>& advancement() { return *m_advancement; }
|
|
||||||
cpp11::atomic<bool>& interrupted() { return *m_interrupted; }
|
|
||||||
void join()
|
|
||||||
{
|
|
||||||
if (m_thread != nullptr)
|
|
||||||
m_thread->join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()()
|
|
||||||
{
|
|
||||||
while (*m_advancement != m_size)
|
|
||||||
{
|
|
||||||
if (!m_callback (*m_advancement / double(m_size)))
|
|
||||||
*m_interrupted = true;
|
|
||||||
if (*m_interrupted)
|
|
||||||
return;
|
|
||||||
cpp11::sleep_for (0.00001);
|
|
||||||
}
|
|
||||||
m_callback (1.);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace Point_set_processing_3
|
|
||||||
} // namespace CGAL
|
|
||||||
|
|
||||||
#endif // CGAL_PSP_INTERNAL_PARALLEL_CALLBACK_H
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
// Copyright (c) 2019 GeometryFactory Sarl (France).
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// This file is part of CGAL (www.cgal.org).
|
|
||||||
//
|
|
||||||
// $URL$
|
|
||||||
// $Id$
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
|
||||||
//
|
|
||||||
// Author(s) : Simon Giraudot
|
|
||||||
|
|
||||||
#ifndef CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H
|
|
||||||
#define CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H
|
|
||||||
|
|
||||||
#include <CGAL/license/Point_set_processing_3.h>
|
|
||||||
|
|
||||||
#include <CGAL/Search_traits_3.h>
|
|
||||||
#include <CGAL/Fuzzy_sphere.h>
|
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
|
||||||
|
|
||||||
#include <boost/function_output_iterator.hpp>
|
|
||||||
|
|
||||||
namespace CGAL {
|
|
||||||
namespace Point_set_processing_3 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
struct Maximum_points_reached_exception : public std::exception { };
|
|
||||||
|
|
||||||
template <typename Point,
|
|
||||||
typename TreeTraits,
|
|
||||||
typename TreeSplitter,
|
|
||||||
typename TreeUseExtendedNode,
|
|
||||||
typename FT,
|
|
||||||
typename PointContainer>
|
|
||||||
void neighbor_query (const Point& query,
|
|
||||||
const CGAL::Kd_tree<TreeTraits, TreeSplitter, TreeUseExtendedNode>& tree,
|
|
||||||
unsigned int k,
|
|
||||||
FT neighbor_radius,
|
|
||||||
PointContainer& points)
|
|
||||||
{
|
|
||||||
typedef typename CGAL::Orthogonal_k_neighbor_search<TreeTraits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::iterator Search_iterator;
|
|
||||||
typedef CGAL::Fuzzy_sphere<TreeTraits> Sphere;
|
|
||||||
|
|
||||||
if (neighbor_radius != FT(0))
|
|
||||||
{
|
|
||||||
Sphere fs (query, neighbor_radius, 0, tree.traits());
|
|
||||||
|
|
||||||
// if k=0, no limit on the number of neighbors returned
|
|
||||||
if (k == 0)
|
|
||||||
k = (std::numeric_limits<unsigned int>::max)();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::function<void(const Point&)> back_insert_with_limit
|
|
||||||
= [&](const Point& point) -> void
|
|
||||||
{
|
|
||||||
points.push_back (point);
|
|
||||||
if (points.size() == k)
|
|
||||||
throw Maximum_points_reached_exception();
|
|
||||||
};
|
|
||||||
|
|
||||||
auto function_output_iterator
|
|
||||||
= boost::make_function_output_iterator (back_insert_with_limit);
|
|
||||||
|
|
||||||
tree.search (function_output_iterator, fs);
|
|
||||||
}
|
|
||||||
catch (const Maximum_points_reached_exception&)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
// Fallback, if less than 3 points are return, search for the 3
|
|
||||||
// first points
|
|
||||||
if (points.size() < 3)
|
|
||||||
k = 3;
|
|
||||||
// Else, no need to search for K nearest neighbors
|
|
||||||
else
|
|
||||||
k = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k != 0)
|
|
||||||
{
|
|
||||||
// Gather set of (k+1) neighboring points.
|
|
||||||
// Perform k+1 queries (as in point set, the query point is
|
|
||||||
// output first). Search may be aborted if k is greater
|
|
||||||
// than number of input points.
|
|
||||||
points.reserve(k+1);
|
|
||||||
Neighbor_search search(tree,query,k+1);
|
|
||||||
Search_iterator search_iterator = search.begin();
|
|
||||||
unsigned int i;
|
|
||||||
for(i=0;i<(k+1);i++)
|
|
||||||
{
|
|
||||||
if(search_iterator == search.end())
|
|
||||||
break; // premature ending
|
|
||||||
points.push_back(search_iterator->first);
|
|
||||||
search_iterator++;
|
|
||||||
}
|
|
||||||
CGAL_point_set_processing_precondition(points.size() >= 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} } } // namespace CGAL::Point_set_processing_3::internal
|
|
||||||
|
|
||||||
#endif // CGAL_PSP_INTERNAL_NEIGHBOR_QUERY_H
|
|
||||||
|
|
@ -17,18 +17,19 @@
|
||||||
#include <CGAL/disable_warnings.h>
|
#include <CGAL/disable_warnings.h>
|
||||||
|
|
||||||
#include <CGAL/number_type_config.h>
|
#include <CGAL/number_type_config.h>
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
#include <CGAL/Point_set_processing_3/internal/Callback_wrapper.h>
|
||||||
#include <CGAL/Point_set_processing_3/internal/neighbor_query.h>
|
#include <CGAL/for_each.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
#include <CGAL/Point_with_normal_3.h>
|
|
||||||
#include <CGAL/squared_distance_3.h>
|
#include <CGAL/squared_distance_3.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <CGAL/boost/graph/Named_function_parameters.h>
|
#include <CGAL/boost/graph/Named_function_parameters.h>
|
||||||
#include <CGAL/boost/graph/named_params_helper.h>
|
#include <CGAL/boost/graph/named_params_helper.h>
|
||||||
|
|
||||||
|
#include <boost/iterator/zip_iterator.hpp>
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -38,23 +39,6 @@
|
||||||
#include <CGAL/Memory_sizer.h>
|
#include <CGAL/Memory_sizer.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/Parallel_callback.h>
|
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/blocked_range.h>
|
|
||||||
#include <tbb/scalable_allocator.h>
|
|
||||||
#include <atomic>
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
// Default allocator: use TBB allocators if available
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
# define CGAL_PSP3_DEFAULT_ALLOCATOR tbb::scalable_allocator
|
|
||||||
#else // CGAL_LINKED_WITH_TBB
|
|
||||||
# define CGAL_PSP3_DEFAULT_ALLOCATOR std::allocator
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
|
|
||||||
//#define CGAL_PSP3_VERBOSE
|
//#define CGAL_PSP3_VERBOSE
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
@ -66,47 +50,6 @@ namespace CGAL {
|
||||||
|
|
||||||
namespace bilateral_smooth_point_set_internal{
|
namespace bilateral_smooth_point_set_internal{
|
||||||
|
|
||||||
// Item in the Kd-tree: position (Point_3) + index
|
|
||||||
template <typename Kernel>
|
|
||||||
class Kd_tree_element : public Point_with_normal_3<Kernel>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
unsigned int index;
|
|
||||||
|
|
||||||
// basic geometric types
|
|
||||||
typedef typename CGAL::Origin Origin;
|
|
||||||
typedef CGAL::Point_with_normal_3<Kernel> Base;
|
|
||||||
|
|
||||||
Kd_tree_element(const Origin& o = ORIGIN, unsigned int id=0)
|
|
||||||
: Base(o), index(id)
|
|
||||||
{}
|
|
||||||
Kd_tree_element(const Base& p, unsigned int id=0)
|
|
||||||
: Base(p), index(id)
|
|
||||||
{}
|
|
||||||
Kd_tree_element(const Kd_tree_element& other)
|
|
||||||
: Base(other), index(other.index)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Kd_tree_element& operator=(const Kd_tree_element&)=default;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Helper class for the Kd-tree
|
|
||||||
template <typename Kernel>
|
|
||||||
class Kd_tree_gt : public Kernel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef Kd_tree_element<Kernel> Point_3;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Kernel>
|
|
||||||
class Kd_tree_traits : public CGAL::Search_traits_3<Kd_tree_gt<Kernel> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename Kernel::Point_3 PointType;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Compute bilateral projection for each point
|
/// Compute bilateral projection for each point
|
||||||
/// according to their KNN neighborhood points
|
/// according to their KNN neighborhood points
|
||||||
///
|
///
|
||||||
|
|
@ -117,12 +60,14 @@ public:
|
||||||
///
|
///
|
||||||
/// @return
|
/// @return
|
||||||
|
|
||||||
template <typename Kernel>
|
template <typename Kernel, typename PointRange,
|
||||||
CGAL::Point_with_normal_3<Kernel>
|
typename PointMap, typename VectorMap>
|
||||||
|
std::pair<typename Kernel::Point_3, typename Kernel::Vector_3>
|
||||||
compute_denoise_projection(
|
compute_denoise_projection(
|
||||||
const CGAL::Point_with_normal_3<Kernel>& query, ///< 3D point to project
|
const typename PointRange::iterator::value_type& vt,
|
||||||
const std::vector<CGAL::Point_with_normal_3<Kernel>,
|
PointMap point_map,
|
||||||
CGAL_PSP3_DEFAULT_ALLOCATOR<CGAL::Point_with_normal_3<Kernel> > >& neighbor_pwns, //
|
VectorMap normal_map,
|
||||||
|
const std::vector<typename PointRange::iterator>& neighbor_pwns,
|
||||||
typename Kernel::FT radius, ///< accept neighborhood radius
|
typename Kernel::FT radius, ///< accept neighborhood radius
|
||||||
typename Kernel::FT sharpness_angle ///< control sharpness(0-90)
|
typename Kernel::FT sharpness_angle ///< control sharpness(0-90)
|
||||||
)
|
)
|
||||||
|
|
@ -133,7 +78,6 @@ compute_denoise_projection(
|
||||||
|
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
typedef CGAL::Point_with_normal_3<Kernel> Pwn;
|
|
||||||
typedef typename Kernel::Vector_3 Vector;
|
typedef typename Kernel::Vector_3 Vector;
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename Kernel::Point_3 Point;
|
||||||
|
|
||||||
|
|
@ -148,23 +92,21 @@ compute_denoise_projection(
|
||||||
FT cos_sigma = cos(sharpness_angle * CGAL_PI / 180.0);
|
FT cos_sigma = cos(sharpness_angle * CGAL_PI / 180.0);
|
||||||
FT sharpness_bandwidth = std::pow((CGAL::max)(1e-8, 1 - cos_sigma), 2);
|
FT sharpness_bandwidth = std::pow((CGAL::max)(1e-8, 1 - cos_sigma), 2);
|
||||||
|
|
||||||
typename std::vector<Pwn,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwn> >::const_iterator
|
for (typename PointRange::iterator it : neighbor_pwns)
|
||||||
pwn_iter = neighbor_pwns.begin();
|
|
||||||
for (; pwn_iter != neighbor_pwns.end(); ++pwn_iter)
|
|
||||||
{
|
{
|
||||||
const Point& np = pwn_iter->position();
|
const Point& np = get(point_map, *it);
|
||||||
const Vector& nn = pwn_iter->normal();
|
const Vector& nn = get(normal_map, *it);
|
||||||
|
|
||||||
FT dist2 = CGAL::squared_distance(query.position(), np);
|
FT dist2 = CGAL::squared_distance(get(point_map, vt), np);
|
||||||
if (dist2 < radius2)
|
if (dist2 < radius2)
|
||||||
{
|
{
|
||||||
FT theta = std::exp(dist2 * iradius16);
|
FT theta = std::exp(dist2 * iradius16);
|
||||||
FT psi = std::exp(-std::pow(1 - query.normal() * nn, 2)
|
FT psi = std::exp(-std::pow(1 - get(normal_map, vt) * nn, 2)
|
||||||
/ sharpness_bandwidth);
|
/ sharpness_bandwidth);
|
||||||
|
|
||||||
weight = theta * psi;
|
weight = theta * psi;
|
||||||
|
|
||||||
project_dist_sum += ((query.position() - np) * nn) * weight;
|
project_dist_sum += ((get(point_map, vt) - np) * nn) * weight;
|
||||||
project_weight_sum += weight;
|
project_weight_sum += weight;
|
||||||
normal_sum = normal_sum + nn * weight;
|
normal_sum = normal_sum + nn * weight;
|
||||||
}
|
}
|
||||||
|
|
@ -173,10 +115,10 @@ compute_denoise_projection(
|
||||||
Vector update_normal = normal_sum / project_weight_sum;
|
Vector update_normal = normal_sum / project_weight_sum;
|
||||||
update_normal = update_normal / sqrt(update_normal.squared_length());
|
update_normal = update_normal / sqrt(update_normal.squared_length());
|
||||||
|
|
||||||
Point update_point = query.position() - update_normal *
|
Point update_point = get(point_map, vt) - update_normal *
|
||||||
(project_dist_sum / project_weight_sum);
|
(project_dist_sum / project_weight_sum);
|
||||||
|
|
||||||
return Pwn(update_point, update_normal);
|
return std::make_pair (update_point, update_normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes max-spacing of one query point from K nearest neighbors.
|
/// Computes max-spacing of one query point from K nearest neighbors.
|
||||||
|
|
@ -187,41 +129,30 @@ compute_denoise_projection(
|
||||||
/// @tparam Tree KD-tree.
|
/// @tparam Tree KD-tree.
|
||||||
///
|
///
|
||||||
/// @return max spacing.
|
/// @return max spacing.
|
||||||
template < typename Kernel,
|
template <typename NeighborQuery>
|
||||||
typename Tree >
|
typename NeighborQuery::Kernel::FT
|
||||||
typename Kernel::FT
|
|
||||||
compute_max_spacing(
|
compute_max_spacing(
|
||||||
const CGAL::Point_with_normal_3<Kernel>& query, ///< 3D point
|
const typename NeighborQuery::value_type& vt,
|
||||||
Tree& tree, ///< KD-tree
|
typename NeighborQuery::Point_map point_map,
|
||||||
|
NeighborQuery& neighbor_query, ///< KD-tree
|
||||||
unsigned int k) ///< number of neighbors
|
unsigned int k) ///< number of neighbors
|
||||||
{
|
{
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename NeighborQuery::Kernel Kernel;
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
typedef CGAL::Point_with_normal_3<Kernel> Pwn;
|
|
||||||
|
|
||||||
// types for K nearest neighbors search
|
|
||||||
typedef bilateral_smooth_point_set_internal::Kd_tree_traits<Kernel> Tree_traits;
|
|
||||||
typedef CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::iterator Search_iterator;
|
|
||||||
|
|
||||||
// performs k + 1 queries (if unique the query point is
|
// performs k + 1 queries (if unique the query point is
|
||||||
// output first). search may be aborted when k is greater
|
// output first). search may be aborted when k is greater
|
||||||
// than number of input points
|
// than number of input points
|
||||||
Neighbor_search search(tree,query,k+1);
|
|
||||||
Search_iterator search_iterator = search.begin();
|
|
||||||
++search_iterator;
|
|
||||||
FT max_distance = (FT)0.0;
|
FT max_distance = (FT)0.0;
|
||||||
unsigned int i;
|
neighbor_query.get_iterators
|
||||||
for(i = 0; i < (k+1) ; ++i)
|
(get(point_map, vt), k, (FT)(0.0),
|
||||||
|
boost::make_function_output_iterator
|
||||||
|
([&](const typename NeighborQuery::input_iterator& it)
|
||||||
{
|
{
|
||||||
if(search_iterator == search.end())
|
double dist2 = CGAL::squared_distance (get(point_map, vt), get(point_map, *it));
|
||||||
break; // premature ending
|
|
||||||
|
|
||||||
Pwn pwn = search_iterator->first;
|
|
||||||
double dist2 = CGAL::squared_distance(query.position(), pwn.position());
|
|
||||||
max_distance = (CGAL::max)(dist2, max_distance);
|
max_distance = (CGAL::max)(dist2, max_distance);
|
||||||
++search_iterator;
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
// output max spacing
|
// output max spacing
|
||||||
return std::sqrt(max_distance);
|
return std::sqrt(max_distance);
|
||||||
|
|
@ -231,102 +162,6 @@ compute_max_spacing(
|
||||||
|
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
/// \cond SKIP_IN_MANUAL
|
|
||||||
/// This is for parallelization of function: bilateral_smooth_point_set()
|
|
||||||
template <typename Kernel, typename Tree>
|
|
||||||
class Compute_pwns_neighbors
|
|
||||||
{
|
|
||||||
typedef typename CGAL::Point_with_normal_3<Kernel> Pwn;
|
|
||||||
typedef typename std::vector<Pwn,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwn> > Pwns;
|
|
||||||
typedef typename std::vector<Pwns,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwns> >
|
|
||||||
Pwns_neighbors;
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
|
|
||||||
unsigned int m_k;
|
|
||||||
FT m_neighbor_radius;
|
|
||||||
const Tree & m_tree;
|
|
||||||
const Pwns & m_pwns;
|
|
||||||
Pwns_neighbors & m_pwns_neighbors;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Compute_pwns_neighbors(unsigned int k, FT neighbor_radius, const Tree &tree,
|
|
||||||
const Pwns &pwns, Pwns_neighbors &neighbors,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted)
|
|
||||||
: m_k(k), m_neighbor_radius (neighbor_radius), m_tree(tree)
|
|
||||||
, m_pwns(pwns), m_pwns_neighbors(neighbors)
|
|
||||||
, advancement (advancement), interrupted (interrupted) {}
|
|
||||||
|
|
||||||
void operator() ( const tbb::blocked_range<size_t>& r ) const
|
|
||||||
{
|
|
||||||
for (size_t i = r.begin(); i!=r.end(); i++)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
|
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
|
||||||
(m_pwns[i], m_tree, m_k, m_neighbor_radius, m_pwns_neighbors[i]);
|
|
||||||
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
/// \cond SKIP_IN_MANUAL
|
|
||||||
/// This is for parallelization of function: compute_denoise_projection()
|
|
||||||
template <typename Kernel>
|
|
||||||
class Pwn_updater
|
|
||||||
{
|
|
||||||
typedef typename CGAL::Point_with_normal_3<Kernel> Pwn;
|
|
||||||
typedef typename std::vector<Pwn,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwn> > Pwns;
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
|
|
||||||
FT sharpness_angle;
|
|
||||||
FT radius;
|
|
||||||
Pwns* pwns;
|
|
||||||
Pwns* update_pwns;
|
|
||||||
std::vector<Pwns,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwns> >* pwns_neighbors;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Pwn_updater(FT sharpness,
|
|
||||||
FT r,
|
|
||||||
Pwns *in,
|
|
||||||
Pwns *out,
|
|
||||||
std::vector<Pwns,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwns> >* neighbors,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted):
|
|
||||||
sharpness_angle(sharpness),
|
|
||||||
radius(r),
|
|
||||||
pwns(in),
|
|
||||||
update_pwns(out),
|
|
||||||
pwns_neighbors(neighbors),
|
|
||||||
advancement (advancement),
|
|
||||||
interrupted (interrupted) {}
|
|
||||||
|
|
||||||
void operator() ( const tbb::blocked_range<size_t>& r ) const
|
|
||||||
{
|
|
||||||
for (size_t i = r.begin(); i != r.end(); ++i)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
(*update_pwns)[i] = bilateral_smooth_point_set_internal::
|
|
||||||
compute_denoise_projection<Kernel>((*pwns)[i],
|
|
||||||
(*pwns_neighbors)[i],
|
|
||||||
radius,
|
|
||||||
sharpness_angle);
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/// \endcond
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Public section
|
// Public section
|
||||||
|
|
@ -400,16 +235,18 @@ bilateral_smooth_point_set(
|
||||||
using parameters::get_parameter;
|
using parameters::get_parameter;
|
||||||
|
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename PointRange::iterator iterator;
|
||||||
|
typedef typename iterator::value_type value_type;
|
||||||
typedef typename CGAL::GetPointMap<PointRange, NamedParameters>::type PointMap;
|
typedef typename CGAL::GetPointMap<PointRange, NamedParameters>::type PointMap;
|
||||||
typedef typename Point_set_processing_3::GetNormalMap<PointRange, NamedParameters>::type NormalMap;
|
typedef typename Point_set_processing_3::GetNormalMap<PointRange, NamedParameters>::type NormalMap;
|
||||||
typedef typename Point_set_processing_3::GetK<PointRange, NamedParameters>::Kernel Kernel;
|
typedef typename Point_set_processing_3::GetK<PointRange, NamedParameters>::Kernel Kernel;
|
||||||
|
typedef typename Kernel::Point_3 Point_3;
|
||||||
|
typedef typename Kernel::Vector_3 Vector_3;
|
||||||
|
|
||||||
CGAL_static_assertion_msg(!(boost::is_same<NormalMap,
|
CGAL_static_assertion_msg(!(boost::is_same<NormalMap,
|
||||||
typename Point_set_processing_3::GetNormalMap<PointRange, NamedParameters>::NoMap>::value),
|
typename Point_set_processing_3::GetNormalMap<PointRange, NamedParameters>::NoMap>::value),
|
||||||
"Error: no normal map");
|
"Error: no normal map");
|
||||||
|
|
||||||
typedef typename CGAL::Point_with_normal_3<Kernel> Pwn;
|
|
||||||
typedef typename std::vector<Pwn,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwn> > Pwns;
|
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
double sharpness_angle = choose_parameter(get_parameter(np, internal_np::sharpness_angle), 30.);
|
double sharpness_angle = choose_parameter(get_parameter(np, internal_np::sharpness_angle), 30.);
|
||||||
|
|
@ -420,43 +257,20 @@ bilateral_smooth_point_set(
|
||||||
CGAL_point_set_processing_precondition(k > 1);
|
CGAL_point_set_processing_precondition(k > 1);
|
||||||
|
|
||||||
// types for K nearest neighbors search structure
|
// types for K nearest neighbors search structure
|
||||||
typedef bilateral_smooth_point_set_internal::
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, PointRange&, PointMap> Neighbor_query;
|
||||||
Kd_tree_element<Kernel> Kd_tree_element;
|
|
||||||
typedef bilateral_smooth_point_set_internal::Kd_tree_traits<Kernel> Tree_traits;
|
|
||||||
typedef CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
PointMap point_map = choose_parameter<PointMap>(get_parameter(np, internal_np::point_map));
|
PointMap point_map = choose_parameter<PointMap>(get_parameter(np, internal_np::point_map));
|
||||||
NormalMap normal_map = choose_parameter<NormalMap>(get_parameter(np, internal_np::normal_map));
|
NormalMap normal_map = choose_parameter<NormalMap>(get_parameter(np, internal_np::normal_map));
|
||||||
FT neighbor_radius = choose_parameter(get_parameter(np, internal_np::neighbor_radius), FT(0));
|
FT neighbor_radius = choose_parameter(get_parameter(np, internal_np::neighbor_radius), FT(0));
|
||||||
|
|
||||||
// copy points and normals
|
std::size_t nb_points = points.size();
|
||||||
Pwns pwns;
|
|
||||||
for(typename PointRange::iterator it = points.begin(); it != points.end(); ++it)
|
|
||||||
{
|
|
||||||
typename boost::property_traits<PointMap>::reference p = get(point_map, *it);
|
|
||||||
typename boost::property_traits<NormalMap>::reference n = get(normal_map, *it);
|
|
||||||
CGAL_point_set_processing_precondition(n.squared_length() > 1e-10);
|
|
||||||
|
|
||||||
pwns.push_back(Pwn(p, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t nb_points = pwns.size();
|
|
||||||
|
|
||||||
#ifdef CGAL_PSP3_VERBOSE
|
#ifdef CGAL_PSP3_VERBOSE
|
||||||
std::cout << "Initialization and compute max spacing: " << std::endl;
|
std::cout << "Initialization and compute max spacing: " << std::endl;
|
||||||
#endif
|
#endif
|
||||||
// initiate a KD-tree search for points
|
// initiate a KD-tree search for points
|
||||||
std::vector<Kd_tree_element,
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
CGAL_PSP3_DEFAULT_ALLOCATOR<Kd_tree_element> > treeElements;
|
|
||||||
treeElements.reserve(pwns.size());
|
|
||||||
typename std::vector<Pwn,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwn> >::iterator
|
|
||||||
pwn_iter = pwns.begin();
|
|
||||||
for (unsigned int i = 0; pwn_iter != pwns.end(); ++pwn_iter)
|
|
||||||
{
|
|
||||||
treeElements.push_back(Kd_tree_element(*pwn_iter, i));
|
|
||||||
}
|
|
||||||
Tree tree(treeElements.begin(), treeElements.end());
|
|
||||||
// Guess spacing
|
// Guess spacing
|
||||||
#ifdef CGAL_PSP3_VERBOSE
|
#ifdef CGAL_PSP3_VERBOSE
|
||||||
CGAL::Real_timer task_timer;
|
CGAL::Real_timer task_timer;
|
||||||
|
|
@ -464,10 +278,10 @@ bilateral_smooth_point_set(
|
||||||
#endif
|
#endif
|
||||||
FT guess_neighbor_radius = 0.0;
|
FT guess_neighbor_radius = 0.0;
|
||||||
|
|
||||||
for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); ++pwn_iter)
|
for (const value_type& vt : points)
|
||||||
{
|
{
|
||||||
FT max_spacing = bilateral_smooth_point_set_internal::
|
FT max_spacing = bilateral_smooth_point_set_internal::
|
||||||
compute_max_spacing<Kernel,Tree>(*pwn_iter, tree, k);
|
compute_max_spacing (vt, point_map, neighbor_query, k);
|
||||||
guess_neighbor_radius = (CGAL::max)(max_spacing, guess_neighbor_radius);
|
guess_neighbor_radius = (CGAL::max)(max_spacing, guess_neighbor_radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -486,49 +300,40 @@ bilateral_smooth_point_set(
|
||||||
task_timer.start();
|
task_timer.start();
|
||||||
#endif
|
#endif
|
||||||
// compute all neighbors
|
// compute all neighbors
|
||||||
std::vector<Pwns,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwns> > pwns_neighbors;
|
typedef std::vector<iterator> iterators;
|
||||||
|
std::vector<iterators> pwns_neighbors;
|
||||||
pwns_neighbors.resize(nb_points);
|
pwns_neighbors.resize(nb_points);
|
||||||
|
|
||||||
#ifndef CGAL_LINKED_WITH_TBB
|
Point_set_processing_3::internal::Callback_wrapper<ConcurrencyTag>
|
||||||
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
callback_wrapper (callback, 2 * nb_points);
|
||||||
"Parallel_tag is enabled but TBB is unavailable.");
|
|
||||||
#else
|
typedef boost::zip_iterator<boost::tuple<iterator, typename std::vector<iterators>::iterator> > Zip_iterator;
|
||||||
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
|
|
||||||
|
CGAL::for_each<ConcurrencyTag>
|
||||||
|
(CGAL::make_range (boost::make_zip_iterator (boost::make_tuple (points.begin(), pwns_neighbors.begin())),
|
||||||
|
boost::make_zip_iterator (boost::make_tuple (points.end(), pwns_neighbors.end()))),
|
||||||
|
[&](const typename Zip_iterator::reference& t)
|
||||||
{
|
{
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
if (callback_wrapper.interrupted())
|
||||||
parallel_callback (callback, 2 * nb_points);
|
return false;
|
||||||
|
|
||||||
Compute_pwns_neighbors<Kernel, Tree> f(k, neighbor_radius, tree, pwns, pwns_neighbors,
|
neighbor_query.get_iterators (get(point_map, get<0>(t)), k, neighbor_radius,
|
||||||
parallel_callback.advancement(),
|
std::back_inserter (get<1>(t)));
|
||||||
parallel_callback.interrupted());
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, nb_points), f);
|
|
||||||
|
|
||||||
bool interrupted = parallel_callback.interrupted();
|
++ callback_wrapper.advancement();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
bool interrupted = callback_wrapper.interrupted();
|
||||||
|
|
||||||
// We interrupt by hand as counter only goes halfway and won't terminate by itself
|
// We interrupt by hand as counter only goes halfway and won't terminate by itself
|
||||||
parallel_callback.interrupted() = true;
|
callback_wrapper.interrupted() = true;
|
||||||
parallel_callback.join();
|
callback_wrapper.join();
|
||||||
|
|
||||||
// If interrupted during this step, nothing is computed, we return NaN
|
// If interrupted during this step, nothing is computed, we return NaN
|
||||||
if (interrupted)
|
if (interrupted)
|
||||||
return std::numeric_limits<double>::quiet_NaN();
|
return std::numeric_limits<double>::quiet_NaN();
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
typename std::vector<Pwns,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwns> >::iterator
|
|
||||||
pwns_iter = pwns_neighbors.begin();
|
|
||||||
|
|
||||||
std::size_t nb = 0;
|
|
||||||
for(pwn_iter = pwns.begin(); pwn_iter != pwns.end(); ++pwn_iter, ++pwns_iter, ++ nb)
|
|
||||||
{
|
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
|
||||||
(*pwn_iter, tree, k, neighbor_radius, *pwns_iter);
|
|
||||||
|
|
||||||
if (callback && !callback ((nb+1) / double(2. * nb_points)))
|
|
||||||
return std::numeric_limits<double>::quiet_NaN();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CGAL_PSP3_VERBOSE
|
#ifdef CGAL_PSP3_VERBOSE
|
||||||
task_timer.stop();
|
task_timer.stop();
|
||||||
|
|
@ -541,53 +346,45 @@ bilateral_smooth_point_set(
|
||||||
task_timer.start();
|
task_timer.start();
|
||||||
#endif
|
#endif
|
||||||
// update points and normals
|
// update points and normals
|
||||||
Pwns update_pwns(nb_points);
|
std::vector<std::pair<Point_3, Vector_3> > update_pwns(nb_points);
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
callback_wrapper.reset (2 * nb_points, nb_points);
|
||||||
if(boost::is_convertible<ConcurrencyTag, CGAL::Parallel_tag>::value)
|
|
||||||
|
typedef boost::zip_iterator
|
||||||
|
<boost::tuple<iterator,
|
||||||
|
typename std::vector<iterators>::iterator,
|
||||||
|
typename std::vector<std::pair<Point_3, Vector_3> >::iterator> > Zip_iterator_2;
|
||||||
|
|
||||||
|
|
||||||
|
CGAL::for_each<ConcurrencyTag>
|
||||||
|
(CGAL::make_range (boost::make_zip_iterator (boost::make_tuple
|
||||||
|
(points.begin(), pwns_neighbors.begin(), update_pwns.begin())),
|
||||||
|
boost::make_zip_iterator (boost::make_tuple
|
||||||
|
(points.end(), pwns_neighbors.end(), update_pwns.end()))),
|
||||||
|
[&](const typename Zip_iterator_2::reference& t)
|
||||||
{
|
{
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
if (callback_wrapper.interrupted())
|
||||||
parallel_callback (callback, 2 * nb_points, nb_points);
|
return false;
|
||||||
|
|
||||||
//tbb::task_scheduler_init init(4);
|
get<2>(t) = bilateral_smooth_point_set_internal::
|
||||||
tbb::blocked_range<size_t> block(0, nb_points);
|
compute_denoise_projection<Kernel, PointRange>
|
||||||
Pwn_updater<Kernel> pwn_updater(sharpness_angle,
|
(get<0>(t),
|
||||||
guess_neighbor_radius,
|
point_map, normal_map,
|
||||||
&pwns,
|
get<1>(t),
|
||||||
&update_pwns,
|
|
||||||
&pwns_neighbors,
|
|
||||||
parallel_callback.advancement(),
|
|
||||||
parallel_callback.interrupted());
|
|
||||||
tbb::parallel_for(block, pwn_updater);
|
|
||||||
|
|
||||||
parallel_callback.join();
|
|
||||||
|
|
||||||
// If interrupted during this step, nothing is computed, we return NaN
|
|
||||||
if (parallel_callback.interrupted())
|
|
||||||
return std::numeric_limits<double>::quiet_NaN();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
{
|
|
||||||
std::size_t nb = nb_points;
|
|
||||||
|
|
||||||
typename std::vector<Pwn,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwn> >::iterator
|
|
||||||
update_iter = update_pwns.begin();
|
|
||||||
typename std::vector<Pwns,CGAL_PSP3_DEFAULT_ALLOCATOR<Pwns> >::iterator
|
|
||||||
neighbor_iter = pwns_neighbors.begin();
|
|
||||||
for(pwn_iter = pwns.begin(); pwn_iter != pwns.end();
|
|
||||||
++pwn_iter, ++update_iter, ++neighbor_iter, ++ nb)
|
|
||||||
{
|
|
||||||
*update_iter = bilateral_smooth_point_set_internal::
|
|
||||||
compute_denoise_projection<Kernel>
|
|
||||||
(*pwn_iter,
|
|
||||||
*neighbor_iter,
|
|
||||||
guess_neighbor_radius,
|
guess_neighbor_radius,
|
||||||
sharpness_angle);
|
sharpness_angle);
|
||||||
if (callback && !callback ((nb+1) / double(2. * nb_points)))
|
|
||||||
|
++ callback_wrapper.advancement();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
callback_wrapper.join();
|
||||||
|
|
||||||
|
// If interrupted during this step, nothing is computed, we return NaN
|
||||||
|
if (callback_wrapper.interrupted())
|
||||||
return std::numeric_limits<double>::quiet_NaN();
|
return std::numeric_limits<double>::quiet_NaN();
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef CGAL_PSP3_VERBOSE
|
#ifdef CGAL_PSP3_VERBOSE
|
||||||
task_timer.stop();
|
task_timer.stop();
|
||||||
memory = CGAL::Memory_sizer().virtual_size();
|
memory = CGAL::Memory_sizer().virtual_size();
|
||||||
|
|
@ -596,13 +393,13 @@ bilateral_smooth_point_set(
|
||||||
#endif
|
#endif
|
||||||
// save results
|
// save results
|
||||||
FT sum_move_error = 0;
|
FT sum_move_error = 0;
|
||||||
typename PointRange::iterator it = points.begin();
|
std::size_t nb = 0;
|
||||||
for(unsigned int i = 0 ; it != points.end(); ++it, ++i)
|
for (value_type& vt : points)
|
||||||
{
|
{
|
||||||
typename boost::property_traits<PointMap>::reference p = get(point_map, *it);
|
sum_move_error += CGAL::squared_distance(get(point_map, vt), update_pwns[nb].first);
|
||||||
sum_move_error += CGAL::squared_distance(p, update_pwns[i].position());
|
put (point_map, vt, update_pwns[nb].first);
|
||||||
put (point_map, *it, update_pwns[i].position());
|
put (normal_map, vt, update_pwns[nb].second);
|
||||||
put (normal_map, *it, update_pwns[i].normal());
|
++ nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum_move_error / nb_points;
|
return sum_move_error / nb_points;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@
|
||||||
|
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Search_traits_3.h>
|
||||||
#include <CGAL/squared_distance_3.h>
|
#include <CGAL/squared_distance_3.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
|
#include <CGAL/Point_set_processing_3/internal/Callback_wrapper.h>
|
||||||
|
#include <CGAL/for_each.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
#include <CGAL/assertions.h>
|
#include <CGAL/assertions.h>
|
||||||
|
|
@ -27,15 +29,12 @@
|
||||||
#include <CGAL/boost/graph/Named_function_parameters.h>
|
#include <CGAL/boost/graph/Named_function_parameters.h>
|
||||||
#include <CGAL/boost/graph/named_params_helper.h>
|
#include <CGAL/boost/graph/named_params_helper.h>
|
||||||
|
|
||||||
|
#include <boost/iterator/zip_iterator.hpp>
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/Parallel_callback.h>
|
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/blocked_range.h>
|
|
||||||
#include <tbb/scalable_allocator.h>
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
#ifdef DOXYGEN_RUNNING
|
#ifdef DOXYGEN_RUNNING
|
||||||
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters
|
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters
|
||||||
|
|
@ -60,81 +59,37 @@ namespace internal {
|
||||||
/// @tparam Tree KD-tree.
|
/// @tparam Tree KD-tree.
|
||||||
///
|
///
|
||||||
/// @return average spacing (scalar).
|
/// @return average spacing (scalar).
|
||||||
template < typename Kernel,
|
template <typename NeighborQuery>
|
||||||
typename Tree >
|
typename NeighborQuery::Kernel::FT
|
||||||
typename Kernel::FT
|
compute_average_spacing(const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point whose spacing we want to compute
|
||||||
compute_average_spacing(const typename Kernel::Point_3& query, ///< 3D point whose spacing we want to compute
|
const NeighborQuery& neighbor_query, ///< KD-tree
|
||||||
const Tree& tree, ///< KD-tree
|
|
||||||
unsigned int k) ///< number of neighbors
|
unsigned int k) ///< number of neighbors
|
||||||
{
|
{
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename NeighborQuery::Kernel Kernel;
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename Kernel::Point_3 Point;
|
||||||
|
|
||||||
// types for K nearest neighbors search
|
|
||||||
typedef Search_traits_3<Kernel> Tree_traits;
|
|
||||||
typedef Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::iterator Search_iterator;
|
|
||||||
|
|
||||||
// performs k + 1 queries (if unique the query point is
|
// performs k + 1 queries (if unique the query point is
|
||||||
// output first). search may be aborted when k is greater
|
// output first). search may be aborted when k is greater
|
||||||
// than number of input points
|
// than number of input points
|
||||||
Neighbor_search search(tree,query,k+1);
|
|
||||||
Search_iterator search_iterator = search.begin();
|
|
||||||
FT sum_distances = (FT)0.0;
|
FT sum_distances = (FT)0.0;
|
||||||
unsigned int i;
|
unsigned int i = 0;
|
||||||
for(i=0;i<(k+1);i++)
|
neighbor_query.get_points
|
||||||
|
(query, k, 0,
|
||||||
|
boost::make_function_output_iterator
|
||||||
|
([&](const Point& p)
|
||||||
{
|
{
|
||||||
if(search_iterator == search.end())
|
|
||||||
break; // premature ending
|
|
||||||
|
|
||||||
Point p = search_iterator->first;
|
|
||||||
sum_distances += std::sqrt(CGAL::squared_distance (query,p));
|
sum_distances += std::sqrt(CGAL::squared_distance (query,p));
|
||||||
search_iterator++;
|
++ i;
|
||||||
}
|
}));
|
||||||
|
|
||||||
// output average spacing
|
// output average spacing
|
||||||
return sum_distances / (FT)i;
|
return sum_distances / (FT)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
template <typename Kernel, typename Tree>
|
|
||||||
class Compute_average_spacings {
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
const Tree& tree;
|
|
||||||
const unsigned int k;
|
|
||||||
const std::vector<Point>& input;
|
|
||||||
std::vector<FT>& output;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Compute_average_spacings(Tree& tree, unsigned int k, std::vector<Point>& points,
|
|
||||||
std::vector<FT>& output,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted)
|
|
||||||
: tree(tree), k (k), input (points), output (output)
|
|
||||||
, advancement (advancement)
|
|
||||||
, interrupted (interrupted)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void operator()(const tbb::blocked_range<std::size_t>& r) const
|
|
||||||
{
|
|
||||||
for( std::size_t i = r.begin(); i != r.end(); ++i)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
|
|
||||||
output[i] = CGAL::internal::compute_average_spacing<Kernel,Tree>(input[i], tree, k);
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
} /* namespace internal */
|
} /* namespace internal */
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
|
|
@ -195,20 +150,17 @@ compute_average_spacing(
|
||||||
using parameters::get_parameter;
|
using parameters::get_parameter;
|
||||||
|
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename PointRange::const_iterator iterator;
|
||||||
typedef typename CGAL::GetPointMap<PointRange, CGAL_BGL_NP_CLASS>::const_type PointMap;
|
typedef typename CGAL::GetPointMap<PointRange, CGAL_BGL_NP_CLASS>::const_type PointMap;
|
||||||
typedef typename Point_set_processing_3::GetK<PointRange, CGAL_BGL_NP_CLASS>::Kernel Kernel;
|
typedef typename Point_set_processing_3::GetK<PointRange, CGAL_BGL_NP_CLASS>::Kernel Kernel;
|
||||||
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap());
|
||||||
|
|
||||||
PointMap point_map = choose_parameter<PointMap>(get_parameter(np, internal_np::point_map));
|
|
||||||
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
||||||
std::function<bool(double)>());
|
std::function<bool(double)>());
|
||||||
|
|
||||||
// types for K nearest neighbors search structure
|
// types for K nearest neighbors search structure
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
typedef Search_traits_3<Kernel> Tree_traits;
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, const PointRange&, PointMap> Neighbor_query;
|
||||||
typedef Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
// precondition: at least one element in the container.
|
// precondition: at least one element in the container.
|
||||||
// to fix: should have at least three distinct points
|
// to fix: should have at least three distinct points
|
||||||
|
|
@ -219,32 +171,35 @@ compute_average_spacing(
|
||||||
CGAL_point_set_processing_precondition(k >= 2);
|
CGAL_point_set_processing_precondition(k >= 2);
|
||||||
|
|
||||||
// Instanciate a KD-tree search.
|
// Instanciate a KD-tree search.
|
||||||
// Note: We have to convert each input iterator to Point_3.
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
std::vector<Point> kd_tree_points;
|
|
||||||
for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++)
|
|
||||||
kd_tree_points.push_back(get(point_map, *it));
|
|
||||||
Tree tree(kd_tree_points.begin(), kd_tree_points.end());
|
|
||||||
|
|
||||||
// iterate over input points, compute and output normal
|
// iterate over input points, compute and output normal
|
||||||
// vectors (already normalized)
|
// vectors (already normalized)
|
||||||
FT sum_spacings = (FT)0.0;
|
FT sum_spacings = (FT)0.0;
|
||||||
std::size_t nb = 0;
|
std::size_t nb = 0;
|
||||||
|
std::size_t nb_points = std::distance(points.begin(), points.end());
|
||||||
|
|
||||||
#ifndef CGAL_LINKED_WITH_TBB
|
Point_set_processing_3::internal::Callback_wrapper<ConcurrencyTag>
|
||||||
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
callback_wrapper (callback, nb_points);
|
||||||
"Parallel_tag is enabled but TBB is unavailable.");
|
|
||||||
#else
|
std::vector<FT> spacings (nb_points, -1);
|
||||||
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
|
|
||||||
|
typedef boost::zip_iterator<boost::tuple<iterator, typename std::vector<FT>::iterator> > Zip_iterator;
|
||||||
|
|
||||||
|
CGAL::for_each<ConcurrencyTag>
|
||||||
|
(CGAL::make_range (boost::make_zip_iterator (boost::make_tuple (points.begin(), spacings.begin())),
|
||||||
|
boost::make_zip_iterator (boost::make_tuple (points.end(), spacings.end()))),
|
||||||
|
[&](const typename Zip_iterator::reference& t)
|
||||||
{
|
{
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
if (callback_wrapper.interrupted())
|
||||||
parallel_callback (callback, kd_tree_points.size());
|
return false;
|
||||||
|
|
||||||
std::vector<FT> spacings (kd_tree_points.size (), -1);
|
get<1>(t) = CGAL::internal::compute_average_spacing<Neighbor_query>
|
||||||
CGAL::internal::Compute_average_spacings<Kernel, Tree>
|
(get(point_map, get<0>(t)), neighbor_query, k);
|
||||||
f (tree, k, kd_tree_points, spacings,
|
++ callback_wrapper.advancement();
|
||||||
parallel_callback.advancement(),
|
|
||||||
parallel_callback.interrupted());
|
return true;
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, kd_tree_points.size ()), f);
|
});
|
||||||
|
|
||||||
for (unsigned int i = 0; i < spacings.size (); ++ i)
|
for (unsigned int i = 0; i < spacings.size (); ++ i)
|
||||||
if (spacings[i] >= 0.)
|
if (spacings[i] >= 0.)
|
||||||
|
|
@ -252,24 +207,7 @@ compute_average_spacing(
|
||||||
sum_spacings += spacings[i];
|
sum_spacings += spacings[i];
|
||||||
++ nb;
|
++ nb;
|
||||||
}
|
}
|
||||||
|
callback_wrapper.join();
|
||||||
parallel_callback.join();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
for(typename PointRange::const_iterator it = points.begin(); it != points.end(); it++, nb++)
|
|
||||||
{
|
|
||||||
sum_spacings += internal::compute_average_spacing<Kernel,Tree>(
|
|
||||||
get(point_map,*it),
|
|
||||||
tree,k);
|
|
||||||
if (callback && !callback ((nb+1) / double(kd_tree_points.size())))
|
|
||||||
{
|
|
||||||
++ nb;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return average spacing
|
// return average spacing
|
||||||
return sum_spacings / (FT)(nb);
|
return sum_spacings / (FT)(nb);
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
#include <CGAL/disable_warnings.h>
|
#include <CGAL/disable_warnings.h>
|
||||||
|
|
||||||
#include <CGAL/IO/trace.h>
|
#include <CGAL/IO/trace.h>
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
#include <CGAL/Point_set_processing_3/internal/Callback_wrapper.h>
|
||||||
#include <CGAL/Point_set_processing_3/internal/neighbor_query.h>
|
#include <CGAL/for_each.h>
|
||||||
#include <CGAL/Monge_via_jet_fitting.h>
|
#include <CGAL/Monge_via_jet_fitting.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
|
|
@ -32,13 +32,6 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/Parallel_callback.h>
|
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/blocked_range.h>
|
|
||||||
#include <tbb/scalable_allocator.h>
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -58,18 +51,16 @@ namespace internal {
|
||||||
/// @tparam Tree KD-tree.
|
/// @tparam Tree KD-tree.
|
||||||
///
|
///
|
||||||
/// @return Computed normal. Orientation is random.
|
/// @return Computed normal. Orientation is random.
|
||||||
template < typename Kernel,
|
template <typename SvdTraits, typename NeighborQuery>
|
||||||
typename SvdTraits,
|
typename NeighborQuery::Kernel::Vector_3
|
||||||
typename Tree
|
jet_estimate_normal(const typename NeighborQuery::Point_3& query, ///< point to compute the normal at
|
||||||
>
|
const NeighborQuery& neighbor_query, ///< KD-tree
|
||||||
typename Kernel::Vector_3
|
|
||||||
jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute the normal at
|
|
||||||
Tree& tree, ///< KD-tree
|
|
||||||
unsigned int k, ///< number of neighbors
|
unsigned int k, ///< number of neighbors
|
||||||
typename Kernel::FT neighbor_radius,
|
typename NeighborQuery::FT neighbor_radius,
|
||||||
unsigned int degree_fitting)
|
unsigned int degree_fitting)
|
||||||
{
|
{
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename NeighborQuery::Kernel Kernel;
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename Kernel::Point_3 Point;
|
||||||
|
|
||||||
// types for jet fitting
|
// types for jet fitting
|
||||||
|
|
@ -79,8 +70,7 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute
|
||||||
typedef typename Monge_jet_fitting::Monge_form Monge_form;
|
typedef typename Monge_jet_fitting::Monge_form Monge_form;
|
||||||
|
|
||||||
std::vector<Point> points;
|
std::vector<Point> points;
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points));
|
||||||
(query, tree, k, neighbor_radius, points);
|
|
||||||
|
|
||||||
// performs jet fitting
|
// performs jet fitting
|
||||||
Monge_jet_fitting monge_fit;
|
Monge_jet_fitting monge_fit;
|
||||||
|
|
@ -92,49 +82,6 @@ jet_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute
|
||||||
return monge_form.normal_direction();
|
return monge_form.normal_direction();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
template <typename Kernel, typename SvdTraits, typename Tree>
|
|
||||||
class Jet_estimate_normals {
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
typedef typename Kernel::Vector_3 Vector;
|
|
||||||
const Tree& tree;
|
|
||||||
const unsigned int k;
|
|
||||||
const FT neighbor_radius;
|
|
||||||
const unsigned int degree_fitting;
|
|
||||||
const std::vector<Point>& input;
|
|
||||||
std::vector<Vector>& output;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Jet_estimate_normals(Tree& tree, unsigned int k, FT neighbor_radius,
|
|
||||||
std::vector<Point>& points,
|
|
||||||
unsigned int degree_fitting, std::vector<Vector>& output,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted)
|
|
||||||
: tree(tree), k (k), neighbor_radius (neighbor_radius)
|
|
||||||
, degree_fitting (degree_fitting), input (points), output (output)
|
|
||||||
, advancement (advancement)
|
|
||||||
, interrupted (interrupted)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void operator()(const tbb::blocked_range<std::size_t>& r) const
|
|
||||||
{
|
|
||||||
for( std::size_t i = r.begin(); i != r.end(); ++i)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
output[i] = CGAL::internal::jet_estimate_normal<Kernel,SvdTraits>(input[i], tree, k, neighbor_radius, degree_fitting);
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace internal */
|
} /* namespace internal */
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
|
|
@ -202,6 +149,8 @@ jet_estimate_normals(
|
||||||
CGAL_TRACE("Calls jet_estimate_normals()\n");
|
CGAL_TRACE("Calls jet_estimate_normals()\n");
|
||||||
|
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename PointRange::iterator iterator;
|
||||||
|
typedef typename iterator::value_type value_type;
|
||||||
typedef typename CGAL::GetPointMap<PointRange, NamedParameters>::type PointMap;
|
typedef typename CGAL::GetPointMap<PointRange, NamedParameters>::type PointMap;
|
||||||
typedef typename Point_set_processing_3::GetNormalMap<PointRange, NamedParameters>::type NormalMap;
|
typedef typename Point_set_processing_3::GetNormalMap<PointRange, NamedParameters>::type NormalMap;
|
||||||
typedef typename Point_set_processing_3::GetK<PointRange, NamedParameters>::Kernel Kernel;
|
typedef typename Point_set_processing_3::GetK<PointRange, NamedParameters>::Kernel Kernel;
|
||||||
|
|
@ -223,15 +172,8 @@ jet_estimate_normals(
|
||||||
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
||||||
std::function<bool(double)>());
|
std::function<bool(double)>());
|
||||||
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
|
|
||||||
// Input points types
|
|
||||||
typedef typename boost::property_traits<NormalMap>::value_type Vector;
|
|
||||||
|
|
||||||
// types for K nearest neighbors search structure
|
// types for K nearest neighbors search structure
|
||||||
typedef typename CGAL::Search_traits_3<Kernel> Tree_traits;
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, PointRange&, PointMap> Neighbor_query;
|
||||||
typedef typename CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
// precondition: at least one element in the container.
|
// precondition: at least one element in the container.
|
||||||
// to fix: should have at least three distinct points
|
// to fix: should have at least three distinct points
|
||||||
|
|
@ -244,60 +186,32 @@ jet_estimate_normals(
|
||||||
std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE(" Creates KD-tree\n");
|
CGAL_TRACE(" Creates KD-tree\n");
|
||||||
|
|
||||||
typename PointRange::iterator it;
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
|
|
||||||
// Instanciate a KD-tree search.
|
|
||||||
// Note: We have to convert each input iterator to Point_3.
|
|
||||||
std::vector<Point> kd_tree_points;
|
|
||||||
for(it = points.begin(); it != points.end(); it++)
|
|
||||||
kd_tree_points.push_back(get(point_map, *it));
|
|
||||||
Tree tree(kd_tree_points.begin(), kd_tree_points.end());
|
|
||||||
|
|
||||||
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE(" Computes normals\n");
|
CGAL_TRACE(" Computes normals\n");
|
||||||
|
|
||||||
// iterate over input points, compute and output normal
|
std::size_t nb_points = points.size();
|
||||||
// vectors (already normalized)
|
|
||||||
#ifndef CGAL_LINKED_WITH_TBB
|
Point_set_processing_3::internal::Callback_wrapper<ConcurrencyTag>
|
||||||
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
callback_wrapper (callback, nb_points);
|
||||||
"Parallel_tag is enabled but TBB is unavailable.");
|
|
||||||
#else
|
CGAL::for_each<ConcurrencyTag>
|
||||||
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
|
(points,
|
||||||
|
[&](value_type& vt)
|
||||||
{
|
{
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
if (callback_wrapper.interrupted())
|
||||||
parallel_callback (callback, kd_tree_points.size());
|
return false;
|
||||||
|
|
||||||
std::vector<Vector> normals (kd_tree_points.size (),
|
put (normal_map, vt,
|
||||||
CGAL::NULL_VECTOR);
|
CGAL::internal::jet_estimate_normal<SvdTraits>
|
||||||
CGAL::internal::Jet_estimate_normals<Kernel, SvdTraits, Tree>
|
(get(point_map, vt), neighbor_query, k, neighbor_radius, degree_fitting));
|
||||||
f (tree, k, neighbor_radius,
|
++ callback_wrapper.advancement();
|
||||||
kd_tree_points, degree_fitting, normals,
|
|
||||||
parallel_callback.advancement(),
|
|
||||||
parallel_callback.interrupted());
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, kd_tree_points.size ()), f);
|
|
||||||
std::size_t i = 0;
|
|
||||||
for(it = points.begin(); it != points.end(); ++ it, ++ i)
|
|
||||||
if (normals[i] != CGAL::NULL_VECTOR)
|
|
||||||
put (normal_map, *it, normals[i]);
|
|
||||||
|
|
||||||
parallel_callback.join();
|
return true;
|
||||||
}
|
});
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
std::size_t nb = 0;
|
|
||||||
for(it = points.begin(); it != points.end(); it++, ++ nb)
|
|
||||||
{
|
|
||||||
Vector normal = internal::jet_estimate_normal<Kernel,SvdTraits,Tree>(
|
|
||||||
get(point_map,*it),
|
|
||||||
tree, k, neighbor_radius, degree_fitting);
|
|
||||||
|
|
||||||
put(normal_map, *it, normal); // normal_map[it] = normal
|
|
||||||
if (callback && !callback ((nb+1) / double(kd_tree_points.size())))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
callback_wrapper.join();
|
||||||
|
|
||||||
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE("End of jet_estimate_normals()\n");
|
CGAL_TRACE("End of jet_estimate_normals()\n");
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
#include <CGAL/disable_warnings.h>
|
#include <CGAL/disable_warnings.h>
|
||||||
|
|
||||||
#include <CGAL/IO/trace.h>
|
#include <CGAL/IO/trace.h>
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
#include <CGAL/Point_set_processing_3/internal/Callback_wrapper.h>
|
||||||
#include <CGAL/Point_set_processing_3/internal/neighbor_query.h>
|
#include <CGAL/for_each.h>
|
||||||
#include <CGAL/Monge_via_jet_fitting.h>
|
#include <CGAL/Monge_via_jet_fitting.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
|
|
@ -31,13 +31,6 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/Parallel_callback.h>
|
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/blocked_range.h>
|
|
||||||
#include <tbb/scalable_allocator.h>
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -57,20 +50,20 @@ namespace internal {
|
||||||
/// @tparam Tree KD-tree.
|
/// @tparam Tree KD-tree.
|
||||||
///
|
///
|
||||||
/// @return computed point
|
/// @return computed point
|
||||||
template <typename Kernel,
|
template <typename SvdTraits,
|
||||||
typename SvdTraits,
|
typename NeighborQuery
|
||||||
typename Tree
|
|
||||||
>
|
>
|
||||||
typename Kernel::Point_3
|
typename NeighborQuery::Kernel::Point_3
|
||||||
jet_smooth_point(
|
jet_smooth_point(
|
||||||
const typename Kernel::Point_3& query, ///< 3D point to project
|
const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point to project
|
||||||
Tree& tree, ///< KD-tree
|
NeighborQuery& neighbor_query, ///< KD-tree
|
||||||
const unsigned int k, ///< number of neighbors.
|
const unsigned int k, ///< number of neighbors.
|
||||||
typename Kernel::FT neighbor_radius,
|
typename NeighborQuery::Kernel::FT neighbor_radius,
|
||||||
const unsigned int degree_fitting,
|
const unsigned int degree_fitting,
|
||||||
const unsigned int degree_monge)
|
const unsigned int degree_monge)
|
||||||
{
|
{
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename NeighborQuery::Kernel Kernel;
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename Kernel::Point_3 Point;
|
||||||
|
|
||||||
// types for jet fitting
|
// types for jet fitting
|
||||||
|
|
@ -80,8 +73,7 @@ jet_smooth_point(
|
||||||
typedef typename Monge_jet_fitting::Monge_form Monge_form;
|
typedef typename Monge_jet_fitting::Monge_form Monge_form;
|
||||||
|
|
||||||
std::vector<Point> points;
|
std::vector<Point> points;
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points));
|
||||||
(query, tree, k, neighbor_radius, points);
|
|
||||||
|
|
||||||
// performs jet fitting
|
// performs jet fitting
|
||||||
Monge_jet_fitting monge_fit;
|
Monge_jet_fitting monge_fit;
|
||||||
|
|
@ -92,50 +84,6 @@ jet_smooth_point(
|
||||||
return monge_form.origin();
|
return monge_form.origin();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
template <typename Kernel, typename SvdTraits, typename Tree>
|
|
||||||
class Jet_smooth_pwns {
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
const Tree& tree;
|
|
||||||
const unsigned int k;
|
|
||||||
const typename Kernel::FT neighbor_radius;
|
|
||||||
unsigned int degree_fitting;
|
|
||||||
unsigned int degree_monge;
|
|
||||||
const std::vector<Point>& input;
|
|
||||||
std::vector<Point>& output;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Jet_smooth_pwns (Tree& tree, unsigned int k, typename Kernel::FT neighbor_radius,
|
|
||||||
std::vector<Point>& points,
|
|
||||||
unsigned int degree_fitting, unsigned int degree_monge, std::vector<Point>& output,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted)
|
|
||||||
: tree(tree), k (k), neighbor_radius(neighbor_radius)
|
|
||||||
, degree_fitting (degree_fitting)
|
|
||||||
, degree_monge (degree_monge), input (points), output (output)
|
|
||||||
, advancement (advancement)
|
|
||||||
, interrupted (interrupted)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void operator()(const tbb::blocked_range<std::size_t>& r) const
|
|
||||||
{
|
|
||||||
for( std::size_t i = r.begin(); i != r.end(); ++i)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
output[i] = CGAL::internal::jet_smooth_point<Kernel, SvdTraits>(input[i], tree, k,
|
|
||||||
neighbor_radius,
|
|
||||||
degree_fitting,
|
|
||||||
degree_monge);
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace internal */
|
} /* namespace internal */
|
||||||
|
|
||||||
|
|
@ -204,6 +152,8 @@ jet_smooth_point_set(
|
||||||
using parameters::get_parameter;
|
using parameters::get_parameter;
|
||||||
|
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename PointRange::iterator iterator;
|
||||||
|
typedef typename iterator::value_type value_type;
|
||||||
typedef typename CGAL::GetPointMap<PointRange, NamedParameters>::type PointMap;
|
typedef typename CGAL::GetPointMap<PointRange, NamedParameters>::type PointMap;
|
||||||
typedef typename Point_set_processing_3::GetK<PointRange, NamedParameters>::Kernel Kernel;
|
typedef typename Point_set_processing_3::GetK<PointRange, NamedParameters>::Kernel Kernel;
|
||||||
typedef typename GetSvdTraits<NamedParameters>::type SvdTraits;
|
typedef typename GetSvdTraits<NamedParameters>::type SvdTraits;
|
||||||
|
|
@ -220,12 +170,8 @@ jet_smooth_point_set(
|
||||||
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
||||||
std::function<bool(double)>());
|
std::function<bool(double)>());
|
||||||
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
|
|
||||||
// types for K nearest neighbors search structure
|
// types for K nearest neighbors search structure
|
||||||
typedef typename CGAL::Search_traits_3<Kernel> Tree_traits;
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, PointRange&, PointMap> Neighbor_query;
|
||||||
typedef typename CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
// precondition: at least one element in the container.
|
// precondition: at least one element in the container.
|
||||||
// to fix: should have at least three distinct points
|
// to fix: should have at least three distinct points
|
||||||
|
|
@ -235,56 +181,37 @@ jet_smooth_point_set(
|
||||||
// precondition: at least 2 nearest neighbors
|
// precondition: at least 2 nearest neighbors
|
||||||
CGAL_point_set_processing_precondition(k >= 2);
|
CGAL_point_set_processing_precondition(k >= 2);
|
||||||
|
|
||||||
typename PointRange::iterator it;
|
|
||||||
|
|
||||||
// Instanciate a KD-tree search.
|
// Instanciate a KD-tree search.
|
||||||
// Note: We have to convert each input iterator to Point_3.
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
std::vector<Point> kd_tree_points;
|
|
||||||
for(it = points.begin(); it != points.end(); it++)
|
|
||||||
kd_tree_points.push_back(get(point_map, *it));
|
|
||||||
Tree tree(kd_tree_points.begin(), kd_tree_points.end());
|
|
||||||
|
|
||||||
// Iterates over input points and mutates them.
|
// Iterates over input points and mutates them.
|
||||||
// Implementation note: the cast to Point& allows to modify only the point's position.
|
// Implementation note: the cast to Point& allows to modify only the point's position.
|
||||||
|
|
||||||
#ifndef CGAL_LINKED_WITH_TBB
|
std::size_t nb_points = points.size();
|
||||||
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
|
||||||
"Parallel_tag is enabled but TBB is unavailable.");
|
|
||||||
#else
|
|
||||||
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
|
|
||||||
{
|
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
|
||||||
parallel_callback (callback, kd_tree_points.size());
|
|
||||||
|
|
||||||
std::vector<Point> mutated_points (kd_tree_points.size (), CGAL::ORIGIN);
|
Point_set_processing_3::internal::Callback_wrapper<ConcurrencyTag>
|
||||||
CGAL::internal::Jet_smooth_pwns<Kernel, SvdTraits, Tree>
|
callback_wrapper (callback, nb_points);
|
||||||
f (tree, k, neighbor_radius, kd_tree_points, degree_fitting, degree_monge,
|
|
||||||
mutated_points,
|
|
||||||
parallel_callback.advancement(),
|
|
||||||
parallel_callback.interrupted());
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, kd_tree_points.size ()), f);
|
|
||||||
unsigned int i = 0;
|
|
||||||
for(it = points.begin(); it != points.end(); ++ it, ++ i)
|
|
||||||
if (mutated_points[i] != CGAL::ORIGIN)
|
|
||||||
put(point_map, *it, mutated_points[i]);
|
|
||||||
|
|
||||||
parallel_callback.join();
|
CGAL::for_each<ConcurrencyTag>
|
||||||
|
(points,
|
||||||
|
[&](value_type vt)
|
||||||
|
{
|
||||||
|
if (callback_wrapper.interrupted())
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
put (point_map, vt,
|
||||||
else
|
CGAL::internal::jet_smooth_point<SvdTraits>
|
||||||
#endif
|
(get (point_map, vt), neighbor_query,
|
||||||
{
|
k,
|
||||||
std::size_t nb = 0;
|
neighbor_radius,
|
||||||
for(it = points.begin(); it != points.end(); it++, ++ nb)
|
degree_fitting,
|
||||||
{
|
degree_monge));
|
||||||
const typename boost::property_traits<PointMap>::reference p = get(point_map, *it);
|
++ callback_wrapper.advancement();
|
||||||
put(point_map, *it ,
|
|
||||||
internal::jet_smooth_point<Kernel, SvdTraits>(
|
return true;
|
||||||
p,tree,k,neighbor_radius,degree_fitting,degree_monge) );
|
});
|
||||||
if (callback && !callback ((nb+1) / double(kd_tree_points.size())))
|
|
||||||
break;
|
callback_wrapper.join();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,7 @@
|
||||||
#include <CGAL/disable_warnings.h>
|
#include <CGAL/disable_warnings.h>
|
||||||
|
|
||||||
#include <CGAL/IO/trace.h>
|
#include <CGAL/IO/trace.h>
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/neighbor_query.h>
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/Search_traits_vertex_handle_3.h>
|
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/Index_property_map.h>
|
#include <CGAL/Index_property_map.h>
|
||||||
#include <CGAL/Memory_sizer.h>
|
#include <CGAL/Memory_sizer.h>
|
||||||
|
|
@ -296,17 +293,16 @@ mst_find_source(
|
||||||
/// @tparam Kernel Geometric traits class.
|
/// @tparam Kernel Geometric traits class.
|
||||||
///
|
///
|
||||||
/// @return the Riemannian graph
|
/// @return the Riemannian graph
|
||||||
template <typename ForwardIterator,
|
template <typename PointRange,
|
||||||
typename PointMap,
|
typename PointMap,
|
||||||
typename NormalMap,
|
typename NormalMap,
|
||||||
typename IndexMap,
|
typename IndexMap,
|
||||||
typename ConstrainedMap,
|
typename ConstrainedMap,
|
||||||
typename Kernel
|
typename Kernel
|
||||||
>
|
>
|
||||||
Riemannian_graph<ForwardIterator>
|
Riemannian_graph<typename PointRange::iterator>
|
||||||
create_riemannian_graph(
|
create_riemannian_graph(
|
||||||
ForwardIterator first, ///< iterator over the first input point.
|
PointRange& points, ///< input points
|
||||||
ForwardIterator beyond, ///< past-the-end iterator over the input points.
|
|
||||||
PointMap point_map, ///< property map: value_type of ForwardIterator -> Point_3
|
PointMap point_map, ///< property map: value_type of ForwardIterator -> Point_3
|
||||||
NormalMap normal_map, ///< property map: value_type of ForwardIterator -> Vector_3
|
NormalMap normal_map, ///< property map: value_type of ForwardIterator -> Vector_3
|
||||||
IndexMap index_map, ///< property map ForwardIterator -> index
|
IndexMap index_map, ///< property map ForwardIterator -> index
|
||||||
|
|
@ -320,43 +316,23 @@ create_riemannian_graph(
|
||||||
typedef typename boost::property_traits<NormalMap>::reference Vector_ref;
|
typedef typename boost::property_traits<NormalMap>::reference Vector_ref;
|
||||||
|
|
||||||
// Types for K nearest neighbors search structure
|
// Types for K nearest neighbors search structure
|
||||||
typedef Point_vertex_handle_3<ForwardIterator> Point_vertex_handle_3;
|
typedef typename PointRange::iterator ForwardIterator;
|
||||||
typedef internal::Search_traits_vertex_handle_3<ForwardIterator> Traits;
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, PointRange&, PointMap> Neighbor_query;
|
||||||
typedef Euclidean_distance_vertex_handle_3<ForwardIterator> KDistance;
|
|
||||||
typedef Orthogonal_k_neighbor_search<Traits,KDistance> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
// Riemannian_graph types
|
// Riemannian_graph types
|
||||||
typedef internal::Riemannian_graph<ForwardIterator> Riemannian_graph;
|
typedef internal::Riemannian_graph<ForwardIterator> Riemannian_graph;
|
||||||
typedef typename boost::property_map<Riemannian_graph, boost::edge_weight_t>::type Riemannian_graph_weight_map;
|
typedef typename boost::property_map<Riemannian_graph, boost::edge_weight_t>::type Riemannian_graph_weight_map;
|
||||||
|
|
||||||
// Precondition: at least one element in the container.
|
|
||||||
CGAL_point_set_processing_precondition(first != beyond);
|
|
||||||
|
|
||||||
// Precondition: at least 2 nearest neighbors
|
// Precondition: at least 2 nearest neighbors
|
||||||
CGAL_point_set_processing_precondition(k >= 2);
|
CGAL_point_set_processing_precondition(k >= 2);
|
||||||
|
|
||||||
// Number of input points
|
// Number of input points
|
||||||
const std::size_t num_input_points = distance(first, beyond);
|
const std::size_t num_input_points = points.size();
|
||||||
|
|
||||||
std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE(" Creates KD-tree\n");
|
CGAL_TRACE(" Creates KD-tree\n");
|
||||||
|
|
||||||
// Instanciate a KD-tree search.
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
// Notes: We have to wrap each input point by a Point_vertex_handle_3.
|
|
||||||
// The KD-tree is allocated dynamically to recover RAM as soon as possible.
|
|
||||||
std::vector<Point_vertex_handle_3> kd_tree_points; kd_tree_points.reserve(num_input_points);
|
|
||||||
for (ForwardIterator it = first; it != beyond; it++)
|
|
||||||
{
|
|
||||||
|
|
||||||
Point_ref point = get(point_map, *it);
|
|
||||||
Point_vertex_handle_3 point_wrapper(point.x(), point.y(), point.z(), it);
|
|
||||||
kd_tree_points.push_back(point_wrapper);
|
|
||||||
}
|
|
||||||
boost::shared_ptr<Tree> tree( new Tree(kd_tree_points.begin(), kd_tree_points.end()) );
|
|
||||||
|
|
||||||
// Recover RAM
|
|
||||||
kd_tree_points.clear();
|
|
||||||
|
|
||||||
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE(" Creates Riemannian Graph\n");
|
CGAL_TRACE(" Creates Riemannian Graph\n");
|
||||||
|
|
@ -369,7 +345,7 @@ create_riemannian_graph(
|
||||||
Riemannian_graph riemannian_graph;
|
Riemannian_graph riemannian_graph;
|
||||||
//
|
//
|
||||||
// add vertices
|
// add vertices
|
||||||
for (ForwardIterator it = first; it != beyond; it++)
|
for (ForwardIterator it = points.begin(); it != points.end(); it++)
|
||||||
{
|
{
|
||||||
typename Riemannian_graph::vertex_descriptor v = add_vertex(riemannian_graph);
|
typename Riemannian_graph::vertex_descriptor v = add_vertex(riemannian_graph);
|
||||||
CGAL_point_set_processing_assertion(v == get(index_map,it));
|
CGAL_point_set_processing_assertion(v == get(index_map,it));
|
||||||
|
|
@ -383,16 +359,14 @@ create_riemannian_graph(
|
||||||
//
|
//
|
||||||
// add edges
|
// add edges
|
||||||
Riemannian_graph_weight_map riemannian_graph_weight_map = get(boost::edge_weight, riemannian_graph);
|
Riemannian_graph_weight_map riemannian_graph_weight_map = get(boost::edge_weight, riemannian_graph);
|
||||||
for (ForwardIterator it = first; it != beyond; it++)
|
for (ForwardIterator it = points.begin(); it != points.end(); it++)
|
||||||
{
|
{
|
||||||
std::size_t it_index = get(index_map,it);
|
std::size_t it_index = get(index_map,it);
|
||||||
Vector_ref it_normal_vector = get(normal_map,*it);
|
Vector_ref it_normal_vector = get(normal_map,*it);
|
||||||
|
|
||||||
Point_ref point = get(point_map, *it);
|
Point_ref point = get(point_map, *it);
|
||||||
Point_vertex_handle_3 point_wrapper(point.x(), point.y(), point.z(), it);
|
std::vector<ForwardIterator> neighbor_points;
|
||||||
std::vector<Point_vertex_handle_3> neighbor_points;
|
neighbor_query.get_iterators (point, k, neighbor_radius, std::back_inserter(neighbor_points));
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
|
||||||
(point_wrapper, *tree, k, neighbor_radius, neighbor_points);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < neighbor_points.size(); ++ i)
|
for (std::size_t i = 0; i < neighbor_points.size(); ++ i)
|
||||||
{
|
{
|
||||||
|
|
@ -665,7 +639,7 @@ mst_orient_normals(
|
||||||
|
|
||||||
if (boost::is_same<ConstrainedMap,
|
if (boost::is_same<ConstrainedMap,
|
||||||
typename CGAL::Point_set_processing_3::GetIsConstrainedMap<PointRange, NamedParameters>::NoMap>::value)
|
typename CGAL::Point_set_processing_3::GetIsConstrainedMap<PointRange, NamedParameters>::NoMap>::value)
|
||||||
riemannian_graph = create_riemannian_graph(points.begin(), points.end(),
|
riemannian_graph = create_riemannian_graph(points,
|
||||||
point_map, normal_map, index_map,
|
point_map, normal_map, index_map,
|
||||||
Default_constrained_map<typename PointRange::iterator>
|
Default_constrained_map<typename PointRange::iterator>
|
||||||
(mst_find_source(points.begin(), points.end(),
|
(mst_find_source(points.begin(), points.end(),
|
||||||
|
|
@ -675,7 +649,7 @@ mst_orient_normals(
|
||||||
neighbor_radius,
|
neighbor_radius,
|
||||||
kernel);
|
kernel);
|
||||||
else
|
else
|
||||||
riemannian_graph = create_riemannian_graph(points.begin(), points.end(),
|
riemannian_graph = create_riemannian_graph(points,
|
||||||
point_map, normal_map, index_map,
|
point_map, normal_map, index_map,
|
||||||
constrained_map,
|
constrained_map,
|
||||||
k,
|
k,
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
|
|
||||||
#include <CGAL/IO/trace.h>
|
#include <CGAL/IO/trace.h>
|
||||||
#include <CGAL/Dimension.h>
|
#include <CGAL/Dimension.h>
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
#include <CGAL/Point_set_processing_3/internal/Callback_wrapper.h>
|
||||||
#include <CGAL/Point_set_processing_3/internal/neighbor_query.h>
|
#include <CGAL/for_each.h>
|
||||||
#include <CGAL/linear_least_squares_fitting_3.h>
|
#include <CGAL/linear_least_squares_fitting_3.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
|
|
@ -33,13 +33,6 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/Parallel_callback.h>
|
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/blocked_range.h>
|
|
||||||
#include <tbb/scalable_allocator.h>
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -58,22 +51,20 @@ namespace internal {
|
||||||
/// @tparam Tree KD-tree.
|
/// @tparam Tree KD-tree.
|
||||||
///
|
///
|
||||||
/// @return Computed normal. Orientation is random.
|
/// @return Computed normal. Orientation is random.
|
||||||
template < typename Kernel,
|
template <typename NeighborQuery>
|
||||||
typename Tree
|
typename NeighborQuery::Kernel::Vector_3
|
||||||
>
|
pca_estimate_normal(const typename NeighborQuery::Kernel::Point_3& query, ///< point to compute the normal at
|
||||||
typename Kernel::Vector_3
|
const NeighborQuery& neighbor_query, ///< KD-tree
|
||||||
pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute the normal at
|
|
||||||
const Tree& tree, ///< KD-tree
|
|
||||||
unsigned int k, ///< number of neighbors
|
unsigned int k, ///< number of neighbors
|
||||||
typename Kernel::FT neighbor_radius)
|
typename NeighborQuery::Kernel::FT neighbor_radius)
|
||||||
{
|
{
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
|
typedef typename NeighborQuery::Kernel Kernel;
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename Kernel::Point_3 Point;
|
||||||
typedef typename Kernel::Plane_3 Plane;
|
typedef typename Kernel::Plane_3 Plane;
|
||||||
|
|
||||||
std::vector<Point> points;
|
std::vector<Point> points;
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points));
|
||||||
(query, tree, k, neighbor_radius, points);
|
|
||||||
|
|
||||||
// performs plane fitting by point-based PCA
|
// performs plane fitting by point-based PCA
|
||||||
Plane plane;
|
Plane plane;
|
||||||
|
|
@ -83,48 +74,6 @@ pca_estimate_normal(const typename Kernel::Point_3& query, ///< point to compute
|
||||||
return plane.orthogonal_vector();
|
return plane.orthogonal_vector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
template <typename Kernel, typename Tree>
|
|
||||||
class PCA_estimate_normals {
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
typedef typename Kernel::Vector_3 Vector;
|
|
||||||
const Tree& tree;
|
|
||||||
const unsigned int k;
|
|
||||||
const FT neighbor_radius;
|
|
||||||
const std::vector<Point>& input;
|
|
||||||
std::vector<Vector>& output;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PCA_estimate_normals(Tree& tree, unsigned int k, FT neighbor_radius,
|
|
||||||
std::vector<Point>& points,
|
|
||||||
std::vector<Vector>& output,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted)
|
|
||||||
: tree(tree), k (k), neighbor_radius (neighbor_radius)
|
|
||||||
, input (points), output (output)
|
|
||||||
, advancement (advancement)
|
|
||||||
, interrupted (interrupted)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void operator()(const tbb::blocked_range<std::size_t>& r) const
|
|
||||||
{
|
|
||||||
for( std::size_t i = r.begin(); i != r.end(); ++i)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
output[i] = CGAL::internal::pca_estimate_normal<Kernel,Tree>(input[i], tree, k, neighbor_radius);
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace internal */
|
} /* namespace internal */
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
|
|
@ -206,15 +155,12 @@ pca_estimate_normals(
|
||||||
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
const std::function<bool(double)>& callback = choose_parameter(get_parameter(np, internal_np::callback),
|
||||||
std::function<bool(double)>());
|
std::function<bool(double)>());
|
||||||
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
|
|
||||||
// Input points types
|
// Input points types
|
||||||
typedef typename boost::property_traits<NormalMap>::value_type Vector;
|
typedef typename PointRange::iterator iterator;
|
||||||
|
typedef typename iterator::value_type value_type;
|
||||||
|
|
||||||
// types for K nearest neighbors search structure
|
// types for K nearest neighbors search structure
|
||||||
typedef typename CGAL::Search_traits_3<Kernel> Tree_traits;
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, PointRange&, PointMap> Neighbor_query;
|
||||||
typedef typename CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
// precondition: at least one element in the container.
|
// precondition: at least one element in the container.
|
||||||
// to fix: should have at least three distinct points
|
// to fix: should have at least three distinct points
|
||||||
|
|
@ -227,59 +173,33 @@ pca_estimate_normals(
|
||||||
std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE(" Creates KD-tree\n");
|
CGAL_TRACE(" Creates KD-tree\n");
|
||||||
|
|
||||||
typename PointRange::iterator it;
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
|
|
||||||
// Instanciate a KD-tree search.
|
|
||||||
// Note: We have to convert each input iterator to Point_3.
|
|
||||||
std::vector<Point> kd_tree_points;
|
|
||||||
for(it = points.begin(); it != points.end(); it++)
|
|
||||||
kd_tree_points.push_back(get(point_map, *it));
|
|
||||||
Tree tree(kd_tree_points.begin(), kd_tree_points.end());
|
|
||||||
|
|
||||||
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE(" Computes normals\n");
|
CGAL_TRACE(" Computes normals\n");
|
||||||
|
|
||||||
// iterate over input points, compute and output normal
|
std::size_t nb_points = points.size();
|
||||||
// vectors (already normalized)
|
|
||||||
#ifndef CGAL_LINKED_WITH_TBB
|
|
||||||
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
|
||||||
"Parallel_tag is enabled but TBB is unavailable.");
|
|
||||||
#else
|
|
||||||
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
|
|
||||||
{
|
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
|
||||||
parallel_callback (callback, kd_tree_points.size());
|
|
||||||
|
|
||||||
std::vector<Vector> normals (kd_tree_points.size (),
|
Point_set_processing_3::internal::Callback_wrapper<ConcurrencyTag>
|
||||||
CGAL::NULL_VECTOR);
|
callback_wrapper (callback, nb_points);
|
||||||
CGAL::internal::PCA_estimate_normals<Kernel, Tree>
|
|
||||||
f (tree, k, neighbor_radius, kd_tree_points, normals,
|
|
||||||
parallel_callback.advancement(),
|
|
||||||
parallel_callback.interrupted());
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, kd_tree_points.size ()), f);
|
|
||||||
unsigned int i = 0;
|
|
||||||
for(it = points.begin(); it != points.end(); ++ it, ++ i)
|
|
||||||
if (normals[i] != CGAL::NULL_VECTOR)
|
|
||||||
put (normal_map, *it, normals[i]);
|
|
||||||
|
|
||||||
parallel_callback.join();
|
CGAL::for_each<ConcurrencyTag>
|
||||||
}
|
(points,
|
||||||
else
|
[&](value_type& vt)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
std::size_t nb = 0;
|
if (callback_wrapper.interrupted())
|
||||||
for(it = points.begin(); it != points.end(); it++, ++ nb)
|
return false;
|
||||||
{
|
|
||||||
Vector normal = internal::pca_estimate_normal<Kernel,Tree>(
|
|
||||||
get(point_map,*it),
|
|
||||||
tree,
|
|
||||||
k, neighbor_radius);
|
|
||||||
|
|
||||||
put(normal_map, *it, normal); // normal_map[it] = normal
|
put (normal_map, vt,
|
||||||
if (callback && !callback ((nb+1) / double(kd_tree_points.size())))
|
CGAL::internal::pca_estimate_normal
|
||||||
break;
|
(get(point_map, vt), neighbor_query, k, neighbor_radius));
|
||||||
}
|
|
||||||
}
|
++ callback_wrapper.advancement();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
callback_wrapper.join();
|
||||||
|
|
||||||
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20);
|
||||||
CGAL_TRACE("End of pca_estimate_normals()\n");
|
CGAL_TRACE("End of pca_estimate_normals()\n");
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,7 @@
|
||||||
|
|
||||||
#include <CGAL/disable_warnings.h>
|
#include <CGAL/disable_warnings.h>
|
||||||
|
|
||||||
#include <CGAL/Search_traits_3.h>
|
#include <CGAL/Point_set_processing_3/internal/Neighbor_query.h>
|
||||||
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
|
||||||
#include <CGAL/Point_set_processing_3/internal/neighbor_query.h>
|
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -49,22 +47,21 @@ namespace internal {
|
||||||
/// @tparam Tree KD-tree.
|
/// @tparam Tree KD-tree.
|
||||||
///
|
///
|
||||||
/// @return computed distance.
|
/// @return computed distance.
|
||||||
template < typename Kernel,
|
template <typename NeighborQuery>
|
||||||
typename Tree >
|
typename NeighborQuery::Kernel::FT
|
||||||
typename Kernel::FT
|
|
||||||
compute_avg_knn_sq_distance_3(
|
compute_avg_knn_sq_distance_3(
|
||||||
const typename Kernel::Point_3& query, ///< 3D point to project
|
const typename NeighborQuery::Kernel::Point_3& query, ///< 3D point to project
|
||||||
Tree& tree, ///< KD-tree
|
NeighborQuery& neighbor_query, ///< KD-tree
|
||||||
unsigned int k, ///< number of neighbors
|
unsigned int k, ///< number of neighbors
|
||||||
typename Kernel::FT neighbor_radius)
|
typename NeighborQuery::Kernel::FT neighbor_radius)
|
||||||
{
|
{
|
||||||
// geometric types
|
// geometric types
|
||||||
|
typedef typename NeighborQuery::Kernel Kernel;
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename Kernel::Point_3 Point;
|
||||||
|
|
||||||
std::vector<Point> points;
|
std::vector<Point> points;
|
||||||
CGAL::Point_set_processing_3::internal::neighbor_query
|
neighbor_query.get_points (query, k, neighbor_radius, std::back_inserter(points));
|
||||||
(query, tree, k, neighbor_radius, points);
|
|
||||||
|
|
||||||
// compute average squared distance
|
// compute average squared distance
|
||||||
typename Kernel::Compute_squared_distance_3 sqd;
|
typename Kernel::Compute_squared_distance_3 sqd;
|
||||||
|
|
@ -162,15 +159,14 @@ remove_outliers(
|
||||||
typedef typename Kernel::FT FT;
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
// basic geometric types
|
// basic geometric types
|
||||||
typedef typename Kernel::Point_3 Point;
|
typedef typename PointRange::iterator iterator;
|
||||||
|
typedef typename iterator::value_type value_type;
|
||||||
|
|
||||||
// actual type of input points
|
// actual type of input points
|
||||||
typedef typename std::iterator_traits<typename PointRange::iterator>::value_type Enriched_point;
|
typedef typename std::iterator_traits<typename PointRange::iterator>::value_type Enriched_point;
|
||||||
|
|
||||||
// types for K nearest neighbors search structure
|
// types for K nearest neighbors search structure
|
||||||
typedef typename CGAL::Search_traits_3<Kernel> Tree_traits;
|
typedef Point_set_processing_3::internal::Neighbor_query<Kernel, PointRange&, PointMap> Neighbor_query;
|
||||||
typedef typename CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
|
||||||
typedef typename Neighbor_search::Tree Tree;
|
|
||||||
|
|
||||||
// precondition: at least one element in the container.
|
// precondition: at least one element in the container.
|
||||||
// to fix: should have at least three distinct points
|
// to fix: should have at least three distinct points
|
||||||
|
|
@ -182,26 +178,22 @@ remove_outliers(
|
||||||
|
|
||||||
CGAL_point_set_processing_precondition(threshold_percent >= 0 && threshold_percent <= 100);
|
CGAL_point_set_processing_precondition(threshold_percent >= 0 && threshold_percent <= 100);
|
||||||
|
|
||||||
typename PointRange::iterator it;
|
Neighbor_query neighbor_query (points, point_map);
|
||||||
|
|
||||||
// Instanciate a KD-tree search.
|
std::size_t nb_points = points.size();
|
||||||
// Note: We have to convert each input iterator to Point_3.
|
|
||||||
std::vector<Point> kd_tree_points;
|
|
||||||
for(it = points.begin(); it != points.end(); it++)
|
|
||||||
kd_tree_points.push_back( get(point_map, *it) );
|
|
||||||
Tree tree(kd_tree_points.begin(), kd_tree_points.end());
|
|
||||||
|
|
||||||
// iterate over input points and add them to multimap sorted by distance to k
|
// iterate over input points and add them to multimap sorted by distance to k
|
||||||
std::multimap<FT,Enriched_point> sorted_points;
|
std::multimap<FT,Enriched_point> sorted_points;
|
||||||
std::size_t nb = 0;
|
std::size_t nb = 0;
|
||||||
for(it = points.begin(); it != points.end(); it++, ++ nb)
|
for(const value_type& vt : points)
|
||||||
{
|
{
|
||||||
FT sq_distance = internal::compute_avg_knn_sq_distance_3<Kernel>(
|
FT sq_distance = internal::compute_avg_knn_sq_distance_3(
|
||||||
get(point_map,*it),
|
get(point_map, vt),
|
||||||
tree, k, neighbor_radius);
|
neighbor_query, k, neighbor_radius);
|
||||||
sorted_points.insert( std::make_pair(sq_distance, *it) );
|
sorted_points.insert( std::make_pair(sq_distance, vt) );
|
||||||
if (callback && !callback ((nb+1) / double(kd_tree_points.size())))
|
if (callback && !callback ((nb+1) / double(nb_points)))
|
||||||
return points.end();
|
return points.end();
|
||||||
|
++ nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces [points.begin(), points.end()) range by the multimap content.
|
// Replaces [points.begin(), points.end()) range by the multimap content.
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,8 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#include <CGAL/Point_set_processing_3/internal/Callback_wrapper.h>
|
||||||
#include <CGAL/Point_set_processing_3/internal/Parallel_callback.h>
|
#include <CGAL/for_each.h>
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/blocked_range.h>
|
|
||||||
#include <tbb/scalable_allocator.h>
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
#include <CGAL/Simple_cartesian.h>
|
#include <CGAL/Simple_cartesian.h>
|
||||||
#include <CGAL/Fuzzy_sphere.h>
|
#include <CGAL/Fuzzy_sphere.h>
|
||||||
|
|
@ -329,67 +325,6 @@ compute_density_weight_for_sample_point(
|
||||||
|
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
|
||||||
/// \cond SKIP_IN_MANUAL
|
|
||||||
/// This is for parallelization of function: compute_denoise_projection()
|
|
||||||
template <typename Kernel, typename Tree, typename RandomAccessIterator>
|
|
||||||
class Sample_point_updater
|
|
||||||
{
|
|
||||||
typedef typename Kernel::Point_3 Point;
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
|
|
||||||
std::vector<Point> &update_sample_points;
|
|
||||||
std::vector<Point> &sample_points;
|
|
||||||
const Tree &original_kd_tree;
|
|
||||||
const Tree &sample_kd_tree;
|
|
||||||
const typename Kernel::FT radius;
|
|
||||||
const std::vector<typename Kernel::FT> &original_densities;
|
|
||||||
const std::vector<typename Kernel::FT> &sample_densities;
|
|
||||||
cpp11::atomic<std::size_t>& advancement;
|
|
||||||
cpp11::atomic<bool>& interrupted;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Sample_point_updater(
|
|
||||||
std::vector<Point> &out,
|
|
||||||
std::vector<Point> &in,
|
|
||||||
const Tree &_original_kd_tree,
|
|
||||||
const Tree &_sample_kd_tree,
|
|
||||||
const typename Kernel::FT _radius,
|
|
||||||
const std::vector<typename Kernel::FT> &_original_densities,
|
|
||||||
const std::vector<typename Kernel::FT> &_sample_densities,
|
|
||||||
cpp11::atomic<std::size_t>& advancement,
|
|
||||||
cpp11::atomic<bool>& interrupted):
|
|
||||||
update_sample_points(out),
|
|
||||||
sample_points(in),
|
|
||||||
original_kd_tree(_original_kd_tree),
|
|
||||||
sample_kd_tree(_sample_kd_tree),
|
|
||||||
radius(_radius),
|
|
||||||
original_densities(_original_densities),
|
|
||||||
sample_densities(_sample_densities),
|
|
||||||
advancement (advancement),
|
|
||||||
interrupted (interrupted) {}
|
|
||||||
|
|
||||||
void operator() ( const tbb::blocked_range<size_t>& r ) const
|
|
||||||
{
|
|
||||||
for (size_t i = r.begin(); i != r.end(); ++i)
|
|
||||||
{
|
|
||||||
if (interrupted)
|
|
||||||
break;
|
|
||||||
update_sample_points[i] = simplify_and_regularize_internal::
|
|
||||||
compute_update_sample_point<Kernel, Tree, RandomAccessIterator>(
|
|
||||||
sample_points[i],
|
|
||||||
original_kd_tree,
|
|
||||||
sample_kd_tree,
|
|
||||||
radius,
|
|
||||||
original_densities,
|
|
||||||
sample_densities);
|
|
||||||
++ advancement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/// \endcond
|
|
||||||
#endif // CGAL_LINKED_WITH_TBB
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Public section
|
// Public section
|
||||||
|
|
@ -529,7 +464,6 @@ wlop_simplify_and_regularize_point_set(
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FT radius2 = radius * radius;
|
|
||||||
CGAL_point_set_processing_precondition(radius > 0);
|
CGAL_point_set_processing_precondition(radius > 0);
|
||||||
|
|
||||||
// Initiate a KD-tree search for original points
|
// Initiate a KD-tree search for original points
|
||||||
|
|
@ -588,79 +522,50 @@ wlop_simplify_and_regularize_point_set(
|
||||||
sample_density_weights.push_back(density);
|
sample_density_weights.push_back(density);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef boost::zip_iterator<boost::tuple<typename std::vector<Point>::iterator,
|
||||||
|
typename std::vector<Point>::iterator> > Zip_iterator;
|
||||||
|
|
||||||
typename std::vector<Point>::iterator update_iter = update_sample_points.begin();
|
Point_set_processing_3::internal::Callback_wrapper<ConcurrencyTag>
|
||||||
#ifndef CGAL_LINKED_WITH_TBB
|
callback_wrapper (callback, iter_number * number_of_sample, iter_n * number_of_sample);
|
||||||
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
|
||||||
"Parallel_tag is enabled but TBB is unavailable.");
|
CGAL::for_each<ConcurrencyTag>
|
||||||
#else
|
(CGAL::make_range (boost::make_zip_iterator (boost::make_tuple (sample_points.begin(), update_sample_points.begin())),
|
||||||
//parallel
|
boost::make_zip_iterator (boost::make_tuple (sample_points.end(), update_sample_points.end()))),
|
||||||
if (boost::is_convertible<ConcurrencyTag, Parallel_tag>::value)
|
[&](const typename Zip_iterator::reference& t)
|
||||||
{
|
{
|
||||||
Point_set_processing_3::internal::Parallel_callback
|
if (callback_wrapper.interrupted())
|
||||||
parallel_callback (callback, iter_number * number_of_sample, iter_n * number_of_sample);
|
return false;
|
||||||
|
|
||||||
tbb::blocked_range<size_t> block(0, number_of_sample);
|
get<1>(t) = simplify_and_regularize_internal::
|
||||||
Sample_point_updater<Kernel, Kd_Tree, typename PointRange::iterator> sample_updater(
|
compute_update_sample_point<Kernel, Kd_Tree, typename PointRange::iterator>(
|
||||||
update_sample_points,
|
get<0>(t),
|
||||||
sample_points,
|
|
||||||
original_kd_tree,
|
original_kd_tree,
|
||||||
sample_kd_tree,
|
sample_kd_tree,
|
||||||
radius2,
|
radius,
|
||||||
original_density_weights,
|
original_density_weights,
|
||||||
sample_density_weights,
|
sample_density_weights);
|
||||||
parallel_callback.advancement(),
|
++ callback_wrapper.advancement();
|
||||||
parallel_callback.interrupted());
|
|
||||||
|
|
||||||
tbb::parallel_for(block, sample_updater);
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
bool interrupted = parallel_callback.interrupted();
|
bool interrupted = callback_wrapper.interrupted();
|
||||||
|
|
||||||
// We interrupt by hand as counter only goes halfway and won't terminate by itself
|
// We interrupt by hand as counter only goes halfway and won't terminate by itself
|
||||||
parallel_callback.interrupted() = true;
|
callback_wrapper.interrupted() = true;
|
||||||
parallel_callback.join();
|
callback_wrapper.join();
|
||||||
|
|
||||||
// If interrupted during this step, nothing is computed, we return NaN
|
// If interrupted during this step, nothing is computed, we return NaN
|
||||||
if (interrupted)
|
if (interrupted)
|
||||||
return output;
|
return output;
|
||||||
}else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
//sequential
|
|
||||||
std::size_t nb = iter_n * number_of_sample;
|
|
||||||
for (sample_iter = sample_points.begin();
|
|
||||||
sample_iter != sample_points.end(); ++sample_iter, ++update_iter, ++ nb)
|
|
||||||
{
|
|
||||||
*update_iter = simplify_and_regularize_internal::
|
|
||||||
compute_update_sample_point<Kernel,
|
|
||||||
Kd_Tree,
|
|
||||||
typename PointRange::iterator>
|
|
||||||
(*sample_iter,
|
|
||||||
original_kd_tree,
|
|
||||||
sample_kd_tree,
|
|
||||||
radius2,
|
|
||||||
original_density_weights,
|
|
||||||
sample_density_weights);
|
|
||||||
if (callback && !callback ((nb+1) / double(iter_number * number_of_sample)))
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_iter = sample_points.begin();
|
sample_iter = sample_points.begin();
|
||||||
for (update_iter = update_sample_points.begin();
|
for (std::size_t i = 0; i < sample_points.size(); ++ i)
|
||||||
update_iter != update_sample_points.end();
|
sample_points[i] = update_sample_points[i];
|
||||||
++update_iter, ++sample_iter)
|
|
||||||
{
|
|
||||||
*sample_iter = *update_iter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// final output
|
// final output
|
||||||
for(sample_iter = sample_points.begin();
|
std::copy (sample_points.begin(), sample_points.end(), output);
|
||||||
sample_iter != sample_points.end(); ++sample_iter)
|
|
||||||
{
|
|
||||||
*output++ = *sample_iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,13 +106,13 @@ struct Poisson_visitor {
|
||||||
|
|
||||||
struct Poisson_skip_vertices {
|
struct Poisson_skip_vertices {
|
||||||
double ratio;
|
double ratio;
|
||||||
Random& m_random;
|
Poisson_skip_vertices(const double ratio = 0)
|
||||||
Poisson_skip_vertices(const double ratio, Random& random)
|
: ratio(ratio) {}
|
||||||
: ratio(ratio), m_random(random) {}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
bool operator()(Iterator) const {
|
bool operator()(Iterator it) const {
|
||||||
return m_random.get_double() < ratio;
|
// make the result deterministic for each iterator
|
||||||
|
return Random((std::size_t)(&*it)).get_double() < ratio;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -417,9 +417,7 @@ public:
|
||||||
|
|
||||||
typedef Filter_iterator<typename Triangulation::Input_point_iterator,
|
typedef Filter_iterator<typename Triangulation::Input_point_iterator,
|
||||||
Poisson_skip_vertices> Some_points_iterator;
|
Poisson_skip_vertices> Some_points_iterator;
|
||||||
//make it deterministic
|
Poisson_skip_vertices skip(1.-approximation_ratio);
|
||||||
Random random(0);
|
|
||||||
Poisson_skip_vertices skip(1.-approximation_ratio,random);
|
|
||||||
|
|
||||||
CGAL_TRACE_STREAM << "SPECIAL PASS that uses an approximation of the result (approximation ratio: "
|
CGAL_TRACE_STREAM << "SPECIAL PASS that uses an approximation of the result (approximation ratio: "
|
||||||
<< approximation_ratio << ")" << std::endl;
|
<< approximation_ratio << ")" << std::endl;
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,22 @@ struct Identity_property_map
|
||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// \cond SKIP_IN_MANUAL
|
||||||
|
template <typename T>
|
||||||
|
struct Identity_property_map_no_lvalue
|
||||||
|
{
|
||||||
|
typedef T key_type; ///< typedef to `T`
|
||||||
|
typedef T value_type; ///< typedef to `T`
|
||||||
|
typedef T reference; ///< typedef to `T`
|
||||||
|
typedef boost::readable_property_map_tag category; ///< `boost::readable_property_map_tag`
|
||||||
|
|
||||||
|
typedef Identity_property_map_no_lvalue<T> Self;
|
||||||
|
|
||||||
|
friend reference get(const Self&, const key_type& k) {return k;}
|
||||||
|
};
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
/// Free function to create a `Identity_property_map` property map.
|
/// Free function to create a `Identity_property_map` property map.
|
||||||
///
|
///
|
||||||
/// \relates Identity_property_map
|
/// \relates Identity_property_map
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
// Copyright (c) 2020 GeometryFactory (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
|
//
|
||||||
|
// Author(s) : Simon Giraudot
|
||||||
|
|
||||||
|
#ifndef CGAL_FOR_EACH_H
|
||||||
|
#define CGAL_FOR_EACH_H
|
||||||
|
|
||||||
|
#include <CGAL/iterator.h>
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
#include <tbb/blocked_range.h>
|
||||||
|
#include <tbb/scalable_allocator.h>
|
||||||
|
#endif // CGAL_LINKED_WITH_TBB
|
||||||
|
|
||||||
|
/*
|
||||||
|
CGAL::for_each<ConcurrencyTag>(Range, Function) does the following:
|
||||||
|
|
||||||
|
- if Sequential_tag is used, apply Function to all elements of Range
|
||||||
|
- if Parallel_tag is used:
|
||||||
|
* static assert that TBB is available
|
||||||
|
* if Range has random access iterators, use a TBB parallel_for
|
||||||
|
loop to apply Function to all elements of Range
|
||||||
|
* if Range doesn't have random access iterators, first copy the
|
||||||
|
iterators in a vector and then use a TBB parallel_for loop to
|
||||||
|
apply Function to all elements of Range
|
||||||
|
|
||||||
|
The loop is interrupted if `functor` returns false (it carries on
|
||||||
|
until the end otherwise).
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename RangeRef, typename IteratorCategory>
|
||||||
|
void for_each (RangeRef range,
|
||||||
|
const std::function<bool(typename std::iterator_traits
|
||||||
|
<typename Range_iterator_type<RangeRef>::type>::reference)>& functor,
|
||||||
|
const Sequential_tag&,
|
||||||
|
IteratorCategory)
|
||||||
|
{
|
||||||
|
for (typename std::iterator_traits
|
||||||
|
<typename Range_iterator_type<RangeRef>::type>::reference r : range)
|
||||||
|
if (!functor(r))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
template <typename RangeRef, typename IteratorCategory>
|
||||||
|
void for_each (RangeRef range,
|
||||||
|
const std::function<bool(typename std::iterator_traits
|
||||||
|
<typename Range_iterator_type<RangeRef>::type>::reference)>& functor,
|
||||||
|
const Parallel_tag&,
|
||||||
|
IteratorCategory)
|
||||||
|
{
|
||||||
|
std::size_t range_size = std::distance (range.begin(), range.end());
|
||||||
|
|
||||||
|
std::vector<typename Range_iterator_type<RangeRef>::type> iterators;
|
||||||
|
iterators.reserve (range_size);
|
||||||
|
for (typename Range_iterator_type<RangeRef>::type it = range.begin(); it != range.end(); ++ it)
|
||||||
|
iterators.push_back (it);
|
||||||
|
|
||||||
|
tbb::parallel_for (tbb::blocked_range<std::size_t>(0, range_size),
|
||||||
|
[&](const tbb::blocked_range<std::size_t>& r)
|
||||||
|
{
|
||||||
|
for (std::size_t i = r.begin(); i != r.end(); ++ i)
|
||||||
|
if (!functor (*(iterators[i])))
|
||||||
|
break;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RangeRef>
|
||||||
|
void for_each (RangeRef range,
|
||||||
|
const std::function<bool(typename std::iterator_traits
|
||||||
|
<typename Range_iterator_type<RangeRef>::type>::reference)>& functor,
|
||||||
|
const Parallel_tag&,
|
||||||
|
std::random_access_iterator_tag)
|
||||||
|
{
|
||||||
|
std::size_t range_size = std::distance (range.begin(), range.end());
|
||||||
|
|
||||||
|
tbb::parallel_for (tbb::blocked_range<std::size_t>(0, range_size),
|
||||||
|
[&](const tbb::blocked_range<std::size_t>& r)
|
||||||
|
{
|
||||||
|
for (std::size_t i = r.begin(); i != r.end(); ++ i)
|
||||||
|
if (!functor (*(range.begin() + i)))
|
||||||
|
break;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
template <typename ConcurrencyTag, typename Range>
|
||||||
|
void for_each (const Range& range,
|
||||||
|
const std::function<bool(typename std::iterator_traits
|
||||||
|
<typename Range::const_iterator>::reference)>& functor)
|
||||||
|
{
|
||||||
|
#ifndef CGAL_LINKED_WITH_TBB
|
||||||
|
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
||||||
|
"Parallel_tag is enabled but TBB is unavailable.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal::for_each<const Range&>
|
||||||
|
(range, functor,
|
||||||
|
ConcurrencyTag(),
|
||||||
|
typename std::iterator_traits<typename Range::const_iterator>::iterator_category());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ConcurrencyTag, typename Range>
|
||||||
|
void for_each (Range& range,
|
||||||
|
const std::function<bool(typename std::iterator_traits
|
||||||
|
<typename Range::iterator>::reference)>& functor)
|
||||||
|
{
|
||||||
|
#ifndef CGAL_LINKED_WITH_TBB
|
||||||
|
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
|
||||||
|
"Parallel_tag is enabled but TBB is unavailable.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal::for_each<Range&>
|
||||||
|
(range, functor,
|
||||||
|
ConcurrencyTag(),
|
||||||
|
typename std::iterator_traits<typename Range::iterator>::iterator_category());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CGAL
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CGAL_FOR_EACH_H
|
||||||
|
|
@ -1471,6 +1471,17 @@ dispatch_or_drop_output(O... o)
|
||||||
return Dispatch_or_drop_output_iterator<std::tuple<V...>, std::tuple<O...> >(o...);
|
return Dispatch_or_drop_output_iterator<std::tuple<V...>, std::tuple<O...> >(o...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Trick to select iterator or const_iterator depending on the range constness
|
||||||
|
template <typename RangeRef>
|
||||||
|
struct Range_iterator_type;
|
||||||
|
template <typename RangeRef>
|
||||||
|
struct Range_iterator_type<RangeRef&> { typedef typename RangeRef::iterator type; };
|
||||||
|
template <typename RangeRef>
|
||||||
|
struct Range_iterator_type<const RangeRef&> { typedef typename RangeRef::const_iterator type; };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace CGAL
|
} //namespace CGAL
|
||||||
|
|
||||||
#include <CGAL/enable_warnings.h>
|
#include <CGAL/enable_warnings.h>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ if ( CGAL_FOUND )
|
||||||
create_single_source_cgal_program( "test_Uncertain.cpp" )
|
create_single_source_cgal_program( "test_Uncertain.cpp" )
|
||||||
create_single_source_cgal_program( "test_vector.cpp" )
|
create_single_source_cgal_program( "test_vector.cpp" )
|
||||||
create_single_source_cgal_program( "test_join_iterators.cpp" )
|
create_single_source_cgal_program( "test_join_iterators.cpp" )
|
||||||
|
create_single_source_cgal_program( "test_for_each.cpp" )
|
||||||
|
if(TBB_FOUND)
|
||||||
|
CGAL_target_use_TBB(test_for_each)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
|
|
||||||
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include <CGAL/for_each.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::vector<int> vec { 0, 1, 2, 3, 4, 5 };
|
||||||
|
std::list<int> list { 0, 1, 2, 3, 4, 5 };
|
||||||
|
|
||||||
|
std::cerr << "Testing sequential random access" << std::endl;
|
||||||
|
CGAL::for_each<CGAL::Sequential_tag>
|
||||||
|
(vec, [](int& i) -> bool { i *= 2; return true; });
|
||||||
|
|
||||||
|
for (const int& i : vec)
|
||||||
|
std::cerr << i << " ";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
std::cerr << "Testing parallel random access" << std::endl;
|
||||||
|
CGAL::for_each<CGAL::Parallel_tag>
|
||||||
|
(vec, [](int& i) -> bool { i *= 2; return true; });
|
||||||
|
|
||||||
|
for (const int& i : vec)
|
||||||
|
std::cerr << i << " ";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cerr << "Testing sequential non-random access" << std::endl;
|
||||||
|
CGAL::for_each<CGAL::Sequential_tag>
|
||||||
|
(list, [](int& i) -> bool { i *= 2; return true; });
|
||||||
|
|
||||||
|
for (const int& i : list)
|
||||||
|
std::cerr << i << " ";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
std::cerr << "Testing parallel non-random access" << std::endl;
|
||||||
|
CGAL::for_each<CGAL::Parallel_tag>
|
||||||
|
(list, [](int& i) -> bool { i *= 2; return true; });
|
||||||
|
|
||||||
|
for (const int& i : list)
|
||||||
|
std::cerr << i << " ";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -105,6 +105,7 @@ namespace CGAL {
|
||||||
}
|
}
|
||||||
|
|
||||||
Kd_tree_rectangle()
|
Kd_tree_rectangle()
|
||||||
|
: max_span_coord_(-1)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -138,6 +139,7 @@ namespace CGAL {
|
||||||
|
|
||||||
template <class Construct_cartesian_const_iterator_d,class PointPointerIter> // was PointIter
|
template <class Construct_cartesian_const_iterator_d,class PointPointerIter> // was PointIter
|
||||||
Kd_tree_rectangle(int, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it)
|
Kd_tree_rectangle(int, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it)
|
||||||
|
: max_span_coord_(-1)
|
||||||
{
|
{
|
||||||
update_from_point_pointers<Construct_cartesian_const_iterator_d>(begin,end,construct_it);
|
update_from_point_pointers<Construct_cartesian_const_iterator_d>(begin,end,construct_it);
|
||||||
}
|
}
|
||||||
|
|
@ -288,7 +290,7 @@ namespace CGAL {
|
||||||
}
|
}
|
||||||
|
|
||||||
Kd_tree_rectangle()
|
Kd_tree_rectangle()
|
||||||
: coords_(0), dim(0)
|
: coords_(0), dim(0), max_span_coord_(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,7 +325,7 @@ namespace CGAL {
|
||||||
|
|
||||||
template <class Construct_cartesian_const_iterator_d,class PointPointerIter> // was PointIter
|
template <class Construct_cartesian_const_iterator_d,class PointPointerIter> // was PointIter
|
||||||
Kd_tree_rectangle(int d, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it)
|
Kd_tree_rectangle(int d, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it)
|
||||||
: coords_(new FT[2*d]), dim(d)
|
: coords_(new FT[2*d]), dim(d), max_span_coord_(-1)
|
||||||
{
|
{
|
||||||
update_from_point_pointers<Construct_cartesian_const_iterator_d>(begin,end,construct_it);
|
update_from_point_pointers<Construct_cartesian_const_iterator_d>(begin,end,construct_it);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Dereference_type&
|
Dereference_type&
|
||||||
dereference() const { return const_cast<Dereference_type&>((*point)[idx]); }
|
dereference() const
|
||||||
|
{
|
||||||
|
// Point::operator[] takes an int as parameter...
|
||||||
|
return const_cast<Dereference_type&>((*point)[static_cast<int>(idx)]);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue