Add an accurate but slow way to generate a sparse point set

This commit is contained in:
Clement Jamin 2014-12-11 18:17:32 +01:00
parent 9e48b7caf4
commit e18ba7133c
3 changed files with 174 additions and 28 deletions

View File

@ -29,13 +29,14 @@
// Solving inconsistencies: only change the weights of the inconsistent simplex
// or more?
#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS
//#define CGAL_TC_ONLY_CHANGE_SIMPLEX_WEIGHTS
// Otherwise...
const int CGAL_TC_NUMBER_OF_ADDITIONNAL_PERTURBED_POINTS = 1;
//========================= Strategy ==========================================
//#define CGAL_TC_USE_NANOFLANN
//#define CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
//========================= Parameters ========================================
const std::size_t NUM_POINTS_FOR_PCA = 50;

View File

@ -6,13 +6,13 @@
# define TBB_USE_THREADING_TOOL
#endif
#include "test_utilities.h"
#include <CGAL/Epick_d.h>
#include <CGAL/Tangential_complex.h>
#include <CGAL/Random.h>
#include <CGAL/Mesh_3/Profiling_tools.h>
#include "test_utilities.h"
#include <fstream>
#include <math.h>
@ -23,7 +23,7 @@
#ifdef _DEBUG
const int NUM_POINTS = 50;
#else
const int NUM_POINTS = 100;
const int NUM_POINTS = 10000;
#endif
int main()
@ -51,7 +51,10 @@ int main()
Wall_clock_timer t;
CGAL::default_random = CGAL::Random(i);
std::cerr << "Random seed = " << i << std::endl;
#ifdef CGAL_TC_PROFILING
Wall_clock_timer t_gen;
#endif
std::vector<Point> points =
//generate_points_on_circle_2<Kernel>(NUM_POINTS, 3.);
//generate_points_on_moment_curve<Kernel>(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.);
@ -61,6 +64,11 @@ int main()
//generate_points_on_klein_bottle_3D<Kernel>(NUM_POINTS, 4., 3.);
generate_points_on_klein_bottle_4D<Kernel>(NUM_POINTS, 4., 3.);
//generate_points_on_klein_bottle_variant_5D<Kernel>(NUM_POINTS, 4., 3.);
#ifdef CGAL_TC_PROFILING
std::cerr << "Point set generated in " << t_gen.elapsed()
<< " seconds." << std::endl;
#endif
points = sparsify_point_set(
k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY));

View File

@ -32,6 +32,56 @@
#include <CGAL/point_generators_d.h>
#include <CGAL/Tangential_complex/Point_cloud.h>
// Actually, this is very slow because the "m_points_ds->insert"
// cleans the tree, which is thus built at each query_ANN call
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
template <typename Kernel, typename Point_container>
class Point_sparsifier
{
public:
typedef typename Kernel::FT FT;
typedef typename Point_container::value_type Point;
typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure<
Kernel, Point_container> Points_ds;
typedef typename Points_ds::KNS_range KNS_range;
// We can't instantiate m_points_ds right now since it requires that
// points is not empty (which be the case here)
Point_sparsifier(Point_container &points,
FT sparsity = FT(INPUT_SPARSITY*INPUT_SPARSITY))
: m_points(points), m_sparsity(sparsity), m_points_ds(NULL)
{}
bool try_to_insert_point(const Point &p)
{
if (m_points_ds == NULL)
{
m_points.push_back(p);
m_points_ds = new Points_ds(m_points);
m_points_ds->insert(0);
return true;
}
else
{
KNS_range kns_range = m_points_ds->query_ANN(p, 1, false);
if (kns_range.begin()->second >= m_sparsity)
{
m_points.push_back(p);
m_points_ds->insert(m_points.size() - 1);
return true;
}
}
return false;
}
private:
Point_container & m_points;
Points_ds * m_points_ds;
FT m_sparsity;
};
#endif
template <typename Kernel, typename Point_container>
std::vector<typename Point_container::value_type>
sparsify_point_set(
@ -102,11 +152,21 @@ std::vector<typename Kernel::Point_d> generate_points_on_plane(std::size_t num_p
CGAL::Random rng;
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
FT x = rng.get_double(0, 5);
FT y = rng.get_double(0, 5);
points.push_back(Kernel().construct_point_d_object()(x, y, 0));
Point p = Kernel().construct_point_d_object()(x, y, 0);
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -121,15 +181,25 @@ std::vector<typename Kernel::Point_d> generate_points_on_moment_curve(
CGAL::Random rng;
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
FT x = rng.get_double(min_x, max_x);
std::vector<FT> coords;
coords.reserve(dim);
for (int p = 1 ; p <= dim ; ++p)
coords.push_back(std::pow(CGAL::to_double(x), p));
points.push_back(
Kernel().construct_point_d_object()(dim, coords.begin(), coords.end()));
Point p = Kernel().construct_point_d_object()(
dim, coords.begin(), coords.end());
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -142,8 +212,20 @@ std::vector<typename Kernel::Point_d> generate_points_on_circle_2(
CGAL::Random_points_on_circle_2<Point> generator(radius);
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
points.push_back(*generator++);
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
Point p = *generator++;
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -155,8 +237,20 @@ std::vector<typename Kernel::Point_d> generate_points_on_sphere_3(
CGAL::Random_points_on_sphere_3<Point> generator(radius);
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
points.push_back(*generator++);
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
Point p = *generator++;
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -168,8 +262,20 @@ std::vector<typename Kernel::Point_d> generate_points_on_sphere_d(
CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
points.push_back(*generator++);
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
Point p = *generator++;
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -188,7 +294,10 @@ std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
FT u, v;
if (uniform)
@ -204,10 +313,17 @@ std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(
v = rng.get_double(0, 6.2832);
}
double tmp = cos(u/2)*sin(v) - sin(u/2)*sin(2.*v);
points.push_back(Kernel().construct_point_d_object()(
Point p = Kernel().construct_point_d_object()(
(a + b*tmp)*cos(u),
(a + b*tmp)*sin(u),
b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v))));
b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)));
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -227,7 +343,10 @@ std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
FT u, v;
if (uniform)
@ -242,11 +361,19 @@ std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(
u = rng.get_double(0, 6.2832);
v = rng.get_double(0, 6.2832);
}
points.push_back(Kernel().construct_point_d_object()(
(a + b*cos(v))*cos(u) /*+ rng.get_double(0, 0.01)*/,
(a + b*cos(v))*sin(u) /*+ rng.get_double(0, 0.01)*/,
b*sin(v)*cos(u/2) /*+ rng.get_double(0, 0.01)*/,
b*sin(v)*sin(u/2) /*+ rng.get_double(0, 0.01)*/) );
Point p = Kernel().construct_point_d_object()(
Kernel().construct_point_d_object()(
(a + b*cos(v))*cos(u) /*+ rng.get_double(0, 0.01)*/,
(a + b*cos(v))*sin(u) /*+ rng.get_double(0, 0.01)*/,
b*sin(v)*cos(u/2) /*+ rng.get_double(0, 0.01)*/,
b*sin(v)*sin(u/2) /*+ rng.get_double(0, 0.01)*/) );
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}
@ -268,7 +395,10 @@ generate_points_on_klein_bottle_variant_5D(
std::vector<Point> points;
points.reserve(num_points);
for (std::size_t i = 0 ; i != num_points ; ++i)
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
#endif
for (std::size_t i = 0 ; i < num_points ; )
{
FT u, v;
if (uniform)
@ -288,8 +418,15 @@ generate_points_on_klein_bottle_variant_5D(
FT x3 = b*sin(v)*cos(u/2);
FT x4 = b*sin(v)*sin(u/2);
FT x5 = x1 + x2 + x3 + x4;
points.push_back(Kernel().construct_point_d_object()(x1, x2, x3, x4, x5) );
Point p = Kernel().construct_point_d_object()(x1, x2, x3, x4, x5);
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
if (sparsifier.try_to_insert_point(p))
++i;
#else
points.push_back(p);
++i;
#endif
}
return points;
}